diff --git a/.gitmodules b/.gitmodules
index 34a2da2894bd64ff122b67596c16e0bed7d08a74..9d649bcdd3fd7bfd77549d47150aa3c3ff70808f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -19,3 +19,6 @@
[submodule "tools/taosadapter"]
path = tools/taosadapter
url = https://github.com/taosdata/taosadapter.git
+[submodule "tools/taosws-rs"]
+ path = tools/taosws-rs
+ url = https://github.com/taosdata/taosws-rs.git
diff --git a/Jenkinsfile2 b/Jenkinsfile2
index 94af11868a67bf3ff0eff5882a737e154f89659f..32e9b1152061d054f253d3bb431cc7d6159f8c7d 100644
--- a/Jenkinsfile2
+++ b/Jenkinsfile2
@@ -4,11 +4,6 @@ import jenkins.model.CauseOfInterruption
node {
}
-win_test_stage = 0
-linux_ready = 0
-linux_node_ip = ""
-linux_node_pass = ""
-
def abortPreviousBuilds() {
def currentJobName = env.JOB_NAME
def currentBuildNumber = env.BUILD_NUMBER.toInteger()
@@ -43,10 +38,8 @@ def pre_test(){
sh '''
cd ${WK}
git reset --hard
- git fetch || git fetch
cd ${WKC}
git reset --hard
- git fetch || git fetch
'''
script {
if (env.CHANGE_TARGET == 'master') {
@@ -82,9 +75,11 @@ def pre_test(){
if (env.CHANGE_URL =~ /\/TDengine\//) {
sh '''
cd ${WKC}
+ git remote prune origin
git pull >/dev/null
git log -5
echo "`date "+%Y%m%d-%H%M%S"` ${JOB_NAME}:${BRANCH_NAME}:${BUILD_ID}:${CHANGE_TARGET}" >>${WKDIR}/jenkins.log
+ echo "CHANGE_BRANCH:${CHANGE_BRANCH}" >>${WKDIR}/jenkins.log
echo "community log: `git log -5`" >>${WKDIR}/jenkins.log
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
@@ -101,12 +96,14 @@ def pre_test(){
git pull >/dev/null
git log -5
echo "`date "+%Y%m%d-%H%M%S"` ${JOB_NAME}:${BRANCH_NAME}:${BUILD_ID}:${CHANGE_TARGET}" >>${WKDIR}/jenkins.log
+ echo "CHANGE_BRANCH:${CHANGE_BRANCH}" >>${WKDIR}/jenkins.log
echo "tdinternal log: `git log -5`" >>${WKDIR}/jenkins.log
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
git log -5
echo "tdinternal log merged: `git log -5`" >>${WKDIR}/jenkins.log
cd ${WKC}
+ git remote prune origin
git pull >/dev/null
git log -5
echo "community log: `git log -5`" >>${WKDIR}/jenkins.log
@@ -130,60 +127,80 @@ def pre_test(){
'''
return 1
}
+def pre_test_build_mac() {
+ sh '''
+ hostname
+ date
+ '''
+ sh '''
+ cd ${WK}
+ rm -rf debug
+ mkdir debug
+ '''
+ sh '''
+ cd ${WK}/debug
+ cmake ..
+ make -j8
+ '''
+ sh '''
+ date
+ '''
+}
def pre_test_win(){
bat '''
hostname
+ taskkill /f /t /im python.exe
+ taskkill /f /t /im bash.exe
+ taskkill /f /t /im taosd.exe
ipconfig
set
date /t
time /t
- rd /s /Q C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\debug || exit 0
+ rd /s /Q %WIN_INTERNAL_ROOT%\\debug || exit 0
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git reset --hard
- git fetch || git fetch
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git reset --hard
- git fetch || git fetch
'''
script {
if (env.CHANGE_TARGET == 'master') {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git checkout master
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git checkout master
'''
} else if(env.CHANGE_TARGET == '2.0') {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git checkout 2.0
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git checkout 2.0
'''
} else if(env.CHANGE_TARGET == '3.0') {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git checkout 3.0
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git checkout 3.0
'''
} else {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git checkout develop
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git checkout develop
'''
}
@@ -191,36 +208,38 @@ def pre_test_win(){
script {
if (env.CHANGE_URL =~ /\/TDengine\//) {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git pull
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
+ git remote prune origin
git pull
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git fetch origin +refs/pull/%CHANGE_ID%/merge
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git checkout -qf FETCH_HEAD
'''
} else if (env.CHANGE_URL =~ /\/TDinternal\//) {
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git pull
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git fetch origin +refs/pull/%CHANGE_ID%/merge
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git checkout -qf FETCH_HEAD
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
+ git remote prune origin
git pull
'''
} else {
@@ -230,27 +249,27 @@ def pre_test_win(){
}
}
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
git branch
git log -5
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git branch
git log -5
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community
+ cd %WIN_COMMUNITY_ROOT%
git submodule update --init --recursive
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\taos-connector-python
+ cd %WIN_CONNECTOR_ROOT%
git branch
git reset --hard
git pull
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\taos-connector-python
+ cd %WIN_CONNECTOR_ROOT%
git log -5
'''
}
@@ -258,7 +277,7 @@ def pre_test_build_win() {
bat '''
echo "building ..."
time /t
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal
+ cd %WIN_INTERNAL_ROOT%
mkdir debug
cd debug
time /t
@@ -273,9 +292,9 @@ def pre_test_build_win() {
time /t
'''
bat '''
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\taos-connector-python
+ cd %WIN_CONNECTOR_ROOT%
python -m pip install .
- xcopy /e/y/i/f C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\debug\\build\\lib\\taos.dll C:\\Windows\\System32
+ xcopy /e/y/i/f %WIN_INTERNAL_ROOT%\\debug\\build\\lib\\taos.dll C:\\Windows\\System32
'''
return 1
}
@@ -283,24 +302,22 @@ def run_win_ctest() {
bat '''
echo "windows ctest ..."
time /t
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\debug
+ cd %WIN_INTERNAL_ROOT%\\debug
ctest -j 1 || exit 7
time /t
'''
}
def run_win_test() {
- echo "LINUX NODE: ${linux_node_ip} - ${linux_node_pass}"
bat '''
echo "windows test ..."
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\taos-connector-python
+ cd %WIN_CONNECTOR_ROOT%
python -m pip install .
- xcopy /e/y/i/f C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\debug\\build\\lib\\taos.dll C:\\Windows\\System32
+ xcopy /e/y/i/f %WIN_INTERNAL_ROOT%\\debug\\build\\lib\\taos.dll C:\\Windows\\System32
ls -l C:\\Windows\\System32\\taos.dll
time /t
- cd C:\\workspace\\%EXECUTOR_NUMBER%\\TDinternal\\community\\tests\\system-test
- echo "node: ''' + linux_node_ip + ''':''' + linux_node_pass + '''"
+ cd %WIN_SYSTEM_TEST_ROOT%
echo "testing ..."
- test-all.bat "{\\\"host\\\":\\\"''' + linux_node_ip + '''\\\",\\\"port\\\":22,\\\"user\\\":\\\"root\\\",\\\"password\\\":\\\"''' + linux_node_pass + '''\\\",\\\"path\\\":\\\"/var/lib/jenkins/workspace/TDinternal\\\"}"
+ test-all.bat ci
time /t
'''
}
@@ -319,22 +336,31 @@ pipeline {
parallel {
stage('windows test') {
agent{label " windows10_01 || windows10_02 || windows10_03 || windows10_04 "}
+ environment{
+ WIN_INTERNAL_ROOT="C:\\workspace\\${env.EXECUTOR_NUMBER}\\TDinternal"
+ WIN_COMMUNITY_ROOT="C:\\workspace\\${env.EXECUTOR_NUMBER}\\TDinternal\\community"
+ WIN_SYSTEM_TEST_ROOT="C:\\workspace\\${env.EXECUTOR_NUMBER}\\TDinternal\\community\\tests\\system-test"
+ WIN_CONNECTOR_ROOT="C:\\workspace\\${env.EXECUTOR_NUMBER}\\taos-connector-python"
+ }
steps {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
timeout(time: 55, unit: 'MINUTES'){
pre_test_win()
pre_test_build_win()
run_win_ctest()
- script {
- while(linux_ready == 0) {
- sleep(8)
- }
- }
run_win_test()
}
}
- script {
- win_test_stage = 1
+ }
+ }
+ stage('mac test') {
+ agent{label " Mac_catalina "}
+ steps {
+ catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
+ timeout(time: 20, unit: 'MINUTES'){
+ pre_test()
+ pre_test_build_mac()
+ }
}
}
}
@@ -346,18 +372,15 @@ pipeline {
}
steps {
script {
- linux_node_ip = sh (
- script: 'jq .ip /home/node_info.json | sed "s/\\\"//g"',
- returnStdout: true
- ).trim()
- linux_node_pass = sh (
- script: 'jq .password /home/node_info.json | sed "s/\\\"//g" |sed "s/\\!/^^^^^^^^\\!/g"',
+ def linux_node_ip = sh (
+ script: 'ip addr|grep 192|grep -v virbr|awk "{print \\\$2}"|sed "s/\\/.*//"',
returnStdout: true
).trim()
- echo "${linux_node_ip}:${linux_node_pass}"
+ echo "${linux_node_ip}"
+ echo "${WKDIR}/restore.sh -p ${BRANCH_NAME} -n ${BUILD_ID} -c {container name}"
}
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
- timeout(time: 40, unit: 'MINUTES'){
+ timeout(time: 120, unit: 'MINUTES'){
pre_test()
script {
sh '''
@@ -368,11 +391,36 @@ pipeline {
rm -f /tmp/cases.task
./collect_cases.sh -e
'''
+ def extra_param = ""
+ def log_server_file = "/home/log_server.json"
+ def timeout_cmd = ""
+ if (fileExists(log_server_file)) {
+ def log_server_enabled = sh (
+ script: 'jq .enabled ' + log_server_file,
+ returnStdout: true
+ ).trim()
+ def timeout_param = sh (
+ script: 'jq .timeout ' + log_server_file,
+ returnStdout: true
+ ).trim()
+ if (timeout_param != "null" && timeout_param != "0") {
+ timeout_cmd = "timeout " + timeout_param
+ }
+ if (log_server_enabled == "1") {
+ def log_server = sh (
+ script: 'jq .server ' + log_server_file + ' | sed "s/\\\"//g"',
+ returnStdout: true
+ ).trim()
+ if (log_server != "null" && log_server != "") {
+ extra_param = "-w " + log_server
+ }
+ }
+ }
sh '''
cd ${WKC}/tests/parallel_test
export DEFAULT_RETRY_TIME=2
date
- timeout 2100 time ./run.sh -e -m /home/m.json -t /tmp/cases.task -b ${BRANCH_NAME}_${BUILD_ID} -l ${WKDIR}/log -o 480
+ ''' + timeout_cmd + ''' time ./run.sh -e -m /home/m.json -t /tmp/cases.task -b ${BRANCH_NAME}_${BUILD_ID} -l ${WKDIR}/log -o 480 ''' + extra_param + '''
'''
}
}
@@ -387,38 +435,9 @@ pipeline {
cd ${WKC}/packaging
./release.sh -v cluster -n 3.0.0.100 -s static
'''
- sh '''
- echo "install ..."
- cd ${WKC}/release
- tar xzf TDengine-enterprise-server-3.0.0.100-Linux-x64.tar.gz
- cd TDengine-enterprise-server-3.0.0.100
- service taosd stop || :
- rm -rf /var/lib/taos
- ./install.sh -e no
- '''
- sh '''
- echo "checking ..."
- which taos
- which taosd
- rm -rf ${WK}/debug
- mv ${WKC}/debug ${WK}/
- '''
- sh '''
- echo "install taospy ..."
- cd ${WKPY}
- pip3 install .
- '''
}
}
}
- script {
- linux_ready = 1
- }
- script {
- while(win_test_stage == 0){
- sleep(12)
- }
- }
}
}
}
diff --git a/README-CN.md b/README-CN.md
index a9bc814e8d6f6bef0ad94e29588f62e2e4c0e7f1..39d979c12337116a98fc52c18216b646e4f41e23 100644
--- a/README-CN.md
+++ b/README-CN.md
@@ -1,38 +1,59 @@
+
+
+
+
+
+
+
+
[](https://travis-ci.org/taosdata/TDengine)
[](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master)
[](https://coveralls.io/github/taosdata/TDengine?branch=develop)
[](https://bestpractices.coreinfrastructure.org/projects/4201)
[](https://snapcraft.io/tdengine)
-[](https://www.taosdata.com)
-
-简体中文 | [English](./README.md)
+简体中文 | [English](README.md) | 很多职位正在热招中,请看[这里](https://www.taosdata.com/cn/careers/)
# TDengine 简介
-TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。
+TDengine 是一款高性能、分布式、支持 SQL 的时序数据库(Time-Series Database)。而且除时序数据库功能外,它还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。与其他时序数据数据库相比,TDengine 有以下特点:
+
+- **高性能**:通过创新的存储引擎设计,无论是数据写入还是查询,TDengine 的性能比通用数据库快 10 倍以上,也远超其他时序数据库,而且存储空间也大为节省。
+
+- **分布式**:通过原生分布式的设计,TDengine 提供了水平扩展的能力,只需要增加节点就能获得更强的数据处理能力,同时通过多副本机制保证了系统的高可用。
+
+- **支持 SQL**:TDengine 采用 SQL 作为数据查询语言,减少学习和迁移成本,同时提供 SQL 扩展来处理时序数据特有的分析,而且支持方便灵活的 schemaless 数据写入。
+
+- **All in One**:将数据库、消息队列、缓存、流式计算等功能融合一起,应用无需再集成 Kafka/Redis/HBase/Spark 等软件,大幅降低应用开发和维护成本。
+
+- **零管理**:安装、集群几秒搞定,无任何依赖,不用分库分表,系统运行状态监测能与 Grafana 或其他运维工具无缝集成。
+
+- **零学习成本**:采用 SQL 查询语言,支持 Python、Java、C/C++、Go、Rust、Node.js 等多种编程语言,与 MySQL 相似,零学习成本。
+
+- **无缝集成**:不用一行代码,即可与 Telegraf、Grafana、EMQX、Prometheus、StatsD、collectd、Matlab、R 等第三方工具无缝集成。
-- 10 倍以上性能提升。定义了创新的数据存储结构,单核每秒就能处理至少2万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快了十倍以上。
-- 硬件或云服务成本降至1/5。由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10。
-- 全栈时序数据处理引擎。将数据库、消息队列、缓存、流式计算等功能融合一起,应用无需再集成Kafka/Redis/HBase/Spark等软件,大幅降低应用开发和维护成本。
-- 强大的分析功能。无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell/Python/R/Matlab随时进行。
-- 与第三方工具无缝连接。不用一行代码,即可与Telegraf, Grafana, EMQ X, Prometheus, Matlab, R集成。后续还将支持MQTT, OPC, Hadoop,Spark等, BI工具也将无缝连接。
-- 零运维成本、零学习成本。安装、集群一秒搞定,无需分库分表,实时备份。标准SQL,支持JDBC,RESTful,支持Python/Java/C/C++/Go/Node.JS, 与MySQL相似,零学习成本。
+- **互动 Console**: 通过命令行 console,不用编程,执行 SQL 语句就能做即席查询、各种数据库的操作、管理以及集群的维护.
+
+TDengine 可以广泛应用于物联网、工业互联网、车联网、IT 运维、能源、金融等领域,让大量设备、数据采集器每天产生的高达 TB 甚至 PB 级的数据能得到高效实时的处理,对业务的运行状态进行实时的监测、预警,从大数据中挖掘出商业价值。
# 文档
-TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是 [数据模型](https://www.taosdata.com/cn/documentation/architecture) 与 [数据建模](https://www.taosdata.com/cn/documentation/model)。除本文档之外,欢迎 [下载产品白皮书](https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf)。
+TDengine 采用传统的关系数据库模型,您可以像使用关系型数据库 MySQL 一样来使用它。但由于引入了超级表,一个采集点一张表的概念,建议您在使用前仔细阅读一遍下面的文档,特别是 [数据模型](https://www.taosdata.com/cn/documentation/architecture) 与 [数据建模](https://www.taosdata.com/cn/documentation/model)。除本文档之外,欢迎 [下载产品白皮书](https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf)。
# 构建
-TDengine目前2.0版服务器仅能在Linux系统上安装和运行,后续会支持Windows、macOS等系统。客户端可以在Windows或Linux上安装和运行。任何OS的应用也可以选择RESTful接口连接服务器taosd。CPU支持X64/ARM64/MIPS64/Alpha64,后续会支持ARM32、RISC-V等CPU架构。用户可根据需求选择通过[源码](https://www.taosdata.com/cn/getting-started/#通过源码安装)或者[安装包](https://www.taosdata.com/cn/getting-started/#通过安装包安装)来安装。本快速指南仅适用于通过源码安装。
+TDengine 目前 2.0 版服务器仅能在 Linux 系统上安装和运行,后续会支持 Windows、macOS 等系统。客户端可以在 Windows 或 Linux 上安装和运行。任何 OS 的应用也可以选择 RESTful 接口连接服务器 taosd。CPU 支持 X64/ARM64/MIPS64/Alpha64,后续会支持 ARM32、RISC-V 等 CPU 架构。用户可根据需求选择通过[源码](https://www.taosdata.com/cn/getting-started/#通过源码安装)或者[安装包](https://www.taosdata.com/cn/getting-started/#通过安装包安装)来安装。本快速指南仅适用于通过源码安装。
## 安装工具
### Ubuntu 16.04 及以上版本 & Debian:
```bash
-sudo apt-get install -y gcc cmake build-essential git
+sudo apt-get install -y gcc cmake build-essential git libssl-dev
```
### Ubuntu 14.04:
@@ -56,10 +77,22 @@ sudo apt-get install -y openjdk-8-jdk
sudo apt-get install -y maven
```
+#### 为 taos-tools 安装编译需要的软件
+
+taosTools 是用于 TDengine 的辅助工具软件集合。目前它包含 taosBenchmark(曾命名为 taosdemo)和 taosdump 两个软件。
+
+默认 TDengine 编译不包含 taosTools。您可以在编译 TDengine 时使用`cmake .. -DBUILD_TOOLS=true` 来同时编译 taosTools。
+
+为了在 Ubuntu/Debian 系统上编译 [taos-tools](https://github.com/taosdata/taos-tools) 需要安装如下软件:
+
+```bash
+sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev pkg-config
+```
+
### CentOS 7:
```bash
-sudo yum install -y gcc gcc-c++ make cmake git
+sudo yum install -y gcc gcc-c++ make cmake git openssl-devel
```
安装 OpenJDK 8:
@@ -74,10 +107,10 @@ sudo yum install -y java-1.8.0-openjdk
sudo yum install -y maven
```
-### CentOS 8 & Fedora:
+### CentOS 8 & Fedora
```bash
-sudo dnf install -y gcc gcc-c++ make cmake epel-release git
+sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
```
安装 OpenJDK 8:
@@ -92,6 +125,33 @@ sudo dnf install -y java-1.8.0-openjdk
sudo dnf install -y maven
```
+#### 在 CentOS 上构建 taosTools 安装依赖软件
+
+为了在 CentOS 上构建 [taosTools](https://github.com/taosdata/taos-tools) 需要安装如下依赖软件
+
+```bash
+sudo yum install zlib-devel xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libstdc++-static openssl-devel
+```
+
+注意:由于 snappy 缺乏 pkg-config 支持
+(参考 [链接](https://github.com/google/snappy/pull/86)),会导致
+cmake 提示无法发现 libsnappy,实际上工作正常。
+
+### 设置 golang 开发环境
+
+TDengine 包含数个使用 Go 语言开发的组件,请参考 golang.org 官方文档设置 go 开发环境。
+
+请使用 1.14 及以上版本。对于中国用户,我们建议使用代理来加速软件包下载。
+
+```
+go env -w GO111MODULE=on
+go env -w GOPROXY=https://goproxy.cn,direct
+```
+
+### 设置 rust 开发环境
+
+TDengine 包含数个使用 Rust 语言开发的组件. 请参考 rust-lang.org 官方文档设置 rust 开发环境。
+
## 获取源码
首先,你需要从 GitHub 克隆源码:
@@ -107,22 +167,41 @@ Go 连接器和 Grafana 插件在其他独立仓库,如果安装它们的话
git submodule update --init --recursive
```
+如果使用 https 协议下载比较慢,可以通过修改 ~/.gitconfig 文件添加以下两行设置使用 ssh 协议下载。需要首先上传 ssh 密钥到 GitHub,详细方法请参考 GitHub 官方文档。
+
+```
+[url "git@github.com:"]
+ insteadOf = https://github.com/
+```
+
## 构建 TDengine
### Linux 系统
+可以运行代码仓库中的 `build.sh` 脚本编译出 TDengine 和 taosTools(包含 taosBenchmark 和 taosdump)。
+
```bash
-mkdir debug && cd debug
-cmake .. && cmake --build .
+./build.sh
```
-您可以选择使用 Jemalloc 作为内存分配器,替代默认的 glibc:
+这个脚本等价于执行如下命令:
+
+```bash
+git submodule update --init --recursive
+mkdir debug
+cd debug
+cmake .. -DBUILD_TOOLS=true
+make
+```
+
+您也可以选择使用 jemalloc 作为内存分配器,替代默认的 glibc:
+
```bash
apt install autoconf
cmake .. -DJEMALLOC_ENABLED=true
```
-在X86-64、X86、arm64、arm32 和 mips64 平台上,TDengine 生成脚本可以自动检测机器架构。也可以手动配置 CPUTYPE 参数来指定 CPU 类型,如 aarch64 或 aarch32 等。
+在 X86-64、X86、arm64、arm32 和 mips64 平台上,TDengine 生成脚本可以自动检测机器架构。也可以手动配置 CPUTYPE 参数来指定 CPU 类型,如 aarch64 或 aarch32 等。
aarch64:
@@ -157,7 +236,7 @@ nmake
如果你使用的是 Visual Studio 2019 或 2017 版本:
-打开cmd.exe,执行 vcvarsall.bat 时,为 64 位操作系统指定“x64”,为 32 位操作系统指定“x86”。
+打开 cmd.exe,执行 vcvarsall.bat 时,为 64 位操作系统指定“x64”,为 32 位操作系统指定“x86”。
```bash
mkdir debug && cd debug
@@ -174,7 +253,7 @@ cmake .. -G "NMake Makefiles"
nmake
```
-### Mac OS X 系统
+### macOS 系统
安装 Xcode 命令行工具和 cmake. 在 Catalina 和 Big Sur 操作系统上,需要安装 XCode 11.4+ 版本。
@@ -185,13 +264,17 @@ cmake .. && cmake --build .
# 安装
-生成完成后,安装 TDengine(下文给出的指令以 Linux 为例,如果是在 Windows 下,那么对应的指令会是 `nmake install`):
+## Linux 系统
+
+生成完成后,安装 TDengine:
```bash
sudo make install
```
用户可以在[文件目录结构](https://www.taosdata.com/cn/documentation/administrator#directories)中了解更多在操作系统中生成的目录或文件。
+从 2.0 版本开始, 从源代码安装也会为 TDengine 配置服务管理。
+用户也可以选择[从安装包中安装](https://www.taosdata.com/en/getting-started/#Install-from-Package)。
安装成功后,在终端中启动 TDengine 服务:
@@ -207,6 +290,40 @@ taos
如果 TDengine Shell 连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印出错误消息。
+## Windows 系统
+
+生成完成后,安装 TDengine:
+
+```cmd
+nmake install
+```
+
+## macOS 系统
+
+生成完成后,安装 TDengine:
+
+```bash
+sudo make install
+```
+
+安装成功后,如果想以服务形式启动,先配置 `.plist` 文件,在终端中执行:
+
+```bash
+sudo cp ../packaging/macOS/com.taosdata.tdengine.plist /Library/LaunchDaemons
+```
+
+在终端中启动 TDengine 服务:
+
+```bash
+sudo launchctl load /Library/LaunchDaemons/com.taosdata.tdengine.plist
+```
+
+在终端中停止 TDengine 服务:
+
+```bash
+sudo launchctl unload /Library/LaunchDaemons/com.taosdata.tdengine.plist
+```
+
## 快速运行
如果不希望以服务方式运行 TDengine,也可以在终端中直接运行它。也即在生成完成后,执行以下命令(在 Windows 下,生成的可执行文件会带有 .exe 后缀,例如会名为 taosd.exe ):
@@ -225,15 +342,15 @@ taos
# 体验 TDengine
-在TDengine终端中,用户可以通过SQL命令来创建/删除数据库、表等,并进行插入查询操作。
+在 TDengine 终端中,用户可以通过 SQL 命令来创建/删除数据库、表等,并进行插入查询操作。
-```bash
-create database demo;
-use demo;
-create table t (ts timestamp, speed int);
-insert into t values ('2019-07-15 00:00:00', 10);
-insert into t values ('2019-07-15 01:00:00', 20);
-select * from t;
+```sql
+CREATE DATABASE demo;
+USE demo;
+CREATE TABLE t (ts TIMESTAMP, speed INT);
+INSERT INTO t VALUES('2019-07-15 00:00:00', 10);
+INSERT INTO t VALUES('2019-07-15 01:00:00', 20);
+SELECT * FROM t;
ts | speed |
===================================
19-07-15 00:00:00.000| 10|
@@ -245,33 +362,35 @@ Query OK, 2 row(s) in set (0.001700s)
## 官方连接器
-TDengine 提供了丰富的应用程序开发接口,其中包括C/C++、Java、Python、Go、Node.js、C# 、RESTful 等,便于用户快速开发应用:
+TDengine 提供了丰富的应用程序开发接口,其中包括 C/C++、Java、Python、Go、Node.js、C# 、RESTful 等,便于用户快速开发应用:
+
+- [Java](https://www.taosdata.com/cn/documentation/connector/java)
-- Java
+- [C/C++](https://www.taosdata.com/cn/documentation/connector#c-cpp)
-- C/C++
+- [Python](https://www.taosdata.com/cn/documentation/connector#python)
-- Python
+- [Go](https://www.taosdata.com/cn/documentation/connector#go)
-- Go
+- [RESTful API](https://www.taosdata.com/cn/documentation/connector#restful)
-- RESTful API
+- [Node.js](https://www.taosdata.com/cn/documentation/connector#nodejs)
-- Node.js
+- [Rust](https://www.taosdata.com/cn/documentation/connector/rust)
## 第三方连接器
TDengine 社区生态中也有一些非常友好的第三方连接器,可以通过以下链接访问它们的源码。
-- [Rust Connector](https://github.com/taosdata/TDengine/tree/master/tests/examples/rust)
+- [Rust Bindings](https://github.com/songtianyi/tdengine-rust-bindings/tree/master/examples)
- [.Net Core Connector](https://github.com/maikebing/Maikebing.EntityFrameworkCore.Taos)
-- [Lua Connector](https://github.com/taosdata/TDengine/tree/develop/tests/examples/lua)
+- [Lua Connector](https://github.com/taosdata/TDengine/tree/develop/examples/lua)
# 运行和添加测试例
TDengine 的测试框架和所有测试例全部开源。
-点击 [这里](tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md),了解如何运行测试例和添加新的测试例。
+点击 [这里](https://github.com/taosdata/TDengine/blob/develop/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md),了解如何运行测试例和添加新的测试例。
# 成为社区贡献者
@@ -279,8 +398,8 @@ TDengine 的测试框架和所有测试例全部开源。
# 加入技术交流群
-TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine",加小T为好友,即可入群。
+TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine",加小 T 为好友,即可入群。
-# [谁在使用TDengine](https://github.com/taosdata/TDengine/issues/2432)
+# [谁在使用 TDengine](https://github.com/taosdata/TDengine/issues/2432)
-欢迎所有 TDengine 用户及贡献者在 [这里](https://github.com/taosdata/TDengine/issues/2432) 分享您在当前工作中开发/使用 TDengine 的故事。
+欢迎所有 TDengine 用户及贡献者在 [这里](https://github.com/taosdata/TDengine/issues/2432) 分享您在当前工作中开发/使用 TDengine 的故事。
diff --git a/README.md b/README.md
index 2dea05f09d268b0d78de15ab98f3584df055c353..d4b8321813235f46842e7307a238623fc952c46a 100644
--- a/README.md
+++ b/README.md
@@ -1,116 +1,218 @@
+
+
+
+
+
+
+
+
[](https://cloud.drone.io/taosdata/TDengine)
[](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master)
[](https://coveralls.io/github/taosdata/TDengine?branch=develop)
[](https://bestpractices.coreinfrastructure.org/projects/4201)
[](https://snapcraft.io/tdengine)
-[](https://www.taosdata.com)
-
-English | [简体中文](./README-CN.md)
+English | [简体中文](README-CN.md) | We are hiring, check [here](https://tdengine.com/careers)
# What is TDengine?
-TDengine is an open-sourced big data platform under [GNU AGPL v3.0](http://www.gnu.org/licenses/agpl-3.0.html), designed and optimized for the Internet of Things (IoT), Connected Cars, Industrial IoT, and IT Infrastructure and Application Monitoring. Besides the 10x faster time-series database, it provides caching, stream computing, message queuing and other functionalities to reduce the complexity and cost of development and operation.
+TDengine is a high-performance, scalable time-series database with SQL support. Its code including cluster feature is open source under [GNU AGPL v3.0](http://www.gnu.org/licenses/agpl-3.0.html). Besides the database, it provides caching, stream processing, data subscription and other functionalities to reduce the complexity and cost of development and operation. TDengine differentiates itself from other TSDBs with the following advantages.
+
+- **High Performance**: TDengine outperforms other time series databases in data ingestion and querying while significantly reducing storage cost and compute costs, with an innovatively designed and purpose-built storage engine.
+
+- **Scalable**: TDengine provides out-of-box scalability and high-availability through its native distributed design. Nodes can be added through simple configuration to achieve greater data processing power. In addition, this feature is open source.
-- **10x Faster on Insert/Query Speeds**: Through the innovative design on storage, on a single-core machine, over 20K requests can be processed, millions of data points can be ingested, and over 10 million data points can be retrieved in a second. It is 10 times faster than other databases.
+- **SQL Support**: TDengine uses SQL as the query language, thereby reducing learning and migration costs, while adding SQL extensions to handle time-series data better, and supporting convenient and flexible schemaless data ingestion.
-- **1/5 Hardware/Cloud Service Costs**: Compared with typical big data solutions, less than 1/5 of computing resources are required. Via column-based storage and tuned compression algorithms for different data types, less than 1/10 of storage space is needed.
+- **All in One**: TDengine has built-in caching, stream processing and data subscription functions, it is no longer necessary to integrate Kafka/Redis/HBase/Spark or other software in some scenarios. It makes the system architecture much simpler and easy to maintain.
-- **Full Stack for Time-Series Data**: By integrating a database with message queuing, caching, and stream computing features together, it is no longer necessary to integrate Kafka/Redis/HBase/Spark or other software. It makes the system architecture much simpler and more robust.
+- **Seamless Integration**: Without a single line of code, TDengine provide seamless integration with third-party tools such as Telegraf, Grafana, EMQX, Prometheus, StatsD, collectd, etc. More will be integrated.
-- **Powerful Data Analysis**: Whether it is 10 years or one minute ago, data can be queried just by specifying the time range. Data can be aggregated over time, multiple time streams or both. Ad Hoc queries or analyses can be executed via TDengine shell, Python, R or Matlab.
+- **Zero Management**: Installation and cluster setup can be done in seconds. Data partitioning and sharding are executed automatically. TDengine’s running status can be monitored via Grafana or other DevOps tools.
-- **Seamless Integration with Other Tools**: Telegraf, Grafana, Matlab, R, and other tools can be integrated with TDengine without a line of code. MQTT, OPC, Hadoop, Spark, and many others will be integrated soon.
+- **Zero Learning Cost**: With SQL as the query language, support for ubiquitous tools like Python, Java, C/C++, Go, Rust, Node.js connectors, there is zero learning cost.
-- **Zero Management, No Learning Curve**: It takes only seconds to download, install, and run it successfully; there are no other dependencies. Automatic partitioning on tables or DBs. Standard SQL is used, with C/C++, Python, JDBC, Go and RESTful connectors.
+- **Interactive Console**: TDengine provides convenient console access to the database to run ad hoc queries, maintain the database, or manage the cluster without any programming.
+
+TDengine can be widely applied to Internet of Things (IoT), Connected Vehicles, Industrial IoT, DevOps, energy, finance and many other scenarios.
# Documentation
+
For user manual, system design and architecture, engineering blogs, refer to [TDengine Documentation](https://www.taosdata.com/en/documentation/)(中文版请点击[这里](https://www.taosdata.com/cn/documentation20/))
- for details. The documentation from our website can also be downloaded locally from *documentation/tdenginedocs-en* or *documentation/tdenginedocs-cn*.
+for details. The documentation from our website can also be downloaded locally from _documentation/tdenginedocs-en_ or _documentation/tdenginedocs-cn_.
# Building
-At the moment, TDengine only supports building and running on Linux systems. You can choose to [install from packages](https://www.taosdata.com/en/getting-started/#Install-from-Package) or from the source code. This quick guide is for installation from the source only.
-To build TDengine, use [CMake](https://cmake.org/) 2.8.12.x or higher versions in the project directory.
+At the moment, TDengine server only supports running on Linux systems. You can choose to [install from packages](https://www.taosdata.com/en/getting-started/#Install-from-Package) or build it from the source code. This quick guide is for installation from the source only.
+
+To build TDengine, use [CMake](https://cmake.org/) 3.0.2 or higher versions in the project directory.
-## Install tools
+## Install build dependencies
+
+### Ubuntu 16.04 and above or Debian
-### Ubuntu 16.04 and above & Debian:
```bash
-sudo apt-get install -y gcc cmake build-essential git
+sudo apt-get install -y gcc cmake build-essential git libssl-dev
```
-### Ubuntu 14.04:
+### Ubuntu 14.04
+
```bash
sudo apt-get install -y gcc cmake3 build-essential git binutils-2.26
export PATH=/usr/lib/binutils-2.26/bin:$PATH
```
-To compile and package the JDBC driver source code, you should have a Java jdk-8 or higher and Apache Maven 2.7 or higher installed.
+To compile and package the JDBC driver source code, you should have a Java jdk-8 or higher and Apache Maven 2.7 or higher installed.
+
To install openjdk-8:
+
```bash
sudo apt-get install -y openjdk-8-jdk
```
To install Apache Maven:
+
```bash
-sudo apt-get install -y maven
+sudo apt-get install -y maven
```
-### Centos 7:
+#### Install build dependencies for taosTools
+
+We provide a few useful tools such as taosBenchmark (was named taosdemo) and taosdump. They were part of TDengine. From TDengine 2.4.0.0, taosBenchmark and taosdump were not released together with TDengine.
+By default, TDengine compiling does not include taosTools. You can use 'cmake .. -DBUILD_TOOLS=true' to make them be compiled with TDengine.
+
+To build the [taosTools](https://github.com/taosdata/taos-tools) on Ubuntu/Debian, the following packages need to be installed.
+
```bash
-sudo yum install -y gcc gcc-c++ make cmake git
+sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev pkg-config
+```
+
+### CentOS 7
+
+```bash
+sudo yum install epel-release
+sudo yum update
+sudo yum install -y gcc gcc-c++ make cmake3 git openssl-devel
+sudo ln -sf /usr/bin/cmake3 /usr/bin/cmake
```
To install openjdk-8:
+
```bash
sudo yum install -y java-1.8.0-openjdk
```
To install Apache Maven:
+
```bash
sudo yum install -y maven
```
-### Centos 8 & Fedora:
+### CentOS 8 & Fedora
+
```bash
-sudo dnf install -y gcc gcc-c++ make cmake epel-release git
+sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
```
To install openjdk-8:
+
```bash
sudo dnf install -y java-1.8.0-openjdk
```
To install Apache Maven:
+
```bash
sudo dnf install -y maven
```
+#### Install build dependencies for taosTools on CentOS
+
+To build the [taosTools](https://github.com/taosdata/taos-tools) on CentOS, the following packages need to be installed.
+
+```bash
+sudo yum install zlib-devel xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libstdc++-static openssl-devel
+```
+
+Note: Since snappy lacks pkg-config support (refer to [link](https://github.com/google/snappy/pull/86)), it lead a cmake prompt libsnappy not found. But snappy will works well.
+
+### Setup golang environment
+
+TDengine includes few components developed by Go language. Please refer to golang.org official documentation for golang environment setup.
+
+Please use version 1.14+. For the user in China, we recommend using a proxy to accelerate package downloading.
+
+```
+go env -w GO111MODULE=on
+go env -w GOPROXY=https://goproxy.cn,direct
+```
+
+### Setup rust environment
+
+TDengine includees few compoments developed by Rust language. Please refer to rust-lang.org official documentation for rust environment setup.
+
## Get the source codes
First of all, you may clone the source codes from github:
+
```bash
git clone https://github.com/taosdata/TDengine.git
cd TDengine
```
-The connectors for go & grafana have been moved to separated repositories,
+The connectors for go & Grafana and some tools have been moved to separated repositories,
so you should run this command in the TDengine directory to install them:
+
```bash
git submodule update --init --recursive
```
+You can modify the file ~/.gitconfig to use ssh protocol instead of https for better download speed. You need to upload ssh public key to GitHub first. Please refer to GitHub official documentation for detail.
+
+```
+[url "git@github.com:"]
+ insteadOf = https://github.com/
+```
+
## Build TDengine
### On Linux platform
+You can run the bash script `build.sh` to build both TDengine and taosTools including taosBenchmark and taosdump as below:
+
```bash
-mkdir debug && cd debug
-cmake .. && cmake --build .
+./build.sh
+```
+
+It equals to execute following commands:
+
+```bash
+git submodule update --init --recursive
+mkdir debug
+cd debug
+cmake .. -DBUILD_TOOLS=true
+make
+```
+
+Note TDengine 2.3.x.0 and later use a component named 'taosAdapter' to play http daemon role by default instead of the http daemon embedded in the early version of TDengine. The taosAdapter is programmed by go language. If you pull TDengine source code to the latest from an existing codebase, please execute 'git submodule update --init --recursive' to pull taosAdapter source code. Please install go language version 1.14 or above for compiling taosAdapter. If you meet difficulties regarding 'go mod', especially you are from China, you can use a proxy to solve the problem.
+
+```
+go env -w GO111MODULE=on
+go env -w GOPROXY=https://goproxy.cn,direct
+```
+
+The embedded http daemon still be built from TDengine source code by default. Or you can use the following command to choose to build taosAdapter.
+
+```
+cmake .. -DBUILD_HTTP=false
```
You can use Jemalloc as memory allocator instead of glibc:
+
```
apt install autoconf
cmake .. -DJEMALLOC_ENABLED=true
@@ -120,16 +222,19 @@ TDengine build script can detect the host machine's architecture on X86-64, X86,
You can also specify CPUTYPE option like aarch64 or aarch32 too if the detection result is not correct:
aarch64:
+
```bash
cmake .. -DCPUTYPE=aarch64 && cmake --build .
```
aarch32:
+
```bash
cmake .. -DCPUTYPE=aarch32 && cmake --build .
```
mips64:
+
```bash
cmake .. -DCPUTYPE=mips64 && cmake --build .
```
@@ -138,6 +243,7 @@ cmake .. -DCPUTYPE=mips64 && cmake --build .
If you use the Visual Studio 2013, please open a command window by executing "cmd.exe".
Please specify "amd64" for 64 bits Windows or specify "x86" is for 32 bits Windows when you execute vcvarsall.bat.
+
```cmd
mkdir debug && cd debug
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" < amd64 | x86 >
@@ -158,13 +264,14 @@ nmake
```
Or, you can simply open a command window by clicking Windows Start -> "Visual Studio < 2019 | 2017 >" folder -> "x64 Native Tools Command Prompt for VS < 2019 | 2017 >" or "x86 Native Tools Command Prompt for VS < 2019 | 2017 >" depends what architecture your Windows is, then execute commands as follows:
+
```cmd
mkdir debug && cd debug
cmake .. -G "NMake Makefiles"
nmake
```
-### On Mac OS X platform
+### On macOS platform
Please install XCode command line tools and cmake. Verified with XCode 11.4+ on Catalina and Big Sur.
@@ -175,7 +282,10 @@ cmake .. && cmake --build .
# Installing
-After building successfully, TDengine can be installed by: (On Windows platform, the following command should be `nmake install`)
+## On Linux platform
+
+After building successfully, TDengine can be installed by
+
```bash
sudo make install
```
@@ -184,68 +294,129 @@ Users can find more information about directories installed on the system in the
Users can also choose to [install from packages](https://www.taosdata.com/en/getting-started/#Install-from-Package) for it.
To start the service after installation, in a terminal, use:
+
```bash
sudo systemctl start taosd
```
Then users can use the [TDengine shell](https://www.taosdata.com/en/getting-started/#TDengine-Shell) to connect the TDengine server. In a terminal, use:
+
```bash
taos
```
If TDengine shell connects the server successfully, welcome messages and version info are printed. Otherwise, an error message is shown.
+### Install TDengine by apt-get
+
+If you use Debian or Ubuntu system, you can use 'apt-get' command to install TDengine from official repository. Please use following commands to setup:
+
+```
+wget -qO - http://repos.taosdata.com/tdengine.key | sudo apt-key add -
+echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-stable stable main" | sudo tee /etc/apt/sources.list.d/tdengine-stable.list
+[Optional] echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-beta beta main" | sudo tee /etc/apt/sources.list.d/tdengine-beta.list
+sudo apt-get update
+apt-cache policy tdengine
+sudo apt-get install tdengine
+```
+
+## On Windows platform
+
+After building successfully, TDengine can be installed by:
+
+```cmd
+nmake install
+```
+
+## On macOS platform
+
+After building successfully, TDengine can be installed by:
+
+```bash
+sudo make install
+```
+
+To start the service after installation, config `.plist` file first, in a terminal, use:
+
+```bash
+sudo cp ../packaging/macOS/com.taosdata.tdengine.plist /Library/LaunchDaemons
+```
+
+To start the service, in a terminal, use:
+
+```bash
+sudo launchctl load /Library/LaunchDaemons/com.taosdata.tdengine.plist
+```
+
+To stop the service, in a terminal, use:
+
+```bash
+sudo launchctl unload /Library/LaunchDaemons/com.taosdata.tdengine.plist
+```
+
## Quick Run
If you don't want to run TDengine as a service, you can run it in current shell. For example, to quickly start a TDengine server after building, run the command below in terminal: (We take Linux as an example, command on Windows will be `taosd.exe`)
+
```bash
./build/bin/taosd -c test/cfg
```
In another terminal, use the TDengine shell to connect the server:
+
```bash
./build/bin/taos -c test/cfg
```
-option "-c test/cfg" specifies the system configuration file directory.
+option "-c test/cfg" specifies the system configuration file directory.
# Try TDengine
+
It is easy to run SQL commands from TDengine shell which is the same as other SQL databases.
+
```sql
-create database db;
-use db;
-create table t (ts timestamp, a int);
-insert into t values ('2019-07-15 00:00:00', 1);
-insert into t values ('2019-07-15 01:00:00', 2);
-select * from t;
-drop database db;
+CREATE DATABASE demo;
+USE demo;
+CREATE TABLE t (ts TIMESTAMP, speed INT);
+INSERT INTO t VALUES('2019-07-15 00:00:00', 10);
+INSERT INTO t VALUES('2019-07-15 01:00:00', 20);
+SELECT * FROM t;
+ ts | speed |
+===================================
+ 19-07-15 00:00:00.000| 10|
+ 19-07-15 01:00:00.000| 20|
+Query OK, 2 row(s) in set (0.001700s)
```
# Developing with TDengine
-### Official Connectors
+
+## Official Connectors
TDengine provides abundant developing tools for users to develop on TDengine. Follow the links below to find your desired connectors and relevant documentation.
-- [Java](https://www.taosdata.com/en/documentation/connector/#Java-Connector)
-- [C/C++](https://www.taosdata.com/en/documentation/connector/#C/C++-Connector)
-- [Python](https://www.taosdata.com/en/documentation/connector/#Python-Connector)
-- [Go](https://www.taosdata.com/en/documentation/connector/#Go-Connector)
-- [RESTful API](https://www.taosdata.com/en/documentation/connector/#RESTful-Connector)
-- [Node.js](https://www.taosdata.com/en/documentation/connector/#Node.js-Connector)
+- [Java](https://www.taosdata.com/en/documentation/connector/java)
+- [C/C++](https://www.taosdata.com/en/documentation/connector#c-cpp)
+- [Python](https://www.taosdata.com/en/documentation/connector#python)
+- [Go](https://www.taosdata.com/en/documentation/connector#go)
+- [RESTful API](https://www.taosdata.com/en/documentation/connector#restful)
+- [Node.js](https://www.taosdata.com/en/documentation/connector#nodejs)
+- [Rust](https://www.taosdata.com/en/documentation/connector/rust)
-### Third Party Connectors
+## Third Party Connectors
The TDengine community has also kindly built some of their own connectors! Follow the links below to find the source code for them.
-- [Rust Connector](https://github.com/taosdata/TDengine/tree/master/tests/examples/rust)
+- [Rust Bindings](https://github.com/songtianyi/tdengine-rust-bindings/tree/master/examples)
- [.Net Core Connector](https://github.com/maikebing/Maikebing.EntityFrameworkCore.Taos)
- [Lua Connector](https://github.com/taosdata/TDengine/tree/develop/tests/examples/lua)
-# How to run the test cases and how to add a new test case?
- TDengine's test framework and all test cases are fully open source.
- Please refer to [this document](tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md) for how to run test and develop new test case.
+# How to run the test cases and how to add a new test case
+
+TDengine's test framework and all test cases are fully open source.
+Please refer to [this document](https://github.com/taosdata/TDengine/blob/develop/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md) for how to run test and develop new test case.
# TDengine Roadmap
+
- Support event-driven stream computing
- Support user defined functions
- Support MQTT connection
diff --git a/cmake/cmake.define b/cmake/cmake.define
index f58c1ad3548202781834cc8c29c54c4d55af953c..a33db902cacb02076f3d5e9caca980163a46d152 100644
--- a/cmake/cmake.define
+++ b/cmake/cmake.define
@@ -18,6 +18,14 @@ if (NOT DEFINED TD_GRANT)
SET(TD_GRANT FALSE)
endif()
+IF ("${WEBSOCKET}" MATCHES "true")
+ SET(TD_WEBSOCKET TRUE)
+ MESSAGE("Enable websocket")
+ ADD_DEFINITIONS(-DWEBSOCKET)
+ELSE ()
+ SET(TD_WEBSOCKET FALSE)
+ENDIF ()
+
IF ("${BUILD_HTTP}" STREQUAL "")
IF (TD_LINUX)
IF (TD_ARM_32)
@@ -97,13 +105,13 @@ ELSE ()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
ENDIF ()
- IF (${SANITIZER} MATCHES "true")
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3")
- MESSAGE(STATUS "Will compile with Address Sanitizer!")
+ IF (${BUILD_SANITIZER})
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3 -Wformat=0")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3 -Wformat=0")
+ MESSAGE(STATUS "Will compile with Address Sanitizer!")
ELSE ()
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3")
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=0")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=0")
ENDIF ()
MESSAGE("System processor ID: ${CMAKE_SYSTEM_PROCESSOR}")
diff --git a/cmake/cmake.install b/cmake/cmake.install
index b2421fac2598d03f271ec2c35896433b796f08a2..27edd8e27a3abd89cfe2cdc23a830292b4428764 100644
--- a/cmake/cmake.install
+++ b/cmake/cmake.install
@@ -13,6 +13,7 @@ ELSEIF (TD_WINDOWS)
INSTALL(FILES ${TD_SOURCE_DIR}/packaging/cfg/taos.cfg DESTINATION cfg)
INSTALL(FILES ${TD_SOURCE_DIR}/include/client/taos.h DESTINATION include)
INSTALL(FILES ${TD_SOURCE_DIR}/include/util/taoserror.h DESTINATION include)
+ INSTALL(FILES ${TD_SOURCE_DIR}/include/libs/function/taosudf.h DESTINATION include)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos_static.lib DESTINATION driver)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver)
diff --git a/cmake/cmake.options b/cmake/cmake.options
index 62816a80d52f0460b9b14035c0032fef8dd7eafa..2acd46694bca7d710f2371fc308411f7d1cd3db5 100644
--- a/cmake/cmake.options
+++ b/cmake/cmake.options
@@ -51,15 +51,44 @@ IF(${TD_WINDOWS})
"If build unit tests using googletest"
ON
)
-ELSE ()
-
+ELSEIF (TD_DARWIN_64)
+ add_definitions(-DCOMPILER_SUPPORTS_CXX13)
option(
- BUILD_TEST
- "If build unit tests using googletest"
+ BUILD_TEST
+ "If build unit tests using googletest"
ON
)
+ELSE ()
+ include(CheckCXXCompilerFlag)
+ CHECK_CXX_COMPILER_FLAG("-std=c++13" COMPILER_SUPPORTS_CXX13)
+ IF(${COMPILER_SUPPORTS_CXX13})
+ add_definitions(-DCOMPILER_SUPPORTS_CXX13)
+ option(
+ BUILD_TEST
+ "If build unit tests using googletest"
+ ON
+ )
+ ELSE ()
+ option(
+ BUILD_TEST
+ "If build unit tests using googletest"
+ OFF
+ )
+ ENDIF ()
ENDIF ()
+option(
+ BUILD_SANITIZER
+ "If build sanitizer"
+ OFF
+ )
+
+option(
+ TDENGINE_3
+ "TDengine 3.x"
+ ON
+ )
+
option(
BUILD_ADDR2LINE
"If build addr2line"
diff --git a/cmake/cmake.platform b/cmake/cmake.platform
index acf17e9427bc453e1ece67cca5cbfe45f8827337..849d31f93e9eaa0f9c834034ee277392201df0cf 100644
--- a/cmake/cmake.platform
+++ b/cmake/cmake.platform
@@ -70,5 +70,46 @@ ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
ENDIF()
+IF ("${CPUTYPE}" STREQUAL "")
+ MESSAGE(STATUS "The current platform " ${CMAKE_SYSTEM_PROCESSOR} " is detected")
+
+ IF (CMAKE_SYSTEM_PROCESSOR MATCHES "(amd64)|(AMD64)")
+ MESSAGE(STATUS "The current platform is amd64")
+ SET(PLATFORM_ARCH_STR "amd64")
+ ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)")
+ MESSAGE(STATUS "The current platform is x86")
+ SET(PLATFORM_ARCH_STR "i386")
+ ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "armv7l")
+ MESSAGE(STATUS "The current platform is aarch32")
+ SET(PLATFORM_ARCH_STR "arm")
+ ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
+ MESSAGE(STATUS "The current platform is aarch64")
+ SET(PLATFORM_ARCH_STR "arm64")
+ ENDIF ()
+ELSE ()
+ # if generate ARM version:
+ # cmake -DCPUTYPE=aarch32 .. or cmake -DCPUTYPE=aarch64
+ IF (${CPUTYPE} MATCHES "aarch32")
+ SET(PLATFORM_ARCH_STR "arm")
+ MESSAGE(STATUS "input cpuType: aarch32")
+ ELSEIF (${CPUTYPE} MATCHES "aarch64")
+ SET(PLATFORM_ARCH_STR "arm64")
+ MESSAGE(STATUS "input cpuType: aarch64")
+ ELSEIF (${CPUTYPE} MATCHES "mips64")
+ SET(PLATFORM_ARCH_STR "mips")
+ MESSAGE(STATUS "input cpuType: mips64")
+ ELSEIF (${CPUTYPE} MATCHES "x64")
+ SET(PLATFORM_ARCH_STR "amd64")
+ MESSAGE(STATUS "input cpuType: x64")
+ ELSEIF (${CPUTYPE} MATCHES "x86")
+ SET(PLATFORM_ARCH_STR "i386")
+ MESSAGE(STATUS "input cpuType: x86")
+ ELSE ()
+ MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE})
+ ENDIF ()
+ENDIF ()
+
+MESSAGE(STATUS "platform arch:" ${PLATFORM_ARCH_STR})
+
MESSAGE("C Compiler ID: ${CMAKE_C_COMPILER_ID}")
MESSAGE("CXX Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt
index 31b9936f3e19fa6c3b943f92b9b0664ac7f3897b..e80e7e411016484632035726bb46fc663ef059ca 100644
--- a/contrib/CMakeLists.txt
+++ b/contrib/CMakeLists.txt
@@ -118,6 +118,7 @@ execute_process(COMMAND "${CMAKE_COMMAND}" --build .
# ================================================================================================
# googletest
if(${BUILD_TEST})
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(googletest EXCLUDE_FROM_ALL)
target_include_directories(
gtest
@@ -259,7 +260,7 @@ if(${BUILD_MSVCREGEX})
SET_TARGET_PROPERTIES(msvcregex PROPERTIES OUTPUT_NAME msvcregex)
endif(${BUILD_MSVCREGEX})
-# msvcregex
+# wcwidth
if(${BUILD_WCWIDTH})
add_library(wcwidth STATIC "")
target_sources(wcwidth
diff --git a/contrib/test/CMakeLists.txt b/contrib/test/CMakeLists.txt
index eacaeb9524be5dde7a231cfd7090f8dfe45f61ae..f35cf0d13d7078e6e90f52f3b49a0c579f3d856b 100644
--- a/contrib/test/CMakeLists.txt
+++ b/contrib/test/CMakeLists.txt
@@ -24,3 +24,4 @@ if(${BUILD_WITH_TRAFT})
endif(${BUILD_WITH_TRAFT})
add_subdirectory(tdev)
+add_subdirectory(lz4)
diff --git a/contrib/test/lz4/CMakeLists.txt b/contrib/test/lz4/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..92ac2aa5b26a6714b4e52f0e66f82f6db4df45a9
--- /dev/null
+++ b/contrib/test/lz4/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_executable(lz4_test "")
+target_sources(lz4_test
+ PRIVATE
+ "main.c"
+)
+target_link_libraries(lz4_test lz4_static)
\ No newline at end of file
diff --git a/contrib/test/lz4/main.c b/contrib/test/lz4/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..49a6d8da01c6186352936bd56180a496660cfef3
--- /dev/null
+++ b/contrib/test/lz4/main.c
@@ -0,0 +1,8 @@
+#include
+
+#include "lz4.h"
+
+int main(int argc, char const *argv[]) {
+ printf("%d\n", LZ4_compressBound(1024));
+ return 0;
+}
diff --git a/docs/en/07-develop/02-model/index.mdx b/docs/en/07-develop/02-model/index.mdx
index e0378cc77ca28a1a82ef6a52fa1f74d6cd580a01..b647c845d070c26398956f8a9de81864b73120e1 100644
--- a/docs/en/07-develop/02-model/index.mdx
+++ b/docs/en/07-develop/02-model/index.mdx
@@ -9,15 +9,15 @@ The data model employed by TDengine is similar to that of a relational database.
The [characteristics of time-series data](https://www.taosdata.com/blog/2019/07/09/86.html) from different data collection points may be different. Characteristics include collection frequency, retention policy and others which determine how you create and configure the database. For e.g. days to keep, number of replicas, data block size, whether data updates are allowed and other configurable parameters would be determined by the characteristics of your data and your business requirements. For TDengine to operate with the best performance, we strongly recommend that you create and configure different databases for data with different characteristics. This allows you, for example, to set up different storage and retention policies. When creating a database, there are a lot of parameters that can be configured such as, the days to keep data, the number of replicas, the number of memory blocks, time precision, the minimum and maximum number of rows in each data block, whether compression is enabled, the time range of the data in single data file and so on. Below is an example of the SQL statement to create a database.
```sql
-CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1;
+CREATE DATABASE power KEEP 365 DURATION 10 BUFFER 16 VGROUPS 100 WAL 1;
```
In the above SQL statement:
- a database named "power" will be created
- the data in it will be kept for 365 days, which means that data older than 365 days will be deleted automatically
- a new data file will be created every 10 days
-- the number of memory blocks is 6
-- data is allowed to be updated
+- the size of memory cache for writing is 16 MB
+- data will be firstly written to WAL without FSYNC
For more details please refer to [Database](/taos-sql/database).
@@ -30,7 +30,6 @@ USE power;
:::note
- Any table or STable must belong to a database. To create a table or STable, the database it belongs to must be ready.
-- JOIN operations can't be performed on tables from two different databases.
- Timestamp needs to be specified when inserting rows or querying historical rows.
:::
@@ -52,7 +51,7 @@ Similar to creating a regular table, when creating a STable, the name and schema
For each kind of data collection point, a corresponding STable must be created. There may be many STables in an application. For electrical power system, we need to create a STable respectively for meters, transformers, busbars, switches. There may be multiple kinds of data collection points on a single device, for example there may be one data collection point for electrical data like current and voltage and another data collection point for environmental data like temperature, humidity and wind direction. Multiple STables are required for these kinds of devices.
-At most 4096 (or 1024 prior to version 2.1.7.0) columns are allowed in a STable. If there are more than 4096 of metrics to be collected for a data collection point, multiple STables are required. There can be multiple databases in a system, while one or more STables can exist in a database.
+At most 4096 columns are allowed in a STable. If there are more than 4096 of metrics to be collected for a data collection point, multiple STables are required. There can be multiple databases in a system, while one or more STables can exist in a database.
## Create Table
@@ -66,12 +65,11 @@ In the above SQL statement, "d1001" is the table name, "meters" is the STable na
In the TDengine system, it's recommended to create a table for a data collection point via STable. A table created via STable is called subtable in some parts of the TDengine documentation. All SQL commands applied on regular tables can be applied on subtables.
-:::warning
-It's not recommended to create a table in a database while using a STable from another database as template.
-
:::tip
It's suggested to use the globally unique ID of a data collection point as the table name. For example the device serial number could be used as a unique ID. If a unique ID doesn't exist, multiple IDs that are not globally unique can be combined to form a globally unique ID. It's not recommended to use a globally unique ID as tag value.
+:::
+
## Create Table Automatically
In some circumstances, it's unknown whether the table already exists when inserting rows. The table can be created automatically using the SQL statement below, and nothing will happen if the table already exists.
diff --git a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx
index d8c4453f409dfaf1db1ec154e9ba35f8db74862e..da0e87abbc2c83ca940dd596ffbf5746a6b65823 100644
--- a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx
+++ b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx
@@ -42,7 +42,7 @@ INSERT INTO d1001 VALUES (1538548684000, 10.2, 220, 0.23) (1538548696650, 10.3,
### Insert into Multiple Tables
-Data can be inserted into multiple tables in the same SQL statement. The example below inserts 2 rows into table "d1001" and 1 row into table "d1002".
+Data can be inserted into multiple tables in single SQL statement. The example below inserts 2 rows into table "d1001" and 1 row into table "d1002".
```sql
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31);
@@ -52,15 +52,15 @@ For more details about `INSERT` please refer to [INSERT](/taos-sql/insert).
:::info
-- Inserting in batches can improve performance. Normally, the higher the batch size, the better the performance. Please note that a single row can't exceed 48K bytes and each SQL statement can't exceed 1MB.
-- Inserting with multiple threads can also improve performance. However, depending on the system resources on the application side and the server side, when the number of inserting threads grows beyond a specific point the performance may drop instead of improving. The proper number of threads needs to be tested in a specific environment to find the best number.
+- Inserting in batches can improve performance. Normally, the higher the batch size, the better the performance. Please note that a single row can't exceed 48 KB bytes and each SQL statement can't exceed 1 MB.
+- Inserting with multiple threads can also improve performance. However, depending on the system resources on the application side and the server side, when the number of inserting threads grows beyond a specific point the performance may drop instead of improving. The proper number of threads needs to be tested in a specific environment to find the best number. The proper number of threads may be impacted by the system resources on the server side, the system resources on the client side, the table schemas, etc.
:::
:::warning
-- If the timestamp for the row to be inserted already exists in the table, the behavior depends on the value of parameter `UPDATE`. If it's set to 0 (the default value), the row will be discarded. If it's set to 1, the new values will override the old values for the same row.
-- The timestamp to be inserted must be newer than the timestamp of subtracting current time by the parameter `KEEP`. If `KEEP` is set to 3650 days, then the data older than 3650 days ago can't be inserted. The timestamp to be inserted can't be newer than the timestamp of current time plus parameter `DAYS`. If `DAYS` is set to 2, the data newer than 2 days later can't be inserted.
+- If the timestamp for the row to be inserted already exists in the table, the old data will be overritten by the new values for the columns for which new values are provided, columns for which no new values are provided are not impacted.
+- The timestamp to be inserted must be newer than the timestamp of subtracting current time by the parameter `KEEP`. If `KEEP` is set to 3650 days, then the data older than 3650 days ago can't be inserted. The timestamp to be inserted can't be newer than the timestamp of current time plus parameter `DURATION`. If `DAYS` is set to 2, the data newer than 2 days later can't be inserted.
:::
@@ -101,7 +101,7 @@ For more details about `INSERT` please refer to [INSERT](/taos-sql/insert).
### Insert with Parameter Binding
-TDengine also provides API support for parameter binding. Similar to MySQL, only `?` can be used in these APIs to represent the parameters to bind. From version 2.1.1.0 and 2.1.2.0, parameter binding support for inserting data has improved significantly to improve the insert performance by avoiding the cost of parsing SQL statements.
+TDengine also provides API support for parameter binding. Similar to MySQL, only `?` can be used in these APIs to represent the parameters to bind. Parameter binding support for inserting data has improved significantly to improve the insert performance by avoiding the cost of parsing SQL statements.
Parameter binding is available only with native connection.
diff --git a/docs/en/10-cluster/02-cluster-mgmt.md b/docs/en/10-cluster/02-cluster-mgmt.md
index 674c92e2766a4eb304079140af19c8efea72d55e..bd3386c41161fc55b4bedcecd6ad3ab5c35be8b6 100644
--- a/docs/en/10-cluster/02-cluster-mgmt.md
+++ b/docs/en/10-cluster/02-cluster-mgmt.md
@@ -54,14 +54,14 @@ Database changed.
taos> show vgroups;
vgId | tables | status | onlines | v1_dnode | v1_status | compacting |
==========================================================================================
- 14 | 38000 | ready | 1 | 1 | master | 0 |
- 15 | 38000 | ready | 1 | 1 | master | 0 |
- 16 | 38000 | ready | 1 | 1 | master | 0 |
- 17 | 38000 | ready | 1 | 1 | master | 0 |
- 18 | 37001 | ready | 1 | 1 | master | 0 |
- 19 | 37000 | ready | 1 | 1 | master | 0 |
- 20 | 37000 | ready | 1 | 1 | master | 0 |
- 21 | 37000 | ready | 1 | 1 | master | 0 |
+ 14 | 38000 | ready | 1 | 1 | leader | 0 |
+ 15 | 38000 | ready | 1 | 1 | leader | 0 |
+ 16 | 38000 | ready | 1 | 1 | leader | 0 |
+ 17 | 38000 | ready | 1 | 1 | leader | 0 |
+ 18 | 37001 | ready | 1 | 1 | leader | 0 |
+ 19 | 37000 | ready | 1 | 1 | leader | 0 |
+ 20 | 37000 | ready | 1 | 1 | leader | 0 |
+ 21 | 37000 | ready | 1 | 1 | leader | 0 |
Query OK, 8 row(s) in set (0.001154s)
```
@@ -161,14 +161,14 @@ First `show vgroups` is executed to show the vgroup distribution.
taos> show vgroups;
vgId | tables | status | onlines | v1_dnode | v1_status | compacting |
==========================================================================================
- 14 | 38000 | ready | 1 | 3 | master | 0 |
- 15 | 38000 | ready | 1 | 3 | master | 0 |
- 16 | 38000 | ready | 1 | 3 | master | 0 |
- 17 | 38000 | ready | 1 | 3 | master | 0 |
- 18 | 37001 | ready | 1 | 3 | master | 0 |
- 19 | 37000 | ready | 1 | 1 | master | 0 |
- 20 | 37000 | ready | 1 | 1 | master | 0 |
- 21 | 37000 | ready | 1 | 1 | master | 0 |
+ 14 | 38000 | ready | 1 | 3 | leader | 0 |
+ 15 | 38000 | ready | 1 | 3 | leader | 0 |
+ 16 | 38000 | ready | 1 | 3 | leader | 0 |
+ 17 | 38000 | ready | 1 | 3 | leader | 0 |
+ 18 | 37001 | ready | 1 | 3 | leader | 0 |
+ 19 | 37000 | ready | 1 | 1 | leader | 0 |
+ 20 | 37000 | ready | 1 | 1 | leader | 0 |
+ 21 | 37000 | ready | 1 | 1 | leader | 0 |
Query OK, 8 row(s) in set (0.001314s)
```
@@ -191,14 +191,14 @@ Query OK, 0 row(s) in set (0.000575s)
taos> show vgroups;
vgId | tables | status | onlines | v1_dnode | v1_status | v2_dnode | v2_status | compacting |
=================================================================================================================
- 14 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
- 15 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
- 16 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
- 17 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
- 18 | 37001 | ready | 2 | 1 | slave | 3 | master | 0 |
- 19 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
- 20 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
- 21 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
+ 14 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
+ 15 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
+ 16 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
+ 17 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
+ 18 | 37001 | ready | 2 | 1 | follower | 3 | leader | 0 |
+ 19 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
+ 20 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
+ 21 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
Query OK, 8 row(s) in set (0.001242s)
```
@@ -207,7 +207,7 @@ It can be seen from above output that vgId 18 has been moved from dnode 3 to dno
:::note
- Manual load balancing can only be performed when the automatic load balancing is disabled, i.e. `balance` is set to 0.
-- Only a vnode in normal state, i.e. master or slave, can be moved. vnode can't be moved when its in status offline, unsynced or syncing.
+- Only a vnode in normal state, i.e. leader or follower, can be moved. vnode can't be moved when its in status offline, unsynced or syncing.
- Before moving a vnode, it's necessary to make sure the target dnode has enough resources: CPU, memory and disk.
:::
diff --git a/docs/en/10-cluster/03-ha-and-lb.md b/docs/en/10-cluster/03-ha-and-lb.md
index bd718eef9f8dc181628132de831dbca2af59d158..9780e8f6c68904e444d07c6a8c87b095c6b70ead 100644
--- a/docs/en/10-cluster/03-ha-and-lb.md
+++ b/docs/en/10-cluster/03-ha-and-lb.md
@@ -27,7 +27,7 @@ There may be multiple dnodes in a cluster, but only one mnode can be started in
SHOW MNODES;
```
-The end point and role/status (master, slave, unsynced, or offline) of all mnodes can be shown by the above command. When the first dnode is started in a cluster, there must be one mnode in this dnode. Without at least one mnode, the cluster cannot work. If `numOfMNodes` is configured to 2, another mnode will be started when the second dnode is launched.
+The end point and role/status (leader, follower, unsynced, or offline) of all mnodes can be shown by the above command. When the first dnode is started in a cluster, there must be one mnode in this dnode. Without at least one mnode, the cluster cannot work. If `numOfMNodes` is configured to 2, another mnode will be started when the second dnode is launched.
For the high availability of mnode, `numOfMnodes` needs to be configured to 2 or a higher value. Because the data consistency between mnodes must be guaranteed, the replica confirmation parameter `quorum` is set to 2 automatically if `numOfMNodes` is set to 2 or higher.
@@ -58,13 +58,13 @@ When a dnode is offline, it can be detected by the TDengine cluster. There are t
- If the dnode has been offline over the threshold configured in `offlineThreshold` in `taos.cfg`, the dnode will be removed from the cluster automatically. A system alert will be generated and automatic load balancing will be triggered if `balance` is set to 1. When the removed dnode is restarted and becomes online, it will not join the cluster automatically. The system administrator has to manually join the dnode to the cluster.
:::note
-If all the vnodes in a vgroup (or mnodes in mnode group) are in offline or unsynced status, the master node can only be voted on, after all the vnodes or mnodes in the group become online and can exchange status. Following this, the vgroup (or mnode group) is able to provide service.
+If all the vnodes in a vgroup (or mnodes in mnode group) are in offline or unsynced status, the leader node can only be voted on, after all the vnodes or mnodes in the group become online and can exchange status. Following this, the vgroup (or mnode group) is able to provide service.
:::
## Arbitrator
-The "arbitrator" component is used to address the special case when the number of replicas is set to an even number like 2,4 etc. If half of the vnodes in a vgroup don't work, it is impossible to vote and select a master node. This situation also applies to mnodes if the number of mnodes is set to an even number like 2,4 etc.
+The "arbitrator" component is used to address the special case when the number of replicas is set to an even number like 2,4 etc. If half of the vnodes in a vgroup don't work, it is impossible to vote and select a leader node. This situation also applies to mnodes if the number of mnodes is set to an even number like 2,4 etc.
To resolve this problem, a new arbitrator component named `tarbitrator`, an abbreviation of TDengine Arbitrator, was introduced. The `tarbitrator` simulates a vnode or mnode but it's only responsible for network communication and doesn't handle any actual data access. As long as more than half of the vnode or mnode, including Arbitrator, are available the vnode group or mnode group can provide data insertion or query services normally.
diff --git a/docs/en/12-taos-sql/02-database.md b/docs/en/12-taos-sql/02-database.md
index 80581b2f1bc7ce9cd046c18873d3f22b6804d8cf..c2961d62415cd7d23b031777082801426b221190 100644
--- a/docs/en/12-taos-sql/02-database.md
+++ b/docs/en/12-taos-sql/02-database.md
@@ -32,7 +32,6 @@ CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [DAYS days] [UPDATE 1];
- cacheLast: [Description](/reference/config/#cachelast)
- replica: [Description](/reference/config/#replica)
- quorum: [Description](/reference/config/#quorum)
- - maxVgroupsPerDb: [Description](/reference/config/#maxvgroupsperdb)
- comp: [Description](/reference/config/#comp)
- precision: [Description](/reference/config/#precision)
6. Please note that all of the parameters mentioned in this section are configured in configuration file `taos.cfg` on the TDengine server. If not specified in the `create database` statement, the values from taos.cfg are used by default. To override default parameters, they must be specified in the `create database` statement.
diff --git a/docs/en/14-reference/02-rest-api/02-rest-api.mdx b/docs/en/14-reference/02-rest-api/02-rest-api.mdx
index 990af861961e9daf4ac775462e21d6d9852d17c1..fe18349a6dae3ad44772b4a30a2c3d4ad75b0f47 100644
--- a/docs/en/14-reference/02-rest-api/02-rest-api.mdx
+++ b/docs/en/14-reference/02-rest-api/02-rest-api.mdx
@@ -21,7 +21,7 @@ The following example is in an Ubuntu environment and uses the `curl` tool to ve
The following example lists all databases on the host h1.taosdata.com. To use it in your environment, replace `h1.taosdata.com` and `6041` (the default port) with the actual running TDengine service FQDN and port number.
```html
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taosdata.com:6041/rest/sql
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "show databases;" h1.taosdata.com:6041/rest/sql
```
The following return value results indicate that the verification passed.
@@ -106,13 +106,13 @@ The HTTP request's BODY is a complete SQL command, and the data table in the SQL
Use `curl` to initiate an HTTP request with a custom authentication method, with the following syntax.
```bash
-curl -H 'Authorization: Basic ' -d '' :/rest/sql/[db_name]
+curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name]
```
Or
```bash
-curl -u username:password -d '' :/rest/sql/[db_name]
+curl -L -u username:password -d "" :/rest/sql/[db_name]
```
where `TOKEN` is the string after Base64 encoding of `{username}:{password}`, e.g. `root:taosdata` is encoded as `cm9vdDp0YW9zZGF0YQ==`.
@@ -192,7 +192,7 @@ Response body:
- query all records from table d1001 of database demo
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.d1001" 192.168.0.1:6041/rest/sql
```
Response body:
@@ -218,7 +218,7 @@ Response body:
- Create database demo:
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "create database demo" 192.168.0.1:6041/rest/sql
```
Response body:
@@ -240,7 +240,7 @@ Response body:
When the HTTP request URL uses `/rest/sqlt`, the returned result set's timestamp value will be in Unix timestamp format, for example:
```bash
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sqlt
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.d1001" 192.168.0.1:6041/rest/sqlt
```
Response body:
@@ -268,7 +268,7 @@ Response body:
When the HTTP request URL uses `/rest/sqlutc`, the timestamp of the returned result set will be expressed as a UTC format, for example:
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.t1' 192.168.0.1:6041/rest/sqlutc
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.t1" 192.168.0.1:6041/rest/sqlutc
```
Response body:
diff --git a/docs/en/14-reference/04-taosadapter.md b/docs/en/14-reference/04-taosadapter.md
index 3264124655e7040e1d94b43500a0b582d95cb5a1..cad229c32d602e8fc595ec06f72a1a486e2af77b 100644
--- a/docs/en/14-reference/04-taosadapter.md
+++ b/docs/en/14-reference/04-taosadapter.md
@@ -206,8 +206,8 @@ Note: InfluxDB token authorization is not supported at present. Only Basic autho
You can use any client that supports the http protocol to access the RESTful interface address `http://:6041/` to write data in OpenTSDB compatible format to TDengine.
```text
-/opentsdb/v1/put/json/:db
-/opentsdb/v1/put/telnet/:db
+/opentsdb/v1/put/json/
+/opentsdb/v1/put/telnet/
```
### collectd
diff --git a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json
index f651983528ca824b4e6b14586aac5a5bfb4ecab8..54dc1062d6440cc0fc7b8c69d9e4c6b53e4cd01e 100644
--- a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json
+++ b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json
@@ -211,7 +211,7 @@
],
"timeFrom": null,
"timeShift": null,
- "title": "Master MNode",
+ "title": "Leader MNode",
"transformations": [
{
"id": "filterByValue",
@@ -221,7 +221,7 @@
"config": {
"id": "regex",
"options": {
- "value": "master"
+ "value": "leader"
}
},
"fieldName": "role"
@@ -300,7 +300,7 @@
],
"timeFrom": null,
"timeShift": null,
- "title": "Master MNode Create Time",
+ "title": "Leader MNode Create Time",
"transformations": [
{
"id": "filterByValue",
@@ -310,7 +310,7 @@
"config": {
"id": "regex",
"options": {
- "value": "master"
+ "value": "leader"
}
},
"fieldName": "role"
diff --git a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json
index b4254c428b28a0084e54b5e3c509dd2e0ec651b9..1add8522a712aa2cfef6187e577c42d205432b66 100644
--- a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json
+++ b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json
@@ -153,7 +153,7 @@
],
"timeFrom": null,
"timeShift": null,
- "title": "Master MNode",
+ "title": "Leader MNode",
"transformations": [
{
"id": "filterByValue",
@@ -163,7 +163,7 @@
"config": {
"id": "regex",
"options": {
- "value": "master"
+ "value": "leader"
}
},
"fieldName": "role"
@@ -246,7 +246,7 @@
],
"timeFrom": null,
"timeShift": null,
- "title": "Master MNode Create Time",
+ "title": "Leader MNode Create Time",
"transformations": [
{
"id": "filterByValue",
@@ -256,7 +256,7 @@
"config": {
"id": "regex",
"options": {
- "value": "master"
+ "value": "leader"
}
},
"fieldName": "role"
diff --git a/docs/en/14-reference/07-tdinsight/index.md b/docs/en/14-reference/07-tdinsight/index.md
index cebfafa225e6e8de75ff84bb51fa664784177910..e74c9de7b2aa71278a99d45f250e0dcaf86d4704 100644
--- a/docs/en/14-reference/07-tdinsight/index.md
+++ b/docs/en/14-reference/07-tdinsight/index.md
@@ -274,8 +274,8 @@ Details of the metrics are as follows.
This section contains the current information and status of the cluster, the alert information is also here (from left to right, top to bottom).
- **First EP**: the `firstEp` setting in the current TDengine cluster.
-- **Version**: TDengine server version (master mnode).
-- **Master Uptime**: The time elapsed since the current Master MNode was elected as Master.
+- **Version**: TDengine server version (leader mnode).
+- **Leader Uptime**: The time elapsed since the current Leader MNode was elected as Leader.
- **Expire Time** - Enterprise version expiration time.
- **Used Measuring Points** - The number of measuring points used by the Enterprise Edition.
- **Databases** - The number of databases.
@@ -333,7 +333,7 @@ Data node resource usage display with repeated multiple rows for the variable `$
2. **Has MNodes?**: whether the current dnode is a mnode.
3. **CPU Cores**: the number of CPU cores.
4. **VNodes Number**: the number of VNodes in the current dnode.
-5. **VNodes Masters**: the number of vnodes in the master role.
+5. **VNodes Masters**: the number of vnodes in the leader role.
6. **Current CPU Usage of taosd**: CPU usage rate of taosd processes.
7. **Current Memory Usage of taosd**: memory usage of taosd processes.
8. **Disk Used**: The total disk usage percentage of the taosd data directory.
diff --git a/docs/en/14-reference/12-directory.md b/docs/en/14-reference/12-directory.md
index 304e3bcb434ee9a6ba338577a4d1ba546b548e3f..d6cffd22e054a759e67d34dd3e8fbb1a8585569c 100644
--- a/docs/en/14-reference/12-directory.md
+++ b/docs/en/14-reference/12-directory.md
@@ -26,7 +26,6 @@ All executable files of TDengine are in the _/usr/local/taos/bin_ directory by d
- _remove.sh_: script to uninstall TDengine, please execute it carefully, link to the **rmtaos** command in the /usr/bin directory. Will remove the TDengine installation directory `/usr/local/taos`, but will keep `/etc/taos`, `/var/lib/taos`, `/var/log/taos`
- _taosadapter_: server-side executable that provides RESTful services and accepts writing requests from a variety of other softwares
- _tarbitrator_: provides arbitration for two-node cluster deployments
-- _run_taosd_and_taosadapter.sh_: script to start both taosd and taosAdapter
- _TDinsight.sh_: script to download TDinsight and install it
- _set_core.sh_: script for setting up the system to generate core dump files for easy debugging
- _taosd-dump-cfg.gdb_: script to facilitate debugging of taosd's gdb execution.
diff --git a/docs/en/21-tdinternal/01-arch.md b/docs/en/21-tdinternal/01-arch.md
index 4d8bed4d2d6b3a0404e10213aeab599767325cc2..44651c0496481c410640e577aaad5781f846e302 100644
--- a/docs/en/21-tdinternal/01-arch.md
+++ b/docs/en/21-tdinternal/01-arch.md
@@ -22,9 +22,9 @@ A complete TDengine system runs on one or more physical nodes. Logically, it inc
**Virtual node (vnode)**: To better support data sharding, load balancing and prevent data from overheating or skewing, data nodes are virtualized into multiple virtual nodes (vnode, V2, V3, V4, etc. in the figure). Each vnode is a relatively independent work unit, which is the basic unit of time-series data storage and has independent running threads, memory space and persistent storage path. A vnode contains a certain number of tables (data collection points). When a new table is created, the system checks whether a new vnode needs to be created. The number of vnodes that can be created on a data node depends on the capacity of the hardware of the physical node where the data node is located. A vnode belongs to only one DB, but a DB can have multiple vnodes. In addition to the stored time-series data, a vnode also stores the schema and tag values of the included tables. A virtual node is uniquely identified in the system by the EP of the data node and the VGroup ID to which it belongs and is created and managed by the management node.
-**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in the figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 5) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The master/slave mechanism is adopted for the mnode group and the data synchronization is carried out in a strongly consistent way. Any data update operation can only be executed on the master. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located, through internal messaging interaction.
+**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in the figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 3) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The leader/follower mechanism is adopted for the mnode group and the data synchronization is carried out in a strongly consistent way. Any data update operation can only be executed on the leader. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located, through internal messaging interaction.
-**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high availability of the system. The virtual node group is managed in a master/slave mechanism. Write operations can only be performed on the master vnode, and then replicated to slave vnodes, thus ensuring that one single replica of data is copied on multiple physical nodes. The number of virtual nodes in a vgroup equals the number of data replicas. If the number of replicas of a DB is N, the system must have at least N data nodes. The number of replicas can be specified by the parameter `“replica”` when creating a DB, and the default is 1. Using the multi-replication feature of TDengine, the same high data reliability can be achieved without the need for expensive storage devices such as disk arrays. Virtual node groups are created and managed by the management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes have the same vnode group ID, it means that they belong to the same group and the data is backed up to each other. The number of virtual nodes in a virtual node group can be dynamically changed, allowing only one, that is, no data replication. VGroup ID is never changed. Even if a virtual node group is deleted, its ID will not be reused.
+**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high availability of the system. The virtual node group is managed in a leader/follower mechanism. Write operations can only be performed on the leader vnode, and then replicated to follower vnodes, thus ensuring that one single replica of data is copied on multiple physical nodes. The number of virtual nodes in a vgroup equals the number of data replicas. If the number of replicas of a DB is N, the system must have at least N data nodes. The number of replicas can be specified by the parameter `“replica”` when creating a DB, and the default is 1. Using the multi-replication feature of TDengine, the same high data reliability can be achieved without the need for expensive storage devices such as disk arrays. Virtual node groups are created and managed by the management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes have the same vnode group ID, it means that they belong to the same group and the data is backed up to each other. The number of virtual nodes in a virtual node group can be dynamically changed, allowing only one, that is, no data replication. VGroup ID is never changed. Even if a virtual node group is deleted, its ID will not be reused.
**TAOSC**: TAOSC is the driver provided by TDengine to applications. It is responsible for dealing with the interaction between application and cluster, and provides the native interface for the C/C++ language. It is also embedded in the JDBC, C #, Python, Go, Node.js language connection libraries. Applications interact with the whole cluster through TAOSC instead of directly connecting to data nodes in the cluster. This module is responsible for obtaining and caching metadata; forwarding requests for insertion, query, etc. to the correct data node; when returning the results to the application, TAOSC also needs to be responsible for the final level of aggregation, sorting, filtering and other operations. For JDBC, C/C++/C#/Python/Go/Node.js interfaces, this module runs on the physical node where the application is located. At the same time, in order to support the fully distributed RESTful interface, TAOSC has a running instance on each dnode of TDengine cluster.
@@ -62,13 +62,13 @@ To explain the relationship between vnode, mnode, TAOSC and application and thei
1. Application initiates a request to insert data through JDBC, ODBC, or other APIs.
2. TAOSC checks the cache to see if meta data exists for the table. If it does, it goes straight to Step 4. If not, TAOSC sends a get meta-data request to mnode.
3. Mnode returns the meta-data of the table to TAOSC. Meta-data contains the schema of the table, and also the vgroup information to which the table belongs (the vnode ID and the End Point of the dnode where the table belongs. If the number of replicas is N, there will be N groups of End Points). If TAOSC does not receive a response from the mnode for a long time, and there are multiple mnodes, TAOSC will send a request to the next mnode.
-4. TAOSC initiates an insert request to master vnode.
+4. TAOSC initiates an insert request to leader vnode.
5. After vnode inserts the data, it gives a reply to TAOSC, indicating that the insertion is successful. If TAOSC doesn't get a response from vnode for a long time, TAOSC will treat this node as offline. In this case, if there are multiple replicas of the inserted database, TAOSC will issue an insert request to the next vnode in vgroup.
6. TAOSC notifies APP that writing is successful.
For Step 2 and 3, when TAOSC starts, it does not know the End Point of mnode, so it will directly initiate a request to the configured serving End Point of the cluster. If the dnode that receives the request does not have a mnode configured, it will reply with the mnode EP list, so that TAOSC will re-issue a request to obtain meta-data to the EP of another mnode.
-For Step 4 and 5, without caching, TAOSC can't recognize the master in the virtual node group, so assumes that the first vnode is the master and sends a request to it. If this vnode is not the master, it will reply to the actual master as a new target to which TAOSC shall send a request. Once a response of successful insertion is obtained, TAOSC will cache the information of master node.
+For Step 4 and 5, without caching, TAOSC can't recognize the leader in the virtual node group, so assumes that the first vnode is the leader and sends a request to it. If this vnode is not the leader, it will reply to the actual leader as a new target to which TAOSC shall send a request. Once a response of successful insertion is obtained, TAOSC will cache the information of leader node.
The above describes the process of inserting data. The processes of querying and computing are the same. TAOSC encapsulates and hides all these complicated processes, and it is transparent to applications.
@@ -119,65 +119,65 @@ The load balancing process does not require any manual intervention, and it is t
## Data Writing and Replication Process
-If a database has N replicas, a virtual node group has N virtual nodes. But only one is the Master and all others are slaves. When the application writes a new record to system, only the Master vnode can accept the writing request. If a slave vnode receives a writing request, the system will notifies TAOSC to redirect.
+If a database has N replicas, a virtual node group has N virtual nodes. But only one is the Leader and all others are slaves. When the application writes a new record to system, only the Leader vnode can accept the writing request. If a follower vnode receives a writing request, the system will notifies TAOSC to redirect.
-### Master vnode Writing Process
+### Leader vnode Writing Process
-Master Vnode uses a writing process as follows:
+Leader Vnode uses a writing process as follows:
-
- Figure 3: TDengine Master writing process
+
+ Figure 3: TDengine Leader writing process
-1. Master vnode receives the application data insertion request, verifies, and moves to next step;
+1. Leader vnode receives the application data insertion request, verifies, and moves to next step;
2. If the system configuration parameter `“walLevel”` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file;
-3. If there are multiple replicas, vnode will forward data packet to slave vnodes in the same virtual node group, and the forwarded packet has a version number with data;
+3. If there are multiple replicas, vnode will forward data packet to follower vnodes in the same virtual node group, and the forwarded packet has a version number with data;
4. Write into memory and add the record to “skip list”;
-5. Master vnode returns a confirmation message to the application, indicating a successful write.
+5. Leader vnode returns a confirmation message to the application, indicating a successful write.
6. If any of Step 2, 3 or 4 fails, the error will directly return to the application.
-### Slave vnode Writing Process
+### Follower vnode Writing Process
-For a slave vnode, the write process as follows:
+For a follower vnode, the write process as follows:
-
- Figure 4: TDengine Slave Writing Process
+
+ Figure 4: TDengine Follower Writing Process
-1. Slave vnode receives a data insertion request forwarded by Master vnode;
+1. Follower vnode receives a data insertion request forwarded by Leader vnode;
2. If the system configuration parameter `“walLevel”` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file;
3. Write into memory and add the record to “skip list”.
-Compared with Master vnode, slave vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory and WAL is exactly the same.
+Compared with Leader vnode, follower vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory and WAL is exactly the same.
### Remote Disaster Recovery and IDC (Internet Data Center) Migration
-As discussed above, TDengine writes using Master and Slave processes. TDengine adopts asynchronous replication for data synchronization. This method can greatly improve write performance, with no obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools.
+As discussed above, TDengine writes using Leader and Follower processes. TDengine adopts asynchronous replication for data synchronization. This method can greatly improve write performance, with no obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools.
-On the other hand, TDengine supports dynamic modification of the replica number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization is complete, added virtual nodes can provide services. In the synchronization process, master and other synchronized virtual nodes keep serving. With this feature, TDengine can provide IDC migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed.
+On the other hand, TDengine supports dynamic modification of the replica number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization is complete, added virtual nodes can provide services. In the synchronization process, leader and other synchronized virtual nodes keep serving. With this feature, TDengine can provide IDC migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed.
However, the asynchronous replication has a very low probability scenario where data may be lost. The specific scenario is as follows:
-1. Master vnode has finished its 5-step operations, confirmed the success of writing to APP, and then goes down;
-2. Slave vnode receives the write request, then processing fails before writing to the log in Step 2;
-3. Slave vnode will become the new master, thus losing one record.
+1. Leader vnode has finished its 5-step operations, confirmed the success of writing to APP, and then goes down;
+2. Follower vnode receives the write request, then processing fails before writing to the log in Step 2;
+3. Follower vnode will become the new leader, thus losing one record.
In theory, for asynchronous replication, there is no guarantee to prevent data loss. However, this is an extremely low probability scenario as described above.
Note: Remote disaster recovery and no-downtime IDC migration are only supported by Enterprise Edition. **Hint: This function is not available yet**
-### Master/slave Selection
+### Leader/follower Selection
Vnode maintains a version number. When memory data is persisted, the version number will also be persisted. For each data update operation, whether it is time-series data or metadata, this version number will be increased by one.
-When a vnode starts, the roles (master, slave) are uncertain, and the data is in an unsynchronized state. It’s necessary to establish TCP connections with other nodes in the virtual node group and exchange status, including version and its own roles. Through the exchange, the system implements a master-selection process. The rules are as follows:
+When a vnode starts, the roles (leader, follower) are uncertain, and the data is in an unsynchronized state. It’s necessary to establish TCP connections with other nodes in the virtual node group and exchange status, including version and its own roles. Through the exchange, the system implements a leader-selection process. The rules are as follows:
-1. If there’s only one replica, it’s always master
-2. When all replicas are online, the one with latest version is master
-3. Over half of online nodes are virtual nodes, and some virtual node is slave, it will automatically become master
-4. For 2 and 3, if multiple virtual nodes meet the requirement, the first vnode in virtual node group list will be selected as master.
+1. If there’s only one replica, it’s always leader
+2. When all replicas are online, the one with latest version is leader
+3. Over half of online nodes are virtual nodes, and some virtual node is follower, it will automatically become leader
+4. For 2 and 3, if multiple virtual nodes meet the requirement, the first vnode in virtual node group list will be selected as leader.
### Synchronous Replication
-For scenarios with strong data consistency requirements, asynchronous data replication is not applicable, because there is a small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Master forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in slave. If “quorum-1” reply confirms are not received within a certain period of time, the master vnode will return an error to the application.
+For scenarios with strong data consistency requirements, asynchronous data replication is not applicable, because there is a small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Leader forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in follower. If “quorum-1” reply confirms are not received within a certain period of time, the leader vnode will return an error to the application.
With synchronous replication, performance of system will decrease and latency will increase. Because metadata needs strong consistency, the default for data synchronization between mnodes is synchronous replication.
diff --git a/docs/en/25-application/03-immigrate.md b/docs/en/25-application/03-immigrate.md
index 4d47aec1d76014ba63f6be91004abcc3934769f7..fe67f973894d460fb017de0e1a2099b8441a4abe 100644
--- a/docs/en/25-application/03-immigrate.md
+++ b/docs/en/25-application/03-immigrate.md
@@ -379,11 +379,11 @@ We still use the hypothetical environment from Chapter 4. There are three measur
### Storage resource estimation
-Assuming that the number of sensor devices that generate data and need to be stored is `n`, the frequency of data generation is `t` per second, and the length of each record is `L` bytes, the scale of data generated per day is `n * t * L` bytes. Assuming the compression ratio is `C`, the daily data size is `(n * t * L)/C` bytes. The storage resources are estimated to accommodate the data scale for 1.5 years. In the production environment, the compression ratio C of TDengine is generally between 5 and 7.
+Assuming that the number of sensor devices that generate data and need to be stored is `n`, the frequency of data generation is `t` per second, and the length of each record is `L` bytes, the scale of data generated per day is `86400 * n * t * L` bytes. Assuming the compression ratio is `C`, the daily data size is `(86400 * n * t * L)/C` bytes. The storage resources are estimated to accommodate the data scale for 1.5 years. In the production environment, the compression ratio C of TDengine is generally between 5 and 7.
With additional 20% redundancy, you can calculate the required storage resources:
```matlab
-(n * t * L) * (365 * 1.5) * (1+20%)/C
+(86400 * n * t * L) * (365 * 1.5) * (1+20%)/C
````
Substituting in the above formula, the raw data generated every year is 11.8TB without considering the label information. Note that tag information is associated with each timeline in TDengine, not every record. The amount of data to be recorded is somewhat reduced relative to the generated data, and label data can be ignored as a whole. Assuming a compression ratio of 5, the size of the retained data ends up being 2.56 TB.
diff --git a/docs/en/27-train-faq/03-docker.md b/docs/en/27-train-faq/03-docker.md
index afee13c1377b0b4331d6f7ec20251d1aa2db81a1..0378fffb8bdbc4cae8d4d2176ec3d745a548c2fe 100644
--- a/docs/en/27-train-faq/03-docker.md
+++ b/docs/en/27-train-faq/03-docker.md
@@ -109,7 +109,7 @@ taos>
It's also able to access the REST interface provided by TDengine in container from the host.
```
-curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql
+curl -L -u root:taosdata -d "show databases" 127.0.0.1:6041/rest/sql
```
Output is like below:
@@ -147,7 +147,7 @@ docker run -d --name tdengine-taosd -p 6030-6042:6030-6042 -p 6030-6042:6030-604
- Verify the REST interface:
```bash
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' 127.0.0.1:6041/rest/sql
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "show databases;" 127.0.0.1:6041/rest/sql
```
Below is an example output:
diff --git a/docs/examples/java/src/main/java/com/taos/example/LineProtocolExample.java b/docs/examples/java/src/main/java/com/taos/example/LineProtocolExample.java
index 990922b7a516bd32a7e299f5743bd1b5e321868a..09c3078e222c1da083c6ed0da19274b7772bba16 100644
--- a/docs/examples/java/src/main/java/com/taos/example/LineProtocolExample.java
+++ b/docs/examples/java/src/main/java/com/taos/example/LineProtocolExample.java
@@ -26,7 +26,7 @@ public class LineProtocolExample {
private static void createDatabase(Connection conn) throws SQLException {
try (Statement stmt = conn.createStatement()) {
- // the default precision is ms (microsecond), but we use us(microsecond) here.
+ // the default precision is ms (millisecond), but we use us(microsecond) here.
stmt.execute("CREATE DATABASE IF NOT EXISTS test PRECISION 'us'");
stmt.execute("USE test");
}
diff --git a/docs/zh/07-develop/02-model/index.mdx b/docs/zh/07-develop/02-model/index.mdx
index 7e2762b6e78393493c2c5b61959e9a6ff57a7b13..be545e8813b26b3abbb22d8231590a909e935a83 100644
--- a/docs/zh/07-develop/02-model/index.mdx
+++ b/docs/zh/07-develop/02-model/index.mdx
@@ -8,13 +8,13 @@ TDengine 采用类关系型数据模型,需要建库、建表。因此对于
## 创建库
-不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能最大效率的工作,TDengine 建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除 SQL 标准的选项外,还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
+不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能最大效率的工作,TDengine 建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除 SQL 标准的选项外,还可以指定保留时长、副本数、缓存大小、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
```sql
-CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1;
+CREATE DATABASE power KEEP 365 DURATION 10 BUFFER 16 VGROUPS 100 WAL 1;
```
-上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,内存块数为 6,允许更新数据。详细的语法及参数请见 [数据库管理](/taos-sql/database) 章节。
+上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,每个 VNODE 的写入内存池的大小为 16 MB,数据库的 VGROUPS 数量,对该数据库入会写 WAL 但不执行 FSYNC。详细的语法及参数请见 [数据库管理](/taos-sql/database) 章节。
创建库之后,需要使用 SQL 命令 `USE` 将当前库切换过来,例如:
@@ -27,7 +27,6 @@ USE power;
:::note
- 任何一张表或超级表必须属于某个库,在创建表之前,必须先创建库。
-- 处于两个不同库的表是不能进行 JOIN 操作的。
- 创建并插入记录、查询历史记录的时候,均需要指定时间戳。
:::
@@ -40,15 +39,11 @@ USE power;
CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);
```
-:::note
-这一指令中的 STABLE 关键字,在 2.0.15 之前的版本中需写作 TABLE 。
-:::
-
与创建普通表一样,创建超级表时,需要提供表名(示例中为 meters),表结构 Schema,即数据列的定义。第一列必须为时间戳(示例中为 ts),其他列为采集的物理量(示例中为 current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的 schema (示例中为 location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组 ID、管理员 ID 等等。标签的 schema 可以事后增加、删除、修改。具体定义以及细节请见 [TAOS SQL 的超级表管理](/taos-sql/stable) 章节。
每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。对于电网,我们就需要对智能电表、变压器、母线、开关等都建立一个超级表。在物联网中,一个设备就可能有多个数据采集点(比如一台风力发电的风机,有的采集点采集电流、电压等电参数,有的采集点采集温度、湿度、风向等环境参数),这个时候,对这一类型的设备,需要建立多张超级表。
-一张超级表最多容许 4096 列 (在 2.1.7.0 版本之前,列数限制为 1024 列),如果一个采集点采集的物理量个数超过 4096,需要建多张超级表来处理。一个系统可以有多个 DB,一个 DB 里可以有一到多个超级表。
+一张超级表最多容许 4096 列,如果一个采集点采集的物理量个数超过 4096,需要建多张超级表来处理。一个系统可以有多个 DB,一个 DB 里可以有一到多个超级表。
## 创建表
@@ -60,11 +55,6 @@ CREATE TABLE d1001 USING meters TAGS ("California.SanFrancisco", 2);
其中 d1001 是表名,meters 是超级表的表名,后面紧跟标签 Location 的具体标签值 "California.SanFrancisco",标签 groupId 的具体标签值 2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 [TAOS SQL 的表管理](/taos-sql/table) 章节。
-:::warning
-目前 TDengine 没有从技术层面限制使用一个 database (db1) 的超级表作为模板建立另一个 database (db2) 的子表,后续会禁止这种用法,不建议使用这种方法建表。
-
-:::
-
TDengine 建议将数据采集点的全局唯一 ID 作为表名(比如设备序列号)。但对于有的场景,并没有唯一的 ID,可以将多个 ID 组合成一个唯一的 ID。不建议将具有唯一性的 ID 作为标签值。
### 自动建表
diff --git a/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx b/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx
index 99a92573c87d0f90f699a8d1352619f4df4aef39..214cbdaa96d02e0cd1251eeda97c6a897887cc7e 100644
--- a/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx
+++ b/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx
@@ -52,15 +52,15 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
:::info
-- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过 48K,一条 SQL 语句总长度不能超过 1M 。
-- TDengine 支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开 20 个以上的线程同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程频繁切换,带来额外开销。
+- 要提高写入效率,需要批量写入。一般来说一批写入的记录条数越多,插入效率就越高。但一条记录不能超过 48K,一条 SQL 语句总长度不能超过 1M 。
+- TDengine 支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开多个同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程频繁切换,会带来额外开销,合适的线程数量与服务端的处理能力,服务端的具体配置,数据库的参数,数据定义的 Schema,写入数据的 Batch Size 等很多因素相关。一般来说,服务端和客户端处理能力越强,所能支持的并发写入的线程可以越多;数据库配置时的 vgroups 越多(但仍然要在服务端的处理能力以内)则所能支持的并发写入越多;数据定义的 Schema 越简单,所能支持的并发写入越多。
:::
:::warning
-- 对同一张表,如果新插入记录的时间戳已经存在,默认情形下(UPDATE=0)新记录将被直接抛弃,也就是说,在一张表里,时间戳必须是唯一的。如果应用自动生成记录,很有可能生成的时间戳是一样的,这样,成功插入的记录条数会小于应用插入的记录条数。如果在创建数据库时使用了 UPDATE 1 选项,插入相同时间戳的新记录将覆盖原有记录。
-- 写入的数据的时间戳必须大于当前时间减去配置参数 keep 的时间。如果 keep 配置为 3650 天,那么无法写入比 3650 天还早的数据。写入数据的时间戳也不能大于当前时间加配置参数 days。如果 days 为 2,那么无法写入比当前时间还晚 2 天的数据。
+- 对同一张表,如果新插入记录的时间戳已经存在,则指定了新值的列会用新值覆盖旧值,而没有指定新值的列则不受影响。
+- 写入的数据的时间戳必须大于当前时间减去配置参数 keep 的时间。如果 keep 配置为 3650 天,那么无法写入比 3650 天还早的数据。写入数据的时间戳也不能大于当前时间加配置参数 duration。如果 duration 为 2,那么无法写入比当前时间还晚 2 天的数据。
:::
@@ -104,7 +104,7 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
### 参数绑定写入
-TDengine 也提供了支持参数绑定的 Prepare API,与 MySQL 类似,这些 API 目前也仅支持用问号 `?` 来代表待绑定的参数。从 2.1.1.0 和 2.1.2.0 版本开始,TDengine 大幅改进了参数绑定接口对数据写入(INSERT)场景的支持。这样在通过参数绑定接口写入数据时,就避免了 SQL 语法解析的资源消耗,从而在绝大多数情况下显著提升写入性能。
+TDengine 也提供了支持参数绑定的 Prepare API,与 MySQL 类似,这些 API 目前也仅支持用问号 `?` 来代表待绑定的参数。在通过参数绑定接口写入数据时,就避免了 SQL 语法解析的资源消耗,从而在绝大多数情况下显著提升写入性能。
需要注意的是,只有使用原生连接的连接器,才能使用参数绑定功能。
diff --git a/docs/zh/12-taos-sql/02-database.md b/docs/zh/12-taos-sql/02-database.md
index 566fec324148fede8d897869656b83e657569f59..e3a0aa7c87461fd1621a38093871a1542e3dbf98 100644
--- a/docs/zh/12-taos-sql/02-database.md
+++ b/docs/zh/12-taos-sql/02-database.md
@@ -32,7 +32,6 @@ CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [DAYS days] [UPDATE 1];
- cacheLast: [详细说明](/reference/config/#cachelast)
- replica: [详细说明](/reference/config/#replica)
- quorum: [详细说明](/reference/config/#quorum)
- - maxVgroupsPerDb: [详细说明](/reference/config/#maxvgroupsperdb)
- comp: [详细说明](/reference/config/#comp)
- precision: [详细说明](/reference/config/#precision)
6. 请注意上面列出的所有参数都可以配置在配置文件 `taosd.cfg` 中作为创建数据库时使用的默认配置, `create database` 的参数中明确指定的会覆盖配置文件中的设置。
diff --git a/docs/zh/14-reference/02-rest-api/02-rest-api.mdx b/docs/zh/14-reference/02-rest-api/02-rest-api.mdx
index 43099319b9c5bb1420c199cfa9f7def0b2c44d3d..a8a92606e4aadf7298359023e739d568788094fd 100644
--- a/docs/zh/14-reference/02-rest-api/02-rest-api.mdx
+++ b/docs/zh/14-reference/02-rest-api/02-rest-api.mdx
@@ -21,7 +21,7 @@ RESTful 接口不依赖于任何 TDengine 的库,因此客户端不需要安
下面示例是列出所有的数据库,请把 h1.taosdata.com 和 6041(缺省值)替换为实际运行的 TDengine 服务 FQDN 和端口号:
```html
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taosdata.com:6041/rest/sql
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "show databases;" h1.taosdata.com:6041/rest/sql
```
返回值结果如下表示验证通过:
@@ -106,13 +106,13 @@ HTTP 请求的 BODY 里就是一个完整的 SQL 语句,SQL 语句中的数据
使用 `curl` 通过自定义身份认证方式来发起一个 HTTP Request,语法如下:
```bash
-curl -H 'Authorization: Basic ' -d '' :/rest/sql/[db_name]
+curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name]
```
或者
```bash
-curl -u username:password -d '' :/rest/sql/[db_name]
+curl -L -u username:password -d "" :/rest/sql/[db_name]
```
其中,`TOKEN` 为 `{username}:{password}` 经过 Base64 编码之后的字符串,例如 `root:taosdata` 编码后为 `cm9vdDp0YW9zZGF0YQ==`
@@ -192,7 +192,7 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
- 在 demo 库里查询表 d1001 的所有记录:
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.d1001" 192.168.0.1:6041/rest/sql
```
返回值:
@@ -218,7 +218,7 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
- 创建库 demo:
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "create database demo" 192.168.0.1:6041/rest/sql
```
返回值:
@@ -240,7 +240,7 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
HTTP 请求 URL 采用 `/rest/sqlt` 时,返回结果集的时间戳将采用 Unix 时间戳格式表示,例如
```bash
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sqlt
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.d1001" 192.168.0.1:6041/rest/sqlt
```
返回结果:
@@ -268,7 +268,7 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001
HTTP 请求 URL 采用 `/rest/sqlutc` 时,返回结果集的时间戳将采用 UTC 时间字符串表示,例如
```bash
- curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.t1' 192.168.0.1:6041/rest/sqlutc
+ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.t1" 192.168.0.1:6041/rest/sqlutc
```
返回值:
diff --git a/docs/zh/14-reference/04-taosadapter.md b/docs/zh/14-reference/04-taosadapter.md
index 6e259391d40acfd48d8db8db3246ad2196ce0520..42bc51a6d3609392537b272d13c414c9382fb9ea 100644
--- a/docs/zh/14-reference/04-taosadapter.md
+++ b/docs/zh/14-reference/04-taosadapter.md
@@ -207,8 +207,8 @@ AllowWebSockets
您可以使用任何支持 http 协议的客户端访问 Restful 接口地址 `http://:6041/` 来写入 OpenTSDB 兼容格式的数据到 TDengine。EndPoint 如下:
```text
-/opentsdb/v1/put/json/:db
-/opentsdb/v1/put/telnet/:db
+/opentsdb/v1/put/json/
+/opentsdb/v1/put/telnet/
```
### collectd
diff --git a/docs/zh/14-reference/12-directory.md b/docs/zh/14-reference/12-directory.md
index f8c8cb4a082f691cf75db9bed3b42d0d6e1bc8a3..0caf7e03c32b475e82b6f0bcf58ba2d9225aa6bc 100644
--- a/docs/zh/14-reference/12-directory.md
+++ b/docs/zh/14-reference/12-directory.md
@@ -26,7 +26,6 @@ TDengine 的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
- _remove.sh_:卸载 TDengine 的脚本,请谨慎执行,链接到/usr/bin 目录下的**rmtaos**命令。会删除 TDengine 的安装目录/usr/local/taos,但会保留/etc/taos、/var/lib/taos、/var/log/taos
- _taosadapter_: 提供 RESTful 服务和接受其他多种软件写入请求的服务端可执行文件
- _tarbitrator_: 提供双节点集群部署的仲裁功能
-- _run_taosd_and_taosadapter.sh_:同时启动 taosd 和 taosAdapter 的脚本
- _TDinsight.sh_:用于下载 TDinsight 并安装的脚本
- _set_core.sh_:用于方便调试设置系统生成 core dump 文件的脚本
- _taosd-dump-cfg.gdb_:用于方便调试 taosd 的 gdb 执行脚本。
diff --git a/docs/zh/21-tdinternal/01-arch.md b/docs/zh/21-tdinternal/01-arch.md
index 433cb4808b60ce73c639a23beef45fb8e1afb7dd..507ccea6291cd2cdd5d2477e151ee58d2865e0be 100644
--- a/docs/zh/21-tdinternal/01-arch.md
+++ b/docs/zh/21-tdinternal/01-arch.md
@@ -23,7 +23,7 @@ TDengine 分布式架构的逻辑结构图如下:
**虚拟节点(vnode):** 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode,图中 V2,V3,V4 等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个 DB,但一个 DB 可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的 schema、标签值等。一个虚拟节点由所属的数据节点的 EP,以及所属的 VGroup ID 在系统内唯一标识,由管理节点创建并管理。
-**管理节点(mnode):** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中 M)。同时,管理节点也负责元数据(包括用户、数据库、表、静态标签等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(开源版最多不超过 3 个)mnode,它们自动构建成为一个虚拟管理节点组(图中 M0,M1,M2)。mnode 间采用 master/slave 的机制进行管理,而且采取强一致方式进行数据同步,任何数据更新操作只能在 Master 上进行。mnode 集群的创建由系统自动完成,无需人工干预。每个 dnode 上至多有一个 mnode,由所属的数据节点的 EP 来唯一标识。每个 dnode 通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的 EP。
+**管理节点(mnode):** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中 M)。同时,管理节点也负责元数据(包括用户、数据库、表、静态标签等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过 3 个)mnode,它们自动构建成为一个虚拟管理节点组(图中 M0,M1,M2)。mnode 间采用 master/slave 的机制进行管理,而且采取强一致方式进行数据同步,任何数据更新操作只能在 Master 上进行。mnode 集群的创建由系统自动完成,无需人工干预。每个 dnode 上至多有一个 mnode,由所属的数据节点的 EP 来唯一标识。每个 dnode 通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的 EP。
**虚拟节点组(VGroup):** 不同数据节点上的 vnode 可以组成一个虚拟节点组(vgroup)来保证系统的高可靠。虚拟节点组内采取 master/slave 的方式进行管理。写操作只能在 master vnode 上进行,系统采用异步复制的方式将数据同步到 slave vnode,这样确保了一份数据在多个物理节点上有拷贝。一个 vgroup 里虚拟节点个数就是数据的副本数。如果一个 DB 的副本数为 N,系统必须有至少 N 数据节点。副本数在创建 DB 时通过参数 replica 可以指定,缺省为 1。使用 TDengine 的多副本特性,可以不再需要昂贵的磁盘阵列等存储设备,就可以获得同样的数据高可靠性。虚拟节点组由管理节点创建、管理,并且由管理节点分配一个系统唯一的 ID,VGroup ID。如果两个虚拟节点的 VGroup ID 相同,说明他们属于同一个组,数据互为备份。虚拟节点组里虚拟节点的个数是可以动态改变的,容许只有一个,也就是没有数据复制。VGroup ID 是永远不变的,即使一个虚拟节点组被删除,它的 ID 也不会被收回重复利用。
diff --git a/docs/zh/25-application/03-immigrate.md b/docs/zh/25-application/03-immigrate.md
index 9d8946bc4a69639c5327ac1ffb6c0539ddbd0e63..d1c9caea099b79494784aa1122e89d7b4d412464 100644
--- a/docs/zh/25-application/03-immigrate.md
+++ b/docs/zh/25-application/03-immigrate.md
@@ -367,10 +367,10 @@ WHERE ts>=1510560000 AND ts<=1515000009
### 存储资源估算
-假设产生数据并需要存储的传感器设备数量为 `n`,数据生成的频率为`t`条/秒,每条记录的长度为 `L` bytes,则每天产生的数据规模为 `n×t×L` bytes。假设压缩比为 C,则每日产生数据规模为 `(n×t×L)/C` bytes。存储资源预估为能够容纳 1.5 年的数据规模,生产环境下 TDengine 的压缩比 C 一般在 5 ~ 7 之间,同时为最后结果增加 20% 的冗余,可计算得到需要存储资源:
+假设产生数据并需要存储的传感器设备数量为 `n`,数据生成的频率为`t`条/秒,每条记录的长度为 `L` bytes,则每天产生的数据规模为 `86400×n×t×L` bytes。假设压缩比为 C,则每日产生数据规模为 `(86400×n×t×L)/C` bytes。存储资源预估为能够容纳 1.5 年的数据规模,生产环境下 TDengine 的压缩比 C 一般在 5 ~ 7 之间,同时为最后结果增加 20% 的冗余,可计算得到需要存储资源:
```matlab
-(n×t×L)×(365×1.5)×(1+20%)/C
+(86400×n×t×L)×(365×1.5)×(1+20%)/C
```
结合以上的计算公式,将参数带入计算公式,在不考虑标签信息的情况下,每年产生的原始数据规模是 11.8TB。需要注意的是,由于标签信息在 TDengine 中关联到每个时间线,并不是每条记录。所以需要记录的数据量规模相对于产生的数据有一定的降低,而这部分标签数据整体上可以忽略不记。假设压缩比为 5,则保留的数据规模最终为 2.56 TB。
diff --git a/docs/zh/27-train-faq/03-docker.md b/docs/zh/27-train-faq/03-docker.md
index 7791569b25e102b4634f0fb899fc0973cacc0aa1..72b4603dda2a078d04427290c560c9818f19915e 100644
--- a/docs/zh/27-train-faq/03-docker.md
+++ b/docs/zh/27-train-faq/03-docker.md
@@ -108,7 +108,7 @@ taos>
也可以在宿主机使用 curl 通过 RESTful 端口访问 Docker 容器内的 TDengine server。
```
-curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql
+curl -L -u root:taosdata -d "show databases" 127.0.0.1:6041/rest/sql
```
输出示例如下:
@@ -148,7 +148,7 @@ docker run -d --name tdengine-taosd -p 6030-6042:6030-6042 -p 6030-6042:6030-604
使用 curl 命令验证 RESTful 接口可以正常工作:
```bash
-curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' 127.0.0.1:6041/rest/sql
+curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "show databases;" 127.0.0.1:6041/rest/sql
```
输出示例如下:
diff --git a/examples/c/stream_demo.c b/examples/c/stream_demo.c
index 5f6e3b2aeb6c27bbcc5f9dd7fcd89af3431e2f25..dd4fbc8d2d400bc9fc257202bda1979a62041895 100644
--- a/examples/c/stream_demo.c
+++ b/examples/c/stream_demo.c
@@ -25,7 +25,7 @@ int32_t init_env() {
return -1;
}
- TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 1");
+ TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 2");
if (taos_errno(pRes) != 0) {
printf("error in create db, reason:%s\n", taos_errstr(pRes));
return -1;
@@ -68,6 +68,14 @@ int32_t init_env() {
return -1;
}
taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table if not exists tu3 using st1 tags(3)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create child table tu3, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
return 0;
}
@@ -90,9 +98,10 @@ int32_t create_stream() {
/*const char* sql = "select min(k), max(k), sum(k) as sum_of_k from st1";*/
/*const char* sql = "select sum(k) from tu1 interval(10m)";*/
/*pRes = tmq_create_stream(pConn, "stream1", "out1", sql);*/
- pRes = taos_query(pConn,
- "create stream stream1 trigger window_close into outstb as select _wstartts, sum(k) from st1 "
- "interval(10s) ");
+ pRes =
+ taos_query(pConn,
+ "create stream stream1 trigger max_delay 10s into outstb as select _wstart, sum(k) from st1 partition "
+ "by tbname session(ts, 10s) ");
if (taos_errno(pRes) != 0) {
printf("failed to create stream stream1, reason:%s\n", taos_errstr(pRes));
return -1;
diff --git a/examples/c/tmq.c b/examples/c/tmq.c
index 7870d7d9a188030806fc113fbadcb2f76172ef66..94e0b86821b4dc601709b4b513027b5ccf882861 100644
--- a/examples/c/tmq.c
+++ b/examples/c/tmq.c
@@ -18,6 +18,7 @@
#include
#include
#include "taos.h"
+#include
static int running = 1;
static void msg_process(TAOS_RES* msg) {
@@ -26,6 +27,40 @@ static void msg_process(TAOS_RES* msg) {
printf("topic: %s\n", tmq_get_topic_name(msg));
printf("db: %s\n", tmq_get_db_name(msg));
printf("vg: %d\n", tmq_get_vgroup_id(msg));
+ if (tmq_get_res_type(msg) == TMQ_RES_TABLE_META) {
+ tmq_raw_data *raw = tmq_get_raw_meta(msg);
+ if(raw){
+ TAOS* pConn = taos_connect("192.168.1.86", "root", "taosdata", NULL, 0);
+ if (pConn == NULL) {
+ return;
+ }
+
+ TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 5");
+ if (taos_errno(pRes) != 0) {
+ printf("error in create db, reason:%s\n", taos_errstr(pRes));
+ return;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "use abc1");
+ if (taos_errno(pRes) != 0) {
+ printf("error in use db, reason:%s\n", taos_errstr(pRes));
+ return;
+ }
+ taos_free_result(pRes);
+
+ int32_t ret = taos_write_raw_meta(pConn, raw);
+ printf("write raw data: %s\n", tmq_err2str(ret));
+ taos_close(pConn);
+ }
+ tmq_free_raw_meta(raw);
+ char* result = tmq_get_json_meta(msg);
+ if(result){
+ printf("meta result: %s\n", result);
+ }
+ tmq_free_json_meta(result);
+ return;
+ }
while (1) {
TAOS_ROW row = taos_fetch_row(msg);
if (row == NULL) break;
@@ -47,7 +82,7 @@ int32_t init_env() {
return -1;
}
- TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 1");
+ TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 5");
if (taos_errno(pRes) != 0) {
printf("error in create db, reason:%s\n", taos_errstr(pRes));
return -1;
@@ -61,34 +96,188 @@ int32_t init_env() {
}
taos_free_result(pRes);
- pRes =
- taos_query(pConn, "create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int)");
+ pRes = taos_query(pConn, "create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 nchar(8), t4 bool)");
if (taos_errno(pRes) != 0) {
printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes));
return -1;
}
taos_free_result(pRes);
- pRes = taos_query(pConn, "create table if not exists ct0 using st1 tags(1000)");
+ pRes = taos_query(pConn, "create table if not exists ct0 using st1 tags(1000, \"ttt\", true)");
if (taos_errno(pRes) != 0) {
printf("failed to create child table tu1, reason:%s\n", taos_errstr(pRes));
return -1;
}
taos_free_result(pRes);
- pRes = taos_query(pConn, "create table if not exists ct1 using st1 tags(2000)");
+ pRes = taos_query(pConn, "insert into ct0 values(now, 1, 2, 'a')");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to insert into ct0, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table if not exists ct1 using st1(t1) tags(2000)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create child table ct1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table if not exists ct2 using st1(t1) tags(NULL)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create child table ct2, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "insert into ct1 values(now, 3, 4, 'b')");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to insert into ct1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table if not exists ct3 using st1(t1) tags(3000)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create child table ct3, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "insert into ct3 values(now, 5, 6, 'c')");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to insert into ct3, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table st1 add column c4 bigint");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table st1 modify column c3 binary(64)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table st1 add tag t2 binary(64)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table ct3 set tag t1=5000");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to slter child table ct3, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "drop table ct3 ct1");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to drop child table ct3, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "drop table st1");
if (taos_errno(pRes) != 0) {
- printf("failed to create child table tu2, reason:%s\n", taos_errstr(pRes));
+ printf("failed to drop super table st1, reason:%s\n", taos_errstr(pRes));
return -1;
}
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table if not exists n1(ts timestamp, c1 int, c2 nchar(4))");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table n1 add column c3 bigint");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table n1 modify column c2 nchar(8)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "alter table n1 rename column c3 cc3");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
- pRes = taos_query(pConn, "create table if not exists ct3 using st1 tags(3000)");
+ pRes = taos_query(pConn, "alter table n1 comment 'hello'");
if (taos_errno(pRes) != 0) {
- printf("failed to create child table tu3, reason:%s\n", taos_errstr(pRes));
+ printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
return -1;
}
+ taos_free_result(pRes);
+ pRes = taos_query(pConn, "alter table n1 drop column c1");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "drop table n1");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to drop normal table n1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table jt(ts timestamp, i int) tags(t json)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create super table jt, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table jt1 using jt tags('{\"k1\":1, \"k2\":\"hello\"}')");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create super table jt, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table jt2 using jt tags('')");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create super table jt2, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 nchar(8), t4 bool)");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "drop table st1");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to drop super table st1, reason:%s\n", taos_errstr(pRes));
+ return -1;
+ }
+ taos_free_result(pRes);
+
return 0;
}
@@ -107,8 +296,8 @@ int32_t create_topic() {
}
taos_free_result(pRes);
- /*pRes = taos_query(pConn, "create topic topic_ctb_column as database abc1");*/
- pRes = taos_query(pConn, "create topic topic_ctb_column as select ts, c1, c2, c3 from st1");
+ 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));
return -1;
@@ -168,6 +357,9 @@ tmq_t* build_consumer() {
tmq_conf_set(conf, "td.connect.pass", "taosdata");
tmq_conf_set(conf, "msg.with.table.name", "true");
tmq_conf_set(conf, "enable.auto.commit", "true");
+
+ /*tmq_conf_set(conf, "experimental.snapshot.enable", "true");*/
+
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
tmq_t* tmq = tmq_consumer_new(conf, NULL, 0);
assert(tmq);
@@ -192,7 +384,7 @@ void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) {
}
int32_t cnt = 0;
while (running) {
- TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 0);
+ TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, -1);
if (tmqmessage) {
cnt++;
msg_process(tmqmessage);
diff --git a/examples/rust b/examples/rust
index 1c8924dc668e6aa848214c2fc54e3ace3f5bf8df..7ed7a97715388fa144718764d6bf20f9bfc29a12 160000
--- a/examples/rust
+++ b/examples/rust
@@ -1 +1 @@
-Subproject commit 1c8924dc668e6aa848214c2fc54e3ace3f5bf8df
+Subproject commit 7ed7a97715388fa144718764d6bf20f9bfc29a12
diff --git a/include/client/taos.h b/include/client/taos.h
index 61538e392a0daa14b3f2def6ed74b0ee51d8d7ef..690c4739866ef8ee8d87a37754c59345aeaa556d 100644
--- a/include/client/taos.h
+++ b/include/client/taos.h
@@ -131,10 +131,10 @@ DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...);
DLL_EXPORT setConfRet taos_set_config(const char *config);
DLL_EXPORT int taos_init(void);
DLL_EXPORT TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port);
-DLL_EXPORT TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port);
-DLL_EXPORT void taos_close(TAOS *taos);
+DLL_EXPORT TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port);
+DLL_EXPORT void taos_close(TAOS *taos);
-const char *taos_data_type(int type);
+const char *taos_data_type(int type);
DLL_EXPORT TAOS_STMT *taos_stmt_init(TAOS *taos);
DLL_EXPORT int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length);
@@ -164,6 +164,7 @@ DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql);
DLL_EXPORT TAOS_ROW taos_fetch_row(TAOS_RES *res);
DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result
DLL_EXPORT void taos_free_result(TAOS_RES *res);
+DLL_EXPORT void taos_kill_query(TAOS *taos);
DLL_EXPORT int taos_field_count(TAOS_RES *res);
DLL_EXPORT int taos_num_fields(TAOS_RES *res);
DLL_EXPORT int taos_affected_rows(TAOS_RES *res);
@@ -187,8 +188,8 @@ DLL_EXPORT TAOS_ROW *taos_result_block(TAOS_RES *res);
DLL_EXPORT const char *taos_get_server_info(TAOS *taos);
DLL_EXPORT const char *taos_get_client_info();
-DLL_EXPORT const char *taos_errstr(TAOS_RES *tres);
-DLL_EXPORT int taos_errno(TAOS_RES *tres);
+DLL_EXPORT const char *taos_errstr(TAOS_RES *res);
+DLL_EXPORT int taos_errno(TAOS_RES *res);
DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param);
DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param);
@@ -252,10 +253,25 @@ DLL_EXPORT void tmq_conf_set_auto_commit_cb(tmq_conf_t *conf, tmq_comm
/* -------------------------TMQ MSG HANDLE INTERFACE---------------------- */
-DLL_EXPORT const char *tmq_get_topic_name(TAOS_RES *res);
-DLL_EXPORT const char *tmq_get_db_name(TAOS_RES *res);
-DLL_EXPORT int32_t tmq_get_vgroup_id(TAOS_RES *res);
-DLL_EXPORT const char *tmq_get_table_name(TAOS_RES *res);
+enum tmq_res_t {
+ TMQ_RES_INVALID = -1,
+ TMQ_RES_DATA = 1,
+ TMQ_RES_TABLE_META = 2,
+};
+
+typedef enum tmq_res_t tmq_res_t;
+typedef struct tmq_raw_data tmq_raw_data;
+
+DLL_EXPORT tmq_res_t tmq_get_res_type(TAOS_RES *res);
+DLL_EXPORT tmq_raw_data *tmq_get_raw_meta(TAOS_RES *res);
+DLL_EXPORT int32_t taos_write_raw_meta(TAOS *taos, tmq_raw_data *raw_meta);
+DLL_EXPORT void tmq_free_raw_meta(tmq_raw_data *rawMeta);
+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);
+DLL_EXPORT const char *tmq_get_topic_name(TAOS_RES *res);
+DLL_EXPORT const char *tmq_get_db_name(TAOS_RES *res);
+DLL_EXPORT int32_t tmq_get_vgroup_id(TAOS_RES *res);
+DLL_EXPORT const char *tmq_get_table_name(TAOS_RES *res);
/* ------------------------------ TMQ END -------------------------------- */
diff --git a/include/common/tcommon.h b/include/common/tcommon.h
index a05287761ef5dbf8d28c075bbc6cb9cac9910651..5a7b32d20b2b7c2fbc57142f8b9a01a66250fbec 100644
--- a/include/common/tcommon.h
+++ b/include/common/tcommon.h
@@ -25,55 +25,89 @@
extern "C" {
#endif
+// TODO remove it
enum {
- TMQ_CONF__RESET_OFFSET__LATEST = -1,
- TMQ_CONF__RESET_OFFSET__EARLIEAST = -2,
TMQ_CONF__RESET_OFFSET__NONE = -3,
+ TMQ_CONF__RESET_OFFSET__EARLIEAST = -2,
+ TMQ_CONF__RESET_OFFSET__LATEST = -1,
};
+// clang-format off
+#define IS_META_MSG(x) ( \
+ x == TDMT_VND_CREATE_STB \
+ || x == TDMT_VND_ALTER_STB \
+ || x == TDMT_VND_DROP_STB \
+ || x == TDMT_VND_CREATE_TABLE \
+ || x == TDMT_VND_ALTER_TABLE \
+ || x == TDMT_VND_DROP_TABLE \
+)
+// clang-format on
+
enum {
TMQ_MSG_TYPE__DUMMY = 0,
TMQ_MSG_TYPE__POLL_RSP,
+ TMQ_MSG_TYPE__POLL_META_RSP,
TMQ_MSG_TYPE__EP_RSP,
TMQ_MSG_TYPE__END_RSP,
};
+enum {
+ STREAM_INPUT__DATA_SUBMIT = 1,
+ STREAM_INPUT__DATA_BLOCK,
+ // STREAM_INPUT__TABLE_SCAN,
+ STREAM_INPUT__TQ_SCAN,
+ STREAM_INPUT__DATA_RETRIEVE,
+ STREAM_INPUT__TRIGGER,
+ STREAM_INPUT__CHECKPOINT,
+ STREAM_INPUT__DROP,
+};
+
typedef enum EStreamType {
STREAM_NORMAL = 1,
STREAM_INVERT,
- STREAM_REPROCESS,
+ STREAM_CLEAR,
STREAM_INVALID,
STREAM_GET_ALL,
+ STREAM_DELETE_RESULT,
+ STREAM_DELETE_DATA,
+ STREAM_RETRIEVE,
+ STREAM_PULL_DATA,
+ STREAM_PULL_OVER,
} EStreamType;
typedef struct {
+ SArray* pGroupList;
SArray* pTableList;
SHashObj* map; // speedup acquire the tableQueryInfo by table uid
+ bool needSortTableByGroupId;
+ void* pTagCond;
+ void* pTagIndexCond;
+ uint64_t suid;
} STableListInfo;
+#pragma pack(push, 1)
typedef struct SColumnDataAgg {
int16_t colId;
- int16_t maxIndex;
- int16_t minIndex;
int16_t numOfNull;
int64_t sum;
int64_t max;
int64_t min;
} SColumnDataAgg;
+#pragma pack(pop)
typedef struct SDataBlockInfo {
STimeWindow window;
- int32_t rows;
+ int32_t rows; // todo hide this attribute
int32_t rowSize;
- int64_t uid; // the uid of table, from which current data block comes
- int64_t blockId; // block id, generated by physical planner
+ uint64_t uid; // the uid of table, from which current data block comes
+ uint16_t blockId; // block id, generated by physical planner
uint64_t groupId; // no need to serialize
- int16_t numOfCols;
int16_t hasVarCol;
- int32_t capacity;
+ uint32_t capacity;
// TODO: optimize and remove following
int32_t childId; // used for stream, do not serialize
EStreamType type; // used for stream, do not serialize
+ STimeWindow calWin; // used for stream, do not serialize
} SDataBlockInfo;
typedef struct SSDataBlock {
@@ -82,6 +116,21 @@ typedef struct SSDataBlock {
SDataBlockInfo info;
} SSDataBlock;
+enum {
+ FETCH_TYPE__DATA = 1,
+ FETCH_TYPE__META,
+ FETCH_TYPE__NONE,
+};
+
+typedef struct {
+ int8_t fetchType;
+ STqOffsetVal offset;
+ union {
+ SSDataBlock data;
+ void* meta;
+ };
+} SFetchRet;
+
typedef struct SVarColAttr {
int32_t* offset; // start position for each entry in the list
uint32_t length; // used buffer size that contain the valid data
@@ -91,7 +140,7 @@ typedef struct SVarColAttr {
// pBlockAgg->numOfNull == info.rows, all data are null
// pBlockAgg->numOfNull == 0, no data are null.
typedef struct SColumnInfoData {
- SColumnInfo info; // TODO filter info needs to be removed
+ SColumnInfo info; // column info
bool hasNull; // if current column data has null value.
char* pData; // the corresponding block data in memory
union {
@@ -101,20 +150,17 @@ typedef struct SColumnInfoData {
} SColumnInfoData;
typedef struct SQueryTableDataCond {
- // STimeWindow twindow;
uint64_t suid;
int32_t order; // desc|asc order to iterate the data block
int32_t numOfCols;
SColumnInfo* colList;
- bool loadExternalRows; // load external rows or not
- int32_t type; // data block load type:
- int32_t numOfTWindows;
- STimeWindow* twindows;
- int32_t startVersion;
- int32_t endVersion;
+ int32_t type; // data block load type:
+// int32_t numOfTWindows;
+ STimeWindow twindows;
+ int64_t startVersion;
+ int64_t endVersion;
} SQueryTableDataCond;
-void* blockDataDestroy(SSDataBlock* pBlock);
int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock);
void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock);
@@ -122,19 +168,6 @@ int32_t tEncodeDataBlocks(void** buf, const SArray* blocks);
void* tDecodeDataBlocks(const void* buf, SArray** blocks);
void colDataDestroy(SColumnInfoData* pColData);
-static FORCE_INLINE void blockDestroyInner(SSDataBlock* pBlock) {
- int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
- for (int32_t i = 0; i < numOfOutput; ++i) {
- SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
- colDataDestroy(pColInfoData);
- }
-
- taosArrayDestroy(pBlock->pDataBlock);
- taosMemoryFreeClear(pBlock->pBlockAgg);
-}
-
-static FORCE_INLINE void tDeleteSSDataBlock(SSDataBlock* pBlock) { blockDestroyInner(pBlock); }
-
//======================================================================================================================
// the following structure shared by parser and executor
typedef struct SColumn {
diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h
index 709462a7449dade291fc06166b7fc08e80f96cb4..a4f59040184221db85ac41a68e3e62f9e21398e9 100644
--- a/include/common/tdatablock.h
+++ b/include/common/tdatablock.h
@@ -71,7 +71,8 @@ SEpSet getEpSet_s(SCorEpSet* pEpSet);
#define colDataGetData(p1_, r_) \
((IS_VAR_DATA_TYPE((p1_)->info.type)) ? colDataGetVarData(p1_, r_) : colDataGetNumData(p1_, r_))
-#define IS_JSON_NULL(type, data) ((type) == TSDB_DATA_TYPE_JSON && *(data) == TSDB_DATA_TYPE_NULL)
+#define IS_JSON_NULL(type, data) \
+ ((type) == TSDB_DATA_TYPE_JSON && (*(data) == TSDB_DATA_TYPE_NULL || tTagIsJsonNull(data)))
static FORCE_INLINE bool colDataIsNull_s(const SColumnInfoData* pColumnInfoData, uint32_t row) {
if (!pColumnInfoData->hasNull) {
@@ -183,9 +184,10 @@ static FORCE_INLINE void colDataAppendDouble(SColumnInfoData* pColumnInfoData, u
int32_t getJsonValueLen(const char* data);
int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull);
-int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, int32_t* capacity,
+int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, uint32_t* capacity,
const SColumnInfoData* pSource, uint32_t numOfRow2);
-int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows);
+int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows,
+ const SDataBlockInfo* pBlockInfo);
int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex);
int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows);
@@ -211,7 +213,7 @@ size_t blockDataGetSerialMetaSize(uint32_t numOfCols);
int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo);
int32_t blockDataSort_rv(SSDataBlock* pDataBlock, SArray* pOrderInfo, bool nullFirst);
-int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, size_t existRows, uint32_t numOfRows);
+int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, uint32_t numOfRows);
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows);
void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows);
@@ -220,14 +222,28 @@ void blockDataCleanup(SSDataBlock* pDataBlock);
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize);
int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n);
+int32_t blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n);
+int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src);
+int32_t copyDataBlock(SSDataBlock* dst, const SSDataBlock* src);
+
+SSDataBlock* createDataBlock();
+void* blockDataDestroy(SSDataBlock* pBlock);
+void blockDataFreeRes(SSDataBlock* pBlock);
SSDataBlock* createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData);
-void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols,
- int8_t needCompress);
-const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData);
+int32_t blockDataAppendColInfo(SSDataBlock* pBlock, SColumnInfoData* pColInfoData);
+
+SColumnInfoData createColumnInfoData(int16_t type, int32_t bytes, int16_t colId);
+SColumnInfoData* bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index);
+
+void blockEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols, int8_t needCompress);
+const char* blockDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData);
-void blockDebugShowData(const SArray* dataBlocks, const char* flag);
+void blockDebugShowDataBlock(SSDataBlock* pBlock, const char* flag);
+void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag);
+// for debug
+char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** dumpBuf);
int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks, STSchema* pTSchema, int32_t vgId,
tb_uid_t suid);
@@ -235,7 +251,7 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks
char* buildCtbNameByGroupId(const char* stbName, uint64_t groupId);
static FORCE_INLINE int32_t blockGetEncodeSize(const SSDataBlock* pBlock) {
- return blockDataGetSerialMetaSize(pBlock->info.numOfCols) + blockDataGetSize(pBlock);
+ return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
}
static FORCE_INLINE int32_t blockCompressColData(SColumnInfoData* pColRes, int32_t numOfRows, char* data,
diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h
index 2e69640a065f9049f2bcb2a2c3f190f0178fca3f..311eb72b4d94564ce0c426e3c460c7980976cae0 100644
--- a/include/common/tdataformat.h
+++ b/include/common/tdataformat.h
@@ -34,21 +34,44 @@ typedef struct SValue SValue;
typedef struct SColVal SColVal;
typedef struct STSRow2 STSRow2;
typedef struct STSRowBuilder STSRowBuilder;
-typedef struct SColData SColData;
typedef struct STagVal STagVal;
typedef struct STag STag;
+// bitmap
+#define N1(n) ((1 << (n)) - 1)
+#define BIT1_SIZE(n) (((n)-1) / 8 + 1)
+#define BIT2_SIZE(n) (((n)-1) / 4 + 1)
+#define SET_BIT1(p, i, v) \
+ do { \
+ (p)[(i) / 8] &= N1((i) % 8); \
+ (p)[(i) / 8] |= (((uint8_t)(v)) << (((i) % 8))); \
+ } while (0)
+
+#define GET_BIT1(p, i) (((p)[(i) / 8] >> ((i) % 8)) & ((uint8_t)1))
+#define SET_BIT2(p, i, v) \
+ do { \
+ p[(i) / 4] &= N1((i) % 4 * 2); \
+ (p)[(i) / 4] |= (((uint8_t)(v)) << (((i) % 4) * 2)); \
+ } while (0)
+#define GET_BIT2(p, i) (((p)[(i) / 4] >> (((i) % 4) * 2)) & ((uint8_t)3))
+
// STSchema
int32_t tTSchemaCreate(int32_t sver, SSchema *pSchema, int32_t nCols, STSchema **ppTSchema);
void tTSchemaDestroy(STSchema *pTSchema);
// SValue
-int tValueCmprFn(const SValue *pValue1, const SValue *pValue2, int8_t type);
+int32_t tPutValue(uint8_t *p, SValue *pValue, int8_t type);
+int32_t tGetValue(uint8_t *p, SValue *pValue, int8_t type);
+int tValueCmprFn(const SValue *pValue1, const SValue *pValue2, int8_t type);
+
+// SColVal
+#define COL_VAL_NONE(CID, TYPE) ((SColVal){.cid = (CID), .type = (TYPE), .isNone = 1})
+#define COL_VAL_NULL(CID, TYPE) ((SColVal){.cid = (CID), .type = (TYPE), .isNull = 1})
+#define COL_VAL_VALUE(CID, TYPE, V) ((SColVal){.cid = (CID), .type = (TYPE), .value = (V)})
// STSRow2
-#define COL_VAL_NONE(CID) ((SColVal){.cid = (CID), .isNone = 1})
-#define COL_VAL_NULL(CID) ((SColVal){.cid = (CID), .isNull = 1})
-#define COL_VAL_VALUE(CID, V) ((SColVal){.cid = (CID), .value = (V)})
+#define TSROW_LEN(PROW, V) tGetI32v((uint8_t *)(PROW)->data, (V) ? &(V) : NULL)
+#define TSROW_SVER(PROW, V) tGetI32v((PROW)->data + TSROW_LEN(PROW, NULL), (V) ? &(V) : NULL)
int32_t tTSRowNew(STSRowBuilder *pBuilder, SArray *pArray, STSchema *pTSchema, STSRow2 **ppRow);
int32_t tTSRowClone(const STSRow2 *pRow, STSRow2 **ppRow);
@@ -56,7 +79,7 @@ void tTSRowFree(STSRow2 *pRow);
void tTSRowGet(STSRow2 *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal);
int32_t tTSRowToArray(STSRow2 *pRow, STSchema *pTSchema, SArray **ppArray);
int32_t tPutTSRow(uint8_t *p, STSRow2 *pRow);
-int32_t tGetTSRow(uint8_t *p, STSRow2 *pRow);
+int32_t tGetTSRow(uint8_t *p, STSRow2 **ppRow);
// STSRowBuilder
#define tsRowBuilderInit() ((STSRowBuilder){0})
@@ -70,13 +93,15 @@ int32_t tGetTSRow(uint8_t *p, STSRow2 *pRow);
// STag
int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag);
void tTagFree(STag *pTag);
+bool tTagIsJson(const void *pTag);
+bool tTagIsJsonNull(void *tagVal);
bool tTagGet(const STag *pTag, STagVal *pTagVal);
char *tTagValToData(const STagVal *pTagVal, bool isJson);
int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag);
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag);
int32_t tTagToValArray(const STag *pTag, SArray **ppArray);
void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remove
-void debugCheckTags(STag *pTag); // TODO: remove
+int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf);
// STRUCT =================
struct STColumn {
@@ -102,16 +127,16 @@ struct STSchema {
#define TSROW_KV_SMALL ((uint8_t)0x10U)
#define TSROW_KV_MID ((uint8_t)0x20U)
#define TSROW_KV_BIG ((uint8_t)0x40U)
+#pragma pack(push, 1)
struct STSRow2 {
- TSKEY ts;
- uint8_t flags;
- int32_t sver;
- uint32_t nData;
- uint8_t *pData;
+ TSKEY ts;
+ uint8_t flags;
+ uint8_t data[];
};
+#pragma pack(pop)
struct STSRowBuilder {
- STSRow2 tsRow;
+ // STSRow2 tsRow;
int32_t szBuf;
uint8_t *pBuf;
};
@@ -138,6 +163,7 @@ struct SValue {
struct SColVal {
int16_t cid;
+ int8_t type;
int8_t isNone;
int8_t isNull;
SValue value;
@@ -145,6 +171,7 @@ struct SColVal {
#pragma pack(push, 1)
struct STagVal {
+// char colName[TSDB_COL_NAME_LEN]; // only used for tmq_get_meta
union {
int16_t cid;
char *pKey;
@@ -170,12 +197,6 @@ struct STag {
};
#pragma pack(pop)
-struct SColData {
- int16_t cid;
- uint32_t nData;
- uint8_t *pData;
-};
-
#if 1 //================================================================================================================================================
// Imported since 3.0 and use bitmap to demonstrate None/Null/Norm, while use Null/Norm below 3.0 without of bitmap.
#define TD_SUPPORT_BITMAP
@@ -210,50 +231,6 @@ struct SColData {
memcpy(varDataVal(x), (str), (_size)); \
} while (0);
-// ----------------- TSDB COLUMN DEFINITION
-
-#define colType(col) ((col)->type)
-#define colFlags(col) ((col)->flags)
-#define colColId(col) ((col)->colId)
-#define colBytes(col) ((col)->bytes)
-#define colOffset(col) ((col)->offset)
-
-#define colSetType(col, t) (colType(col) = (t))
-#define colSetFlags(col, f) (colFlags(col) = (f))
-#define colSetColId(col, id) (colColId(col) = (id))
-#define colSetBytes(col, b) (colBytes(col) = (b))
-#define colSetOffset(col, o) (colOffset(col) = (o))
-
-// ----------------- TSDB SCHEMA DEFINITION
-
-#define schemaNCols(s) ((s)->numOfCols)
-#define schemaVersion(s) ((s)->version)
-#define schemaTLen(s) ((s)->tlen)
-#define schemaFLen(s) ((s)->flen)
-#define schemaVLen(s) ((s)->vlen)
-#define schemaColAt(s, i) ((s)->columns + i)
-#define tdFreeSchema(s) taosMemoryFreeClear((s))
-
-STSchema *tdDupSchema(const STSchema *pSchema);
-int32_t tdEncodeSchema(void **buf, STSchema *pSchema);
-void *tdDecodeSchema(void *buf, STSchema **pRSchema);
-
-static FORCE_INLINE int32_t comparColId(const void *key1, const void *key2) {
- if (*(int16_t *)key1 > ((STColumn *)key2)->colId) {
- return 1;
- } else if (*(int16_t *)key1 < ((STColumn *)key2)->colId) {
- return -1;
- } else {
- return 0;
- }
-}
-
-static FORCE_INLINE STColumn *tdGetColOfID(STSchema *pSchema, int16_t colId) {
- void *ptr = bsearch(&colId, (void *)pSchema->columns, schemaNCols(pSchema), sizeof(STColumn), comparColId);
- if (ptr == NULL) return NULL;
- return (STColumn *)ptr;
-}
-
// ----------------- SCHEMA BUILDER DEFINITION
typedef struct {
int32_t tCols;
@@ -283,141 +260,6 @@ void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version)
int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, col_id_t colId, col_bytes_t bytes);
STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder);
-// ----------------- Semantic timestamp key definition
-// typedef uint64_t TKEY;
-#define TKEY TSKEY
-
-#define TKEY_INVALID UINT64_MAX
-#define TKEY_NULL TKEY_INVALID
-#define TKEY_NEGATIVE_FLAG (((TKEY)1) << 63)
-#define TKEY_VALUE_FILTER (~(TKEY_NEGATIVE_FLAG))
-
-#define TKEY_IS_NEGATIVE(tkey) (((tkey)&TKEY_NEGATIVE_FLAG) != 0)
-#define TKEY_IS_DELETED(tkey) (false)
-
-#define tdGetTKEY(key) (key)
-#define tdGetKey(tskey) (tskey)
-
-#define MIN_TS_KEY ((TSKEY)0x8000000000000001)
-#define MAX_TS_KEY ((TSKEY)0x7fffffffffffffff)
-
-#define TD_TO_TKEY(key) tdGetTKEY(((key) < MIN_TS_KEY) ? MIN_TS_KEY : (((key) > MAX_TS_KEY) ? MAX_TS_KEY : key))
-
-static FORCE_INLINE TKEY keyToTkey(TSKEY key) {
- TSKEY lkey = key;
- if (key > MAX_TS_KEY) {
- lkey = MAX_TS_KEY;
- } else if (key < MIN_TS_KEY) {
- lkey = MIN_TS_KEY;
- }
-
- return tdGetTKEY(lkey);
-}
-
-static FORCE_INLINE int32_t tkeyComparFn(const void *tkey1, const void *tkey2) {
- TSKEY key1 = tdGetKey(*(TKEY *)tkey1);
- TSKEY key2 = tdGetKey(*(TKEY *)tkey2);
-
- if (key1 < key2) {
- return -1;
- } else if (key1 > key2) {
- return 1;
- } else {
- return 0;
- }
-}
-
-// ----------------- Data column structure
-// SDataCol arrangement: data => bitmap => dataOffset
-typedef struct SDataCol {
- int8_t type; // column type
- uint8_t bitmap : 1; // 0: no bitmap if all rows are NORM, 1: has bitmap if has NULL/NORM rows
- uint8_t reserve : 7;
- int16_t colId; // column ID
- int32_t bytes; // column data bytes defined
- int32_t offset; // data offset in a SDataRow (including the header size)
- int32_t spaceSize; // Total space size for this column
- int32_t len; // column data length
- VarDataOffsetT *dataOff; // For binary and nchar data, the offset in the data column
- void *pData; // Actual data pointer
- void *pBitmap; // Bitmap pointer
- TSKEY ts; // only used in last NULL column
-} SDataCol;
-
-#define isAllRowsNull(pCol) ((pCol)->len == 0)
-#define isAllRowsNone(pCol) ((pCol)->len == 0)
-static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; }
-
-int32_t tdAllocMemForCol(SDataCol *pCol, int32_t maxPoints);
-
-void dataColInit(SDataCol *pDataCol, STColumn *pCol, int32_t maxPoints);
-int32_t dataColAppendVal(SDataCol *pCol, const void *value, int32_t numOfRows, int32_t maxPoints);
-void *dataColSetOffset(SDataCol *pCol, int32_t nEle);
-
-bool isNEleNull(SDataCol *pCol, int32_t nEle);
-
-typedef struct {
- col_id_t maxCols; // max number of columns
- col_id_t numOfCols; // Total number of cols
- int32_t maxPoints; // max number of points
- int32_t numOfRows;
- int32_t bitmapMode : 1; // default is 0(2 bits), otherwise 1(1 bit)
- int32_t sversion : 31; // TODO: set sversion(not used yet)
- SDataCol *cols;
-} SDataCols;
-
-static FORCE_INLINE bool tdDataColsIsBitmapI(SDataCols *pCols) { return pCols->bitmapMode != TSDB_BITMODE_DEFAULT; }
-static FORCE_INLINE void tdDataColsSetBitmapI(SDataCols *pCols) { pCols->bitmapMode = TSDB_BITMODE_ONE_BIT; }
-static FORCE_INLINE bool tdIsBitmapModeI(int8_t bitmapMode) { return bitmapMode != TSDB_BITMODE_DEFAULT; }
-
-#define keyCol(pCols) (&((pCols)->cols[0])) // Key column
-#define dataColsTKeyAt(pCols, idx) ((TKEY *)(keyCol(pCols)->pData))[(idx)] // the idx row of column-wised data
-#define dataColsKeyAt(pCols, idx) tdGetKey(dataColsTKeyAt(pCols, idx))
-static FORCE_INLINE TKEY dataColsTKeyFirst(SDataCols *pCols) {
- if (pCols->numOfRows) {
- return dataColsTKeyAt(pCols, 0);
- } else {
- return TKEY_INVALID;
- }
-}
-
-static FORCE_INLINE TSKEY dataColsKeyAtRow(SDataCols *pCols, int32_t row) {
- assert(row < pCols->numOfRows);
- return dataColsKeyAt(pCols, row);
-}
-
-static FORCE_INLINE TSKEY dataColsKeyFirst(SDataCols *pCols) {
- if (pCols->numOfRows) {
- return dataColsKeyAt(pCols, 0);
- } else {
- return TSDB_DATA_TIMESTAMP_NULL;
- }
-}
-
-static FORCE_INLINE TKEY dataColsTKeyLast(SDataCols *pCols) {
- if (pCols->numOfRows) {
- return dataColsTKeyAt(pCols, pCols->numOfRows - 1);
- } else {
- return TKEY_INVALID;
- }
-}
-
-static FORCE_INLINE TSKEY dataColsKeyLast(SDataCols *pCols) {
- if (pCols->numOfRows) {
- return dataColsKeyAt(pCols, pCols->numOfRows - 1);
- } else {
- return TSDB_DATA_TIMESTAMP_NULL;
- }
-}
-
-SDataCols *tdNewDataCols(int32_t maxCols, int32_t maxRows);
-void tdResetDataCols(SDataCols *pCols);
-int32_t tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
-SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
-SDataCols *tdFreeDataCols(SDataCols *pCols);
-int32_t tdMergeDataCols(SDataCols *target, SDataCols *source, int32_t rowsToMerge, int32_t *pOffset, bool update,
- TDRowVerT maxVer);
-
#endif
#ifdef __cplusplus
diff --git a/include/common/tglobal.h b/include/common/tglobal.h
index 8c03d3ff42b5b0b28f8f1958acfcd7dc8520d464..96014b12341395994e3409cff37c3e090cfa07a6 100644
--- a/include/common/tglobal.h
+++ b/include/common/tglobal.h
@@ -64,10 +64,10 @@ extern int32_t tsNumOfMnodeQueryThreads;
extern int32_t tsNumOfMnodeFetchThreads;
extern int32_t tsNumOfMnodeReadThreads;
extern int32_t tsNumOfVnodeQueryThreads;
+extern int32_t tsNumOfVnodeStreamThreads;
extern int32_t tsNumOfVnodeFetchThreads;
extern int32_t tsNumOfVnodeWriteThreads;
extern int32_t tsNumOfVnodeSyncThreads;
-extern int32_t tsNumOfVnodeMergeThreads;
extern int32_t tsNumOfQnodeQueryThreads;
extern int32_t tsNumOfQnodeFetchThreads;
extern int32_t tsNumOfSnodeSharedThreads;
@@ -137,6 +137,8 @@ extern bool tsSmlDataFormat;
// internal
extern int32_t tsTransPullupInterval;
extern int32_t tsMqRebalanceInterval;
+extern int32_t tsTtlUnit;
+extern int32_t tsTtlPushInterval;
#define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
@@ -149,6 +151,7 @@ void taosCfgDynamicOptions(const char *option, const char *value);
void taosAddDataDir(int32_t index, char *v1, int32_t level, int32_t primary);
struct SConfig *taosGetCfg();
+int32_t taosSetCfg(SConfig *pCfg, char* name);
#ifdef __cplusplus
}
diff --git a/include/common/tmsg.h b/include/common/tmsg.h
index 08e5d2ab7d2fa17b65e73c580a70741f5d62dafe..c8e13fce3d6fdc45c8bd15fc2f59e6f91dc39c4c 100644
--- a/include/common/tmsg.h
+++ b/include/common/tmsg.h
@@ -55,8 +55,13 @@ extern int32_t tMsgDict[];
#define TMSG_SEG_CODE(TYPE) (((TYPE)&0xff00) >> 8)
#define TMSG_SEG_SEQ(TYPE) ((TYPE)&0xff)
-#define TMSG_INFO(TYPE) tMsgInfo[tMsgDict[TMSG_SEG_CODE(TYPE)] + TMSG_SEG_SEQ(TYPE)]
-#define TMSG_INDEX(TYPE) (tMsgDict[TMSG_SEG_CODE(TYPE)] + TMSG_SEG_SEQ(TYPE))
+#define TMSG_INFO(TYPE) \
+ ((TYPE) >= 0 && ((TYPE) < TDMT_DND_MAX_MSG || (TYPE) < TDMT_MND_MAX_MSG || (TYPE) < TDMT_VND_MAX_MSG || \
+ (TYPE) < TDMT_SCH_MAX_MSG || (TYPE) < TDMT_STREAM_MAX_MSG || (TYPE) < TDMT_MON_MAX_MSG || \
+ (TYPE) < TDMT_SYNC_MAX_MSG)) \
+ ? tMsgInfo[tMsgDict[TMSG_SEG_CODE(TYPE)] + TMSG_SEG_SEQ(TYPE)] \
+ : 0
+#define TMSG_INDEX(TYPE) (tMsgDict[TMSG_SEG_CODE(TYPE)] + TMSG_SEG_SEQ(TYPE))
typedef uint16_t tmsg_t;
@@ -164,11 +169,14 @@ typedef enum _mgmt_table {
#define TD_CHILD_TABLE TSDB_CHILD_TABLE
#define TD_NORMAL_TABLE TSDB_NORMAL_TABLE
+#define TD_REQ_FROM_APP 0
+#define TD_REQ_FROM_TAOX 1
+
typedef struct {
int32_t vgId;
char* dbFName;
char* tbName;
-} SBuildTableMetaInput;
+} SBuildTableInput;
typedef struct {
char db[TSDB_DB_FNAME_LEN];
@@ -427,23 +435,30 @@ static FORCE_INLINE int32_t tDecodeSSchemaWrapperEx(SDecoder* pDecoder, SSchemaW
STSchema* tdGetSTSChemaFromSSChema(SSchema** pSchema, int32_t nCols);
typedef struct {
- char name[TSDB_TABLE_FNAME_LEN];
- int8_t igExists;
- int64_t delay1;
- int64_t delay2;
- int64_t watermark1;
- int64_t watermark2;
- int32_t ttl;
- int32_t numOfColumns;
- int32_t numOfTags;
- int32_t commentLen;
- int32_t ast1Len;
- int32_t ast2Len;
- SArray* pColumns; // array of SField
- SArray* pTags; // array of SField
- char* comment;
- char* pAst1;
- char* pAst2;
+ char name[TSDB_TABLE_FNAME_LEN];
+ int8_t igExists;
+ int8_t source; // 1-taosX or 0-taosClient
+ int8_t reserved[6];
+ tb_uid_t suid;
+ int64_t delay1;
+ int64_t delay2;
+ int64_t watermark1;
+ int64_t watermark2;
+ int32_t ttl;
+ int32_t colVer;
+ int32_t tagVer;
+ int32_t numOfColumns;
+ int32_t numOfTags;
+ int32_t numOfFuncs;
+ int32_t commentLen;
+ int32_t ast1Len;
+ int32_t ast2Len;
+ SArray* pColumns; // array of SField
+ SArray* pTags; // array of SField
+ SArray* pFuncs;
+ char* pComment;
+ char* pAst1;
+ char* pAst2;
} SMCreateStbReq;
int32_t tSerializeSMCreateStbReq(void* buf, int32_t bufLen, SMCreateStbReq* pReq);
@@ -451,8 +466,11 @@ int32_t tDeserializeSMCreateStbReq(void* buf, int32_t bufLen, SMCreateStbReq* pR
void tFreeSMCreateStbReq(SMCreateStbReq* pReq);
typedef struct {
- char name[TSDB_TABLE_FNAME_LEN];
- int8_t igNotExists;
+ char name[TSDB_TABLE_FNAME_LEN];
+ int8_t igNotExists;
+ int8_t source; // 1-taosX or 0-taosClient
+ int8_t reserved[6];
+ tb_uid_t suid;
} SMDropStbReq;
int32_t tSerializeSMDropStbReq(void* buf, int32_t bufLen, SMDropStbReq* pReq);
@@ -461,8 +479,6 @@ int32_t tDeserializeSMDropStbReq(void* buf, int32_t bufLen, SMDropStbReq* pReq);
typedef struct {
char name[TSDB_TABLE_FNAME_LEN];
int8_t alterType;
- int32_t tagVer;
- int32_t colVer;
int32_t numOfFields;
SArray* pFields;
int32_t ttl;
@@ -509,7 +525,8 @@ typedef struct {
int8_t superUser;
int8_t connType;
SEpSet epSet;
- char sVersion[128];
+ char sVer[TSDB_VERSION_LEN];
+ char sDetailVer[128];
} SConnectRsp;
int32_t tSerializeSConnectRsp(void* buf, int32_t bufLen, SConnectRsp* pRsp);
@@ -621,6 +638,7 @@ typedef struct {
col_id_t colId;
int16_t slotId;
};
+ bool output; // TODO remove it later
int16_t type;
int32_t bytes;
@@ -628,11 +646,6 @@ typedef struct {
uint8_t scale;
} SColumnInfo;
-typedef struct {
- int64_t uid;
- TSKEY key; // last accessed ts, for subscription
-} STableIdInfo;
-
typedef struct STimeWindow {
TSKEY skey;
TSKEY ekey;
@@ -661,12 +674,48 @@ typedef struct {
char tbFName[TSDB_TABLE_FNAME_LEN];
int32_t sversion;
int32_t tversion;
+ int64_t affectedRows;
} SQueryTableRsp;
int32_t tSerializeSQueryTableRsp(void* buf, int32_t bufLen, SQueryTableRsp* pRsp);
int32_t tDeserializeSQueryTableRsp(void* buf, int32_t bufLen, SQueryTableRsp* pRsp);
+typedef struct {
+ SMsgHead header;
+ char dbFName[TSDB_DB_FNAME_LEN];
+ char tbName[TSDB_TABLE_NAME_LEN];
+} STableCfgReq;
+
+typedef struct {
+ char tbName[TSDB_TABLE_NAME_LEN];
+ char stbName[TSDB_TABLE_NAME_LEN];
+ char dbFName[TSDB_DB_FNAME_LEN];
+ int32_t numOfTags;
+ int32_t numOfColumns;
+ int8_t tableType;
+ int64_t delay1;
+ int64_t delay2;
+ int64_t watermark1;
+ int64_t watermark2;
+ int32_t ttl;
+ SArray* pFuncs;
+ int32_t commentLen;
+ char* pComment;
+ SSchema* pSchemas;
+ int32_t tagsLen;
+ char* pTags;
+} STableCfg;
+
+typedef STableCfg STableCfgRsp;
+
+int32_t tSerializeSTableCfgReq(void* buf, int32_t bufLen, STableCfgReq* pReq);
+int32_t tDeserializeSTableCfgReq(void* buf, int32_t bufLen, STableCfgReq* pReq);
+
+int32_t tSerializeSTableCfgRsp(void* buf, int32_t bufLen, STableCfgRsp* pRsp);
+int32_t tDeserializeSTableCfgRsp(void* buf, int32_t bufLen, STableCfgRsp* pRsp);
+void tFreeSTableCfgRsp(STableCfgRsp* pRsp);
+
typedef struct {
char db[TSDB_DB_FNAME_LEN];
int32_t numOfVgroups;
@@ -674,6 +723,7 @@ typedef struct {
int32_t buffer; // MB
int32_t pageSize;
int32_t pages;
+ int32_t cacheLastSize;
int32_t daysPerFile;
int32_t daysToKeep0;
int32_t daysToKeep1;
@@ -686,7 +736,7 @@ typedef struct {
int8_t compression;
int8_t replications;
int8_t strict;
- int8_t cacheLastRow;
+ int8_t cacheLast;
int8_t schemaless;
int8_t ignoreExist;
int32_t numOfRetensions;
@@ -702,6 +752,7 @@ typedef struct {
int32_t buffer;
int32_t pageSize;
int32_t pages;
+ int32_t cacheLastSize;
int32_t daysPerFile;
int32_t daysToKeep0;
int32_t daysToKeep1;
@@ -709,7 +760,7 @@ typedef struct {
int32_t fsyncPeriod;
int8_t walLevel;
int8_t strict;
- int8_t cacheLastRow;
+ int8_t cacheLast;
int8_t replications;
} SAlterDbReq;
@@ -764,6 +815,27 @@ typedef struct {
int32_t tSerializeSDbCfgReq(void* buf, int32_t bufLen, SDbCfgReq* pReq);
int32_t tDeserializeSDbCfgReq(void* buf, int32_t bufLen, SDbCfgReq* pReq);
+typedef struct {
+ char db[TSDB_DB_FNAME_LEN];
+} STrimDbReq;
+
+int32_t tSerializeSTrimDbReq(void* buf, int32_t bufLen, STrimDbReq* pReq);
+int32_t tDeserializeSTrimDbReq(void* buf, int32_t bufLen, STrimDbReq* pReq);
+
+typedef struct {
+ int32_t timestamp;
+} SVTrimDbReq;
+
+int32_t tSerializeSVTrimDbReq(void* buf, int32_t bufLen, SVTrimDbReq* pReq);
+int32_t tDeserializeSVTrimDbReq(void* buf, int32_t bufLen, SVTrimDbReq* pReq);
+
+typedef struct {
+ int32_t timestamp;
+} SVDropTtlTableReq;
+
+int32_t tSerializeSVDropTtlTableReq(void* buf, int32_t bufLen, SVDropTtlTableReq* pReq);
+int32_t tDeserializeSVDropTtlTableReq(void* buf, int32_t bufLen, SVDropTtlTableReq* pReq);
+
typedef struct {
int32_t numOfVgroups;
int32_t numOfStables;
@@ -782,7 +854,7 @@ typedef struct {
int8_t compression;
int8_t replications;
int8_t strict;
- int8_t cacheLastRow;
+ int8_t cacheLast;
int32_t numOfRetensions;
SArray* pRetensions;
int8_t schemaless;
@@ -798,6 +870,27 @@ typedef struct {
int32_t tSerializeSQnodeListReq(void* buf, int32_t bufLen, SQnodeListReq* pReq);
int32_t tDeserializeSQnodeListReq(void* buf, int32_t bufLen, SQnodeListReq* pReq);
+typedef struct {
+ int32_t rowNum;
+} SDnodeListReq;
+
+int32_t tSerializeSDnodeListReq(void* buf, int32_t bufLen, SDnodeListReq* pReq);
+int32_t tDeserializeSDnodeListReq(void* buf, int32_t bufLen, SDnodeListReq* pReq);
+
+typedef struct {
+ int32_t useless; // useless
+} SServerVerReq;
+
+int32_t tSerializeSServerVerReq(void* buf, int32_t bufLen, SServerVerReq* pReq);
+int32_t tDeserializeSServerVerReq(void* buf, int32_t bufLen, SServerVerReq* pReq);
+
+typedef struct {
+ char ver[TSDB_VERSION_LEN];
+} SServerVerRsp;
+
+int32_t tSerializeSServerVerRsp(void* buf, int32_t bufLen, SServerVerRsp* pRsp);
+int32_t tDeserializeSServerVerRsp(void* buf, int32_t bufLen, SServerVerRsp* pRsp);
+
typedef struct SQueryNodeAddr {
int32_t nodeId; // vgId or qnodeId
SEpSet epSet;
@@ -816,6 +909,14 @@ int32_t tSerializeSQnodeListRsp(void* buf, int32_t bufLen, SQnodeListRsp* pRsp);
int32_t tDeserializeSQnodeListRsp(void* buf, int32_t bufLen, SQnodeListRsp* pRsp);
void tFreeSQnodeListRsp(SQnodeListRsp* pRsp);
+typedef struct {
+ SArray* dnodeList; // SArray
+} SDnodeListRsp;
+
+int32_t tSerializeSDnodeListRsp(void* buf, int32_t bufLen, SDnodeListRsp* pRsp);
+int32_t tDeserializeSDnodeListRsp(void* buf, int32_t bufLen, SDnodeListRsp* pRsp);
+void tFreeSDnodeListRsp(SDnodeListRsp* pRsp);
+
typedef struct {
SArray* pArray; // Array of SUseDbRsp
} SUseDbBatchRsp;
@@ -960,8 +1061,10 @@ typedef struct {
int64_t clusterId;
int64_t rebootTime;
int64_t updateTime;
- int32_t numOfCores;
+ float numOfCores;
int32_t numOfSupportVnodes;
+ int64_t memTotal;
+ int64_t memAvail;
char dnodeEp[TSDB_EP_LEN];
SMnodeLoad mload;
SQnodeLoad qload;
@@ -1016,6 +1119,7 @@ typedef struct {
int32_t buffer;
int32_t pageSize;
int32_t pages;
+ int32_t cacheLastSize;
int32_t daysPerFile;
int32_t daysToKeep0;
int32_t daysToKeep1;
@@ -1030,7 +1134,7 @@ typedef struct {
int8_t precision;
int8_t compression;
int8_t strict;
- int8_t cacheLastRow;
+ int8_t cacheLast;
int8_t isTsma;
int8_t standby;
int8_t replica;
@@ -1068,6 +1172,7 @@ typedef struct {
int32_t buffer;
int32_t pageSize;
int32_t pages;
+ int32_t cacheLastSize;
int32_t daysPerFile;
int32_t daysToKeep0;
int32_t daysToKeep1;
@@ -1075,7 +1180,7 @@ typedef struct {
int32_t fsyncPeriod;
int8_t walLevel;
int8_t strict;
- int8_t cacheLastRow;
+ int8_t cacheLast;
int8_t selfIndex;
int8_t replica;
SReplica replicas[TSDB_MAX_REPLICA];
@@ -1174,6 +1279,27 @@ typedef struct {
char* data;
} STagData;
+typedef struct {
+ int32_t useless; // useless
+} SShowVariablesReq;
+
+int32_t tSerializeSShowVariablesReq(void* buf, int32_t bufLen, SShowVariablesReq* pReq);
+int32_t tDeserializeSShowVariablesReq(void* buf, int32_t bufLen, SShowVariablesReq* pReq);
+
+typedef struct {
+ char name[TSDB_CONFIG_OPTION_LEN + 1];
+ char value[TSDB_CONFIG_VALUE_LEN + 1];
+} SVariablesInfo;
+
+typedef struct {
+ SArray* variables; // SArray
+} SShowVariablesRsp;
+
+int32_t tSerializeSShowVariablesRsp(void* buf, int32_t bufLen, SShowVariablesRsp* pReq);
+int32_t tDeserializeSShowVariablesRsp(void* buf, int32_t bufLen, SShowVariablesRsp* pReq);
+
+void tFreeSShowVariablesRsp(SShowVariablesRsp* pRsp);
+
/*
* sql: show tables like '%a_%'
* payload is the query condition, e.g., '%a_%'
@@ -1202,6 +1328,7 @@ void tFreeSShowRsp(SShowRsp* pRsp);
typedef struct {
char db[TSDB_DB_FNAME_LEN];
char tb[TSDB_TABLE_NAME_LEN];
+ char user[TSDB_USER_LEN];
int64_t showId;
} SRetrieveTableReq;
@@ -1223,6 +1350,8 @@ typedef struct {
int32_t compLen;
int32_t numOfRows;
int32_t numOfCols;
+ int64_t skey;
+ int64_t ekey;
char data[];
} SRetrieveTableRsp;
@@ -1286,11 +1415,19 @@ typedef struct {
int32_t dnodeId;
char config[TSDB_DNODE_CONFIG_LEN];
char value[TSDB_DNODE_VALUE_LEN];
-} SMCfgDnodeReq, SDCfgDnodeReq;
+} SMCfgDnodeReq;
int32_t tSerializeSMCfgDnodeReq(void* buf, int32_t bufLen, SMCfgDnodeReq* pReq);
int32_t tDeserializeSMCfgDnodeReq(void* buf, int32_t bufLen, SMCfgDnodeReq* pReq);
+typedef struct {
+ char config[TSDB_DNODE_CONFIG_LEN];
+ char value[TSDB_DNODE_VALUE_LEN];
+} SDCfgDnodeReq;
+
+int32_t tSerializeSDCfgDnodeReq(void* buf, int32_t bufLen, SDCfgDnodeReq* pReq);
+int32_t tDeserializeSDCfgDnodeReq(void* buf, int32_t bufLen, SDCfgDnodeReq* pReq);
+
typedef struct {
int32_t dnodeId;
} SMCreateMnodeReq, SMDropMnodeReq, SDDropMnodeReq, SMCreateQnodeReq, SMDropQnodeReq, SDCreateQnodeReq, SDDropQnodeReq,
@@ -1401,8 +1538,10 @@ typedef struct SSubQueryMsg {
uint64_t queryId;
uint64_t taskId;
int64_t refId;
+ int32_t execId;
int8_t taskType;
int8_t explain;
+ int8_t needFetch;
uint32_t sqlLen; // the query sql,
uint32_t phyLen;
char msg[];
@@ -1420,6 +1559,7 @@ typedef struct {
uint64_t sId;
uint64_t queryId;
uint64_t taskId;
+ int32_t execId;
} SQueryContinueReq;
typedef struct {
@@ -1441,6 +1581,7 @@ typedef struct {
uint64_t sId;
uint64_t queryId;
uint64_t taskId;
+ int32_t execId;
} SResFetchReq;
typedef struct {
@@ -1452,6 +1593,7 @@ typedef struct {
uint64_t queryId;
uint64_t taskId;
int64_t refId;
+ int32_t execId;
int8_t status;
} STaskStatus;
@@ -1497,6 +1639,7 @@ typedef struct {
uint64_t queryId;
uint64_t taskId;
int64_t refId;
+ int32_t execId;
} STaskCancelReq;
typedef struct {
@@ -1509,6 +1652,7 @@ typedef struct {
uint64_t queryId;
uint64_t taskId;
int64_t refId;
+ int32_t execId;
} STaskDropReq;
typedef struct {
@@ -1529,6 +1673,7 @@ typedef struct {
int8_t triggerType;
int64_t maxDelay;
int64_t watermark;
+ int8_t igExpired;
} SCMCreateStreamReq;
typedef struct {
@@ -1560,6 +1705,7 @@ typedef struct {
char name[TSDB_TOPIC_FNAME_LEN]; // accout.topic
int8_t igExists;
int8_t subType;
+ int8_t withMeta;
char* sql;
char subDbName[TSDB_DB_FNAME_LEN];
union {
@@ -1792,7 +1938,9 @@ typedef struct SVCreateStbReq {
int8_t rollup;
SSchemaWrapper schemaRow;
SSchemaWrapper schemaTag;
- SRSmaParam pRSmaParam;
+ SRSmaParam rsmaParam;
+ int32_t alterOriDataLen;
+ void* alterOriData;
} SVCreateStbReq;
int tEncodeSVCreateStbReq(SEncoder* pCoder, const SVCreateStbReq* pReq);
@@ -1820,7 +1968,9 @@ typedef struct SVCreateTbReq {
int8_t type;
union {
struct {
+ char* name; // super table name
tb_uid_t suid;
+ SArray* tagName;
uint8_t* pTag;
} ctb;
struct {
@@ -1837,6 +1987,9 @@ static FORCE_INLINE void tdDestroySVCreateTbReq(SVCreateTbReq* req) {
taosMemoryFreeClear(req->comment);
if (req->type == TSDB_CHILD_TABLE) {
taosMemoryFreeClear(req->ctb.pTag);
+ taosMemoryFreeClear(req->ctb.name);
+ taosArrayDestroy(req->ctb.tagName);
+ req->ctb.tagName = NULL;
} else if (req->type == TSDB_NORMAL_TABLE) {
taosMemoryFreeClear(req->ntb.schemaRow.pSchema);
}
@@ -1920,12 +2073,14 @@ typedef struct {
int32_t bytes;
// TSDB_ALTER_TABLE_DROP_COLUMN
// TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES
+ int8_t colModType;
int32_t colModBytes;
// TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME
char* colNewName;
// TSDB_ALTER_TABLE_UPDATE_TAG_VAL
char* tagName;
int8_t isNull;
+ int8_t tagType;
uint32_t nTagVal;
uint8_t* pTagVal;
// TSDB_ALTER_TABLE_UPDATE_OPTIONS
@@ -2306,6 +2461,7 @@ typedef struct {
int64_t newConsumerId;
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
int8_t subType;
+ int8_t withMeta;
char* qmsg;
int64_t suid;
} SMqRebVgReq;
@@ -2318,6 +2474,7 @@ static FORCE_INLINE int32_t tEncodeSMqRebVgReq(void** buf, const SMqRebVgReq* pR
tlen += taosEncodeFixedI64(buf, pReq->newConsumerId);
tlen += taosEncodeString(buf, pReq->subKey);
tlen += taosEncodeFixedI8(buf, pReq->subType);
+ tlen += taosEncodeFixedI8(buf, pReq->withMeta);
if (pReq->subType == TOPIC_SUB_TYPE__COLUMN) {
tlen += taosEncodeString(buf, pReq->qmsg);
} else if (pReq->subType == TOPIC_SUB_TYPE__TABLE) {
@@ -2333,6 +2490,7 @@ static FORCE_INLINE void* tDecodeSMqRebVgReq(const void* buf, SMqRebVgReq* pReq)
buf = taosDecodeFixedI64(buf, &pReq->newConsumerId);
buf = taosDecodeStringTo(buf, pReq->subKey);
buf = taosDecodeFixedI8(buf, &pReq->subType);
+ buf = taosDecodeFixedI8(buf, &pReq->withMeta);
if (pReq->subType == TOPIC_SUB_TYPE__COLUMN) {
buf = taosDecodeString(buf, &pReq->qmsg);
} else if (pReq->subType == TOPIC_SUB_TYPE__TABLE) {
@@ -2364,22 +2522,37 @@ int32_t tDecodeSMqCMCommitOffsetReq(SDecoder* decoder, SMqCMCommitOffsetReq* pRe
// tqOffset
enum {
- TMQ_OFFSET__SNAPSHOT = 1,
- TMQ_OFFSET__LOG,
+ TMQ_OFFSET__RESET_NONE = -3,
+ TMQ_OFFSET__RESET_EARLIEAST = -2,
+ TMQ_OFFSET__RESET_LATEST = -1,
+ TMQ_OFFSET__LOG = 1,
+ TMQ_OFFSET__SNAPSHOT_DATA = 2,
+ TMQ_OFFSET__SNAPSHOT_META = 3,
};
typedef struct {
int8_t type;
union {
+ // snapshot data
struct {
int64_t uid;
int64_t ts;
};
+ // log
struct {
int64_t version;
};
};
- char subKey[TSDB_SUBSCRIBE_KEY_LEN];
+} STqOffsetVal;
+
+int32_t tEncodeSTqOffsetVal(SEncoder* pEncoder, const STqOffsetVal* pOffsetVal);
+int32_t tDecodeSTqOffsetVal(SDecoder* pDecoder, STqOffsetVal* pOffsetVal);
+int32_t tFormatOffset(char* buf, int32_t maxLen, const STqOffsetVal* pVal);
+bool tOffsetEqual(const STqOffsetVal* pLeft, const STqOffsetVal* pRight);
+
+typedef struct {
+ STqOffsetVal val;
+ char subKey[TSDB_SUBSCRIBE_KEY_LEN];
} STqOffset;
int32_t tEncodeSTqOffset(SEncoder* pEncoder, const STqOffset* pOffset);
@@ -2396,6 +2569,8 @@ typedef struct {
int64_t interval;
int64_t offset;
int64_t sliding;
+ int64_t maxDelay;
+ int64_t watermark;
int32_t exprLen; // strlen + 1
int32_t tagsFilterLen; // strlen + 1
int32_t sqlLen; // strlen + 1
@@ -2605,11 +2780,13 @@ typedef struct {
SMsgHead head;
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
int8_t withTbName;
+ int8_t useSnapshot;
int32_t epoch;
uint64_t reqId;
int64_t consumerId;
int64_t timeout;
- int64_t currentOffset;
+ // int64_t currentOffset;
+ STqOffsetVal reqOffset;
} SMqPollReq;
typedef struct {
@@ -2677,6 +2854,53 @@ static FORCE_INLINE void tDeleteSMqSubTopicEp(SMqSubTopicEp* pSubTopicEp) {
taosArrayDestroy(pSubTopicEp->vgs);
}
+typedef struct {
+ SMqRspHead head;
+ int64_t reqOffset;
+ int64_t rspOffset;
+ STqOffsetVal reqOffsetNew;
+ STqOffsetVal rspOffsetNew;
+ int16_t resMsgType;
+ int32_t metaRspLen;
+ void* metaRsp;
+} SMqMetaRsp;
+
+static FORCE_INLINE int32_t tEncodeSMqMetaRsp(void** buf, const SMqMetaRsp* pRsp) {
+ int32_t tlen = 0;
+ tlen += taosEncodeFixedI64(buf, pRsp->reqOffset);
+ tlen += taosEncodeFixedI64(buf, pRsp->rspOffset);
+ tlen += taosEncodeFixedI16(buf, pRsp->resMsgType);
+ tlen += taosEncodeFixedI32(buf, pRsp->metaRspLen);
+ tlen += taosEncodeBinary(buf, pRsp->metaRsp, pRsp->metaRspLen);
+ return tlen;
+}
+
+static FORCE_INLINE void* tDecodeSMqMetaRsp(const void* buf, SMqMetaRsp* pRsp) {
+ buf = taosDecodeFixedI64(buf, &pRsp->reqOffset);buf = taosDecodeFixedI64(buf, &pRsp->rspOffset);
+ buf = taosDecodeFixedI16(buf, &pRsp->resMsgType);
+ buf = taosDecodeFixedI32(buf, &pRsp->metaRspLen);
+ buf = taosDecodeBinary(buf, &pRsp->metaRsp, pRsp->metaRspLen);
+ return (void*)buf;
+}
+
+typedef struct {
+ SMqRspHead head;
+ STqOffsetVal reqOffset;
+ STqOffsetVal rspOffset;
+ int32_t skipLogNum;
+ int32_t blockNum;
+ int8_t withTbName;
+ int8_t withSchema;
+ SArray* blockDataLen;
+ SArray* blockData;
+ SArray* blockTbName;
+ SArray* blockSchema;
+} SMqDataRsp;
+
+int32_t tEncodeSMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pRsp);
+int32_t tDecodeSMqDataRsp(SDecoder* pDecoder, SMqDataRsp* pRsp);
+
+#if 0
typedef struct {
SMqRspHead head;
int64_t reqOffset;
@@ -2685,13 +2909,10 @@ typedef struct {
int32_t blockNum;
int8_t withTbName;
int8_t withSchema;
- int8_t withTag;
- SArray* blockDataLen; // SArray
- SArray* blockData; // SArray
- SArray* blockTbName; // SArray
- SArray* blockSchema; // SArray
- SArray* blockTags; // SArray
- SArray* blockTagSchema; // SArray
+ SArray* blockDataLen; // SArray
+ SArray* blockData; // SArray
+ SArray* blockTbName; // SArray
+ SArray* blockSchema; // SArray
} SMqDataBlkRsp;
static FORCE_INLINE int32_t tEncodeSMqDataBlkRsp(void** buf, const SMqDataBlkRsp* pRsp) {
@@ -2703,7 +2924,6 @@ static FORCE_INLINE int32_t tEncodeSMqDataBlkRsp(void** buf, const SMqDataBlkRsp
if (pRsp->blockNum != 0) {
tlen += taosEncodeFixedI8(buf, pRsp->withTbName);
tlen += taosEncodeFixedI8(buf, pRsp->withSchema);
- tlen += taosEncodeFixedI8(buf, pRsp->withTag);
for (int32_t i = 0; i < pRsp->blockNum; i++) {
int32_t bLen = *(int32_t*)taosArrayGet(pRsp->blockDataLen, i);
@@ -2733,7 +2953,6 @@ static FORCE_INLINE void* tDecodeSMqDataBlkRsp(const void* buf, SMqDataBlkRsp* p
pRsp->blockDataLen = taosArrayInit(pRsp->blockNum, sizeof(int32_t));
buf = taosDecodeFixedI8(buf, &pRsp->withTbName);
buf = taosDecodeFixedI8(buf, &pRsp->withSchema);
- buf = taosDecodeFixedI8(buf, &pRsp->withTag);
if (pRsp->withTbName) {
pRsp->blockTbName = taosArrayInit(pRsp->blockNum, sizeof(void*));
}
@@ -2762,6 +2981,7 @@ static FORCE_INLINE void* tDecodeSMqDataBlkRsp(const void* buf, SMqDataBlkRsp* p
}
return (void*)buf;
}
+#endif
typedef struct {
SMqRspHead head;
@@ -2844,6 +3064,17 @@ typedef struct {
int32_t tEncodeSVDeleteRsp(SEncoder* pCoder, const SVDeleteRsp* pReq);
int32_t tDecodeSVDeleteRsp(SDecoder* pCoder, SVDeleteRsp* pReq);
+typedef struct SDeleteRes {
+ uint64_t suid;
+ SArray* uidList;
+ int64_t skey;
+ int64_t ekey;
+ int64_t affectedRows;
+} SDeleteRes;
+
+int32_t tEncodeDeleteRes(SEncoder* pCoder, const SDeleteRes* pRes);
+int32_t tDecodeDeleteRes(SDecoder* pCoder, SDeleteRes* pRes);
+
#pragma pack(pop)
#ifdef __cplusplus
diff --git a/include/common/tmsgcb.h b/include/common/tmsgcb.h
index b56f7552666dd23650f9911dc23e03b9ae2fa707..c13c50e1616146e43d3a74dc4145a5e7c7ffccf3 100644
--- a/include/common/tmsgcb.h
+++ b/include/common/tmsgcb.h
@@ -34,6 +34,7 @@ typedef enum {
WRITE_QUEUE,
APPLY_QUEUE,
SYNC_QUEUE,
+ STREAM_QUEUE,
QUEUE_MAX,
} EQueueType;
diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h
index eeac619105c1ff9bc909833c02d6d4ba2e41352e..488bc6346e56922b9b7ff0efe99407f2cadef805 100644
--- a/include/common/tmsgdef.h
+++ b/include/common/tmsgdef.h
@@ -81,6 +81,8 @@ enum {
TD_DEF_MSG_TYPE(TDMT_DND_SERVER_STATUS, "server-status", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_DND_NET_TEST, "net-test", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_DND_CONFIG_DNODE, "config-dnode", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_DND_SYSTABLE_RETRIEVE, "dnode-retrieve", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_DND_MAX_MSG, "dnd-max", NULL, NULL)
TD_NEW_MSG_SEG(TDMT_MND_MSG)
TD_DEF_MSG_TYPE(TDMT_MND_CONNECT, "connect", NULL, NULL)
@@ -101,6 +103,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_ALTER_QNODE, "alter-qnode", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_DROP_QNODE, "drop-qnode", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_QNODE_LIST, "qnode-list", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_DNODE_LIST, "dnode-list", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_CREATE_SNODE, "create-snode", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_ALTER_SNODE, "alter-snode", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_DROP_SNODE, "drop-snode", NULL, NULL)
@@ -113,6 +116,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_ALTER_DB, "alter-db", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_SYNC_DB, "sync-db", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_COMPACT_DB, "compact-db", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_TRIM_DB, "trim-db", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_GET_DB_CFG, "get-db-cfg", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_VGROUP_LIST, "vgroup-list", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_CREATE_FUNC, "create-func", NULL, NULL)
@@ -131,6 +135,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_DROP_INDEX, "drop-index", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_GET_INDEX, "get-index", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_GET_TABLE_INDEX, "get-table-index", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_TABLE_CFG, "table-cfg", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_CREATE_TOPIC, "create-topic", SMCreateTopicReq, SMCreateTopicRsp)
TD_DEF_MSG_TYPE(TDMT_MND_ALTER_TOPIC, "alter-topic", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_DROP_TOPIC, "drop-topic", NULL, NULL)
@@ -144,13 +149,14 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_MQ_TIMER, "mq-tmr", SMTimerReq, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_TELEM_TIMER, "telem-tmr", SMTimerReq, SMTimerReq)
TD_DEF_MSG_TYPE(TDMT_MND_TRANS_TIMER, "trans-tmr", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_TTL_TIMER, "ttl-tmr", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_KILL_TRANS, "kill-trans", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_KILL_QUERY, "kill-query", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_KILL_CONN, "kill-conn", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_HEARTBEAT, "heartbeat", SClientHbBatchReq, SClientHbBatchRsp)
TD_DEF_MSG_TYPE(TDMT_MND_STATUS, "status", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_SHOW, "show", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_MND_SYSTABLE_RETRIEVE, "retrieve", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_SYSTABLE_RETRIEVE, "mnd-retrieve", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_GRANT, "grant", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_AUTH, "auth", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_APPLY_MSG, "mnode-apply", NULL, NULL)
@@ -158,36 +164,32 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_MERGE_VGROUP, "merge-vgroup", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_REDISTRIBUTE_VGROUP, "redistribute-vgroup", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_SPLIT_VGROUP, "split-vgroup", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_SHOW_VARIABLES, "show-variables", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_SERVER_VERSION, "server-version", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MND_MAX_MSG, "mnd-max", NULL, NULL)
TD_NEW_MSG_SEG(TDMT_VND_MSG)
TD_DEF_MSG_TYPE(TDMT_VND_SUBMIT, "submit", SSubmitReq, SSubmitRsp)
- TD_DEF_MSG_TYPE(TDMT_VND_QUERY, "query", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_QUERY_CONTINUE, "query-continue", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_QUERY_HEARTBEAT, "query-heartbeat", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_FETCH, "fetch", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_CREATE_TABLE, "create-table", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_TABLE, "alter-table", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_DROP_TABLE, "drop-table", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_UPDATE_TAG_VAL, "update-tag-val", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_TABLE_META, "vnode-table-meta", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_TABLES_META, "vnode-tables-meta", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_VND_TABLE_CFG, "vnode-table-cfg", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_CREATE_STB, "vnode-create-stb", SVCreateStbReq, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_STB, "vnode-alter-stb", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_DROP_STB, "vnode-drop-stb", SVDropStbReq, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_VG_CHANGE, "vnode-mq-vg-change", SMqRebVgReq, SMqRebVgRsp)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_VG_DELETE, "vnode-mq-vg-delete", SMqVDeleteReq, SMqVDeleteRsp)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_COMMIT_OFFSET, "vnode-commit-offset", STqOffset, STqOffset)
- TD_DEF_MSG_TYPE(TDMT_VND_CANCEL_TASK, "vnode-cancel-task", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_DROP_TASK, "vnode-drop-task", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_CREATE_TOPIC, "vnode-create-topic", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_TOPIC, "vnode-alter-topic", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_DROP_TOPIC, "vnode-drop-topic", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_EXPLAIN, "vnode-explain", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_SUBSCRIBE, "vnode-subscribe", SMVSubscribeReq, SMVSubscribeRsp)
TD_DEF_MSG_TYPE(TDMT_VND_CONSUME, "vnode-consume", SMqPollReq, SMqDataBlkRsp)
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TRIGGER, "vnode-stream-trigger", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_DISPATCH_WRITE, "vnode-stream-task-dispatch-write", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TASK_DROP, "vnode-stream-task-drop", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_CREATE_SMA, "vnode-create-sma", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_CANCEL_SMA, "vnode-cancel-sma", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_DROP_SMA, "vnode-drop-sma", NULL, NULL)
@@ -197,19 +199,33 @@ enum {
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_REPLICA, "alter-replica", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIRM, "alter-confirm", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_ALTER_HASHRANGE, "alter-hashrange", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_COMPACT, "compact", NULL, NULL)
- TD_DEF_MSG_TYPE(TDMT_VND_DROP_TTL_TABLE, "drop-ttl-stb", NULL, NULL)
- TD_NEW_MSG_SEG(TDMT_QND_MSG)
+ TD_DEF_MSG_TYPE(TDMT_VND_COMPACT, "vnode-compact", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_VND_DROP_TTL_TABLE, "vnode-drop-ttl-stb", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_VND_TRIM, "vnode-trim", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_VND_COMMIT, "vnode-commit", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_VND_MAX_MSG, "vnd-max", NULL, NULL)
+
+ TD_NEW_MSG_SEG(TDMT_SCH_MSG)
+ TD_DEF_MSG_TYPE(TDMT_SCH_QUERY, "query", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_MERGE_QUERY, "merge-query", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_QUERY_CONTINUE, "query-continue", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_QUERY_HEARTBEAT, "query-heartbeat", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_FETCH, "fetch", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_MERGE_FETCH, "merge-fetch", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_CANCEL_TASK, "cancel-task", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_DROP_TASK, "drop-task", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_EXPLAIN, "explain", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_LINK_BROKEN, "link-broken", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SCH_MAX_MSG, "sch-max", NULL, NULL)
- //shared by snode and vnode
TD_NEW_MSG_SEG(TDMT_STREAM_MSG)
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_DEPLOY, "stream-task-deploy", SStreamTaskDeployReq, SStreamTaskDeployRsp)
+ TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_DROP, "stream-task-drop", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_RUN, "stream-task-run", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_DISPATCH, "stream-task-dispatch", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_RECOVER, "stream-task-recover", NULL, NULL)
-
- TD_NEW_MSG_SEG(TDMT_SCH_MSG)
- TD_DEF_MSG_TYPE(TDMT_SCH_LINK_BROKEN, "link-broken", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_STREAM_RETRIEVE, "stream-retrieve", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_STREAM_MAX_MSG, "stream-max", NULL, NULL)
TD_NEW_MSG_SEG(TDMT_MON_MSG)
TD_DEF_MSG_TYPE(TDMT_MON_MM_INFO, "monitor-minfo", NULL, NULL)
@@ -220,16 +236,19 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MON_VM_LOAD, "monitor-vload", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MON_MM_LOAD, "monitor-mload", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MON_QM_LOAD, "monitor-qload", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_MON_MAX_MSG, "monitor-max", NULL, NULL)
TD_NEW_MSG_SEG(TDMT_SYNC_MSG)
TD_DEF_MSG_TYPE(TDMT_SYNC_TIMEOUT, "sync-timer", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_PING, "sync-ping", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_PING_REPLY, "sync-ping-reply", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_CLIENT_REQUEST, "sync-client-request", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SYNC_CLIENT_REQUEST_BATCH, "sync-client-request-batch", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_CLIENT_REQUEST_REPLY, "sync-client-request-reply", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_REQUEST_VOTE, "sync-request-vote", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_REQUEST_VOTE_REPLY, "sync-request-vote-reply", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_APPEND_ENTRIES, "sync-append-entries", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SYNC_APPEND_ENTRIES_BATCH, "sync-append-entries-batch", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_APPEND_ENTRIES_REPLY, "sync-append-entries-reply", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_NOOP, "sync-noop", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_UNKNOWN, "sync-unknown", NULL, NULL)
@@ -242,6 +261,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_SYNC_LEADER_TRANSFER, "sync-leader-transfer", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_SET_MNODE_STANDBY, "set-mnode-standby", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_SYNC_SET_VNODE_STANDBY, "set-vnode-standby", NULL, NULL)
+ TD_DEF_MSG_TYPE(TDMT_SYNC_MAX_MSG, "sync-max", NULL, NULL)
#if defined(TD_MSG_NUMBER_)
TDMT_MAX
diff --git a/include/common/tname.h b/include/common/tname.h
index 28f97d10285d0f620ef919db9e691c98e3a28197..77965947adaf35c5cd98c4c76e06e00ce208af64 100644
--- a/include/common/tname.h
+++ b/include/common/tname.h
@@ -37,6 +37,8 @@ typedef struct SName {
char tname[TSDB_TABLE_NAME_LEN];
} SName;
+SName* toName(int32_t acctId, const char* pDbName, const char* pTableName, SName* pName);
+
int32_t tNameExtractFullName(const SName* name, char* dst);
int32_t tNameLen(const SName* name);
@@ -57,12 +59,16 @@ void tNameAssign(SName* dst, const SName* src);
int32_t tNameSetDbName(SName* dst, int32_t acctId, const char* dbName, size_t nameLen);
+int32_t tNameAddTbName(SName* dst, const char* tbName, size_t nameLen);
+
int32_t tNameFromString(SName* dst, const char* str, uint32_t type);
int32_t tNameSetAcctId(SName* dst, int32_t acctId);
bool tNameDBNameEqual(SName* left, SName* right);
+bool tNameTbNameEqual(SName* left, SName* right);
+
typedef struct {
// input
SArray* tags; // element is SSmlKv
diff --git a/include/common/trow.h b/include/common/trow.h
index 4031946ee855d9d9622e8c5085f7288c03e40817..807a4c0f0a9d8b6396db72848c7815c7deb63888 100644
--- a/include/common/trow.h
+++ b/include/common/trow.h
@@ -168,7 +168,7 @@ typedef struct {
// N.B. If without STSchema, getExtendedRowSize() is used to get the rowMaxBytes and
// (int32_t)ceil((double)nCols/TD_VTYPE_PARTS) should be added if TD_SUPPORT_BITMAP defined.
-#define TD_ROW_MAX_BYTES_FROM_SCHEMA(s) (schemaTLen(s) + TD_ROW_HEAD_LEN)
+#define TD_ROW_MAX_BYTES_FROM_SCHEMA(s) ((s)->tlen + TD_ROW_HEAD_LEN)
#define TD_ROW_SET_INFO(r, i) (TD_ROW_INFO(r) = (i))
#define TD_ROW_SET_TYPE(r, t) (TD_ROW_TYPE(r) = (t))
@@ -223,9 +223,10 @@ int32_t tdSetBitmapValTypeN(void *pBitmap, int16_t nEle, TDR
static FORCE_INLINE int32_t tdGetBitmapValType(const void *pBitmap, int16_t colIdx, TDRowValT *pValType,
int8_t bitmapMode);
bool tdIsBitmapBlkNorm(const void *pBitmap, int32_t numOfBits, int8_t bitmapMode);
-int32_t tdAppendValToDataCol(SDataCol *pCol, TDRowValT valType, const void *val, int32_t numOfRows, int32_t maxPoints,
- int8_t bitmapMode, bool isMerge);
-int32_t tdAppendSTSRowToDataCol(STSRow *pRow, STSchema *pSchema, SDataCols *pCols, bool isMerge);
+// int32_t tdAppendValToDataCol(SDataCol *pCol, TDRowValT valType, const void *val, int32_t numOfRows, int32_t
+// maxPoints,
+// int8_t bitmapMode, bool isMerge);
+// int32_t tdAppendSTSRowToDataCol(STSRow *pRow, STSchema *pSchema, SDataCols *pCols, bool isMerge);
int32_t tdGetBitmapValTypeII(const void *pBitmap, int16_t colIdx, TDRowValT *pValType);
int32_t tdSetBitmapValTypeI(void *pBitmap, int16_t colIdx, TDRowValT valType);
@@ -299,6 +300,7 @@ int32_t tdAppendColValToRow(SRowBuilder *pBuilder, col_id_t colId, int8_t colTyp
int32_t tdGetTpRowValOfCol(SCellVal *output, STSRow *pRow, void *pBitmap, int8_t colType, int32_t offset,
int16_t colIdx);
int32_t tdGetKvRowValOfCol(SCellVal *output, STSRow *pRow, void *pBitmap, int32_t offset, int16_t colIdx);
+void tTSRowGetVal(STSRow *pRow, STSchema *pTSchema, int16_t iCol, SColVal *pColVal);
typedef struct {
STSchema *pSchema;
@@ -312,16 +314,14 @@ typedef struct {
void tdSTSRowIterReset(STSRowIter *pIter, STSRow *pRow);
void tdSTSRowIterInit(STSRowIter *pIter, STSchema *pSchema);
+int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow);
bool tdSTSRowGetVal(STSRowIter *pIter, col_id_t colId, col_type_t colType, SCellVal *pVal);
bool tdGetTpRowDataOfCol(STSRowIter *pIter, col_type_t colType, int32_t offset, SCellVal *pVal);
bool tdGetKvRowValOfColEx(STSRowIter *pIter, col_id_t colId, col_type_t colType, col_id_t *nIdx, SCellVal *pVal);
bool tdSTSRowIterNext(STSRowIter *pIter, col_id_t colId, col_type_t colType, SCellVal *pVal);
-STSRow *mergeTwoRows(void *buffer, STSRow *row1, STSRow *row2, STSchema *pSchema1, STSchema *pSchema2);
-int32_t tdGetColDataOfRow(SCellVal *pVal, SDataCol *pCol, int32_t row, int8_t bitmapMode);
bool tdSTpRowGetVal(STSRow *pRow, col_id_t colId, col_type_t colType, int32_t flen, uint32_t offset, col_id_t colIdx,
SCellVal *pVal);
-bool tdSKvRowGetVal(STSRow *pRow, col_id_t colId, uint32_t offset, col_id_t colIdx, SCellVal *pVal);
-int32_t dataColGetNEleLen(SDataCol *pDataCol, int32_t rows, int8_t bitmapMode);
+bool tdSKvRowGetVal(STSRow *pRow, col_id_t colId, col_id_t colIdx, SCellVal *pVal);
void tdSCellValPrint(SCellVal *pVal, int8_t colType);
void tdSRowPrint(STSRow *row, STSchema *pSchema, const char *tag);
diff --git a/include/common/ttime.h b/include/common/ttime.h
index cd704bb1f7971526cbfacc9f6167852d21b8ec5d..de55b016cdacf2acb43c9f4c0b26599a310eb619 100644
--- a/include/common/ttime.h
+++ b/include/common/ttime.h
@@ -72,6 +72,8 @@ static FORCE_INLINE int64_t taosGetTimestampToday(int32_t precision) {
}
int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision);
+int64_t taosTimeSub(int64_t t, int64_t duration, char unit, int32_t precision);
+
int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precision);
int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char unit, int32_t precision);
diff --git a/include/common/ttokendef.h b/include/common/ttokendef.h
index 35b4a5ce7de5301941e9013e55138d65d964616f..e2089f30236fc68923d35948da3d16a5283e373e 100644
--- a/include/common/ttokendef.h
+++ b/include/common/ttokendef.h
@@ -16,247 +16,261 @@
#ifndef _TD_COMMON_TOKEN_H_
#define _TD_COMMON_TOKEN_H_
-#define TK_OR 1
-#define TK_AND 2
-#define TK_UNION 3
-#define TK_ALL 4
-#define TK_MINUS 5
-#define TK_EXCEPT 6
-#define TK_INTERSECT 7
-#define TK_NK_BITAND 8
-#define TK_NK_BITOR 9
-#define TK_NK_LSHIFT 10
-#define TK_NK_RSHIFT 11
-#define TK_NK_PLUS 12
-#define TK_NK_MINUS 13
-#define TK_NK_STAR 14
-#define TK_NK_SLASH 15
-#define TK_NK_REM 16
-#define TK_NK_CONCAT 17
-#define TK_CREATE 18
-#define TK_ACCOUNT 19
-#define TK_NK_ID 20
-#define TK_PASS 21
-#define TK_NK_STRING 22
-#define TK_ALTER 23
-#define TK_PPS 24
-#define TK_TSERIES 25
-#define TK_STORAGE 26
-#define TK_STREAMS 27
-#define TK_QTIME 28
-#define TK_DBS 29
-#define TK_USERS 30
-#define TK_CONNS 31
-#define TK_STATE 32
-#define TK_USER 33
-#define TK_PRIVILEGE 34
-#define TK_DROP 35
-#define TK_GRANT 36
-#define TK_ON 37
-#define TK_TO 38
-#define TK_REVOKE 39
-#define TK_FROM 40
-#define TK_NK_COMMA 41
-#define TK_READ 42
-#define TK_WRITE 43
-#define TK_NK_DOT 44
-#define TK_DNODE 45
-#define TK_PORT 46
-#define TK_NK_INTEGER 47
-#define TK_DNODES 48
-#define TK_NK_IPTOKEN 49
-#define TK_LOCAL 50
-#define TK_QNODE 51
-#define TK_BNODE 52
-#define TK_SNODE 53
-#define TK_MNODE 54
-#define TK_DATABASE 55
-#define TK_USE 56
-#define TK_IF 57
-#define TK_NOT 58
-#define TK_EXISTS 59
-#define TK_BUFFER 60
-#define TK_CACHELAST 61
-#define TK_COMP 62
-#define TK_DURATION 63
-#define TK_NK_VARIABLE 64
-#define TK_FSYNC 65
-#define TK_MAXROWS 66
-#define TK_MINROWS 67
-#define TK_KEEP 68
-#define TK_PAGES 69
-#define TK_PAGESIZE 70
-#define TK_PRECISION 71
-#define TK_REPLICA 72
-#define TK_STRICT 73
-#define TK_WAL 74
-#define TK_VGROUPS 75
-#define TK_SINGLE_STABLE 76
-#define TK_RETENTIONS 77
-#define TK_SCHEMALESS 78
-#define TK_NK_COLON 79
-#define TK_TABLE 80
-#define TK_NK_LP 81
-#define TK_NK_RP 82
-#define TK_STABLE 83
-#define TK_ADD 84
-#define TK_COLUMN 85
-#define TK_MODIFY 86
-#define TK_RENAME 87
-#define TK_TAG 88
-#define TK_SET 89
-#define TK_NK_EQ 90
-#define TK_USING 91
-#define TK_TAGS 92
-#define TK_COMMENT 93
-#define TK_BOOL 94
-#define TK_TINYINT 95
-#define TK_SMALLINT 96
-#define TK_INT 97
-#define TK_INTEGER 98
-#define TK_BIGINT 99
-#define TK_FLOAT 100
-#define TK_DOUBLE 101
-#define TK_BINARY 102
-#define TK_TIMESTAMP 103
-#define TK_NCHAR 104
-#define TK_UNSIGNED 105
-#define TK_JSON 106
-#define TK_VARCHAR 107
-#define TK_MEDIUMBLOB 108
-#define TK_BLOB 109
-#define TK_VARBINARY 110
-#define TK_DECIMAL 111
-#define TK_MAX_DELAY 112
-#define TK_WATERMARK 113
-#define TK_ROLLUP 114
-#define TK_TTL 115
-#define TK_SMA 116
-#define TK_FIRST 117
-#define TK_LAST 118
-#define TK_SHOW 119
-#define TK_DATABASES 120
-#define TK_TABLES 121
-#define TK_STABLES 122
-#define TK_MNODES 123
-#define TK_MODULES 124
-#define TK_QNODES 125
-#define TK_FUNCTIONS 126
-#define TK_INDEXES 127
-#define TK_ACCOUNTS 128
-#define TK_APPS 129
-#define TK_CONNECTIONS 130
-#define TK_LICENCE 131
-#define TK_GRANTS 132
-#define TK_QUERIES 133
-#define TK_SCORES 134
-#define TK_TOPICS 135
-#define TK_VARIABLES 136
-#define TK_BNODES 137
-#define TK_SNODES 138
-#define TK_CLUSTER 139
-#define TK_TRANSACTIONS 140
-#define TK_DISTRIBUTED 141
-#define TK_LIKE 142
-#define TK_INDEX 143
-#define TK_FULLTEXT 144
-#define TK_FUNCTION 145
-#define TK_INTERVAL 146
-#define TK_TOPIC 147
-#define TK_AS 148
-#define TK_CONSUMER 149
-#define TK_GROUP 150
-#define TK_DESC 151
-#define TK_DESCRIBE 152
-#define TK_RESET 153
-#define TK_QUERY 154
-#define TK_CACHE 155
-#define TK_EXPLAIN 156
-#define TK_ANALYZE 157
-#define TK_VERBOSE 158
-#define TK_NK_BOOL 159
-#define TK_RATIO 160
-#define TK_NK_FLOAT 161
-#define TK_COMPACT 162
-#define TK_VNODES 163
-#define TK_IN 164
-#define TK_OUTPUTTYPE 165
-#define TK_AGGREGATE 166
-#define TK_BUFSIZE 167
-#define TK_STREAM 168
-#define TK_INTO 169
-#define TK_TRIGGER 170
-#define TK_AT_ONCE 171
-#define TK_WINDOW_CLOSE 172
-#define TK_KILL 173
-#define TK_CONNECTION 174
-#define TK_TRANSACTION 175
-#define TK_BALANCE 176
-#define TK_VGROUP 177
-#define TK_MERGE 178
-#define TK_REDISTRIBUTE 179
-#define TK_SPLIT 180
-#define TK_SYNCDB 181
-#define TK_DELETE 182
-#define TK_NULL 183
-#define TK_NK_QUESTION 184
-#define TK_NK_ARROW 185
-#define TK_ROWTS 186
-#define TK_TBNAME 187
-#define TK_QSTARTTS 188
-#define TK_QENDTS 189
-#define TK_WSTARTTS 190
-#define TK_WENDTS 191
-#define TK_WDURATION 192
-#define TK_CAST 193
-#define TK_NOW 194
-#define TK_TODAY 195
-#define TK_TIMEZONE 196
-#define TK_COUNT 197
-#define TK_LAST_ROW 198
-#define TK_BETWEEN 199
-#define TK_IS 200
-#define TK_NK_LT 201
-#define TK_NK_GT 202
-#define TK_NK_LE 203
-#define TK_NK_GE 204
-#define TK_NK_NE 205
-#define TK_MATCH 206
-#define TK_NMATCH 207
-#define TK_CONTAINS 208
-#define TK_JOIN 209
-#define TK_INNER 210
-#define TK_SELECT 211
-#define TK_DISTINCT 212
-#define TK_WHERE 213
-#define TK_PARTITION 214
-#define TK_BY 215
-#define TK_SESSION 216
-#define TK_STATE_WINDOW 217
-#define TK_SLIDING 218
-#define TK_FILL 219
-#define TK_VALUE 220
-#define TK_NONE 221
-#define TK_PREV 222
-#define TK_LINEAR 223
-#define TK_NEXT 224
-#define TK_HAVING 225
-#define TK_RANGE 226
-#define TK_EVERY 227
-#define TK_ORDER 228
-#define TK_SLIMIT 229
-#define TK_SOFFSET 230
-#define TK_LIMIT 231
-#define TK_OFFSET 232
-#define TK_ASC 233
-#define TK_NULLS 234
-#define TK_ID 235
-#define TK_NK_BITNOT 236
-#define TK_INSERT 237
-#define TK_VALUES 238
-#define TK_IMPORT 239
-#define TK_NK_SEMI 240
-#define TK_FILE 241
+#define TK_OR 1
+#define TK_AND 2
+#define TK_UNION 3
+#define TK_ALL 4
+#define TK_MINUS 5
+#define TK_EXCEPT 6
+#define TK_INTERSECT 7
+#define TK_NK_BITAND 8
+#define TK_NK_BITOR 9
+#define TK_NK_LSHIFT 10
+#define TK_NK_RSHIFT 11
+#define TK_NK_PLUS 12
+#define TK_NK_MINUS 13
+#define TK_NK_STAR 14
+#define TK_NK_SLASH 15
+#define TK_NK_REM 16
+#define TK_NK_CONCAT 17
+#define TK_CREATE 18
+#define TK_ACCOUNT 19
+#define TK_NK_ID 20
+#define TK_PASS 21
+#define TK_NK_STRING 22
+#define TK_ALTER 23
+#define TK_PPS 24
+#define TK_TSERIES 25
+#define TK_STORAGE 26
+#define TK_STREAMS 27
+#define TK_QTIME 28
+#define TK_DBS 29
+#define TK_USERS 30
+#define TK_CONNS 31
+#define TK_STATE 32
+#define TK_USER 33
+#define TK_ENABLE 34
+#define TK_NK_INTEGER 35
+#define TK_SYSINFO 36
+#define TK_DROP 37
+#define TK_GRANT 38
+#define TK_ON 39
+#define TK_TO 40
+#define TK_REVOKE 41
+#define TK_FROM 42
+#define TK_NK_COMMA 43
+#define TK_READ 44
+#define TK_WRITE 45
+#define TK_NK_DOT 46
+#define TK_DNODE 47
+#define TK_PORT 48
+#define TK_DNODES 49
+#define TK_NK_IPTOKEN 50
+#define TK_LOCAL 51
+#define TK_QNODE 52
+#define TK_BNODE 53
+#define TK_SNODE 54
+#define TK_MNODE 55
+#define TK_DATABASE 56
+#define TK_USE 57
+#define TK_FLUSH 58
+#define TK_TRIM 59
+#define TK_IF 60
+#define TK_NOT 61
+#define TK_EXISTS 62
+#define TK_BUFFER 63
+#define TK_CACHELAST 64
+#define TK_CACHELASTSIZE 65
+#define TK_COMP 66
+#define TK_DURATION 67
+#define TK_NK_VARIABLE 68
+#define TK_FSYNC 69
+#define TK_MAXROWS 70
+#define TK_MINROWS 71
+#define TK_KEEP 72
+#define TK_PAGES 73
+#define TK_PAGESIZE 74
+#define TK_PRECISION 75
+#define TK_REPLICA 76
+#define TK_STRICT 77
+#define TK_WAL 78
+#define TK_VGROUPS 79
+#define TK_SINGLE_STABLE 80
+#define TK_RETENTIONS 81
+#define TK_SCHEMALESS 82
+#define TK_NK_COLON 83
+#define TK_TABLE 84
+#define TK_NK_LP 85
+#define TK_NK_RP 86
+#define TK_STABLE 87
+#define TK_ADD 88
+#define TK_COLUMN 89
+#define TK_MODIFY 90
+#define TK_RENAME 91
+#define TK_TAG 92
+#define TK_SET 93
+#define TK_NK_EQ 94
+#define TK_USING 95
+#define TK_TAGS 96
+#define TK_COMMENT 97
+#define TK_BOOL 98
+#define TK_TINYINT 99
+#define TK_SMALLINT 100
+#define TK_INT 101
+#define TK_INTEGER 102
+#define TK_BIGINT 103
+#define TK_FLOAT 104
+#define TK_DOUBLE 105
+#define TK_BINARY 106
+#define TK_TIMESTAMP 107
+#define TK_NCHAR 108
+#define TK_UNSIGNED 109
+#define TK_JSON 110
+#define TK_VARCHAR 111
+#define TK_MEDIUMBLOB 112
+#define TK_BLOB 113
+#define TK_VARBINARY 114
+#define TK_DECIMAL 115
+#define TK_MAX_DELAY 116
+#define TK_WATERMARK 117
+#define TK_ROLLUP 118
+#define TK_TTL 119
+#define TK_SMA 120
+#define TK_FIRST 121
+#define TK_LAST 122
+#define TK_SHOW 123
+#define TK_DATABASES 124
+#define TK_TABLES 125
+#define TK_STABLES 126
+#define TK_MNODES 127
+#define TK_MODULES 128
+#define TK_QNODES 129
+#define TK_FUNCTIONS 130
+#define TK_INDEXES 131
+#define TK_ACCOUNTS 132
+#define TK_APPS 133
+#define TK_CONNECTIONS 134
+#define TK_LICENCE 135
+#define TK_GRANTS 136
+#define TK_QUERIES 137
+#define TK_SCORES 138
+#define TK_TOPICS 139
+#define TK_VARIABLES 140
+#define TK_BNODES 141
+#define TK_SNODES 142
+#define TK_CLUSTER 143
+#define TK_TRANSACTIONS 144
+#define TK_DISTRIBUTED 145
+#define TK_CONSUMERS 146
+#define TK_SUBSCRIPTIONS 147
+#define TK_LIKE 148
+#define TK_INDEX 149
+#define TK_FUNCTION 150
+#define TK_INTERVAL 151
+#define TK_TOPIC 152
+#define TK_AS 153
+#define TK_WITH 154
+#define TK_META 155
+#define TK_CONSUMER 156
+#define TK_GROUP 157
+#define TK_DESC 158
+#define TK_DESCRIBE 159
+#define TK_RESET 160
+#define TK_QUERY 161
+#define TK_CACHE 162
+#define TK_EXPLAIN 163
+#define TK_ANALYZE 164
+#define TK_VERBOSE 165
+#define TK_NK_BOOL 166
+#define TK_RATIO 167
+#define TK_NK_FLOAT 168
+#define TK_COMPACT 169
+#define TK_VNODES 170
+#define TK_IN 171
+#define TK_OUTPUTTYPE 172
+#define TK_AGGREGATE 173
+#define TK_BUFSIZE 174
+#define TK_STREAM 175
+#define TK_INTO 176
+#define TK_TRIGGER 177
+#define TK_AT_ONCE 178
+#define TK_WINDOW_CLOSE 179
+#define TK_IGNORE 180
+#define TK_EXPIRED 181
+#define TK_KILL 182
+#define TK_CONNECTION 183
+#define TK_TRANSACTION 184
+#define TK_BALANCE 185
+#define TK_VGROUP 186
+#define TK_MERGE 187
+#define TK_REDISTRIBUTE 188
+#define TK_SPLIT 189
+#define TK_SYNCDB 190
+#define TK_DELETE 191
+#define TK_INSERT 192
+#define TK_NULL 193
+#define TK_NK_QUESTION 194
+#define TK_NK_ARROW 195
+#define TK_ROWTS 196
+#define TK_TBNAME 197
+#define TK_QSTART 198
+#define TK_QEND 199
+#define TK_QDURATION 200
+#define TK_WSTART 201
+#define TK_WEND 202
+#define TK_WDURATION 203
+#define TK_CAST 204
+#define TK_NOW 205
+#define TK_TODAY 206
+#define TK_TIMEZONE 207
+#define TK_CLIENT_VERSION 208
+#define TK_SERVER_VERSION 209
+#define TK_SERVER_STATUS 210
+#define TK_CURRENT_USER 211
+#define TK_COUNT 212
+#define TK_LAST_ROW 213
+#define TK_BETWEEN 214
+#define TK_IS 215
+#define TK_NK_LT 216
+#define TK_NK_GT 217
+#define TK_NK_LE 218
+#define TK_NK_GE 219
+#define TK_NK_NE 220
+#define TK_MATCH 221
+#define TK_NMATCH 222
+#define TK_CONTAINS 223
+#define TK_JOIN 224
+#define TK_INNER 225
+#define TK_SELECT 226
+#define TK_DISTINCT 227
+#define TK_WHERE 228
+#define TK_PARTITION 229
+#define TK_BY 230
+#define TK_SESSION 231
+#define TK_STATE_WINDOW 232
+#define TK_SLIDING 233
+#define TK_FILL 234
+#define TK_VALUE 235
+#define TK_NONE 236
+#define TK_PREV 237
+#define TK_LINEAR 238
+#define TK_NEXT 239
+#define TK_HAVING 240
+#define TK_RANGE 241
+#define TK_EVERY 242
+#define TK_ORDER 243
+#define TK_SLIMIT 244
+#define TK_SOFFSET 245
+#define TK_LIMIT 246
+#define TK_OFFSET 247
+#define TK_ASC 248
+#define TK_NULLS 249
+#define TK_ID 250
+#define TK_NK_BITNOT 251
+#define TK_VALUES 252
+#define TK_IMPORT 253
+#define TK_NK_SEMI 254
+#define TK_FILE 255
#define TK_NK_SPACE 300
#define TK_NK_COMMENT 301
diff --git a/include/dnode/mnode/mnode.h b/include/dnode/mnode/mnode.h
index 2509c106015682ff38c5de3d1965fa7b97d0d7a7..3bed77d682f14d3409b02bccd366bd99b3be2a94 100644
--- a/include/dnode/mnode/mnode.h
+++ b/include/dnode/mnode/mnode.h
@@ -52,6 +52,7 @@ SMnode *mndOpen(const char *path, const SMnodeOpt *pOption);
* @param pMnode The mnode object to close.
*/
void mndClose(SMnode *pMnode);
+void mndPreClose(SMnode *pMnode);
/**
* @brief Start mnode
@@ -73,10 +74,12 @@ void mndStop(SMnode *pMnode);
* @param pMnode The mnode object.
* @param pCluster
* @param pVgroup
+ * @param pStbInfo
* @param pGrant
* @return int32_t 0 for success, -1 for failure.
*/
-int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pCluster, SMonVgroupInfo *pVgroup, SMonGrantInfo *pGrant);
+int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgroupInfo *pVgroupInfo,
+ SMonStbInfo *pStbInfo, SMonGrantInfo *pGrantInfo);
/**
* @brief Get mnode loads for status msg.
diff --git a/include/libs/catalog/catalog.h b/include/libs/catalog/catalog.h
index 0c720138bd55d9b1c6fcc1bb08f2ec9717609315..1d1849f24a72b33e2eff3ec23c8076b74f785206 100644
--- a/include/libs/catalog/catalog.h
+++ b/include/libs/catalog/catalog.h
@@ -68,8 +68,10 @@ typedef struct SCatalogReq {
SArray* pIndex; // element is index name
SArray* pUser; // element is SUserAuthInfo
SArray* pTableIndex; // element is SNAME
+ SArray* pTableCfg; // element is SNAME
bool qNodeRequired; // valid qnode
bool dNodeRequired; // valid dnode
+ bool svrVerRequired;
bool forceUpdate;
} SCatalogReq;
@@ -79,17 +81,19 @@ typedef struct SMetaRes {
} SMetaRes;
typedef struct SMetaData {
- SArray* pDbVgroup; // pRes = SArray*
- SArray* pDbCfg; // pRes = SDbCfgInfo*
- SArray* pDbInfo; // pRes = SDbInfo*
- SArray* pTableMeta; // pRes = STableMeta*
- SArray* pTableHash; // pRes = SVgroupInfo*
- SArray* pTableIndex; // pRes = SArray*
- SArray* pUdfList; // pRes = SFuncInfo*
- SArray* pIndex; // pRes = SIndexInfo*
- SArray* pUser; // pRes = bool*
- SArray* pQnodeList; // pRes = SArray*
- SArray* pDnodeList; // pRes = SArray*
+ SArray* pDbVgroup; // pRes = SArray*
+ SArray* pDbCfg; // pRes = SDbCfgInfo*
+ SArray* pDbInfo; // pRes = SDbInfo*
+ SArray* pTableMeta; // pRes = STableMeta*
+ SArray* pTableHash; // pRes = SVgroupInfo*
+ SArray* pTableIndex; // pRes = SArray*
+ SArray* pUdfList; // pRes = SFuncInfo*
+ SArray* pIndex; // pRes = SIndexInfo*
+ SArray* pUser; // pRes = bool*
+ SArray* pQnodeList; // pRes = SArray*
+ SArray* pTableCfg; // pRes = STableCfg*
+ SArray* pDnodeList; // pRes = SArray*
+ SMetaRes* pSvrVer; // pRes = char*
} SMetaData;
typedef struct SCatalogCfg {
@@ -143,14 +147,6 @@ int32_t catalogInit(SCatalogCfg* cfg);
*/
int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle);
-/**
- * Free a cluster's all catalog info, usually it's not necessary, until the application is closing.
- * no current or future usage should be guaranteed by application
- * @param pCatalog (input, NO more usage)
- * @return error code
- */
-void catalogFreeHandle(SCatalog* pCatalog);
-
int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t* tableNum);
/**
@@ -266,7 +262,7 @@ int32_t catalogGetTableHashVgroup(SCatalog* pCatalog, SRequestConnInfo* pConn, c
*/
int32_t catalogGetAllMeta(SCatalog* pCatalog, SRequestConnInfo* pConn, const SCatalogReq* pReq, SMetaData* pRsp);
-int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, SRequestConnInfo* pConn, uint64_t reqId, const SCatalogReq* pReq, catalogCallback fp, void* param, int64_t* jobId);
+int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, SRequestConnInfo* pConn, const SCatalogReq* pReq, catalogCallback fp, void* param, int64_t* jobId);
int32_t catalogGetQnodeList(SCatalog* pCatalog, SRequestConnInfo* pConn, SArray* pQnodeList);
@@ -284,6 +280,8 @@ int32_t catalogGetIndexMeta(SCatalog* pCtg, SRequestConnInfo* pConn, const char*
int32_t catalogGetTableIndex(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SArray** pRes);
+int32_t catalogRefreshGetTableCfg(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, STableCfg** pCfg);
+
int32_t catalogUpdateTableIndex(SCatalog* pCtg, STableIndexRsp *pRsp);
int32_t catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* funcName, SFuncInfo* pInfo);
@@ -294,6 +292,8 @@ int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth);
int32_t catalogUpdateVgEpSet(SCatalog* pCtg, const char* dbFName, int32_t vgId, SEpSet *epSet);
+int32_t catalogGetServerVersion(SCatalog* pCtg, SRequestConnInfo *pConn, char** pVersion);
+
int32_t ctgdLaunchAsyncCall(SCatalog* pCtg, SRequestConnInfo* pConn, uint64_t reqId, bool forceUpdate);
int32_t catalogClearCache(void);
diff --git a/include/libs/command/command.h b/include/libs/command/command.h
index aee6b837837d7b3d9e3cbf37cde21c7a626c1a4f..8a4ecad37da3089c32ff0e3fca7473dcc334971c 100644
--- a/include/libs/command/command.h
+++ b/include/libs/command/command.h
@@ -13,6 +13,9 @@
* along with this program. If not, see .
*/
+#ifndef TDENGINE_COMMAND_H
+#define TDENGINE_COMMAND_H
+
#include "cmdnodes.h"
#include "tmsg.h"
#include "plannodes.h"
@@ -27,4 +30,4 @@ int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp);
int32_t qExplainUpdateExecInfo(SExplainCtx *pCtx, SExplainRsp *pRspMsg, int32_t groupId, SRetrieveTableRsp **pRsp);
void qExplainFreeCtx(SExplainCtx *pCtx);
-
+#endif
diff --git a/include/libs/executor/dataSinkMgt.h b/include/libs/executor/dataSinkMgt.h
index c23cf162aa6e1ca35e3750aa54e91659c45d6b08..8d5a8abcb4aa595086d5b223e6b8dc028554384f 100644
--- a/include/libs/executor/dataSinkMgt.h
+++ b/include/libs/executor/dataSinkMgt.h
@@ -33,7 +33,7 @@ struct SDataSink;
struct SSDataBlock;
typedef struct SDeleterRes {
- uint64_t uid;
+ uint64_t suid;
SArray* uidList;
int64_t skey;
int64_t ekey;
@@ -41,9 +41,14 @@ typedef struct SDeleterRes {
} SDeleterRes;
typedef struct SDeleterParam {
- SArray* pUidList;
+ uint64_t suid;
+ SArray* pUidList;
} SDeleterParam;
+typedef struct SInserterParam {
+ SReadHandle* readHandle;
+} SInserterParam;
+
typedef struct SDataSinkStat {
uint64_t cachedSize;
} SDataSinkStat;
@@ -95,7 +100,7 @@ void dsEndPut(DataSinkHandle handle, uint64_t useconds);
* @param handle
* @param pLen data length
*/
-void dsGetDataLength(DataSinkHandle handle, int32_t* pLen, bool* pQueryEnd);
+void dsGetDataLength(DataSinkHandle handle, int64_t* pLen, bool* pQueryEnd);
/**
* Get data, the caller needs to allocate data memory.
diff --git a/include/libs/executor/executor.h b/include/libs/executor/executor.h
index 083f6ae1b07d4db9e7f4d339b63b8b89c0a8becc..dd64c5bf713794d136a829e9c116283831f9c9c0 100644
--- a/include/libs/executor/executor.h
+++ b/include/libs/executor/executor.h
@@ -30,31 +30,40 @@ struct SRpcMsg;
struct SSubplan;
typedef struct SReadHandle {
- void* reader;
+ void* tqReader;
void* meta;
void* config;
void* vnode;
void* mnd;
SMsgCb* pMsgCb;
+ int64_t version;
+ bool initMetaReader;
+ bool initTableReader;
+ bool initTqReader;
} SReadHandle;
-enum {
- STREAM_DATA_TYPE_SUBMIT_BLOCK = 1,
- STREAM_DATA_TYPE_SSDATA_BLOCK = 2,
-};
-
+// in queue mode, data streams are seperated by msg
typedef enum {
OPTR_EXEC_MODEL_BATCH = 0x1,
OPTR_EXEC_MODEL_STREAM = 0x2,
+ OPTR_EXEC_MODEL_QUEUE = 0x3,
} EOPTR_EXEC_MODEL;
/**
- * Create the exec task for streaming mode
+ * Create the exec task for stream mode
+ * @param pMsg
+ * @param SReadHandle
+ * @return
+ */
+qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers);
+
+/**
+ * Create the exec task for queue mode
* @param pMsg
- * @param streamReadHandle
+ * @param SReadHandle
* @return
*/
-qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, void* streamReadHandle);
+qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers);
/**
* Set the input data block for the stream scan.
@@ -104,8 +113,8 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId,
* @param tversion
* @return
*/
-int32_t qGetQueriedTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* tableName, int32_t* sversion,
- int32_t* tversion);
+int32_t qGetQueryTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* tableName, int32_t* sversion,
+ int32_t* tversion);
/**
* The main task execution function, including query on both table and multiple tables,
@@ -131,13 +140,6 @@ int32_t qKillTask(qTaskInfo_t tinfo);
*/
int32_t qAsyncKillTask(qTaskInfo_t tinfo);
-/**
- * return whether query is completed or not
- * @param tinfo
- * @return
- */
-int32_t qIsTaskCompleted(qTaskInfo_t tinfo);
-
/**
* destroy query info structure
* @param qHandle
@@ -159,7 +161,7 @@ int64_t qGetQueriedTableUid(qTaskInfo_t tinfo);
*/
int32_t qGetQualifiedTableIdList(void* pTableList, const char* tagCond, int32_t tagCondLen, SArray* pTableIdList);
-void qProcessFetchRsp(void* parent, struct SRpcMsg* pMsg, struct SEpSet* pEpSet);
+void qProcessRspMsg(void* parent, struct SRpcMsg* pMsg, struct SEpSet* pEpSet);
int32_t qGetExplainExecInfo(qTaskInfo_t tinfo, int32_t* resNum, SExplainExecInfo** pRes);
@@ -167,6 +169,29 @@ int32_t qSerializeTaskStatus(qTaskInfo_t tinfo, char** pOutput, int32_t* len);
int32_t qDeserializeTaskStatus(qTaskInfo_t tinfo, const char* pInput, int32_t len);
+/**
+ * return the scan info, in the form of tuple of two items, including table uid and current timestamp
+ * @param tinfo
+ * @param uid
+ * @param ts
+ * @return
+ */
+int32_t qGetStreamScanStatus(qTaskInfo_t tinfo, uint64_t* uid, int64_t* ts);
+
+int32_t qStreamPrepareTsdbScan(qTaskInfo_t tinfo, uint64_t uid, int64_t ts);
+
+int32_t qStreamPrepareScan(qTaskInfo_t tinfo, const STqOffsetVal* pOffset);
+
+int32_t qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset);
+
+void* qStreamExtractMetaMsg(qTaskInfo_t tinfo);
+
+void* qExtractReaderFromStreamScanner(void* scanner);
+
+int32_t qExtractStreamScanner(qTaskInfo_t tinfo, void** scanner);
+
+int32_t qStreamInput(qTaskInfo_t tinfo, void* pItem);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/libs/function/function.h b/include/libs/function/function.h
index e543f0f653dcd8b28c6f159b52efa817015964f3..4d27325d7575a2c2704671ec9193e3a7ae7dbf3b 100644
--- a/include/libs/function/function.h
+++ b/include/libs/function/function.h
@@ -172,24 +172,13 @@ typedef struct tExprNode {
void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *));
-typedef struct SAggFunctionInfo {
- char name[FUNCTIONS_NAME_MAX_LENGTH];
- int8_t type; // Scalar function or aggregation function
- uint32_t functionId; // Function Id
- int8_t sFunctionId; // Transfer function for super table query
- uint16_t status;
-
- bool (*init)(SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment
- void (*addInput)(SqlFunctionCtx *pCtx);
-
- // finalizer must be called after all exec has been executed to generated final result.
- void (*finalize)(SqlFunctionCtx *pCtx);
- void (*combine)(SqlFunctionCtx *pCtx);
-
- int32_t (*dataReqFunc)(SqlFunctionCtx *pCtx, STimeWindow* w, int32_t colId);
-} SAggFunctionInfo;
+typedef enum {
+ SHOULD_FREE_COLDATA = 0x1, // the newly created column data needs to be destroyed.
+ DELEGATED_MGMT_COLDATA = 0x2, // input column data should not be released.
+} ECOLDATA_MGMT_TYPE_E;
struct SScalarParam {
+ ECOLDATA_MGMT_TYPE_E type;
SColumnInfoData *columnData;
SHashObj *pHashFilter;
int32_t hashValueType;
diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h
index cbaff29cb2de5ab4e93d39caa1cd89810fbdddde..04825f376fb12912282f74aa4256422289850f6c 100644
--- a/include/libs/function/functionMgt.h
+++ b/include/libs/function/functionMgt.h
@@ -34,6 +34,7 @@ typedef enum EFunctionType {
FUNCTION_TYPE_ELAPSED,
FUNCTION_TYPE_IRATE,
FUNCTION_TYPE_LAST_ROW,
+ FUNCTION_TYPE_LAST_ROWT, // TODO: removed
FUNCTION_TYPE_MAX,
FUNCTION_TYPE_MIN,
FUNCTION_TYPE_MODE,
@@ -105,7 +106,7 @@ typedef enum EFunctionType {
// system function
FUNCTION_TYPE_DATABASE = 3000,
FUNCTION_TYPE_CLIENT_VERSION,
- FUNCTION_TYPE_SERVER_SERSION,
+ FUNCTION_TYPE_SERVER_VERSION,
FUNCTION_TYPE_SERVER_STATUS,
FUNCTION_TYPE_CURRENT_USER,
FUNCTION_TYPE_USER,
@@ -113,16 +114,20 @@ typedef enum EFunctionType {
// pseudo column function
FUNCTION_TYPE_ROWTS = 3500,
FUNCTION_TYPE_TBNAME,
- FUNCTION_TYPE_QSTARTTS,
- FUNCTION_TYPE_QENDTS,
- FUNCTION_TYPE_WSTARTTS,
- FUNCTION_TYPE_WENDTS,
+ FUNCTION_TYPE_QSTART,
+ FUNCTION_TYPE_QEND,
+ FUNCTION_TYPE_QDURATION,
+ FUNCTION_TYPE_WSTART,
+ FUNCTION_TYPE_WEND,
FUNCTION_TYPE_WDURATION,
// internal function
FUNCTION_TYPE_SELECT_VALUE,
FUNCTION_TYPE_BLOCK_DIST, // block distribution aggregate function
FUNCTION_TYPE_BLOCK_DIST_INFO, // block distribution pseudo column function
+ FUNCTION_TYPE_TO_COLUMN,
+ FUNCTION_TYPE_GROUP_KEY,
+ FUNCTION_TYPE_CACHE_LAST_ROW,
// distributed splitting functions
FUNCTION_TYPE_APERCENTILE_PARTIAL = 4000,
@@ -190,6 +195,10 @@ bool fmIsForbidWindowFunc(int32_t funcId);
bool fmIsForbidGroupByFunc(int32_t funcId);
bool fmIsIntervalInterpoFunc(int32_t funcId);
bool fmIsInterpFunc(int32_t funcId);
+bool fmIsLastRowFunc(int32_t funcId);
+bool fmIsSystemInfoFunc(int32_t funcId);
+bool fmIsImplicitTsFunc(int32_t funcId);
+bool fmIsClientPseudoColumnFunc(int32_t funcId);
int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);
diff --git a/include/libs/function/taosudf.h b/include/libs/function/taosudf.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e84b87a81ec1808dfc368ac285f4dabd2e1d57e
--- /dev/null
+++ b/include/libs/function/taosudf.h
@@ -0,0 +1,266 @@
+/*
+* Copyright (c) 2019 TAOS Data, Inc.
+*
+* This program is free software: you can use, redistribute, and/or modify
+* it under the terms of the GNU Affero General Public License, version 3
+* or later ("AGPL"), as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see .
+*/
+
+#ifndef TDENGINE_TAOSUDF_H
+#define TDENGINE_TAOSUDF_H
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__)
+#define FORCE_INLINE inline __attribute__((always_inline))
+#else
+#define FORCE_INLINE
+#endif
+typedef struct SUdfColumnMeta {
+ int16_t type;
+ int32_t bytes;
+ uint8_t precision;
+ uint8_t scale;
+} SUdfColumnMeta;
+
+typedef struct SUdfColumnData {
+ int32_t numOfRows;
+ int32_t rowsAlloc;
+ union {
+ struct {
+ int32_t nullBitmapLen;
+ char *nullBitmap;
+ int32_t dataLen;
+ char *data;
+ } fixLenCol;
+
+ struct {
+ int32_t varOffsetsLen;
+ int32_t *varOffsets;
+ int32_t payloadLen;
+ char *payload;
+ int32_t payloadAllocLen;
+ } varLenCol;
+ };
+} SUdfColumnData;
+
+
+typedef struct SUdfColumn {
+ SUdfColumnMeta colMeta;
+ bool hasNull;
+ SUdfColumnData colData;
+} SUdfColumn;
+
+typedef struct SUdfDataBlock {
+ int32_t numOfRows;
+ int32_t numOfCols;
+ SUdfColumn **udfCols;
+} SUdfDataBlock;
+
+typedef struct SUdfInterBuf {
+ int32_t bufLen;
+ char* buf;
+ int8_t numOfResult; //zero or one
+} SUdfInterBuf;
+typedef void *UdfcFuncHandle;
+
+// dynamic lib init and destroy
+typedef int32_t (*TUdfInitFunc)();
+typedef int32_t (*TUdfDestroyFunc)();
+
+#define UDF_MEMORY_EXP_GROWTH 1.5
+#define NBIT (3u)
+#define BitPos(_n) ((_n) & ((1 << NBIT) - 1))
+#define BMCharPos(bm_, r_) ((bm_)[(r_) >> NBIT])
+#define BitmapLen(_n) (((_n) + ((1 << NBIT) - 1)) >> NBIT)
+
+#define udfColDataIsNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] == -1)
+#define udfColDataIsNull_f(pColumn, row) ((BMCharPos(pColumn->colData.fixLenCol.nullBitmap, row) & (1u << (7u - BitPos(row)))) == (1u << (7u - BitPos(row))))
+#define udfColDataSetNull_f(pColumn, row) \
+ do { \
+ BMCharPos(pColumn->colData.fixLenCol.nullBitmap, row) |= (1u << (7u - BitPos(row))); \
+ } while (0)
+
+#define udfColDataSetNotNull_f(pColumn, r_) \
+ do { \
+ BMCharPos(pColumn->colData.fixLenCol.nullBitmap, r_) &= ~(1u << (7u - BitPos(r_))); \
+ } while (0)
+#define udfColDataSetNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] = -1)
+
+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 varDataTLen(v) (sizeof(VarDataLenT) + varDataLen(v))
+#define varDataCopy(dst, v) memcpy((dst), (void *)(v), varDataTLen(v))
+#define varDataLenByData(v) (*(VarDataLenT *)(((char *)(v)) - VARSTR_HEADER_SIZE))
+#define varDataSetLen(v, _len) (((VarDataLenT *)(v))[0] = (VarDataLenT)(_len))
+#define IS_VAR_DATA_TYPE(t) \
+ (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON))
+#define IS_STR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR))
+
+
+static FORCE_INLINE char* udfColDataGetData(const SUdfColumn* pColumn, int32_t row) {
+ if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
+ return pColumn->colData.varLenCol.payload + pColumn->colData.varLenCol.varOffsets[row];
+ } else {
+ return pColumn->colData.fixLenCol.data + pColumn->colMeta.bytes * row;
+ }
+}
+
+static FORCE_INLINE bool udfColDataIsNull(const SUdfColumn* pColumn, int32_t row) {
+ if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
+ if (pColumn->colMeta.type == TSDB_DATA_TYPE_JSON) {
+ if (udfColDataIsNull_var(pColumn, row)) {
+ return true;
+ }
+ char* data = udfColDataGetData(pColumn, row);
+ return (*data == TSDB_DATA_TYPE_NULL);
+ } else {
+ return udfColDataIsNull_var(pColumn, row);
+ }
+ } else {
+ return udfColDataIsNull_f(pColumn, row);
+ }
+}
+
+static FORCE_INLINE int32_t udfColEnsureCapacity(SUdfColumn* pColumn, int32_t newCapacity) {
+ SUdfColumnMeta *meta = &pColumn->colMeta;
+ SUdfColumnData *data = &pColumn->colData;
+
+ if (newCapacity== 0 || newCapacity <= data->rowsAlloc) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int allocCapacity = (data->rowsAlloc< 8) ? 8 : data->rowsAlloc;
+ while (allocCapacity < newCapacity) {
+ allocCapacity *= UDF_MEMORY_EXP_GROWTH;
+ }
+
+ if (IS_VAR_DATA_TYPE(meta->type)) {
+ char* tmp = (char*)realloc(data->varLenCol.varOffsets, sizeof(int32_t) * allocCapacity);
+ if (tmp == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ data->varLenCol.varOffsets = (int32_t*)tmp;
+ data->varLenCol.varOffsetsLen = sizeof(int32_t) * allocCapacity;
+ // for payload, add data in udfColDataAppend
+ } else {
+ char* tmp = (char*)realloc(data->fixLenCol.nullBitmap, BitmapLen(allocCapacity));
+ if (tmp == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ data->fixLenCol.nullBitmap = tmp;
+ data->fixLenCol.nullBitmapLen = BitmapLen(allocCapacity);
+ if (meta->type == TSDB_DATA_TYPE_NULL) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ tmp = (char*)realloc(data->fixLenCol.data, allocCapacity* meta->bytes);
+ if (tmp == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ data->fixLenCol.data = tmp;
+ data->fixLenCol.dataLen = allocCapacity* meta->bytes;
+ }
+
+ data->rowsAlloc = allocCapacity;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static FORCE_INLINE void udfColDataSetNull(SUdfColumn* pColumn, int32_t row) {
+ udfColEnsureCapacity(pColumn, row+1);
+ if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
+ udfColDataSetNull_var(pColumn, row);
+ } else {
+ udfColDataSetNull_f(pColumn, row);
+ }
+ pColumn->hasNull = true;
+}
+
+static FORCE_INLINE int32_t udfColDataSet(SUdfColumn* pColumn, uint32_t currentRow, const char* pData, bool isNull) {
+ SUdfColumnMeta *meta = &pColumn->colMeta;
+ SUdfColumnData *data = &pColumn->colData;
+ udfColEnsureCapacity(pColumn, currentRow+1);
+ bool isVarCol = IS_VAR_DATA_TYPE(meta->type);
+ if (isNull) {
+ udfColDataSetNull(pColumn, currentRow);
+ } else {
+ if (!isVarCol) {
+ udfColDataSetNotNull_f(pColumn, currentRow);
+ memcpy(data->fixLenCol.data + meta->bytes * currentRow, pData, meta->bytes);
+ } else {
+ int32_t dataLen = varDataTLen(pData);
+ if (meta->type == TSDB_DATA_TYPE_JSON) {
+ if (*pData == TSDB_DATA_TYPE_NULL) {
+ dataLen = 0;
+ } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
+ dataLen = varDataTLen(pData + sizeof(char));
+ } else if (*pData == TSDB_DATA_TYPE_BIGINT || *pData == TSDB_DATA_TYPE_DOUBLE) {
+ dataLen = sizeof(int64_t);
+ } else if (*pData == TSDB_DATA_TYPE_BOOL) {
+ dataLen = sizeof(char);
+ }
+ dataLen += sizeof(char);
+ }
+
+ if (data->varLenCol.payloadAllocLen < data->varLenCol.payloadLen + dataLen) {
+ uint32_t newSize = data->varLenCol.payloadAllocLen;
+ if (newSize <= 1) {
+ newSize = 8;
+ }
+
+ while (newSize < data->varLenCol.payloadLen + dataLen) {
+ newSize = newSize * UDF_MEMORY_EXP_GROWTH;
+ }
+
+ char *buf = (char*)realloc(data->varLenCol.payload, newSize);
+ if (buf == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ data->varLenCol.payload = buf;
+ data->varLenCol.payloadAllocLen = newSize;
+ }
+
+ uint32_t len = data->varLenCol.payloadLen;
+ data->varLenCol.varOffsets[currentRow] = len;
+
+ memcpy(data->varLenCol.payload + len, pData, dataLen);
+ data->varLenCol.payloadLen += dataLen;
+ }
+ }
+ data->numOfRows = (currentRow + 1 > data->numOfRows) ? (currentRow+1) : data->numOfRows;
+ return 0;
+}
+
+typedef int32_t (*TUdfScalarProcFunc)(SUdfDataBlock* block, SUdfColumn *resultCol);
+
+typedef int32_t (*TUdfAggStartFunc)(SUdfInterBuf *buf);
+typedef int32_t (*TUdfAggProcessFunc)(SUdfDataBlock* block, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf);
+typedef int32_t (*TUdfAggFinishFunc)(SUdfInterBuf* buf, SUdfInterBuf *resultData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // TDENGINE_TAOSUDF_H
diff --git a/include/libs/function/tudf.h b/include/libs/function/tudf.h
index 28b1fbe8cef24e8734dcb4d88ff4999e09d43865..b4c05fea87448bab3e7872ebdbb0a9de20b1c289 100644
--- a/include/libs/function/tudf.h
+++ b/include/libs/function/tudf.h
@@ -16,6 +16,13 @@
#ifndef TDENGINE_TUDF_H
#define TDENGINE_TUDF_H
+#undef malloc
+#define malloc malloc
+#undef free
+#define free free
+#undef realloc
+#define alloc alloc
+#include
#include
#include
@@ -36,56 +43,6 @@ extern "C" {
#endif
#define UDF_DNODE_ID_ENV_NAME "DNODE_ID"
-//======================================================================================
-//begin API to taosd and qworker
-
-typedef struct SUdfColumnMeta {
- int16_t type;
- int32_t bytes;
- uint8_t precision;
- uint8_t scale;
-} SUdfColumnMeta;
-
-typedef struct SUdfColumnData {
- int32_t numOfRows;
- int32_t rowsAlloc;
- union {
- struct {
- int32_t nullBitmapLen;
- char *nullBitmap;
- int32_t dataLen;
- char *data;
- } fixLenCol;
-
- struct {
- int32_t varOffsetsLen;
- int32_t *varOffsets;
- int32_t payloadLen;
- char *payload;
- int32_t payloadAllocLen;
- } varLenCol;
- };
-} SUdfColumnData;
-
-
-typedef struct SUdfColumn {
- SUdfColumnMeta colMeta;
- bool hasNull;
- SUdfColumnData colData;
-} SUdfColumn;
-
-typedef struct SUdfDataBlock {
- int32_t numOfRows;
- int32_t numOfCols;
- SUdfColumn **udfCols;
-} SUdfDataBlock;
-
-typedef struct SUdfInterBuf {
- int32_t bufLen;
- char* buf;
- int8_t numOfResult; //zero or one
-} SUdfInterBuf;
-typedef void *UdfcFuncHandle;
//low level APIs
/**
@@ -127,177 +84,6 @@ int32_t udfAggFinalize(struct SqlFunctionCtx *pCtx, SSDataBlock* pBlock);
int32_t callUdfScalarFunc(char *udfName, SScalarParam *input, int32_t numOfCols, SScalarParam *output);
int32_t cleanUpUdfs();
-// end API to taosd and qworker
-//=============================================================================================================================
-// begin API to UDF writer.
-
-// dynamic lib init and destroy
-typedef int32_t (*TUdfInitFunc)();
-typedef int32_t (*TUdfDestroyFunc)();
-
-//TODO: add API to check function arguments type, number etc.
-
-#define UDF_MEMORY_EXP_GROWTH 1.5
-
-#define udfColDataIsNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] == -1)
-#define udfColDataIsNull_f(pColumn, row) ((BMCharPos(pColumn->colData.fixLenCol.nullBitmap, row) & (1u << (7u - BitPos(row)))) == (1u << (7u - BitPos(row))))
-#define udfColDataSetNull_f(pColumn, row) \
- do { \
- BMCharPos(pColumn->colData.fixLenCol.nullBitmap, row) |= (1u << (7u - BitPos(row))); \
- } while (0)
-
-#define udfColDataSetNotNull_f(pColumn, r_) \
- do { \
- BMCharPos(pColumn->colData.fixLenCol.nullBitmap, r_) &= ~(1u << (7u - BitPos(r_))); \
- } while (0)
-#define udfColDataSetNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] = -1)
-
-
-static FORCE_INLINE char* udfColDataGetData(const SUdfColumn* pColumn, int32_t row) {
- if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
- return pColumn->colData.varLenCol.payload + pColumn->colData.varLenCol.varOffsets[row];
- } else {
- return pColumn->colData.fixLenCol.data + pColumn->colMeta.bytes * row;
- }
-}
-
-static FORCE_INLINE bool udfColDataIsNull(const SUdfColumn* pColumn, int32_t row) {
- if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
- if (pColumn->colMeta.type == TSDB_DATA_TYPE_JSON) {
- if (udfColDataIsNull_var(pColumn, row)) {
- return true;
- }
- char* data = udfColDataGetData(pColumn, row);
- return (*data == TSDB_DATA_TYPE_NULL);
- } else {
- return udfColDataIsNull_var(pColumn, row);
- }
- } else {
- return udfColDataIsNull_f(pColumn, row);
- }
-}
-
-static FORCE_INLINE int32_t udfColEnsureCapacity(SUdfColumn* pColumn, int32_t newCapacity) {
- SUdfColumnMeta *meta = &pColumn->colMeta;
- SUdfColumnData *data = &pColumn->colData;
-
- if (newCapacity== 0 || newCapacity <= data->rowsAlloc) {
- return TSDB_CODE_SUCCESS;
- }
-
- int allocCapacity = TMAX(data->rowsAlloc, 8);
- while (allocCapacity < newCapacity) {
- allocCapacity *= UDF_MEMORY_EXP_GROWTH;
- }
-
- if (IS_VAR_DATA_TYPE(meta->type)) {
- char* tmp = taosMemoryRealloc(data->varLenCol.varOffsets, sizeof(int32_t) * allocCapacity);
- if (tmp == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- data->varLenCol.varOffsets = (int32_t*)tmp;
- data->varLenCol.varOffsetsLen = sizeof(int32_t) * allocCapacity;
- // for payload, add data in udfColDataAppend
- } else {
- char* tmp = taosMemoryRealloc(data->fixLenCol.nullBitmap, BitmapLen(allocCapacity));
- if (tmp == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- data->fixLenCol.nullBitmap = tmp;
- data->fixLenCol.nullBitmapLen = BitmapLen(allocCapacity);
- if (meta->type == TSDB_DATA_TYPE_NULL) {
- return TSDB_CODE_SUCCESS;
- }
-
- tmp = taosMemoryRealloc(data->fixLenCol.data, allocCapacity* meta->bytes);
- if (tmp == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- data->fixLenCol.data = tmp;
- data->fixLenCol.dataLen = allocCapacity* meta->bytes;
- }
-
- data->rowsAlloc = allocCapacity;
-
- return TSDB_CODE_SUCCESS;
-}
-
-static FORCE_INLINE void udfColDataSetNull(SUdfColumn* pColumn, int32_t row) {
- udfColEnsureCapacity(pColumn, row+1);
- if (IS_VAR_DATA_TYPE(pColumn->colMeta.type)) {
- udfColDataSetNull_var(pColumn, row);
- } else {
- udfColDataSetNull_f(pColumn, row);
- }
- pColumn->hasNull = true;
-}
-
-static FORCE_INLINE int32_t udfColDataSet(SUdfColumn* pColumn, uint32_t currentRow, const char* pData, bool isNull) {
- SUdfColumnMeta *meta = &pColumn->colMeta;
- SUdfColumnData *data = &pColumn->colData;
- udfColEnsureCapacity(pColumn, currentRow+1);
- bool isVarCol = IS_VAR_DATA_TYPE(meta->type);
- if (isNull) {
- udfColDataSetNull(pColumn, currentRow);
- } else {
- if (!isVarCol) {
- colDataSetNotNull_f(data->fixLenCol.nullBitmap, currentRow);
- memcpy(data->fixLenCol.data + meta->bytes * currentRow, pData, meta->bytes);
- } else {
- int32_t dataLen = varDataTLen(pData);
- if (meta->type == TSDB_DATA_TYPE_JSON) {
- if (*pData == TSDB_DATA_TYPE_NULL) {
- dataLen = 0;
- } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
- dataLen = varDataTLen(pData + CHAR_BYTES);
- } else if (*pData == TSDB_DATA_TYPE_BIGINT || *pData == TSDB_DATA_TYPE_DOUBLE) {
- dataLen = LONG_BYTES;
- } else if (*pData == TSDB_DATA_TYPE_BOOL) {
- dataLen = CHAR_BYTES;
- }
- dataLen += CHAR_BYTES;
- }
-
- if (data->varLenCol.payloadAllocLen < data->varLenCol.payloadLen + dataLen) {
- uint32_t newSize = data->varLenCol.payloadAllocLen;
- if (newSize <= 1) {
- newSize = 8;
- }
-
- while (newSize < data->varLenCol.payloadLen + dataLen) {
- newSize = newSize * UDF_MEMORY_EXP_GROWTH;
- }
-
- char *buf = taosMemoryRealloc(data->varLenCol.payload, newSize);
- if (buf == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- data->varLenCol.payload = buf;
- data->varLenCol.payloadAllocLen = newSize;
- }
-
- uint32_t len = data->varLenCol.payloadLen;
- data->varLenCol.varOffsets[currentRow] = len;
-
- memcpy(data->varLenCol.payload + len, pData, dataLen);
- data->varLenCol.payloadLen += dataLen;
- }
- }
- data->numOfRows = TMAX(currentRow + 1, data->numOfRows);
- return 0;
-}
-
-typedef int32_t (*TUdfScalarProcFunc)(SUdfDataBlock* block, SUdfColumn *resultCol);
-
-typedef int32_t (*TUdfAggStartFunc)(SUdfInterBuf *buf);
-typedef int32_t (*TUdfAggProcessFunc)(SUdfDataBlock* block, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf);
-typedef int32_t (*TUdfAggFinishFunc)(SUdfInterBuf* buf, SUdfInterBuf *resultData);
-
-
-// end API to UDF writer
-//=======================================================================================================================
#ifdef __cplusplus
}
diff --git a/include/libs/index/index.h b/include/libs/index/index.h
index 9e71c941d36b6646a34aed8a69be4cb08864934e..c6641f8b020a94b4a25eea612ef74978bb0b7e38 100644
--- a/include/libs/index/index.h
+++ b/include/libs/index/index.h
@@ -127,7 +127,7 @@ int indexSearch(SIndex* index, SIndexMultiTermQuery* query, SArray* result);
* @parma opt (input, rebuild index opts)
* @return error code
*/
-int indexRebuild(SIndex* index, SIndexOpts* opt);
+// int indexRebuild(SIndex* index, SIndexOpts* opt);
/*
* open index
@@ -185,6 +185,25 @@ SIndexTerm* indexTermCreate(int64_t suid, SIndexOperOnColumn operType, uint8_t c
int32_t nColName, const char* colVal, int32_t nColVal);
void indexTermDestroy(SIndexTerm* p);
+/*
+ * rebuild index
+ */
+void indexRebuild(SIndexJson* idx, void* iter);
+
+/*
+ * check index json status
+ **/
+bool indexIsRebuild(SIndex* idx);
+/*
+ * rebuild index json
+ */
+void indexJsonRebuild(SIndexJson* idx, void* iter);
+
+/*
+ * check index json status
+ **/
+bool indexJsonIsRebuild(SIndexJson* idx);
+
/*
* init index env
*
@@ -203,12 +222,12 @@ typedef enum { SFLT_NOT_INDEX, SFLT_COARSE_INDEX, SFLT_ACCURATE_INDEX } SIdxFltS
SIdxFltStatus idxGetFltStatus(SNode* pFilterNode);
-int32_t doFilterTag(const SNode* pFilterNode, SIndexMetaArg* metaArg, SArray* result);
+int32_t doFilterTag(SNode* pFilterNode, SIndexMetaArg* metaArg, SArray* result, SIdxFltStatus* status);
/*
* destory index env
*
*/
-void indexCleanUp();
+void indexCleanup();
#ifdef __cplusplus
}
diff --git a/include/libs/monitor/monitor.h b/include/libs/monitor/monitor.h
index 39e8042b931ecbee48fbe389ab1160c613636f28..41d80c1a83a1b01eae5bae71e150b33569706556 100644
--- a/include/libs/monitor/monitor.h
+++ b/include/libs/monitor/monitor.h
@@ -109,6 +109,9 @@ typedef struct {
char version[MON_VER_LEN];
float master_uptime; // day
int32_t monitor_interval; // sec
+ int32_t dbs_total;
+ int32_t stbs_total;
+ int64_t tbs_total;
int32_t vgroups_total;
int32_t vgroups_alive;
int32_t vnodes_total;
@@ -135,6 +138,15 @@ typedef struct {
SArray *vgroups; // array of SMonVgroupDesc
} SMonVgroupInfo;
+typedef struct {
+ char stb_name[TSDB_TABLE_NAME_LEN];
+ char database_name[TSDB_DB_NAME_LEN];
+} SMonStbDesc;
+
+typedef struct {
+ SArray *stbs; // array of SMonStbDesc
+} SMonStbInfo;
+
typedef struct {
int32_t expire_time;
int64_t timeseries_used;
@@ -144,6 +156,7 @@ typedef struct {
typedef struct {
SMonClusterInfo cluster;
SMonVgroupInfo vgroup;
+ SMonStbInfo stb;
SMonGrantInfo grant;
SMonSysInfo sys;
SMonLogs log;
diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h
index 4578087164be768067df842c341d861241a1d78d..53119156126e9e80399d2a96f9f650b651fa1f93 100644
--- a/include/libs/nodes/cmdnodes.h
+++ b/include/libs/nodes/cmdnodes.h
@@ -28,6 +28,18 @@ extern "C" {
#define DESCRIBE_RESULT_TYPE_LEN (20 + VARSTR_HEADER_SIZE)
#define DESCRIBE_RESULT_NOTE_LEN (8 + VARSTR_HEADER_SIZE)
+#define SHOW_CREATE_DB_RESULT_COLS 2
+#define SHOW_CREATE_DB_RESULT_FIELD1_LEN (TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE)
+#define SHOW_CREATE_DB_RESULT_FIELD2_LEN (TSDB_MAX_BINARY_LEN + VARSTR_HEADER_SIZE)
+
+#define SHOW_CREATE_TB_RESULT_COLS 2
+#define SHOW_CREATE_TB_RESULT_FIELD1_LEN (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE)
+#define SHOW_CREATE_TB_RESULT_FIELD2_LEN (TSDB_MAX_BINARY_LEN + VARSTR_HEADER_SIZE)
+
+#define SHOW_LOCAL_VARIABLES_RESULT_COLS 2
+#define SHOW_LOCAL_VARIABLES_RESULT_FIELD1_LEN (TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE)
+#define SHOW_LOCAL_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE)
+
#define PRIVILEGE_TYPE_MASK(n) (1 << n)
#define PRIVILEGE_TYPE_ALL PRIVILEGE_TYPE_MASK(0)
@@ -39,7 +51,8 @@ extern "C" {
typedef struct SDatabaseOptions {
ENodeType type;
int32_t buffer;
- int8_t cachelast;
+ int8_t cacheLast;
+ int32_t cacheLastSize;
int8_t compressionLevel;
int32_t daysPerFile;
SValueNode* pDaysPerFile;
@@ -85,6 +98,16 @@ typedef struct SAlterDatabaseStmt {
SDatabaseOptions* pOptions;
} SAlterDatabaseStmt;
+typedef struct SFlushDatabaseStmt {
+ ENodeType type;
+ char dbName[TSDB_DB_NAME_LEN];
+} SFlushDatabaseStmt;
+
+typedef struct STrimDatabaseStmt {
+ ENodeType type;
+ char dbName[TSDB_DB_NAME_LEN];
+} STrimDatabaseStmt;
+
typedef struct STableOptions {
ENodeType type;
bool commentNull;
@@ -170,13 +193,16 @@ typedef struct SCreateUserStmt {
ENodeType type;
char useName[TSDB_USER_LEN];
char password[TSDB_USET_PASSWORD_LEN];
+ int8_t sysinfo;
} SCreateUserStmt;
typedef struct SAlterUserStmt {
ENodeType type;
char useName[TSDB_USER_LEN];
- char password[TSDB_USET_PASSWORD_LEN];
int8_t alterType;
+ char password[TSDB_USET_PASSWORD_LEN];
+ int8_t enable;
+ int8_t sysinfo;
} SAlterUserStmt;
typedef struct SDropUserStmt {
@@ -218,10 +244,10 @@ typedef struct SShowCreateDatabaseStmt {
} SShowCreateDatabaseStmt;
typedef struct SShowCreateTableStmt {
- ENodeType type;
- char dbName[TSDB_DB_NAME_LEN];
- char tableName[TSDB_TABLE_NAME_LEN];
- STableMeta* pMeta;
+ ENodeType type;
+ char dbName[TSDB_DB_NAME_LEN];
+ char tableName[TSDB_TABLE_NAME_LEN];
+ void* pCfg; // STableCfg
} SShowCreateTableStmt;
typedef struct SShowTableDistributedStmt {
@@ -243,6 +269,7 @@ typedef struct SIndexOptions {
SNode* pInterval;
SNode* pOffset;
SNode* pSliding;
+ SNode* pStreamOptions;
} SIndexOptions;
typedef struct SCreateIndexStmt {
@@ -259,7 +286,6 @@ typedef struct SDropIndexStmt {
ENodeType type;
bool ignoreNotExists;
char indexName[TSDB_INDEX_NAME_LEN];
- char tableName[TSDB_TABLE_NAME_LEN];
} SDropIndexStmt;
typedef struct SCreateComponentNodeStmt {
@@ -278,6 +304,7 @@ typedef struct SCreateTopicStmt {
char subDbName[TSDB_DB_NAME_LEN];
char subSTbName[TSDB_TABLE_NAME_LEN];
bool ignoreExists;
+ bool withMeta;
SNode* pQuery;
} SCreateTopicStmt;
@@ -322,6 +349,7 @@ typedef struct SStreamOptions {
int8_t triggerType;
SNode* pDelay;
SNode* pWatermark;
+ bool ignoreExpired;
} SStreamOptions;
typedef struct SCreateStreamStmt {
diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h
index 58e2393970089e49b71f3ab616da9f5893e007de..c453ce98f8c4278ea81716f8d7ae31f1965a400f 100644
--- a/include/libs/nodes/nodes.h
+++ b/include/libs/nodes/nodes.h
@@ -22,8 +22,8 @@ extern "C" {
#include "tdef.h"
-#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
-#define setNodeType(nodeptr, type) (((SNode*)(nodeptr))->type = (type))
+#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
+#define setNodeType(nodeptr, nodetype) (((SNode*)(nodeptr))->type = (nodetype))
#define LIST_LENGTH(l) (NULL != (l) ? (l)->length : 0)
@@ -59,10 +59,10 @@ extern "C" {
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
-#define DESTORY_LIST(list) \
- do { \
- nodesDestroyList((list)); \
- (list) = NULL; \
+#define NODES_DESTORY_LIST(list) \
+ do { \
+ nodesDestroyList((list)); \
+ (list) = NULL; \
} while (0)
#define NODES_CLEAR_LIST(list) \
@@ -111,6 +111,8 @@ typedef enum ENodeType {
QUERY_NODE_CREATE_DATABASE_STMT,
QUERY_NODE_DROP_DATABASE_STMT,
QUERY_NODE_ALTER_DATABASE_STMT,
+ QUERY_NODE_FLUSH_DATABASE_STMT,
+ QUERY_NODE_TRIM_DATABASE_STMT,
QUERY_NODE_CREATE_TABLE_STMT,
QUERY_NODE_CREATE_SUBTABLE_CLAUSE,
QUERY_NODE_CREATE_MULTI_TABLE_STMT,
@@ -118,6 +120,7 @@ typedef enum ENodeType {
QUERY_NODE_DROP_TABLE_STMT,
QUERY_NODE_DROP_SUPER_TABLE_STMT,
QUERY_NODE_ALTER_TABLE_STMT,
+ QUERY_NODE_ALTER_SUPER_TABLE_STMT,
QUERY_NODE_CREATE_USER_STMT,
QUERY_NODE_ALTER_USER_STMT,
QUERY_NODE_DROP_USER_STMT,
@@ -188,10 +191,12 @@ typedef enum ENodeType {
QUERY_NODE_SHOW_CREATE_STABLE_STMT,
QUERY_NODE_SHOW_TRANSACTIONS_STMT,
QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT,
+ QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT,
QUERY_NODE_KILL_CONNECTION_STMT,
QUERY_NODE_KILL_QUERY_STMT,
QUERY_NODE_KILL_TRANSACTION_STMT,
QUERY_NODE_DELETE_STMT,
+ QUERY_NODE_INSERT_STMT,
QUERY_NODE_QUERY,
// logic plan node
@@ -219,14 +224,17 @@ typedef enum ENodeType {
QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN,
QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN,
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN,
+ QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN,
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN,
QUERY_NODE_PHYSICAL_PLAN_HASH_AGG,
QUERY_NODE_PHYSICAL_PLAN_EXCHANGE,
QUERY_NODE_PHYSICAL_PLAN_MERGE,
QUERY_NODE_PHYSICAL_PLAN_SORT,
+ QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT,
QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL,
QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL,
+ QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL,
QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL,
QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL,
@@ -242,6 +250,7 @@ typedef enum ENodeType {
QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC,
QUERY_NODE_PHYSICAL_PLAN_DISPATCH,
QUERY_NODE_PHYSICAL_PLAN_INSERT,
+ QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT,
QUERY_NODE_PHYSICAL_PLAN_DELETE,
QUERY_NODE_PHYSICAL_SUBPLAN,
QUERY_NODE_PHYSICAL_PLAN
@@ -281,6 +290,7 @@ int32_t nodesListPushFront(SNodeList* pList, SNode* pNode);
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc);
SNode* nodesListGetNode(SNodeList* pList, int32_t index);
+SListCell* nodesListGetCell(SNodeList* pList, int32_t index);
void nodesDestroyList(SNodeList* pList);
// Only clear the linked list structure, without releasing the elements inside
void nodesClearList(SNodeList* pList);
diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h
index b07e8f39d5bcae86ebd32208613f98c7e2bff497..6a865b4e2a01b6bab882caf1ea810786bc7aca44 100644
--- a/include/libs/nodes/plannodes.h
+++ b/include/libs/nodes/plannodes.h
@@ -24,6 +24,8 @@ extern "C" {
#include "querynodes.h"
#include "tname.h"
+#define SLOT_NAME_LEN TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN
+
typedef struct SLogicNode {
ENodeType type;
SNodeList* pTargets; // SColumnNode
@@ -32,6 +34,8 @@ typedef struct SLogicNode {
struct SLogicNode* pParent;
int32_t optimizedFlag;
uint8_t precision;
+ SNode* pLimit;
+ SNode* pSlimit;
} SLogicNode;
typedef enum EScanType {
@@ -40,7 +44,8 @@ typedef enum EScanType {
SCAN_TYPE_SYSTEM_TABLE,
SCAN_TYPE_STREAM,
SCAN_TYPE_TABLE_MERGE,
- SCAN_TYPE_BLOCK_INFO
+ SCAN_TYPE_BLOCK_INFO,
+ SCAN_TYPE_LAST_ROW
} EScanType;
typedef struct SScanLogicNode {
@@ -65,17 +70,19 @@ typedef struct SScanLogicNode {
int8_t intervalUnit;
int8_t slidingUnit;
SNode* pTagCond;
+ SNode* pTagIndexCond;
int8_t triggerType;
int64_t watermark;
- int16_t tsColId;
- double filesFactor;
+ int8_t igExpired;
SArray* pSmaIndexes;
- SNodeList* pPartTags;
+ SNodeList* pGroupTags;
+ bool groupSort;
} SScanLogicNode;
typedef struct SJoinLogicNode {
SLogicNode node;
EJoinType joinType;
+ SNode* pMergeCondition;
SNode* pOnConditions;
bool isSingleTableJoin;
} SJoinLogicNode;
@@ -84,21 +91,21 @@ typedef struct SAggLogicNode {
SLogicNode node;
SNodeList* pGroupKeys;
SNodeList* pAggFuncs;
+ bool hasLastRow;
} SAggLogicNode;
typedef struct SProjectLogicNode {
SLogicNode node;
SNodeList* pProjections;
char stmtName[TSDB_TABLE_NAME_LEN];
- int64_t limit;
- int64_t offset;
- int64_t slimit;
- int64_t soffset;
} SProjectLogicNode;
typedef struct SIndefRowsFuncLogicNode {
SLogicNode node;
SNodeList* pFuncs;
+ bool isTailFunc;
+ bool isUniqueFunc;
+ bool isTimeLineFunc;
} SIndefRowsFuncLogicNode;
typedef struct SInterpFuncLogicNode {
@@ -121,9 +128,12 @@ typedef struct SVnodeModifyLogicNode {
SVgDataBlocks* pVgDataBlocks;
SNode* pAffectedRows; // SColumnNode
uint64_t tableId;
+ uint64_t stableId;
int8_t tableType; // table type
char tableFName[TSDB_TABLE_FNAME_LEN];
STimeWindow deleteTimeRange;
+ SVgroupsInfo* pVgroupList;
+ SNodeList* pInsertCols;
} SVnodeModifyLogicNode;
typedef struct SExchangeLogicNode {
@@ -137,6 +147,7 @@ typedef struct SMergeLogicNode {
SNodeList* pInputs;
int32_t numOfChannels;
int32_t srcGroupId;
+ bool groupSort;
} SMergeLogicNode;
typedef enum EWindowType { WINDOW_TYPE_INTERVAL = 1, WINDOW_TYPE_SESSION, WINDOW_TYPE_STATE } EWindowType;
@@ -168,7 +179,7 @@ typedef struct SWindowLogicNode {
SNode* pStateExpr;
int8_t triggerType;
int64_t watermark;
- double filesFactor;
+ int8_t igExpired;
EWindowAlgorithm windowAlgo;
} SWindowLogicNode;
@@ -183,6 +194,7 @@ typedef struct SFillLogicNode {
typedef struct SSortLogicNode {
SLogicNode node;
SNodeList* pSortKeys;
+ bool groupSort;
} SSortLogicNode;
typedef struct SPartitionLogicNode {
@@ -229,6 +241,7 @@ typedef struct SSlotDescNode {
bool reserve;
bool output;
bool tag;
+ char name[SLOT_NAME_LEN];
} SSlotDescNode;
typedef struct SDataBlockDescNode {
@@ -246,6 +259,8 @@ typedef struct SPhysiNode {
SNode* pConditions;
SNodeList* pChildren;
struct SPhysiNode* pParent;
+ SNode* pLimit;
+ SNode* pSlimit;
} SPhysiNode;
typedef struct SScanPhysiNode {
@@ -260,6 +275,7 @@ typedef struct SScanPhysiNode {
typedef SScanPhysiNode STagScanPhysiNode;
typedef SScanPhysiNode SBlockDistScanPhysiNode;
+typedef SScanPhysiNode SLastRowScanPhysiNode;
typedef struct SSystemTableScanPhysiNode {
SScanPhysiNode scan;
@@ -275,7 +291,8 @@ typedef struct STableScanPhysiNode {
double ratio;
int32_t dataRequired;
SNodeList* pDynamicScanFuncs;
- SNodeList* pPartitionTags;
+ SNodeList* pGroupTags;
+ bool groupSort;
int64_t interval;
int64_t offset;
int64_t sliding;
@@ -283,8 +300,7 @@ typedef struct STableScanPhysiNode {
int8_t slidingUnit;
int8_t triggerType;
int64_t watermark;
- int16_t tsColId;
- double filesFactor;
+ int8_t igExpired;
} STableScanPhysiNode;
typedef STableScanPhysiNode STableSeqScanPhysiNode;
@@ -294,10 +310,6 @@ typedef STableScanPhysiNode SStreamScanPhysiNode;
typedef struct SProjectPhysiNode {
SPhysiNode node;
SNodeList* pProjections;
- int64_t limit;
- int64_t offset;
- int64_t slimit;
- int64_t soffset;
} SProjectPhysiNode;
typedef struct SIndefRowsFuncPhysiNode {
@@ -312,6 +324,7 @@ typedef struct SInterpFuncPhysiNode {
SNodeList* pFuncs;
STimeWindow timeRange;
int64_t interval;
+ int8_t intervalUnit;
EFillMode fillMode;
SNode* pFillValues; // SNodeListNode
SNode* pTimeSeries; // SColumnNode
@@ -320,6 +333,7 @@ typedef struct SInterpFuncPhysiNode {
typedef struct SJoinPhysiNode {
SPhysiNode node;
EJoinType joinType;
+ SNode* pMergeCondition;
SNode* pOnConditions;
SNodeList* pTargets;
} SJoinPhysiNode;
@@ -338,6 +352,8 @@ typedef struct SDownstreamSourceNode {
SQueryNodeAddr addr;
uint64_t taskId;
uint64_t schedId;
+ int32_t execId;
+ int32_t fetchMsgType;
} SDownstreamSourceNode;
typedef struct SExchangePhysiNode {
@@ -353,6 +369,7 @@ typedef struct SMergePhysiNode {
SNodeList* pTargets;
int32_t numOfChannels;
int32_t srcGroupId;
+ bool groupSort;
} SMergePhysiNode;
typedef struct SWinodwPhysiNode {
@@ -363,7 +380,7 @@ typedef struct SWinodwPhysiNode {
SNode* pTsEnd; // window end timestamp
int8_t triggerType;
int64_t watermark;
- double filesFactor;
+ int8_t igExpired;
} SWinodwPhysiNode;
typedef struct SIntervalPhysiNode {
@@ -376,6 +393,7 @@ typedef struct SIntervalPhysiNode {
} SIntervalPhysiNode;
typedef SIntervalPhysiNode SMergeIntervalPhysiNode;
+typedef SIntervalPhysiNode SMergeAlignedIntervalPhysiNode;
typedef SIntervalPhysiNode SStreamIntervalPhysiNode;
typedef SIntervalPhysiNode SStreamFinalIntervalPhysiNode;
typedef SIntervalPhysiNode SStreamSemiIntervalPhysiNode;
@@ -417,6 +435,8 @@ typedef struct SSortPhysiNode {
SNodeList* pTargets;
} SSortPhysiNode;
+typedef SSortPhysiNode SGroupSortPhysiNode;
+
typedef struct SPartitionPhysiNode {
SPhysiNode node;
SNodeList* pExprs; // these are expression list of partition_by_clause
@@ -440,6 +460,17 @@ typedef struct SDataInserterNode {
char* pData;
} SDataInserterNode;
+typedef struct SQueryInserterNode {
+ SDataSinkNode sink;
+ SNodeList* pCols;
+ uint64_t tableId;
+ uint64_t stableId;
+ int8_t tableType; // table type
+ char tableFName[TSDB_TABLE_FNAME_LEN];
+ int32_t vgId;
+ SEpSet epSet;
+} SQueryInserterNode;
+
typedef struct SDataDeleterNode {
SDataSinkNode sink;
uint64_t tableId;
@@ -456,6 +487,7 @@ typedef struct SSubplan {
int32_t msgType; // message type for subplan, used to denote the send message type to vnode.
int32_t level; // the execution level of current subplan, starting from 0 in a top-down manner.
char dbFName[TSDB_DB_FNAME_LEN];
+ char user[TSDB_USER_LEN];
SQueryNodeAddr execNode; // for the scan/modify subplan, the optional execution node
SQueryNodeStat execNodeStat; // only for scan subplan
SNodeList* pChildren; // the datasource subplan,from which to fetch the result
@@ -463,6 +495,7 @@ typedef struct SSubplan {
SPhysiNode* pNode; // physical plan of current subplan
SDataSinkNode* pDataSink; // data of the subplan flow into the datasink
SNode* pTagCond;
+ SNode* pTagIndexCond;
} SSubplan;
typedef enum EExplainMode { EXPLAIN_MODE_DISABLE = 1, EXPLAIN_MODE_STATIC, EXPLAIN_MODE_ANALYZE } EExplainMode;
diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h
index 73e487f073ac44d5ddeee0086da203f329b3238d..234b554526ea198aa78aece70a28988b61de8c1c 100644
--- a/include/libs/nodes/querynodes.h
+++ b/include/libs/nodes/querynodes.h
@@ -50,9 +50,10 @@ typedef struct SExprNode {
char aliasName[TSDB_COL_NAME_LEN];
char userAlias[TSDB_COL_NAME_LEN];
SArray* pAssociation;
+ bool orderAlias;
} SExprNode;
-typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG } EColumnType;
+typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG, COLUMN_TYPE_TBNAME } EColumnType;
typedef struct SColumnNode {
SExprNode node; // QUERY_NODE_COLUMN
@@ -88,6 +89,7 @@ typedef struct SValueNode {
bool isDuration;
bool translate;
bool notReserved;
+ bool isNull;
int16_t placeholderNo;
union {
bool b;
@@ -226,7 +228,7 @@ typedef struct SFillNode {
ENodeType type; // QUERY_NODE_FILL
EFillMode mode;
SNode* pValues; // SNodeListNode
- SNode* pWStartTs; // _wstartts pseudo column
+ SNode* pWStartTs; // _wstart pseudo column
STimeWindow timeRange;
} SFillNode;
@@ -246,18 +248,24 @@ typedef struct SSelectStmt {
SNodeList* pOrderByList; // SOrderByExprNode
SLimitNode* pLimit;
SLimitNode* pSlimit;
+ STimeWindow timeRange;
char stmtName[TSDB_TABLE_NAME_LEN];
uint8_t precision;
+ int32_t selectFuncNum;
bool isEmptyResult;
- bool isTimeOrderQuery;
+ bool isTimeLineResult;
bool hasAggFuncs;
bool hasRepeatScanFuncs;
bool hasIndefiniteRowsFunc;
bool hasSelectFunc;
bool hasSelectValFunc;
+ bool hasOtherVectorFunc;
bool hasUniqueFunc;
bool hasTailFunc;
bool hasInterpFunc;
+ bool hasLastRowFunc;
+ bool hasTimeLineFunc;
+ bool groupSort;
} SSelectStmt;
typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType;
@@ -287,16 +295,24 @@ typedef enum ESqlClause {
} ESqlClause;
typedef struct SDeleteStmt {
- ENodeType type; // QUERY_NODE_DELETE_STMT
- SNode* pFromTable; // FROM clause
- SNode* pWhere; // WHERE clause
- SNode* pCountFunc; // count the number of rows affected
- SNode* pTagIndexCond; // pWhere divided into pTagIndexCond and timeRange
+ ENodeType type; // QUERY_NODE_DELETE_STMT
+ SNode* pFromTable; // FROM clause
+ SNode* pWhere; // WHERE clause
+ SNode* pCountFunc; // count the number of rows affected
+ SNode* pTagCond; // pWhere divided into pTagCond and timeRange
STimeWindow timeRange;
uint8_t precision;
bool deleteZeroRows;
} SDeleteStmt;
+typedef struct SInsertStmt {
+ ENodeType type; // QUERY_NODE_INSERT_STMT
+ SNode* pTable;
+ SNodeList* pCols;
+ SNode* pQuery;
+ uint8_t precision;
+} SInsertStmt;
+
typedef enum {
PAYLOAD_TYPE_KV = 0,
PAYLOAD_TYPE_RAW = 1,
@@ -371,6 +387,7 @@ void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewrit
typedef enum ECollectColType { COLLECT_COL_TYPE_COL = 1, COLLECT_COL_TYPE_TAG, COLLECT_COL_TYPE_ALL } ECollectColType;
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, ECollectColType type,
SNodeList** pCols);
+int32_t nodesCollectColumnsFromNode(SNode* node, const char* pTableAlias, ECollectColType type, SNodeList** pCols);
typedef bool (*FFuncClassifier)(int32_t funcId);
int32_t nodesCollectFuncs(SSelectStmt* pSelect, ESqlClause clause, FFuncClassifier classifier, SNodeList** pFuncs);
@@ -384,6 +401,7 @@ bool nodesIsArithmeticOp(const SOperatorNode* pOp);
bool nodesIsComparisonOp(const SOperatorNode* pOp);
bool nodesIsJsonOp(const SOperatorNode* pOp);
bool nodesIsRegularOp(const SOperatorNode* pOp);
+bool nodesIsBitwiseOp(const SOperatorNode* pOp);
bool nodesExprHasColumn(SNode* pNode);
bool nodesExprsHasColumn(SNodeList* pList);
@@ -395,7 +413,8 @@ 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** pTagCond, SNode** pOtherCond);
+int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
+ SNode** pOtherCond);
#ifdef __cplusplus
}
diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h
index e45e5bd1608861a82520569df36587bacb8dfc4c..a3de9164a2d4418dd1edc8493d46c20f2fafdcac 100644
--- a/include/libs/parser/parser.h
+++ b/include/libs/parser/parser.h
@@ -29,7 +29,7 @@ struct SMetaData;
typedef struct SStmtCallback {
TAOS_STMT* pStmt;
int32_t (*getTbNameFn)(TAOS_STMT*, char**);
- int32_t (*setInfoFn)(TAOS_STMT*, STableMeta*, void*, char*, bool, SHashObj*, SHashObj*);
+ int32_t (*setInfoFn)(TAOS_STMT*, STableMeta*, void*, char*, bool, SHashObj*, SHashObj*, const char*);
int32_t (*getExecInfoFn)(TAOS_STMT*, SHashObj**, SHashObj**);
} SStmtCallback;
@@ -51,10 +51,12 @@ typedef struct SParseContext {
bool isSuperUser;
bool async;
int8_t schemalessType;
+ const char* svrVer;
+ bool nodeOffline;
} SParseContext;
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery);
-bool qIsInsertSql(const char* pStr, size_t length);
+bool qIsInsertValuesSql(const char* pStr, size_t length);
// for async mode
int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq);
@@ -82,7 +84,7 @@ int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBu
int32_t rowNum);
int32_t qBuildStmtColFields(void* pDataBlock, int32_t* fieldNum, TAOS_FIELD_E** fields);
int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD_E** fields);
-int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tName, TAOS_MULTI_BIND* bind,
+int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName, TAOS_MULTI_BIND* bind,
char* msgBuf, int32_t msgBufLen);
void destroyBoundColumnInfo(void* pBoundInfo);
int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* dbName, char* msgBuf,
@@ -91,9 +93,12 @@ int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char*
void* smlInitHandle(SQuery* pQuery);
void smlDestroyHandle(void* pHandle);
int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols, bool format, STableMeta* pTableMeta,
- char* tableName, char* msgBuf, int16_t msgBufLen);
+ char* tableName, const char* sTableName, int32_t sTableNameLen, char* msgBuf, int16_t msgBufLen);
int32_t smlBuildOutput(void* handle, SHashObj* pVgHash);
+int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray);
+SArray* serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap);
+SArray* serializeVgroupsDropTableBatch(SHashObj* pVgroupHashmap);
#ifdef __cplusplus
}
#endif
diff --git a/include/libs/planner/planner.h b/include/libs/planner/planner.h
index c4f71e57a8174c62cf331e4afec35604786282a0..d1a5c5db103d940c9e36dd9ad637461b2e3361b5 100644
--- a/include/libs/planner/planner.h
+++ b/include/libs/planner/planner.h
@@ -24,18 +24,20 @@ extern "C" {
#include "taos.h"
typedef struct SPlanContext {
- uint64_t queryId;
- int32_t acctId;
- SEpSet mgmtEpSet;
- SNode* pAstRoot;
- bool topicQuery;
- bool streamQuery;
- bool rSmaQuery;
- bool showRewrite;
- int8_t triggerType;
- int64_t watermark;
- char* pMsg;
- int32_t msgLen;
+ uint64_t queryId;
+ int32_t acctId;
+ SEpSet mgmtEpSet;
+ SNode* pAstRoot;
+ bool topicQuery;
+ bool streamQuery;
+ bool rSmaQuery;
+ bool showRewrite;
+ int8_t triggerType;
+ int64_t watermark;
+ int8_t igExpired;
+ char* pMsg;
+ int32_t msgLen;
+ const char* pUser;
} SPlanContext;
// Create the physical plan for the query, according to the AST.
@@ -47,6 +49,8 @@ int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNo
// @pSource one execution location of this group of datasource subplans
int32_t qSetSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId, SDownstreamSourceNode* pSource);
+void qClearSubplanExecutionNode(SSubplan* pSubplan);
+
// Convert to subplan to string for the scheduler to send to the executor
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen);
int32_t qStringToSubplan(const char* pStr, SSubplan** pSubplan);
diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h
index d562d07d776052d9e6a797da9adfe507e05ccfd3..a93cf1f9b81faec1d0bdb60361a4de3b44749371 100644
--- a/include/libs/qcom/query.h
+++ b/include/libs/qcom/query.h
@@ -16,6 +16,7 @@
#ifndef _TD_QUERY_H_
#define _TD_QUERY_H_
+// clang-foramt off
#ifdef __cplusplus
extern "C" {
#endif
@@ -28,12 +29,13 @@ extern "C" {
typedef enum {
JOB_TASK_STATUS_NULL = 0,
- JOB_TASK_STATUS_NOT_START = 1,
- JOB_TASK_STATUS_EXECUTING,
- JOB_TASK_STATUS_PARTIAL_SUCCEED,
- JOB_TASK_STATUS_SUCCEED,
- JOB_TASK_STATUS_FAILED,
- JOB_TASK_STATUS_DROPPING,
+ JOB_TASK_STATUS_INIT,
+ JOB_TASK_STATUS_EXEC,
+ JOB_TASK_STATUS_PART_SUCC,
+ JOB_TASK_STATUS_SUCC,
+ JOB_TASK_STATUS_FAIL,
+ JOB_TASK_STATUS_DROP,
+ JOB_TASK_STATUS_MAX,
} EJobTaskType;
typedef enum {
@@ -58,20 +60,23 @@ typedef struct STableComInfo {
int32_t rowSize; // row size of the schema
} STableComInfo;
-typedef struct SQueryExecRes {
- int32_t msgType;
- void* res;
-} SQueryExecRes;
typedef struct SIndexMeta {
-#ifdef WINDOWS
+#if defined(WINDOWS) || defined(_TD_DARWIN_64)
size_t avoidCompilationErrors;
#endif
} SIndexMeta;
+typedef struct SExecResult {
+ int32_t code;
+ uint64_t numOfRows;
+ int32_t msgType;
+ void* res;
+} SExecResult;
+
typedef struct STbVerInfo {
- char tbFName[TSDB_TABLE_FNAME_LEN];
+ char tbFName[TSDB_TABLE_FNAME_LEN];
int32_t sversion;
int32_t tversion;
} STbVerInfo;
@@ -134,30 +139,32 @@ typedef struct STableMetaOutput {
} STableMetaOutput;
typedef struct SDataBuf {
+ int32_t msgType;
void* pData;
uint32_t len;
void* handle;
+ SEpSet* pEpSet;
} SDataBuf;
typedef struct STargetInfo {
ETargetType type;
- char* dbFName; // used to update db's vgroup epset
+ char* dbFName; // used to update db's vgroup epset
int32_t vgId;
} STargetInfo;
-typedef int32_t (*__async_send_cb_fn_t)(void* param, const SDataBuf* pMsg, int32_t code);
+typedef int32_t (*__async_send_cb_fn_t)(void* param, SDataBuf* pMsg, int32_t code);
typedef int32_t (*__async_exec_fn_t)(void* param);
typedef struct SRequestConnInfo {
- void* pTrans;
- uint64_t requestId;
- int64_t requestObjRefId;
- SEpSet mgmtEps;
+ void* pTrans;
+ uint64_t requestId;
+ int64_t requestObjRefId;
+ SEpSet mgmtEps;
} SRequestConnInfo;
typedef struct SMsgSendInfo {
- __async_send_cb_fn_t fp; // async callback function
- STargetInfo target; // for update epset
+ __async_send_cb_fn_t fp; // async callback function
+ STargetInfo target; // for update epset
void* param;
uint64_t requestId;
uint64_t requestObjRefId;
@@ -206,9 +213,15 @@ int32_t queryCreateTableMetaFromMsg(STableMetaRsp* msg, bool isSuperTable, STabl
char* jobTaskStatusStr(int32_t status);
SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* name);
-void destroyQueryExecRes(SQueryExecRes* pRes);
-extern int32_t (*queryBuildMsg[TDMT_MAX])(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallocFp)(int32_t));
+void destroyQueryExecRes(SExecResult* pRes);
+int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t* len);
+char* parseTagDatatoJson(void* p);
+int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst);
+int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst);
+
+extern int32_t (*queryBuildMsg[TDMT_MAX])(void* input, char** msg, int32_t msgSize, int32_t* msgLen,
+ void* (*mallocFp)(int32_t));
extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t msgSize);
#define SET_META_TYPE_NULL(t) (t) = META_TYPE_NULL_TABLE
@@ -219,7 +232,7 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
#define NEED_CLIENT_RM_TBLMETA_ERROR(_code) \
((_code) == TSDB_CODE_PAR_TABLE_NOT_EXIST || (_code) == TSDB_CODE_VND_TB_NOT_EXIST || \
(_code) == TSDB_CODE_PAR_INVALID_COLUMNS_NUM || (_code) == TSDB_CODE_PAR_INVALID_COLUMN || \
- (_code) == TSDB_CODE_PAR_TAGS_NOT_MATCHED || (_code) == TSDB_CODE_PAR_VALUE_TOO_LONG || \
+ (_code) == TSDB_CODE_PAR_TAGS_NOT_MATCHED || (_code) == TSDB_CODE_PAR_VALUE_TOO_LONG || \
(_code) == TSDB_CODE_PAR_INVALID_DROP_COL || ((_code) == TSDB_CODE_TDB_INVALID_TABLE_ID))
#define NEED_CLIENT_REFRESH_VG_ERROR(_code) \
((_code) == TSDB_CODE_VND_HASH_MISMATCH || (_code) == TSDB_CODE_VND_INVALID_VGROUP_ID)
@@ -227,11 +240,18 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
#define NEED_CLIENT_HANDLE_ERROR(_code) \
(NEED_CLIENT_RM_TBLMETA_ERROR(_code) || NEED_CLIENT_REFRESH_VG_ERROR(_code) || \
NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code))
-#define NEED_CLIENT_RM_TBLMETA_REQ(_type) ((_type) == TDMT_VND_CREATE_TABLE || (_type) == TDMT_VND_CREATE_STB \
- || (_type) == TDMT_VND_DROP_TABLE || (_type) == TDMT_VND_DROP_STB)
-
-#define NEED_SCHEDULER_RETRY_ERROR(_code) \
- ((_code) == TSDB_CODE_RPC_REDIRECT || (_code) == TSDB_CODE_RPC_NETWORK_UNAVAIL || (_code) == TSDB_CODE_SCH_TIMEOUT_ERROR)
+#define NEED_REDIRECT_ERROR(_code) \
+ ((_code) == TSDB_CODE_RPC_REDIRECT || (_code) == TSDB_CODE_RPC_NETWORK_UNAVAIL || \
+ (_code) == TSDB_CODE_NODE_NOT_DEPLOYED || (_code) == TSDB_CODE_SYN_NOT_LEADER || \
+ (_code) == TSDB_CODE_APP_NOT_READY || (_code) == TSDB_CODE_RPC_BROKEN_LINK)
+
+#define NEED_CLIENT_RM_TBLMETA_REQ(_type) \
+ ((_type) == TDMT_VND_CREATE_TABLE || (_type) == TDMT_VND_CREATE_STB || (_type) == TDMT_VND_DROP_TABLE || \
+ (_type) == TDMT_VND_DROP_STB)
+
+#define NEED_SCHEDULER_REDIRECT_ERROR(_code) \
+ ((_code) == TSDB_CODE_RPC_REDIRECT || (_code) == TSDB_CODE_NODE_NOT_DEPLOYED || \
+ (_code) == TSDB_CODE_SYN_NOT_LEADER || (_code) == TSDB_CODE_APP_NOT_READY)
#define REQUEST_TOTAL_EXEC_TIMES 2
@@ -308,3 +328,4 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
#endif
#endif /*_TD_QUERY_H_*/
+ // clang-foramt on
diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h
index 3b8a37f4208386eb06ff4f3153fab271e3ddb011..87aefe5187ec7ca61a4de5f6f14adbbf26861dfc 100644
--- a/include/libs/qworker/qworker.h
+++ b/include/libs/qworker/qworker.h
@@ -20,9 +20,9 @@
extern "C" {
#endif
+#include "executor.h"
#include "tmsgcb.h"
#include "trpc.h"
-#include "executor.h"
enum {
NODE_TYPE_VNODE = 1,
@@ -31,13 +31,6 @@ enum {
NODE_TYPE_MNODE,
};
-typedef struct SDeleteRes {
- uint64_t uid;
- SArray* uidList;
- int64_t skey;
- int64_t ekey;
-} SDeleteRes;
-
typedef struct SQWorkerCfg {
uint32_t maxSchedulerNum;
uint32_t maxTaskNum;
@@ -46,19 +39,19 @@ typedef struct SQWorkerCfg {
typedef struct {
uint64_t cacheDataSize;
-
+
uint64_t queryProcessed;
uint64_t cqueryProcessed;
uint64_t fetchProcessed;
uint64_t dropProcessed;
uint64_t hbProcessed;
uint64_t deleteProcessed;
-
+
uint64_t numOfQueryInQueue;
uint64_t numOfFetchInQueue;
uint64_t timeInQueryQueue;
uint64_t timeInFetchQueue;
-
+
uint64_t numOfErrors;
} SQWorkerStat;
@@ -74,7 +67,7 @@ int32_t qWorkerProcessCQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, in
int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts);
-int32_t qWorkerProcessFetchRsp(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts);
+int32_t qWorkerProcessRspMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts);
int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts);
@@ -82,7 +75,7 @@ int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int6
int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts);
-int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SRpcMsg *pRsp, SDeleteRes *pRes);
+int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SDeleteRes *pRes);
void qWorkerDestroy(void **qWorkerMgmt);
diff --git a/include/libs/scalar/scalar.h b/include/libs/scalar/scalar.h
index 555274599a1028c0a9dd875f9bd16cd438cc5f54..517c5ff0e6c25e403306fd3e4cce875dcc8adc71 100644
--- a/include/libs/scalar/scalar.h
+++ b/include/libs/scalar/scalar.h
@@ -25,11 +25,14 @@ extern "C" {
typedef struct SFilterInfo SFilterInfo;
+int32_t scalarGetOperatorResultType(SOperatorNode* pOp);
+
/*
pNode will be freed in API;
*pRes need to freed in caller
*/
int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes);
+int32_t scalarCalculateConstantsFromDual(SNode *pNode, SNode **pRes);
/*
pDst need to freed in caller
@@ -40,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 vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut, int32_t* overflow);
/* Math functions */
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h
index ecb21335b9cf9edb566c1861042fcaffd6da13c4..70ac7a630460a2917f11b93984e4c1434567e6ef 100644
--- a/include/libs/scheduler/scheduler.h
+++ b/include/libs/scheduler/scheduler.h
@@ -53,12 +53,6 @@ typedef struct SQueryProfileSummary {
uint64_t resultSize; // generated result size in Kb.
} SQueryProfileSummary;
-typedef struct SQueryResult {
- int32_t code;
- uint64_t numOfRows;
- SQueryExecRes res;
-} SQueryResult;
-
typedef struct STaskInfo {
SQueryNodeAddr addr;
SSubQueryMsg *msg;
@@ -69,48 +63,34 @@ typedef struct SSchdFetchParam {
int32_t* code;
} SSchdFetchParam;
-typedef void (*schedulerExecCallback)(SQueryResult* pResult, void* param, int32_t code);
-typedef void (*schedulerFetchCallback)(void* pResult, void* param, int32_t code);
+typedef void (*schedulerExecFp)(SExecResult* pResult, void* param, int32_t code);
+typedef void (*schedulerFetchFp)(void* pResult, void* param, int32_t code);
+typedef bool (*schedulerChkKillFp)(void* param);
typedef struct SSchedulerReq {
- bool *reqKilled;
+ bool syncReq;
SRequestConnInfo *pConn;
SArray *pNodeList;
SQueryPlan *pDag;
const char *sql;
int64_t startTs;
- schedulerExecCallback fp;
+ schedulerExecFp execFp;
+ schedulerFetchFp fetchFp;
void* cbParam;
+ schedulerChkKillFp chkKillFp;
+ void* chkKillParam;
+ SExecResult* pExecRes;
+ void** pFetchRes;
} SSchedulerReq;
int32_t schedulerInit(SSchedulerCfg *cfg);
-/**
- * Process the query job, generated according to the query physical plan.
- * This is a synchronized API, and is also thread-safety.
- * @param nodeList Qnode/Vnode address list, element is SQueryNodeAddr
- * @return
- */
-int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes);
-
-/**
- * Process the query job, generated according to the query physical plan.
- * This is a asynchronized API, and is also thread-safety.
- * @param pNodeList Qnode/Vnode address list, element is SQueryNodeAddr
- * @return
- */
- int32_t schedulerAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob);
+int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob);
-/**
- * Fetch query result from the remote query executor
- * @param pJob
- * @param data
- * @return
- */
-int32_t schedulerFetchRows(int64_t job, void **data);
+int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq *pReq);
-void schedulerAsyncFetchRows(int64_t job, schedulerFetchCallback fp, void* param);
+void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param);
int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub);
@@ -128,11 +108,11 @@ void schedulerStopQueryHb(void *pTrans);
* Free the query job
* @param pJob
*/
-void schedulerFreeJob(int64_t job, int32_t errCode);
+void schedulerFreeJob(int64_t* job, int32_t errCode);
void schedulerDestroy(void);
-void schdExecCallback(SQueryResult* pResult, void* param, int32_t code);
+void schdExecCallback(SExecResult* pResult, void* param, int32_t code);
#ifdef __cplusplus
}
diff --git a/include/libs/stream/tstream.h b/include/libs/stream/tstream.h
index 937ac2b408ed0e720d24ae648f920352c7eb5712..071c539ff32c3a47b996c0b3a15a168fe0e87490 100644
--- a/include/libs/stream/tstream.h
+++ b/include/libs/stream/tstream.h
@@ -13,7 +13,9 @@
* along with this program. If not, see .
*/
+#include "executor.h"
#include "os.h"
+#include "query.h"
#include "tdatablock.h"
#include "tmsg.h"
#include "tmsgcb.h"
@@ -30,9 +32,14 @@ extern "C" {
typedef struct SStreamTask SStreamTask;
enum {
- TASK_STATUS__IDLE = 1,
- TASK_STATUS__EXECUTING,
- TASK_STATUS__CLOSING,
+ TASK_STATUS__NORMAL = 0,
+ TASK_STATUS__DROPPING,
+};
+
+enum {
+ TASK_EXEC_STATUS__IDLE = 1,
+ TASK_EXEC_STATUS__EXECUTING,
+ TASK_EXEC_STATUS__CLOSING,
};
enum {
@@ -50,18 +57,6 @@ enum {
TASK_OUTPUT_STATUS__BLOCKED,
};
-enum {
- STREAM_CREATED_BY__USER = 1,
- STREAM_CREATED_BY__SMA,
-};
-
-enum {
- STREAM_INPUT__DATA_SUBMIT = 1,
- STREAM_INPUT__DATA_BLOCK,
- STREAM_INPUT__TRIGGER,
- STREAM_INPUT__CHECKPOINT,
-};
-
typedef struct {
int8_t type;
} SStreamQueueItem;
@@ -76,7 +71,7 @@ typedef struct {
typedef struct {
int8_t type;
- int32_t sourceVg;
+ int32_t srcVgId;
int64_t sourceVer;
SArray* blocks; // SArray
@@ -144,21 +139,12 @@ void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit);
SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit);
-#if 0
-int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput);
-void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput);
-#endif
-
typedef struct {
char* qmsg;
// followings are not applicable to encoder and decoder
void* executor;
} STaskExec;
-typedef struct {
- int32_t taskId;
-} STaskDispatcherInplace;
-
typedef struct {
int32_t taskId;
int32_t nodeId;
@@ -211,7 +197,6 @@ enum {
enum {
TASK_DISPATCH__NONE = 1,
- TASK_DISPATCH__INPLACE,
TASK_DISPATCH__FIXED,
TASK_DISPATCH__SHUFFLE,
};
@@ -233,28 +218,37 @@ enum {
TASK_TRIGGER_STATUS__ACTIVE,
};
-struct SStreamTask {
- int64_t streamId;
+typedef struct {
+ int32_t nodeId;
+ int32_t childId;
int32_t taskId;
- int8_t inputType;
- int8_t status;
+ SEpSet epSet;
+} SStreamChildEpInfo;
+typedef struct SStreamTask {
+ int64_t streamId;
+ int32_t taskId;
+ int8_t isDataScan;
int8_t execType;
int8_t sinkType;
int8_t dispatchType;
int16_t dispatchMsgType;
- int8_t dataScan;
+ int8_t taskStatus;
+ int8_t execStatus;
// node info
- int32_t childId;
+ int32_t selfChildId;
int32_t nodeId;
SEpSet epSet;
+ // children info
+ SArray* childEpInfo; // SArray
+
// exec
STaskExec exec;
- // TODO: merge sink and dispatch
+ // TODO: unify sink and dispatch
// local sink
union {
@@ -263,9 +257,8 @@ struct SStreamTask {
STaskSinkFetch fetchSink;
};
- // dispatch
+ // remote dispatcher
union {
- STaskDispatcherInplace inplaceDispatcher;
STaskDispatcherFixedEp fixedEpDispatcher;
STaskDispatcherShuffle shuffleDispatcher;
};
@@ -286,7 +279,10 @@ struct SStreamTask {
// msg handle
SMsgCb* pMsgCb;
-};
+} SStreamTask;
+
+int32_t tEncodeStreamEpInfo(SEncoder* pEncoder, const SStreamChildEpInfo* pInfo);
+int32_t tDecodeStreamEpInfo(SDecoder* pDecoder, SStreamChildEpInfo* pInfo);
SStreamTask* tNewSStreamTask(int64_t streamId);
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask);
@@ -294,6 +290,7 @@ 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);
@@ -302,6 +299,7 @@ static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem
}
ASSERT(0);
}
+#endif
if (pItem->type == STREAM_INPUT__DATA_SUBMIT) {
SStreamDataSubmit* pSubmitClone = streamSubmitRefClone((SStreamDataSubmit*)pItem);
@@ -309,22 +307,28 @@ static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
return -1;
}
+ qDebug("task %d %p submit enqueue %p %p %p", pTask->taskId, pTask, pItem, pSubmitClone, pSubmitClone->data);
taosWriteQitem(pTask->inputQueue->queue, pSubmitClone);
- } else if (pItem->type == STREAM_INPUT__DATA_BLOCK) {
+ // qStreamInput(pTask->exec.executor, pSubmitClone);
+ } else if (pItem->type == STREAM_INPUT__DATA_BLOCK || pItem->type == STREAM_INPUT__DATA_RETRIEVE) {
taosWriteQitem(pTask->inputQueue->queue, pItem);
+ // qStreamInput(pTask->exec.executor, pItem);
} else if (pItem->type == STREAM_INPUT__CHECKPOINT) {
taosWriteQitem(pTask->inputQueue->queue, pItem);
+ // qStreamInput(pTask->exec.executor, pItem);
} else if (pItem->type == STREAM_INPUT__TRIGGER) {
taosWriteQitem(pTask->inputQueue->queue, pItem);
+ // qStreamInput(pTask->exec.executor, pItem);
}
- if (pItem->type != STREAM_INPUT__TRIGGER && pItem->type != STREAM_INPUT__CHECKPOINT && pTask->triggerParam != 0 &&
- pTask->triggerStatus == TASK_TRIGGER_STATUS__IN_ACTIVE) {
- atomic_store_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__ACTIVE);
+ if (pItem->type != STREAM_INPUT__TRIGGER && pItem->type != STREAM_INPUT__CHECKPOINT && pTask->triggerParam != 0) {
+ atomic_val_compare_exchange_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__IN_ACTIVE, TASK_TRIGGER_STATUS__ACTIVE);
}
+#if 0
// TODO: back pressure
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL);
+#endif
return 0;
}
@@ -336,10 +340,12 @@ static FORCE_INLINE int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBloc
if (pTask->sinkType == TASK_SINK__TABLE) {
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
pTask->tbSink.tbSinkFunc(pTask, pTask->tbSink.vnode, 0, pBlock->blocks);
+ taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes);
taosFreeQitem(pBlock);
} else if (pTask->sinkType == TASK_SINK__SMA) {
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
pTask->smaSink.smaSink(pTask->smaSink.vnode, pTask->smaSink.smaId, pBlock->blocks);
+ taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes);
taosFreeQitem(pBlock);
} else {
ASSERT(pTask->dispatchType != TASK_DISPATCH__NONE);
@@ -366,9 +372,9 @@ typedef struct {
typedef struct {
int64_t streamId;
int32_t taskId;
- int32_t sourceTaskId;
- int32_t sourceVg;
- int32_t sourceChildId;
+ int32_t dataSrcVgId;
+ int32_t upstreamTaskId;
+ int32_t upstreamChildId;
int32_t upstreamNodeId;
#if 0
int64_t sourceVer;
@@ -384,6 +390,23 @@ typedef struct {
int8_t inputStatus;
} SStreamDispatchRsp;
+typedef struct {
+ int64_t streamId;
+ int32_t srcTaskId;
+ int32_t srcNodeId;
+ int32_t dstTaskId;
+ int32_t dstNodeId;
+ int32_t retrieveLen;
+ SRetrieveTableRsp* pRetrieve;
+} SStreamRetrieveReq;
+
+typedef struct {
+ int64_t streamId;
+ int32_t childId;
+ int32_t rspFromTaskId;
+ int32_t rspToTaskId;
+} SStreamRetrieveRsp;
+
typedef struct {
int64_t streamId;
int32_t taskId;
@@ -398,6 +421,7 @@ typedef struct {
} SStreamTaskRecoverRsp;
int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq);
+int32_t tDecodeStreamRetrieveReq(SDecoder* pDecoder, SStreamRetrieveReq* pReq);
int32_t streamLaunchByWrite(SStreamTask* pTask, int32_t vgId);
int32_t streamSetupTrigger(SStreamTask* pTask);
@@ -408,6 +432,9 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp);
int32_t streamProcessRecoverReq(SStreamTask* pTask, SStreamTaskRecoverReq* pReq, SRpcMsg* pMsg);
int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp);
+int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pMsg);
+int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/libs/stream/tstreamUpdate.h b/include/libs/stream/tstreamUpdate.h
index 398851a09f139fe009cabfd3939d1ebc4416d0c5..21a1515d8f79dfe17eee61420e07843d896b57eb 100644
--- a/include/libs/stream/tstreamUpdate.h
+++ b/include/libs/stream/tstreamUpdate.h
@@ -32,12 +32,15 @@ typedef struct SUpdateInfo {
int64_t interval;
int64_t watermark;
TSKEY minTS;
+ SScalableBf* pCloseWinSBF;
} SUpdateInfo;
SUpdateInfo *updateInfoInitP(SInterval* pInterval, int64_t watermark);
SUpdateInfo *updateInfoInit(int64_t interval, int32_t precision, int64_t watermark);
bool updateInfoIsUpdated(SUpdateInfo *pInfo, tb_uid_t tableId, TSKEY ts);
void updateInfoDestroy(SUpdateInfo *pInfo);
+void updateInfoAddCloseWindowSBF(SUpdateInfo *pInfo);
+void updateInfoDestoryColseWinSBF(SUpdateInfo *pInfo);
#ifdef __cplusplus
}
diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h
index e963f25616cc92ebb64a75c9de6daecca50c8116..c226d7c8ccbd2cb2e9c248ec895d1220ef40e104 100644
--- a/include/libs/sync/sync.h
+++ b/include/libs/sync/sync.h
@@ -26,8 +26,18 @@ extern "C" {
extern bool gRaftDetailLog;
+#define SYNC_RESP_TTL_MS 5000
+
+#define SYNC_MAX_BATCH_SIZE 500
#define SYNC_INDEX_BEGIN 0
#define SYNC_INDEX_INVALID -1
+#define SYNC_TERM_INVALID 0xFFFFFFFFFFFFFFFF
+
+typedef enum {
+ SYNC_STRATEGY_NO_SNAPSHOT = 0,
+ SYNC_STRATEGY_STANDARD_SNAPSHOT = 1,
+ SYNC_STRATEGY_WAL_FIRST = 2,
+} ESyncStrategy;
typedef uint64_t SyncNodeId;
typedef int32_t SyncGroupId;
@@ -46,11 +56,6 @@ typedef enum {
TAOS_SYNC_STATE_ERROR = 103,
} ESyncState;
-typedef enum {
- TAOS_SYNC_FSM_CB_SUCCESS = 0,
- TAOS_SYNC_FSM_CB_OTHER_ERROR = 1,
-} ESyncFsmCbCode;
-
typedef struct SNodeInfo {
uint16_t nodePort;
char nodeFqdn[TSDB_FQDN_LEN];
@@ -94,6 +99,11 @@ typedef struct SReConfigCbMeta {
} SReConfigCbMeta;
+typedef struct SSnapshotParam {
+ SyncIndex start;
+ SyncIndex end;
+} SSnapshotParam;
+
typedef struct SSnapshot {
void* data;
SyncIndex lastApplyIndex;
@@ -119,11 +129,11 @@ typedef struct SSyncFSM {
int32_t (*FpGetSnapshot)(struct SSyncFSM* pFsm, SSnapshot* pSnapshot, void* pReaderParam, void** ppReader);
int32_t (*FpGetSnapshotInfo)(struct SSyncFSM* pFsm, SSnapshot* pSnapshot);
- int32_t (*FpSnapshotStartRead)(struct SSyncFSM* pFsm, void** ppReader);
+ int32_t (*FpSnapshotStartRead)(struct SSyncFSM* pFsm, void* pReaderParam, void** ppReader);
int32_t (*FpSnapshotStopRead)(struct SSyncFSM* pFsm, void* pReader);
int32_t (*FpSnapshotDoRead)(struct SSyncFSM* pFsm, void* pReader, void** ppBuf, int32_t* len);
- int32_t (*FpSnapshotStartWrite)(struct SSyncFSM* pFsm, void** ppWriter);
+ int32_t (*FpSnapshotStartWrite)(struct SSyncFSM* pFsm, void* pWriterParam, void** ppWriter);
int32_t (*FpSnapshotStopWrite)(struct SSyncFSM* pFsm, void* pWriter, bool isApply);
int32_t (*FpSnapshotDoWrite)(struct SSyncFSM* pFsm, void* pWriter, void* pBuf, int32_t len);
@@ -155,14 +165,12 @@ typedef struct SSyncLogStore {
// return commit index of log
SyncIndex (*getCommitIndex)(struct SSyncLogStore* pLogStore);
- // refactor, log[0 .. n] ==> log[m .. n]
- int32_t (*syncLogSetBeginIndex)(struct SSyncLogStore* pLogStore, SyncIndex beginIndex);
- int32_t (*syncLogResetBeginIndex)(struct SSyncLogStore* pLogStore);
SyncIndex (*syncLogBeginIndex)(struct SSyncLogStore* pLogStore);
SyncIndex (*syncLogEndIndex)(struct SSyncLogStore* pLogStore);
bool (*syncLogIsEmpty)(struct SSyncLogStore* pLogStore);
int32_t (*syncLogEntryCount)(struct SSyncLogStore* pLogStore);
- bool (*syncLogInRange)(struct SSyncLogStore* pLogStore, SyncIndex index);
+ int32_t (*syncLogRestoreFromSnapshot)(struct SSyncLogStore* pLogStore, SyncIndex index);
+ bool (*syncLogExist)(struct SSyncLogStore* pLogStore, SyncIndex index);
SyncIndex (*syncLogWriteIndex)(struct SSyncLogStore* pLogStore);
SyncIndex (*syncLogLastIndex)(struct SSyncLogStore* pLogStore);
@@ -175,14 +183,15 @@ typedef struct SSyncLogStore {
} SSyncLogStore;
typedef struct SSyncInfo {
- bool isStandBy;
- bool snapshotEnable;
- SyncGroupId vgId;
- SSyncCfg syncCfg;
- char path[TSDB_FILENAME_LEN];
- SWal* pWal;
- SSyncFSM* pFsm;
- SMsgCb* msgcb;
+ bool isStandBy;
+ ESyncStrategy snapshotStrategy;
+ SyncGroupId vgId;
+ int32_t batchSize;
+ SSyncCfg syncCfg;
+ char path[TSDB_FILENAME_LEN];
+ SWal* pWal;
+ SSyncFSM* pFsm;
+ SMsgCb* msgcb;
int32_t (*FpSendMsg)(const SEpSet* pEpSet, SRpcMsg* pMsg);
int32_t (*FpEqMsg)(const SMsgCb* msgcb, SRpcMsg* pMsg);
} SSyncInfo;
@@ -199,10 +208,13 @@ const char* syncGetMyRoleStr(int64_t rid);
SyncTerm syncGetMyTerm(int64_t rid);
SyncGroupId syncGetVgId(int64_t rid);
void syncGetEpSet(int64_t rid, SEpSet* pEpSet);
-int32_t syncPropose(int64_t rid, const SRpcMsg* pMsg, bool isWeak);
+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);
bool syncEnvIsStart();
const char* syncStr(ESyncState state);
bool syncIsRestoreFinish(int64_t rid);
+int32_t syncGetSnapshotByIndex(int64_t rid, SyncIndex index, SSnapshot* pSnapshot);
int32_t syncReconfig(int64_t rid, const SSyncCfg* pNewCfg);
diff --git a/include/libs/sync/syncTools.h b/include/libs/sync/syncTools.h
index 37b465e56ea18420cdb4880099c4b2f8bdf4c322..7e956237401bed6140201ff84427e9cda2aa9e8b 100644
--- a/include/libs/sync/syncTools.h
+++ b/include/libs/sync/syncTools.h
@@ -43,7 +43,7 @@ void setElectTimerMS(int64_t rid, int32_t electTimerMS);
void setHeartbeatTimerMS(int64_t rid, int32_t hbTimerMS);
// for compatibility, the same as syncPropose
-int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pMsg, bool isWeak);
+int32_t syncForwardToPeer(int64_t rid, SRpcMsg* pMsg, bool isWeak);
// utils
const char* syncUtilState2String(ESyncState state);
@@ -191,12 +191,12 @@ void syncTimeoutLog2(char* s, const SyncTimeout* pMsg);
typedef struct SyncClientRequest {
uint32_t bytes;
int32_t vgId;
- uint32_t msgType; // SyncClientRequest msgType
- uint32_t originalRpcType; // user RpcMsg msgType
+ uint32_t msgType; // TDMT_SYNC_CLIENT_REQUEST
+ uint32_t originalRpcType; // origin RpcMsg msgType
uint64_t seqNum;
bool isWeak;
- uint32_t dataLen; // user RpcMsg.contLen
- char data[]; // user RpcMsg.pCont
+ uint32_t dataLen; // origin RpcMsg.contLen
+ char data[]; // origin RpcMsg.pCont
} SyncClientRequest;
SyncClientRequest* syncClientRequestBuild(uint32_t dataLen);
@@ -219,6 +219,42 @@ void syncClientRequestPrint2(char* s, const SyncClientRequest* pMsg);
void syncClientRequestLog(const SyncClientRequest* pMsg);
void syncClientRequestLog2(char* s, const SyncClientRequest* pMsg);
+// ---------------------------------------------
+typedef struct SRaftMeta {
+ uint64_t seqNum;
+ bool isWeak;
+} SRaftMeta;
+
+// block1:
+// block2: SRaftMeta array
+// block3: rpc msg array (with pCont pointer)
+
+typedef struct SyncClientRequestBatch {
+ uint32_t bytes;
+ int32_t vgId;
+ uint32_t msgType; // TDMT_SYNC_CLIENT_REQUEST_BATCH
+ uint32_t dataCount;
+ uint32_t dataLen;
+ char data[]; // block2, block3
+} SyncClientRequestBatch;
+
+SyncClientRequestBatch* syncClientRequestBatchBuild(SRpcMsg* rpcMsgArr, SRaftMeta* raftArr, int32_t arrSize,
+ int32_t vgId);
+void syncClientRequestBatch2RpcMsg(const SyncClientRequestBatch* pSyncMsg, SRpcMsg* pRpcMsg);
+void syncClientRequestBatchDestroy(SyncClientRequestBatch* pMsg);
+void syncClientRequestBatchDestroyDeep(SyncClientRequestBatch* pMsg);
+SRaftMeta* syncClientRequestBatchMetaArr(const SyncClientRequestBatch* pSyncMsg);
+SRpcMsg* syncClientRequestBatchRpcMsgArr(const SyncClientRequestBatch* pSyncMsg);
+SyncClientRequestBatch* syncClientRequestBatchFromRpcMsg(const SRpcMsg* pRpcMsg);
+cJSON* syncClientRequestBatch2Json(const SyncClientRequestBatch* pMsg);
+char* syncClientRequestBatch2Str(const SyncClientRequestBatch* pMsg);
+
+// for debug ----------------------
+void syncClientRequestBatchPrint(const SyncClientRequestBatch* pMsg);
+void syncClientRequestBatchPrint2(char* s, const SyncClientRequestBatch* pMsg);
+void syncClientRequestBatchLog(const SyncClientRequestBatch* pMsg);
+void syncClientRequestBatchLog2(char* s, const SyncClientRequestBatch* pMsg);
+
// ---------------------------------------------
typedef struct SyncClientRequestReply {
uint32_t bytes;
@@ -290,12 +326,15 @@ void syncRequestVoteReplyLog(const SyncRequestVoteReply* pMsg);
void syncRequestVoteReplyLog2(char* s, const SyncRequestVoteReply* pMsg);
// ---------------------------------------------
+// data: entry
+
typedef struct SyncAppendEntries {
uint32_t bytes;
int32_t vgId;
uint32_t msgType;
SRaftId srcId;
SRaftId destId;
+
// private data
SyncTerm term;
SyncIndex prevLogIndex;
@@ -324,6 +363,54 @@ void syncAppendEntriesPrint2(char* s, const SyncAppendEntries* pMsg);
void syncAppendEntriesLog(const SyncAppendEntries* pMsg);
void syncAppendEntriesLog2(char* s, const SyncAppendEntries* pMsg);
+// ---------------------------------------------
+
+typedef struct SOffsetAndContLen {
+ int32_t offset;
+ int32_t contLen;
+} SOffsetAndContLen;
+
+// data:
+// block1: SOffsetAndContLen Array
+// block2: entry Array
+
+typedef struct SyncAppendEntriesBatch {
+ uint32_t bytes;
+ int32_t vgId;
+ uint32_t msgType;
+ SRaftId srcId;
+ SRaftId destId;
+
+ // private data
+ SyncTerm term;
+ SyncIndex prevLogIndex;
+ SyncTerm prevLogTerm;
+ SyncIndex commitIndex;
+ SyncTerm privateTerm;
+ int32_t dataCount;
+ uint32_t dataLen;
+ char data[]; // block1, block2
+} SyncAppendEntriesBatch;
+
+SyncAppendEntriesBatch* syncAppendEntriesBatchBuild(SSyncRaftEntry** entryPArr, int32_t arrSize, int32_t vgId);
+SOffsetAndContLen* syncAppendEntriesBatchMetaTableArray(SyncAppendEntriesBatch* pMsg);
+void syncAppendEntriesBatchDestroy(SyncAppendEntriesBatch* pMsg);
+void syncAppendEntriesBatchSerialize(const SyncAppendEntriesBatch* pMsg, char* buf, uint32_t bufLen);
+void syncAppendEntriesBatchDeserialize(const char* buf, uint32_t len, SyncAppendEntriesBatch* pMsg);
+char* syncAppendEntriesBatchSerialize2(const SyncAppendEntriesBatch* pMsg, uint32_t* len);
+SyncAppendEntriesBatch* syncAppendEntriesBatchDeserialize2(const char* buf, uint32_t len);
+void syncAppendEntriesBatch2RpcMsg(const SyncAppendEntriesBatch* pMsg, SRpcMsg* pRpcMsg);
+void syncAppendEntriesBatchFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntriesBatch* pMsg);
+SyncAppendEntriesBatch* syncAppendEntriesBatchFromRpcMsg2(const SRpcMsg* pRpcMsg);
+cJSON* syncAppendEntriesBatch2Json(const SyncAppendEntriesBatch* pMsg);
+char* syncAppendEntriesBatch2Str(const SyncAppendEntriesBatch* pMsg);
+
+// for debug ----------------------
+void syncAppendEntriesBatchPrint(const SyncAppendEntriesBatch* pMsg);
+void syncAppendEntriesBatchPrint2(char* s, const SyncAppendEntriesBatch* pMsg);
+void syncAppendEntriesBatchLog(const SyncAppendEntriesBatch* pMsg);
+void syncAppendEntriesBatchLog2(char* s, const SyncAppendEntriesBatch* pMsg);
+
// ---------------------------------------------
typedef struct SyncAppendEntriesReply {
uint32_t bytes;
@@ -396,9 +483,10 @@ typedef struct SyncSnapshotSend {
SRaftId destId;
SyncTerm term;
- SyncIndex lastIndex; // lastIndex of snapshot
- SyncTerm lastTerm; // lastTerm of snapshot
- SyncIndex lastConfigIndex;
+ SyncIndex beginIndex; // snapshot.beginIndex
+ SyncIndex lastIndex; // snapshot.lastIndex
+ SyncTerm lastTerm; // snapshot.lastTerm
+ SyncIndex lastConfigIndex; // snapshot.lastConfigIndex
SSyncCfg lastConfig;
SyncTerm privateTerm;
int32_t seq;
@@ -468,7 +556,7 @@ typedef struct SyncLeaderTransfer {
SRaftId destId;
*/
SNodeInfo newNodeInfo;
- SRaftId newLeaderId;
+ SRaftId newLeaderId;
} SyncLeaderTransfer;
SyncLeaderTransfer* syncLeaderTransferBuild(int32_t vgId);
@@ -489,17 +577,16 @@ void syncLeaderTransferPrint2(char* s, const SyncLeaderTransfer* pMsg);
void syncLeaderTransferLog(const SyncLeaderTransfer* pMsg);
void syncLeaderTransferLog2(char* s, const SyncLeaderTransfer* pMsg);
-
// ---------------------------------------------
typedef struct SyncReconfigFinish {
- uint32_t bytes;
- int32_t vgId;
- uint32_t msgType;
- SSyncCfg oldCfg;
- SSyncCfg newCfg;
+ uint32_t bytes;
+ int32_t vgId;
+ uint32_t msgType;
+ SSyncCfg oldCfg;
+ SSyncCfg newCfg;
SyncIndex newCfgIndex;
- SyncTerm newCfgTerm;
- uint64_t newCfgSeqNum;
+ SyncTerm newCfgTerm;
+ uint64_t newCfgSeqNum;
} SyncReconfigFinish;
@@ -521,13 +608,12 @@ void syncReconfigFinishPrint2(char* s, const SyncReconfigFinish* pMsg);
void syncReconfigFinishLog(const SyncReconfigFinish* pMsg);
void syncReconfigFinishLog2(char* s, const SyncReconfigFinish* pMsg);
-
-
// on message ----------------------
int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg);
int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg);
int32_t syncNodeOnTimeoutCb(SSyncNode* ths, SyncTimeout* pMsg);
-int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg);
+int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg, SyncIndex* pRetIndex);
+int32_t syncNodeOnClientRequestBatchCb(SSyncNode* ths, SyncClientRequestBatch* pMsg);
int32_t syncNodeOnRequestVoteCb(SSyncNode* ths, SyncRequestVote* pMsg);
int32_t syncNodeOnRequestVoteReplyCb(SSyncNode* ths, SyncRequestVoteReply* pMsg);
int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg);
@@ -538,13 +624,16 @@ int32_t syncNodeOnRequestVoteReplySnapshotCb(SSyncNode* ths, SyncRequestVoteRepl
int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMsg);
int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg);
+int32_t syncNodeOnAppendEntriesSnapshot2Cb(SSyncNode* ths, SyncAppendEntriesBatch* pMsg);
+int32_t syncNodeOnAppendEntriesReplySnapshot2Cb(SSyncNode* ths, SyncAppendEntriesReply* pMsg);
+
int32_t syncNodeOnSnapshotSendCb(SSyncNode* ths, SyncSnapshotSend* pMsg);
int32_t syncNodeOnSnapshotRspCb(SSyncNode* ths, SyncSnapshotRsp* pMsg);
// -----------------------------------------
typedef int32_t (*FpOnPingCb)(SSyncNode* ths, SyncPing* pMsg);
typedef int32_t (*FpOnPingReplyCb)(SSyncNode* ths, SyncPingReply* pMsg);
-typedef int32_t (*FpOnClientRequestCb)(SSyncNode* ths, SyncClientRequest* pMsg);
+typedef int32_t (*FpOnClientRequestCb)(SSyncNode* ths, SyncClientRequest* pMsg, SyncIndex* pRetIndex);
typedef int32_t (*FpOnRequestVoteCb)(SSyncNode* ths, SyncRequestVote* pMsg);
typedef int32_t (*FpOnRequestVoteReplyCb)(SSyncNode* ths, SyncRequestVoteReply* pMsg);
typedef int32_t (*FpOnAppendEntriesCb)(SSyncNode* ths, SyncAppendEntries* pMsg);
@@ -554,7 +643,8 @@ typedef int32_t (*FpOnSnapshotSendCb)(SSyncNode* ths, SyncSnapshotSend* pMsg);
typedef int32_t (*FpOnSnapshotRspCb)(SSyncNode* ths, SyncSnapshotRsp* pMsg);
// option ----------------------------------
-bool syncNodeSnapshotEnable(SSyncNode* pSyncNode);
+bool syncNodeSnapshotEnable(SSyncNode* pSyncNode);
+ESyncStrategy syncNodeStrategy(SSyncNode* pSyncNode);
// ---------------------------------------------
diff --git a/include/libs/transport/trpc.h b/include/libs/transport/trpc.h
index 77de5f47562897815e6cd8633c09345dee82794a..d8dea8a1bed03493ba57365c30cb3a84c071b515 100644
--- a/include/libs/transport/trpc.h
+++ b/include/libs/transport/trpc.h
@@ -34,20 +34,19 @@ extern int32_t tsRpcHeadSize;
typedef struct {
uint32_t clientIp;
uint16_t clientPort;
- union {
- char user[TSDB_USER_LEN];
- int64_t applyIndex;
- };
+ int64_t applyIndex;
+ uint64_t applyTerm;
+ char user[TSDB_USER_LEN];
} SRpcConnInfo;
typedef struct SRpcHandleInfo {
// rpc info
- void * handle; // rpc handle returned to app
+ void *handle; // rpc handle returned to app
int64_t refId; // refid, used by server
int32_t noResp; // has response or not(default 0, 0: resp, 1: no resp);
int32_t persistHandle; // persist handle or not
STraceId traceId;
- // int64_t traceId;
+ int8_t hasEpSet;
// app info
void *ahandle; // app handle set by client
@@ -55,7 +54,7 @@ typedef struct SRpcHandleInfo {
void *node; // node mgmt handle
// resp info
- void * rsp;
+ void *rsp;
int32_t rspLen;
// conn info
@@ -64,19 +63,19 @@ typedef struct SRpcHandleInfo {
typedef struct SRpcMsg {
tmsg_t msgType;
- void * pCont;
+ void *pCont;
int32_t contLen;
int32_t code;
SRpcHandleInfo info;
} SRpcMsg;
typedef void (*RpcCfp)(void *parent, SRpcMsg *, SEpSet *rf);
-typedef bool (*RpcRfp)(int32_t code);
+typedef bool (*RpcRfp)(int32_t code, tmsg_t msgType);
typedef struct SRpcInit {
char localFqdn[TSDB_FQDN_LEN];
uint16_t localPort; // local port
- char * label; // for debug purpose
+ char *label; // for debug purpose
int32_t numOfThreads; // number of threads to handle connections
int32_t sessions; // number of sessions allowed
int8_t connType; // TAOS_CONN_UDP, TAOS_CONN_TCPC, TAOS_CONN_TCPS
@@ -101,23 +100,26 @@ typedef struct {
typedef struct {
int32_t msgType;
- void * val;
+ void *val;
int32_t (*clone)(void *src, void **dst);
} SRpcBrokenlinkVal;
typedef struct {
- SHashObj * args;
+ SHashObj *args;
SRpcBrokenlinkVal brokenVal;
void (*freeFunc)(const void *arg);
} SRpcCtx;
int32_t rpcInit();
-void rpcCleanup();
-void * rpcOpen(const SRpcInit *pRpc);
-void rpcClose(void *);
-void * rpcMallocCont(int32_t contLen);
-void rpcFreeCont(void *pCont);
-void * rpcReallocCont(void *ptr, int32_t contLen);
+
+void rpcCleanup();
+void *rpcOpen(const SRpcInit *pRpc);
+
+void rpcClose(void *);
+void rpcCloseImpl(void *);
+void *rpcMallocCont(int32_t contLen);
+void rpcFreeCont(void *pCont);
+void *rpcReallocCont(void *ptr, int32_t contLen);
// Because taosd supports multi-process mode
// These functions should not be used on the server side
@@ -125,7 +127,7 @@ void * rpcReallocCont(void *ptr, int32_t contLen);
void rpcSendRequest(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid);
void rpcSendResponse(const SRpcMsg *pMsg);
void rpcRegisterBrokenLinkArg(SRpcMsg *msg);
-void rpcReleaseHandle(void *handle, int8_t type); // just release client conn to rpc instance, no close sock
+void rpcReleaseHandle(void *handle, int8_t type); // just release conn to rpc instance, no close sock
// These functions will not be called in the child process
void rpcSendRedirectRsp(void *pConn, const SEpSet *pEpSet);
diff --git a/include/libs/wal/wal.h b/include/libs/wal/wal.h
index c7d1ccd3de8f6e2e921cf605c96d6fa2b1fc231f..7e2d09dd6369d3107691d86a94b457819b78beff 100644
--- a/include/libs/wal/wal.h
+++ b/include/libs/wal/wal.h
@@ -24,82 +24,31 @@
extern "C" {
#endif
-#define wFatal(...) \
- { \
- if (wDebugFlag & DEBUG_FATAL) { \
- taosPrintLog("WAL FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); \
- } \
- }
-#define wError(...) \
- { \
- if (wDebugFlag & DEBUG_ERROR) { \
- taosPrintLog("WAL ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); \
- } \
- }
-#define wWarn(...) \
- { \
- if (wDebugFlag & DEBUG_WARN) { \
- taosPrintLog("WAL WARN ", DEBUG_WARN, 255, __VA_ARGS__); \
- } \
- }
-#define wInfo(...) \
- { \
- if (wDebugFlag & DEBUG_INFO) { \
- taosPrintLog("WAL ", DEBUG_INFO, 255, __VA_ARGS__); \
- } \
- }
-#define wDebug(...) \
- { \
- if (wDebugFlag & DEBUG_DEBUG) { \
- taosPrintLog("WAL ", DEBUG_DEBUG, wDebugFlag, __VA_ARGS__); \
- } \
- }
-#define wTrace(...) \
- { \
- if (wDebugFlag & DEBUG_TRACE) { \
- taosPrintLog("WAL ", DEBUG_TRACE, wDebugFlag, __VA_ARGS__); \
- } \
- }
-
-#define WAL_HEAD_VER 0
+// clang-format off
+#define wFatal(...) { if (wDebugFlag & DEBUG_FATAL) { taosPrintLog("WAL FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
+#define wError(...) { if (wDebugFlag & DEBUG_ERROR) { taosPrintLog("WAL ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
+#define wWarn(...) { if (wDebugFlag & DEBUG_WARN) { taosPrintLog("WAL WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
+#define wInfo(...) { if (wDebugFlag & DEBUG_INFO) { taosPrintLog("WAL ", DEBUG_INFO, 255, __VA_ARGS__); }}
+#define wDebug(...) { if (wDebugFlag & DEBUG_DEBUG) { taosPrintLog("WAL ", DEBUG_DEBUG, wDebugFlag, __VA_ARGS__); }}
+#define wTrace(...) { if (wDebugFlag & DEBUG_TRACE) { taosPrintLog("WAL ", DEBUG_TRACE, wDebugFlag, __VA_ARGS__); }}
+// clang-format on
+
+#define WAL_PROTO_VER 0
#define WAL_NOSUFFIX_LEN 20
#define WAL_SUFFIX_AT (WAL_NOSUFFIX_LEN + 1)
#define WAL_LOG_SUFFIX "log"
#define WAL_INDEX_SUFFIX "idx"
#define WAL_REFRESH_MS 1000
-#define WAL_MAX_SIZE (TSDB_MAX_WAL_SIZE + sizeof(SWalHead))
+#define WAL_MAX_SIZE (TSDB_MAX_WAL_SIZE + sizeof(SWalCkHead))
#define WAL_PATH_LEN (TSDB_FILENAME_LEN + 12)
#define WAL_FILE_LEN (WAL_PATH_LEN + 32)
#define WAL_MAGIC 0xFAFBFCFDULL
-#pragma pack(push, 1)
typedef enum {
- TAOS_WAL_NOLOG = 0,
TAOS_WAL_WRITE = 1,
TAOS_WAL_FSYNC = 2,
} EWalType;
-// used by sync module
-typedef struct {
- int8_t isWeek;
- uint64_t seqNum;
- uint64_t term;
-} SSyncLogMeta;
-
-typedef struct SWalReadHead {
- int8_t headVer;
- int8_t reserved;
- int16_t msgType;
- int32_t bodyLen;
- int64_t ingestTs; // not implemented
- int64_t version;
-
- // sync meta
- SSyncLogMeta syncMeta;
-
- char body[];
-} SWalReadHead;
-
typedef struct {
int32_t vgId;
int32_t fsyncPeriod; // millisecond
@@ -111,13 +60,6 @@ typedef struct {
} SWalCfg;
typedef struct {
- uint64_t magic;
- uint32_t cksumHead;
- uint32_t cksumBody;
- SWalReadHead head;
-} SWalHead;
-
-typedef struct SWalVer {
int64_t firstVer;
int64_t verInSnapshotting;
int64_t snapshotVer;
@@ -125,6 +67,35 @@ typedef struct SWalVer {
int64_t lastVer;
} SWalVer;
+#pragma pack(push, 1)
+// used by sync module
+typedef struct {
+ int8_t isWeek;
+ uint64_t seqNum;
+ uint64_t term;
+} SWalSyncInfo;
+
+typedef struct {
+ int8_t protoVer;
+ int64_t version;
+ int16_t msgType;
+ int32_t bodyLen;
+ int64_t ingestTs; // not implemented
+
+ // sync meta
+ SWalSyncInfo syncMeta;
+
+ char body[];
+} SWalCont;
+
+typedef struct {
+ uint64_t magic;
+ uint32_t cksumHead;
+ uint32_t cksumBody;
+ SWalCont head;
+} SWalCkHead;
+#pragma pack(pop)
+
typedef struct SWal {
// cfg
SWalCfg cfg;
@@ -134,7 +105,7 @@ typedef struct SWal {
TdFilePtr pWriteLogTFile;
TdFilePtr pWriteIdxTFile;
int32_t writeCur;
- SArray *fileInfoSet;
+ SArray *fileInfoSet; // SArray
// status
int64_t totSize;
int64_t lastRollSeq;
@@ -146,23 +117,27 @@ typedef struct SWal {
// path
char path[WAL_PATH_LEN];
// reusable write head
- SWalHead writeHead;
+ SWalCkHead writeHead;
} SWal; // WAL HANDLE
-typedef struct SWalReadHandle {
- SWal *pWal;
- TdFilePtr pReadLogTFile;
- TdFilePtr pReadIdxTFile;
- int64_t curFileFirstVer;
- int64_t curVersion;
- int64_t capacity;
- int64_t status; // if cursor valid
- TdThreadMutex mutex;
- SWalHead *pHead;
-} SWalReadHandle;
-#pragma pack(pop)
+typedef struct {
+ int8_t scanUncommited;
+ int8_t scanMeta;
+ int8_t enableRef;
+} SWalFilterCond;
-// typedef int32_t (*FWalWrite)(void *ahandle, void *pHead);
+typedef struct {
+ SWal *pWal;
+ TdFilePtr pLogFile;
+ TdFilePtr pIdxFile;
+ int64_t curFileFirstVer;
+ int64_t curVersion;
+ int64_t capacity;
+ int8_t curInvalid;
+ TdThreadMutex mutex;
+ SWalFilterCond cond;
+ SWalCkHead *pHead;
+} SWalReader;
// module initialization
int32_t walInit();
@@ -173,15 +148,25 @@ SWal *walOpen(const char *path, SWalCfg *pCfg);
int32_t walAlter(SWal *, SWalCfg *pCfg);
void walClose(SWal *);
-// write
-int64_t walWriteWithSyncInfo(SWal *, int64_t index, tmsg_t msgType, SSyncLogMeta syncMeta, const void *body,
+// write interfaces
+
+// By assigning index by the caller, wal gurantees linearizability
+int32_t walWrite(SWal *, int64_t index, tmsg_t msgType, const void *body, int32_t bodyLen);
+int32_t walWriteWithSyncInfo(SWal *, int64_t index, tmsg_t msgType, SWalSyncInfo syncMeta, const void *body,
int32_t bodyLen);
-int64_t walWrite(SWal *, int64_t index, tmsg_t msgType, const void *body, int32_t bodyLen);
-void walFsync(SWal *, bool force);
+
+// This interface assign version automatically and return to caller.
+// When using this interface with concurrent writes,
+// wal will write all logs atomically,
+// but not sure which one will be actually write first,
+// and then the unique index of successful writen is returned.
+// -1 will be returned for failed writes
+int64_t walAppendLog(SWal *, tmsg_t msgType, SWalSyncInfo syncMeta, const void *body, int32_t bodyLen);
+
+void walFsync(SWal *, bool force);
// apis for lifecycle management
int32_t walCommit(SWal *, int64_t ver);
-// truncate after
int32_t walRollback(SWal *, int64_t ver);
// notify that previous logs can be pruned safely
int32_t walBeginSnapshot(SWal *, int64_t ver);
@@ -190,16 +175,17 @@ int32_t walRestoreFromSnapshot(SWal *, int64_t ver);
// int32_t walDataCorrupted(SWal*);
// read
-SWalReadHandle *walOpenReadHandle(SWal *);
-void walCloseReadHandle(SWalReadHandle *);
-int32_t walReadWithHandle(SWalReadHandle *pRead, int64_t ver);
+SWalReader *walOpenReader(SWal *, SWalFilterCond *pCond);
+void walCloseReader(SWalReader *pRead);
+int32_t walReadVer(SWalReader *pRead, int64_t ver);
+int32_t walReadSeekVer(SWalReader *pRead, int64_t ver);
+int32_t walNextValidMsg(SWalReader *pRead);
// only for tq usage
-// int32_t walReadWithHandle_s(SWalReadHandle *pRead, int64_t ver, SWalReadHead **ppHead);
-void walSetReaderCapacity(SWalReadHandle *pRead, int32_t capacity);
-int32_t walFetchHead(SWalReadHandle *pRead, int64_t ver, SWalHead *pHead);
-int32_t walFetchBody(SWalReadHandle *pRead, SWalHead **ppHead);
-int32_t walSkipFetchBody(SWalReadHandle *pRead, const SWalHead *pHead);
+void walSetReaderCapacity(SWalReader *pRead, int32_t capacity);
+int32_t walFetchHead(SWalReader *pRead, int64_t ver, SWalCkHead *pHead);
+int32_t walFetchBody(SWalReader *pRead, SWalCkHead **ppHead);
+int32_t walSkipFetchBody(SWalReader *pRead, const SWalCkHead *pHead);
typedef struct {
int64_t refId;
@@ -211,11 +197,9 @@ void walCloseRef(SWalRef *);
int32_t walRefVer(SWalRef *, int64_t ver);
int32_t walUnrefVer(SWal *);
-// deprecated
-#if 0
-int32_t walRead(SWal *, SWalHead **, int64_t ver);
-int32_t walReadWithFp(SWal *, FWalWrite writeFp, int64_t verStart, int32_t readNum);
-#endif
+// help function for raft
+bool walLogExist(SWal *, int64_t ver);
+bool walIsEmpty(SWal *);
// lifecycle check
int64_t walGetFirstVer(SWal *);
diff --git a/include/os/os.h b/include/os/os.h
index 41180ba49edf6ecee2482ab70cc419983bd11d8d..b036002f8adb5d246db8346112f2189f779f73cd 100644
--- a/include/os/os.h
+++ b/include/os/os.h
@@ -41,7 +41,6 @@ extern "C" {
#include
#include
#include
-#include
#include
#include
@@ -52,6 +51,7 @@ extern "C" {
#endif
#else
+#include
#include
#ifndef TD_USE_WINSOCK
#include
@@ -104,8 +104,6 @@ extern "C" {
#include "osTimezone.h"
#include "osEnv.h"
-void osDefaultInit();
-
#ifdef __cplusplus
}
#endif
diff --git a/include/os/osAtomic.h b/include/os/osAtomic.h
index 8600992d68050d3ba80767cf687c6b21b4a23c77..9fd00cefb4f42869098ad745f521d4cc1ca49020 100644
--- a/include/os/osAtomic.h
+++ b/include/os/osAtomic.h
@@ -63,7 +63,7 @@ int8_t atomic_add_fetch_8(int8_t volatile *ptr, int8_t val);
int16_t atomic_add_fetch_16(int16_t volatile *ptr, int16_t val);
int32_t atomic_add_fetch_32(int32_t volatile *ptr, int32_t val);
int64_t atomic_add_fetch_64(int64_t volatile *ptr, int64_t val);
-void *atomic_add_fetch_ptr(void *ptr, void *val);
+void *atomic_add_fetch_ptr(void *ptr, int64_t val);
int8_t atomic_fetch_add_8(int8_t volatile *ptr, int8_t val);
int16_t atomic_fetch_add_16(int16_t volatile *ptr, int16_t val);
int32_t atomic_fetch_add_32(int32_t volatile *ptr, int32_t val);
@@ -73,7 +73,7 @@ int8_t atomic_sub_fetch_8(int8_t volatile *ptr, int8_t val);
int16_t atomic_sub_fetch_16(int16_t volatile *ptr, int16_t val);
int32_t atomic_sub_fetch_32(int32_t volatile *ptr, int32_t val);
int64_t atomic_sub_fetch_64(int64_t volatile *ptr, int64_t val);
-void *atomic_sub_fetch_ptr(void *ptr, void *val);
+void *atomic_sub_fetch_ptr(void *ptr, int64_t val);
int8_t atomic_fetch_sub_8(int8_t volatile *ptr, int8_t val);
int16_t atomic_fetch_sub_16(int16_t volatile *ptr, int16_t val);
int32_t atomic_fetch_sub_32(int32_t volatile *ptr, int32_t val);
diff --git a/include/os/osDef.h b/include/os/osDef.h
index 6f6199de7af6a09d7be1b4b60009f2d7507f2d46..14f38eb7ffbe15dbf07ca5e57f6963f1624a7352 100644
--- a/include/os/osDef.h
+++ b/include/os/osDef.h
@@ -22,7 +22,10 @@ extern "C" {
#if defined(_TD_DARWIN_64)
// specific
+#ifndef __COMPAR_FN_T
+#define __COMPAR_FN_T
typedef int(*__compar_fn_t)(const void *, const void *);
+#endif
// for send function in tsocket.c
#if defined(MSG_NOSIGNAL)
@@ -41,7 +44,10 @@ extern "C" {
#endif
#if defined(_ALPINE)
+#ifndef __COMPAR_FN_T
+#define __COMPAR_FN_T
typedef int(*__compar_fn_t)(const void *, const void *);
+#endif
void error (int, int, const char *);
#ifndef PTHREAD_MUTEX_RECURSIVE_NP
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
@@ -54,7 +60,10 @@ extern "C" {
char *stpncpy (char *dest, const char *src, size_t n);
// specific
+#ifndef __COMPAR_FN_T
+#define __COMPAR_FN_T
typedef int (*__compar_fn_t)(const void *, const void *);
+#endif
#define ssize_t int
#define _SSIZE_T_
#define bzero(ptr, size) memset((ptr), 0, (size))
@@ -69,7 +78,6 @@ extern "C" {
char * strsep(char **stringp, const char *delim);
char * getpass(const char *prefix);
char * strndup(const char *s, size_t n);
- int gettimeofday(struct timeval *ptv, void *pTimeZone);
// for send function in tsocket.c
#define MSG_NOSIGNAL 0
diff --git a/include/os/osFile.h b/include/os/osFile.h
index 8751e175a5a644527917bb9e67b6d58222954df8..2f6a6ba4800147465a494a88dd886258701e2e9c 100644
--- a/include/os/osFile.h
+++ b/include/os/osFile.h
@@ -25,17 +25,17 @@ extern "C" {
// If the error is in a third-party library, place this header file under the third-party library header file.
// When you want to use this feature, you should find or add the same function in the following sectio
#ifndef ALLOW_FORBID_FUNC
- #define open OPEN_FUNC_TAOS_FORBID
- #define fopen FOPEN_FUNC_TAOS_FORBID
- #define access ACCESS_FUNC_TAOS_FORBID
- #define stat STAT_FUNC_TAOS_FORBID
- #define lstat LSTAT_FUNC_TAOS_FORBID
- #define fstat FSTAT_FUNC_TAOS_FORBID
- #define close CLOSE_FUNC_TAOS_FORBID
- #define fclose FCLOSE_FUNC_TAOS_FORBID
- #define fsync FSYNC_FUNC_TAOS_FORBID
- #define getline GETLINE_FUNC_TAOS_FORBID
- // #define fflush FFLUSH_FUNC_TAOS_FORBID
+#define open OPEN_FUNC_TAOS_FORBID
+#define fopen FOPEN_FUNC_TAOS_FORBID
+#define access ACCESS_FUNC_TAOS_FORBID
+#define stat STAT_FUNC_TAOS_FORBID
+#define lstat LSTAT_FUNC_TAOS_FORBID
+#define fstat FSTAT_FUNC_TAOS_FORBID
+#define close CLOSE_FUNC_TAOS_FORBID
+#define fclose FCLOSE_FUNC_TAOS_FORBID
+#define fsync FSYNC_FUNC_TAOS_FORBID
+#define getline GETLINE_FUNC_TAOS_FORBID
+// #define fflush FFLUSH_FUNC_TAOS_FORBID
#endif
#ifndef PATH_MAX
@@ -43,54 +43,54 @@ extern "C" {
#endif
typedef struct TdFile *TdFilePtr;
-
-#define TD_FILE_CREATE 0x0001
-#define TD_FILE_WRITE 0x0002
-#define TD_FILE_READ 0x0004
-#define TD_FILE_TRUNC 0x0008
-#define TD_FILE_APPEND 0x0010
-#define TD_FILE_TEXT 0x0020
-#define TD_FILE_AUTO_DEL 0x0040
-#define TD_FILE_EXCL 0x0080
-#define TD_FILE_STREAM 0x0100 // Only support taosFprintfFile, taosGetLineFile, taosEOFFile
-TdFilePtr taosOpenFile(const char *path,int32_t tdFileOptions);
+
+#define TD_FILE_CREATE 0x0001
+#define TD_FILE_WRITE 0x0002
+#define TD_FILE_READ 0x0004
+#define TD_FILE_TRUNC 0x0008
+#define TD_FILE_APPEND 0x0010
+#define TD_FILE_TEXT 0x0020
+#define TD_FILE_AUTO_DEL 0x0040
+#define TD_FILE_EXCL 0x0080
+#define TD_FILE_STREAM 0x0100 // Only support taosFprintfFile, taosGetLineFile, taosEOFFile
+TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions);
#define TD_FILE_ACCESS_EXIST_OK 0x1
#define TD_FILE_ACCESS_READ_OK 0x2
#define TD_FILE_ACCESS_WRITE_OK 0x4
-bool taosCheckAccessFile(const char *pathname, int mode);
-
+bool taosCheckAccessFile(const char *pathname, int mode);
+
int32_t taosLockFile(TdFilePtr pFile);
int32_t taosUnLockFile(TdFilePtr pFile);
-
+
int32_t taosUmaskFile(int32_t maskVal);
-
+
int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime);
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno);
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime);
bool taosCheckExistFile(const char *pathname);
-
+
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence);
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t length);
int32_t taosFsyncFile(TdFilePtr pFile);
-
+
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count);
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset);
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count);
void taosFprintfFile(TdFilePtr pFile, const char *format, ...);
-int64_t taosGetLineFile(TdFilePtr pFile, char ** __restrict ptrBuf);
+int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf);
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf);
int32_t taosEOFFile(TdFilePtr pFile);
-
-int64_t taosCloseFile(TdFilePtr *ppFile);
-
+
+int32_t taosCloseFile(TdFilePtr *ppFile);
+
int32_t taosRenameFile(const char *oldName, const char *newName);
int64_t taosCopyFile(const char *from, const char *to);
int32_t taosRemoveFile(const char *path);
-
-void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath);
+
+void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath);
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size);
diff --git a/include/os/osMath.h b/include/os/osMath.h
index f17ca56c9ee7741723a95ba764afccf16dee62ff..74973d9bb22168ba99b6eb48dd9f98976c77c17c 100644
--- a/include/os/osMath.h
+++ b/include/os/osMath.h
@@ -20,16 +20,21 @@
extern "C" {
#endif
+// If the error is in a third-party library, place this header file under the third-party library header file.
+// When you want to use this feature, you should find or add the same function in the following sectio
+#ifndef ALLOW_FORBID_FUNC
+#define qsort QSORT_FUNC_TAOS_FORBID
+#endif
+
#define TPOW2(x) ((x) * (x))
#define TABS(x) ((x) > 0 ? (x) : -(x))
#define TSWAP(a, b) \
do { \
- char *__tmp = taosMemoryMalloc(sizeof(a)); \
+ char *__tmp = alloca(sizeof(a)); \
memcpy(__tmp, &(a), sizeof(a)); \
memcpy(&(a), &(b), sizeof(a)); \
memcpy(&(b), __tmp, sizeof(a)); \
- taosMemoryFree(__tmp); \
} while (0)
#ifdef WINDOWS
@@ -61,6 +66,13 @@ extern "C" {
})
#endif
+#ifndef __COMPAR_FN_T
+#define __COMPAR_FN_T
+typedef int32_t (*__compar_fn_t)(const void *, const void *);
+#endif
+
+void taosSort(void* arr, int64_t sz, int64_t width, __compar_fn_t compar);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/os/osMemory.h b/include/os/osMemory.h
index ba69a329417200f0cb4080288f83f1f96ef4b554..88dfe02074fa3d8940c71b5aa4354ab2871d070d 100644
--- a/include/os/osMemory.h
+++ b/include/os/osMemory.h
@@ -32,7 +32,7 @@ extern "C" {
void *taosMemoryMalloc(int32_t size);
void *taosMemoryCalloc(int32_t num, int32_t size);
void *taosMemoryRealloc(void *ptr, int32_t size);
-void *taosMemoryStrDup(void *ptr);
+void *taosMemoryStrDup(const char *ptr);
void taosMemoryFree(void *ptr);
int32_t taosMemorySize(void *ptr);
void taosPrintBackTrace();
diff --git a/include/os/osSemaphore.h b/include/os/osSemaphore.h
index 21c88c9976d14d3cf9fc9504bae9383fce25b4e8..7fca20d75e2eaece441656bc4ae2c707e0b15cd3 100644
--- a/include/os/osSemaphore.h
+++ b/include/os/osSemaphore.h
@@ -24,7 +24,9 @@ extern "C" {
#if defined(_TD_DARWIN_64)
-typedef struct tsem_s *tsem_t;
+// typedef struct tsem_s *tsem_t;
+typedef struct bosal_sem_t *tsem_t;
+
int tsem_init(tsem_t *sem, int pshared, unsigned int value);
int tsem_wait(tsem_t *sem);
@@ -51,11 +53,11 @@ int tsem_timewait(tsem_t *sim, int64_t nanosecs);
// #define taosThreadRwlockRdlock(lock) taosThreadMutexLock(lock)
// #define taosThreadRwlockUnlock(lock) taosThreadMutexUnlock(lock)
-#define TdThreadSpinlock TdThreadMutex
-#define taosThreadSpinInit(lock, NULL) taosThreadMutexInit(lock, NULL)
-#define taosThreadSpinDestroy(lock) taosThreadMutexDestroy(lock)
-#define taosThreadSpinLock(lock) taosThreadMutexLock(lock)
-#define taosThreadSpinUnlock(lock) taosThreadMutexUnlock(lock)
+// #define TdThreadSpinlock TdThreadMutex
+// #define taosThreadSpinInit(lock, NULL) taosThreadMutexInit(lock, NULL)
+// #define taosThreadSpinDestroy(lock) taosThreadMutexDestroy(lock)
+// #define taosThreadSpinLock(lock) taosThreadMutexLock(lock)
+// #define taosThreadSpinUnlock(lock) taosThreadMutexUnlock(lock)
#endif
bool taosCheckPthreadValid(TdThread thread);
diff --git a/include/os/osSocket.h b/include/os/osSocket.h
index 213a6930eebb4fe7a97bf45f1f5db80a5d026a22..4bad51e26322405d9c4187e3bd7a12a75ee011b9 100644
--- a/include/os/osSocket.h
+++ b/include/os/osSocket.h
@@ -64,7 +64,6 @@
#include
#else
#include
-#include
#endif
#endif
@@ -77,15 +76,12 @@ typedef int socklen_t;
#define TAOS_EPOLL_WAIT_TIME 100
typedef SOCKET eventfd_t;
#define eventfd(a, b) -1
-#define EpollClose(pollFd) epoll_close(pollFd)
#ifndef EPOLLWAKEUP
#define EPOLLWAKEUP (1u << 29)
#endif
#elif defined(_TD_DARWIN_64)
#define TAOS_EPOLL_WAIT_TIME 500
typedef int32_t SOCKET;
-typedef SOCKET EpollFd;
-#define EpollClose(pollFd) epoll_close(pollFd)
#else
#define TAOS_EPOLL_WAIT_TIME 500
typedef int32_t SOCKET;
@@ -122,14 +118,6 @@ typedef SOCKET EpollFd;
typedef int32_t SocketFd;
typedef SocketFd EpollFd;
-typedef struct TdSocket {
-#if SOCKET_WITH_LOCK
- TdThreadRwlock rwlock;
-#endif
- int refId;
- SocketFd fd;
-} * TdSocketPtr, TdSocket;
-
typedef struct TdSocketServer *TdSocketServerPtr;
typedef struct TdSocket * TdSocketPtr;
typedef struct TdEpoll * TdEpollPtr;
@@ -157,7 +145,10 @@ int32_t taosNonblockwrite(TdSocketPtr pSocket, char *ptr, int32_t nbytes);
int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len);
void taosWinSocketInit();
-int taosCreateSocketWithTimeOutOpt(uint32_t conn_timeout_sec);
+/*
+ * set timeout(ms)
+ */
+int32_t taosCreateSocketWithTimeout(uint32_t timeout);
TdSocketPtr taosOpenUdpSocket(uint32_t localIp, uint16_t localPort);
TdSocketPtr taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp);
@@ -178,11 +169,6 @@ void taosSetMaskSIGPIPE();
uint32_t taosInetAddr(const char *ipAddr);
const char *taosInetNtoa(struct in_addr ipInt);
-TdEpollPtr taosCreateEpoll(int32_t size);
-int32_t taosCtlEpoll(TdEpollPtr pEpoll, int32_t epollOperate, TdSocketPtr pSocket, struct epoll_event *event);
-int32_t taosWaitEpoll(TdEpollPtr pEpoll, struct epoll_event *event, int32_t maxEvents, int32_t timeout);
-int32_t taosCloseEpoll(TdEpollPtr *ppEpoll);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/os/osString.h b/include/os/osString.h
index 1b518f9b81ee6879b4dde6524ca9bd920d31b0e2..3a4ff18694489c995c8849bcd9c39a14637472c2 100644
--- a/include/os/osString.h
+++ b/include/os/osString.h
@@ -67,7 +67,7 @@ bool taosMbsToUcs4(const char *mbs, size_t mbs_len, TdUcs4 *ucs4, int32_t ucs
int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes);
TdUcs4* tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4);
bool taosValidateEncodec(const char *encodec);
-int32_t taosHexEncode(const char *src, char *dst, int32_t len);
+int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len);
int32_t taosHexDecode(const char *src, char *dst, int32_t len);
int32_t taosWcharWidth(TdWchar wchar);
diff --git a/include/os/osSystem.h b/include/os/osSystem.h
index 6770be6e461c45c55238e4f9b3f059cfbf81487f..581e688ccb1adedf75552c6f21a9828eb01f9d99 100644
--- a/include/os/osSystem.h
+++ b/include/os/osSystem.h
@@ -29,6 +29,9 @@ extern "C" {
#define tcgetattr TCGETATTR_FUNC_TAOS_FORBID
#endif
+#define TAOS_CONSOLE_PROMPT_HEADER "taos> "
+#define TAOS_CONSOLE_PROMPT_CONTINUE " -> "
+
typedef struct TdCmd *TdCmdPtr;
TdCmdPtr taosOpenCmd(const char* cmd);
diff --git a/include/os/osThread.h b/include/os/osThread.h
index 6252a0cb60b83a4065ba99c992ce92574006dadd..b1ea8277f0b405be876d51b123e1103d1676d6c2 100644
--- a/include/os/osThread.h
+++ b/include/os/osThread.h
@@ -188,27 +188,27 @@ int32_t taosThreadJoin(TdThread thread, void **valuePtr);
int32_t taosThreadKeyCreate(TdThreadKey * key, void(*destructor)(void *));
int32_t taosThreadKeyDelete(TdThreadKey key);
int32_t taosThreadKill(TdThread thread, int32_t sig);
-int32_t taosThreadMutexConsistent(TdThreadMutex* mutex);
+// int32_t taosThreadMutexConsistent(TdThreadMutex* mutex);
int32_t taosThreadMutexDestroy(TdThreadMutex * mutex);
int32_t taosThreadMutexInit(TdThreadMutex * mutex, const TdThreadMutexAttr * attr);
int32_t taosThreadMutexLock(TdThreadMutex * mutex);
-int32_t taosThreadMutexTimedLock(TdThreadMutex * mutex, const struct timespec *abstime);
+// int32_t taosThreadMutexTimedLock(TdThreadMutex * mutex, const struct timespec *abstime);
int32_t taosThreadMutexTryLock(TdThreadMutex * mutex);
int32_t taosThreadMutexUnlock(TdThreadMutex * mutex);
int32_t taosThreadMutexAttrDestroy(TdThreadMutexAttr * attr);
int32_t taosThreadMutexAttrGetPshared(const TdThreadMutexAttr * attr, int32_t *pshared);
-int32_t taosThreadMutexAttrGetRobust(const TdThreadMutexAttr * attr, int32_t * robust);
+// int32_t taosThreadMutexAttrGetRobust(const TdThreadMutexAttr * attr, int32_t * robust);
int32_t taosThreadMutexAttrGetType(const TdThreadMutexAttr * attr, int32_t *kind);
int32_t taosThreadMutexAttrInit(TdThreadMutexAttr * attr);
int32_t taosThreadMutexAttrSetPshared(TdThreadMutexAttr * attr, int32_t pshared);
-int32_t taosThreadMutexAttrSetRobust(TdThreadMutexAttr * attr, int32_t robust);
+// int32_t taosThreadMutexAttrSetRobust(TdThreadMutexAttr * attr, int32_t robust);
int32_t taosThreadMutexAttrSetType(TdThreadMutexAttr * attr, int32_t kind);
int32_t taosThreadOnce(TdThreadOnce * onceControl, void(*initRoutine)(void));
int32_t taosThreadRwlockDestroy(TdThreadRwlock * rwlock);
int32_t taosThreadRwlockInit(TdThreadRwlock * rwlock, const TdThreadRwlockAttr * attr);
int32_t taosThreadRwlockRdlock(TdThreadRwlock * rwlock);
-int32_t taosThreadRwlockTimedRdlock(TdThreadRwlock * rwlock, const struct timespec *abstime);
-int32_t taosThreadRwlockTimedWrlock(TdThreadRwlock * rwlock, const struct timespec *abstime);
+// int32_t taosThreadRwlockTimedRdlock(TdThreadRwlock * rwlock, const struct timespec *abstime);
+// int32_t taosThreadRwlockTimedWrlock(TdThreadRwlock * rwlock, const struct timespec *abstime);
int32_t taosThreadRwlockTryRdlock(TdThreadRwlock * rwlock);
int32_t taosThreadRwlockTryWrlock(TdThreadRwlock * rwlock);
int32_t taosThreadRwlockUnlock(TdThreadRwlock * rwlock);
diff --git a/include/os/osTime.h b/include/os/osTime.h
index 949c15ed0d7c7a4e4c317edaace21f29a9eaab36..965ec61671925dd4d9e22e07a58826d47ecd9ed3 100644
--- a/include/os/osTime.h
+++ b/include/os/osTime.h
@@ -38,7 +38,7 @@ extern "C" {
#define MILLISECOND_PER_SECOND (1000i64)
#else
-#define MILLISECOND_PER_SECOND ((int64_t)1000L)
+#define MILLISECOND_PER_SECOND ((int64_t)1000LL)
#endif
#define MILLISECOND_PER_MINUTE (MILLISECOND_PER_SECOND * 60)
@@ -46,9 +46,9 @@ extern "C" {
#define MILLISECOND_PER_DAY (MILLISECOND_PER_HOUR * 24)
#define MILLISECOND_PER_WEEK (MILLISECOND_PER_DAY * 7)
-#define NANOSECOND_PER_USEC (1000L)
-#define NANOSECOND_PER_MSEC (1000000L)
-#define NANOSECOND_PER_SEC (1000000000L)
+#define NANOSECOND_PER_USEC (1000LL)
+#define NANOSECOND_PER_MSEC (1000000LL)
+#define NANOSECOND_PER_SEC (1000000000LL)
#define NANOSECOND_PER_MINUTE (NANOSECOND_PER_SEC * 60)
#define NANOSECOND_PER_HOUR (NANOSECOND_PER_MINUTE * 60)
#define NANOSECOND_PER_DAY (NANOSECOND_PER_HOUR * 24)
@@ -65,21 +65,21 @@ int32_t taosGetTimestampSec();
static FORCE_INLINE int64_t taosGetTimestampMs() {
struct timeval systemTime;
taosGetTimeOfDay(&systemTime);
- return (int64_t)systemTime.tv_sec * 1000L + (int64_t)systemTime.tv_usec / 1000;
+ return (int64_t)systemTime.tv_sec * 1000LL + (int64_t)systemTime.tv_usec / 1000;
}
//@return timestamp in microsecond
static FORCE_INLINE int64_t taosGetTimestampUs() {
struct timeval systemTime;
taosGetTimeOfDay(&systemTime);
- return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec;
+ return (int64_t)systemTime.tv_sec * 1000000LL + (int64_t)systemTime.tv_usec;
}
//@return timestamp in nanosecond
static FORCE_INLINE int64_t taosGetTimestampNs() {
struct timespec systemTime = {0};
taosClockGetTime(CLOCK_REALTIME, &systemTime);
- return (int64_t)systemTime.tv_sec * 1000000000L + (int64_t)systemTime.tv_nsec;
+ return (int64_t)systemTime.tv_sec * 1000000000LL + (int64_t)systemTime.tv_nsec;
}
char * taosStrpTime(const char *buf, const char *fmt, struct tm *tm);
diff --git a/include/util/tRealloc.h b/include/util/tRealloc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3593d5818cd626c7268ec1b721bd961fba3a845
--- /dev/null
+++ b/include/util/tRealloc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _TD_UTIL_TREALLOC_H_
+#define _TD_UTIL_TREALLOC_H_
+
+#include "os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static FORCE_INLINE int32_t tRealloc(uint8_t **ppBuf, int64_t size) {
+ int32_t code = 0;
+ int64_t bsize = 0;
+ uint8_t *pBuf = NULL;
+
+ if (*ppBuf) {
+ pBuf = (*ppBuf) - sizeof(int64_t);
+ bsize = *(int64_t *)pBuf;
+ }
+
+ if (bsize >= size) goto _exit;
+
+ if (bsize == 0) bsize = 64;
+ while (bsize < size) {
+ bsize *= 2;
+ }
+
+ pBuf = (uint8_t *)taosMemoryRealloc(pBuf, bsize + sizeof(int64_t));
+ if (pBuf == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+ *(int64_t *)pBuf = bsize;
+ *ppBuf = pBuf + sizeof(int64_t);
+
+_exit:
+ return code;
+}
+
+static FORCE_INLINE void tFree(uint8_t *pBuf) {
+ if (pBuf) {
+ taosMemoryFree(pBuf - sizeof(int64_t));
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_UTIL_TREALLOC_H_*/
diff --git a/include/util/taoserror.h b/include/util/taoserror.h
index f4d8c2a663f1f4214434af7e38facd767399e6a1..562fbc5f2e15d42ad8fa740607bdbfc556e87d96 100644
--- a/include/util/taoserror.h
+++ b/include/util/taoserror.h
@@ -25,7 +25,7 @@ extern "C" {
// clang-format off
#define TAOS_DEF_ERROR_CODE(mod, code) ((int32_t)((0x80000000 | ((mod)<<16) | (code))))
-
+
#define TAOS_SYSTEM_ERROR(code) (0x80ff0000 | (code))
#define TAOS_SUCCEEDED(err) ((err) >= 0)
#define TAOS_FAILED(err) ((err) < 0)
@@ -35,7 +35,7 @@ const char* terrstr();
int32_t* taosGetErrno();
#define terrno (*taosGetErrno())
-
+
#define TSDB_CODE_SUCCESS 0
#define TSDB_CODE_FAILED -1 // unknown or needn't tell detail error
@@ -71,6 +71,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE TAOS_DEF_ERROR_CODE(0, 0x0029)
#define TSDB_CODE_INVALID_TIMESTAMP TAOS_DEF_ERROR_CODE(0, 0x0030)
#define TSDB_CODE_MSG_DECODE_ERROR TAOS_DEF_ERROR_CODE(0, 0x0031)
+#define TSDB_CODE_NO_AVAIL_DISK TAOS_DEF_ERROR_CODE(0, 0x0032)
+#define TSDB_CODE_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0033)
#define TSDB_CODE_REF_NO_MEMORY TAOS_DEF_ERROR_CODE(0, 0x0040)
#define TSDB_CODE_REF_FULL TAOS_DEF_ERROR_CODE(0, 0x0041)
@@ -85,6 +87,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_RPC_NETWORK_UNAVAIL TAOS_DEF_ERROR_CODE(0, 0x0102)
#define TSDB_CODE_RPC_FQDN_ERROR TAOS_DEF_ERROR_CODE(0, 0x0103)
#define TSDB_CODE_RPC_PORT_EADDRINUSE TAOS_DEF_ERROR_CODE(0, 0x0104)
+#define TSDB_CODE_RPC_BROKEN_LINK TAOS_DEF_ERROR_CODE(0, 0x0105)
//client
#define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200)
@@ -119,7 +122,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_TSC_DUP_COL_NAMES TAOS_DEF_ERROR_CODE(0, 0x021D)
#define TSDB_CODE_TSC_INVALID_TAG_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021E)
#define TSDB_CODE_TSC_INVALID_COLUMN_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021F)
-#define TSDB_CODE_TSC_DUP_TAG_NAMES TAOS_DEF_ERROR_CODE(0, 0x0220)
+#define TSDB_CODE_TSC_DUP_NAMES TAOS_DEF_ERROR_CODE(0, 0x0220)
#define TSDB_CODE_TSC_INVALID_JSON TAOS_DEF_ERROR_CODE(0, 0x0221)
#define TSDB_CODE_TSC_INVALID_JSON_TYPE TAOS_DEF_ERROR_CODE(0, 0x0222)
#define TSDB_CODE_TSC_VALUE_OUT_OF_RANGE TAOS_DEF_ERROR_CODE(0, 0x0223)
@@ -129,6 +132,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_TSC_STMT_CLAUSE_ERROR TAOS_DEF_ERROR_CODE(0, 0X0227)
#define TSDB_CODE_TSC_QUERY_KILLED TAOS_DEF_ERROR_CODE(0, 0X0228)
#define TSDB_CODE_TSC_NO_EXEC_NODE TAOS_DEF_ERROR_CODE(0, 0X0229)
+#define TSDB_CODE_TSC_NOT_STABLE_ERROR TAOS_DEF_ERROR_CODE(0, 0X022a)
// mnode-common
#define TSDB_CODE_MND_APP_ERROR TAOS_DEF_ERROR_CODE(0, 0x0300)
@@ -170,11 +174,12 @@ int32_t* taosGetErrno();
#define TSDB_CODE_MND_DNODE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0341)
#define TSDB_CODE_MND_TOO_MANY_DNODES TAOS_DEF_ERROR_CODE(0, 0x0342)
#define TSDB_CODE_MND_NO_ENOUGH_DNODES TAOS_DEF_ERROR_CODE(0, 0x0343)
-#define TSDB_CODE_MND_INVALID_CLUSTER_CFG TAOS_DEF_ERROR_CODE(0, 0x0344)
-#define TSDB_CODE_MND_INVALID_CLUSTER_ID TAOS_DEF_ERROR_CODE(0, 0x0345)
-#define TSDB_CODE_MND_INVALID_DNODE_CFG TAOS_DEF_ERROR_CODE(0, 0x0346)
-#define TSDB_CODE_MND_INVALID_DNODE_EP TAOS_DEF_ERROR_CODE(0, 0x0347)
-#define TSDB_CODE_MND_INVALID_DNODE_ID TAOS_DEF_ERROR_CODE(0, 0x0348)
+#define TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE TAOS_DEF_ERROR_CODE(0, 0x0344)
+#define TSDB_CODE_MND_INVALID_CLUSTER_CFG TAOS_DEF_ERROR_CODE(0, 0x0345)
+#define TSDB_CODE_MND_INVALID_CLUSTER_ID TAOS_DEF_ERROR_CODE(0, 0x0346)
+#define TSDB_CODE_MND_INVALID_DNODE_CFG TAOS_DEF_ERROR_CODE(0, 0x0347)
+#define TSDB_CODE_MND_INVALID_DNODE_EP TAOS_DEF_ERROR_CODE(0, 0x0348)
+#define TSDB_CODE_MND_INVALID_DNODE_ID TAOS_DEF_ERROR_CODE(0, 0x0349)
// mnode-node
#define TSDB_CODE_MND_MNODE_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0350)
@@ -242,9 +247,11 @@ int32_t* taosGetErrno();
#define TSDB_CODE_MND_COLUMN_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x03AE)
#define TSDB_CODE_MND_FIELD_CONFLICT_WITH_TOPIC TAOS_DEF_ERROR_CODE(0, 0x03AF)
#define TSDB_CODE_MND_SINGLE_STB_MODE_DB TAOS_DEF_ERROR_CODE(0, 0x03B0)
+#define TSDB_CODE_MND_INVALID_SCHEMA_VER TAOS_DEF_ERROR_CODE(0, 0x03B1)
+#define TSDB_CODE_MND_STABLE_UID_NOT_MATCH TAOS_DEF_ERROR_CODE(0, 0x03B2)
// mnode-infoSchema
-#define TSDB_CODE_MND_INVALID_SYS_TABLENAME TAOS_DEF_ERROR_CODE(0, 0x03BA)
+#define TSDB_CODE_MND_INVALID_SYS_TABLENAME TAOS_DEF_ERROR_CODE(0, 0x03BA)
// mnode-func
#define TSDB_CODE_MND_FUNC_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x03C0)
@@ -385,6 +392,10 @@ int32_t* taosGetErrno();
#define TSDB_CODE_QRY_TASK_MSG_ERROR TAOS_DEF_ERROR_CODE(0, 0x0719)
#define TSDB_CODE_QRY_JOB_FREED TAOS_DEF_ERROR_CODE(0, 0x071A)
#define TSDB_CODE_QRY_TASK_STATUS_ERROR TAOS_DEF_ERROR_CODE(0, 0x071B)
+#define TSDB_CODE_QRY_JSON_IN_ERROR TAOS_DEF_ERROR_CODE(0, 0x071C)
+#define TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR TAOS_DEF_ERROR_CODE(0, 0x071D)
+#define TSDB_CODE_QRY_JSON_IN_GROUP_ERROR TAOS_DEF_ERROR_CODE(0, 0x071E)
+#define TSDB_CODE_QRY_JOB_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x071F)
// grant
#define TSDB_CODE_GRANT_EXPIRED TAOS_DEF_ERROR_CODE(0, 0x0800)
@@ -419,6 +430,9 @@ int32_t* taosGetErrno();
#define TSDB_CODE_SYN_NEW_CONFIG_ERROR TAOS_DEF_ERROR_CODE(0, 0x090F)
#define TSDB_CODE_SYN_RECONFIG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0910)
#define TSDB_CODE_SYN_PROPOSE_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0911)
+#define TSDB_CODE_SYN_STANDBY_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0912)
+#define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913)
+#define TSDB_CODE_SYN_TIMEOUT TAOS_DEF_ERROR_CODE(0, 0x0914)
#define TSDB_CODE_SYN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x09FF)
// tq
@@ -463,11 +477,11 @@ int32_t* taosGetErrno();
#define TSDB_CODE_CTG_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2400)
#define TSDB_CODE_CTG_INVALID_INPUT TAOS_DEF_ERROR_CODE(0, 0x2401)
#define TSDB_CODE_CTG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x2402)
-#define TSDB_CODE_CTG_MEM_ERROR TAOS_DEF_ERROR_CODE(0, 0x2403)
-#define TSDB_CODE_CTG_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x2404)
-#define TSDB_CODE_CTG_DB_DROPPED TAOS_DEF_ERROR_CODE(0, 0x2405)
-#define TSDB_CODE_CTG_OUT_OF_SERVICE TAOS_DEF_ERROR_CODE(0, 0x2406)
-#define TSDB_CODE_CTG_VG_META_MISMATCH TAOS_DEF_ERROR_CODE(0, 0x2407)
+#define TSDB_CODE_CTG_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x2403)
+#define TSDB_CODE_CTG_DB_DROPPED TAOS_DEF_ERROR_CODE(0, 0x2404)
+#define TSDB_CODE_CTG_OUT_OF_SERVICE TAOS_DEF_ERROR_CODE(0, 0x2405)
+#define TSDB_CODE_CTG_VG_META_MISMATCH TAOS_DEF_ERROR_CODE(0, 0x2406)
+#define TSDB_CODE_CTG_EXIT TAOS_DEF_ERROR_CODE(0, 0x2407)
//scheduler&qworker
#define TSDB_CODE_SCH_STATUS_ERROR TAOS_DEF_ERROR_CODE(0, 0x2501)
@@ -568,6 +582,10 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x265B)
#define TSDB_CODE_PAR_INVALID_TABLE_OPTION TAOS_DEF_ERROR_CODE(0, 0x265C)
#define TSDB_CODE_PAR_INVALID_INTERP_CLAUSE TAOS_DEF_ERROR_CODE(0, 0x265D)
+#define TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN TAOS_DEF_ERROR_CODE(0, 0x265E)
+#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)
//planner
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
@@ -597,6 +615,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_SML_INVALID_PRECISION_TYPE TAOS_DEF_ERROR_CODE(0, 0x3001)
#define TSDB_CODE_SML_INVALID_DATA TAOS_DEF_ERROR_CODE(0, 0x3002)
#define TSDB_CODE_SML_INVALID_DB_CONF TAOS_DEF_ERROR_CODE(0, 0x3003)
+#define TSDB_CODE_SML_NOT_SAME_TYPE TAOS_DEF_ERROR_CODE(0, 0x3004)
//tsma
#define TSDB_CODE_TSMA_INIT_FAILED TAOS_DEF_ERROR_CODE(0, 0x3100)
@@ -612,9 +631,13 @@ int32_t* taosGetErrno();
//rsma
#define TSDB_CODE_RSMA_INVALID_ENV TAOS_DEF_ERROR_CODE(0, 0x3150)
#define TSDB_CODE_RSMA_INVALID_STAT TAOS_DEF_ERROR_CODE(0, 0x3151)
+#define TSDB_CODE_RSMA_QTASKINFO_CREATE TAOS_DEF_ERROR_CODE(0, 0x3152)
+#define TSDB_CODE_RSMA_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x3153)
//index
#define TSDB_CODE_INDEX_REBUILDING TAOS_DEF_ERROR_CODE(0, 0x3200)
+#define TSDB_CODE_INDEX_INVALID_FILE TAOS_DEF_ERROR_CODE(0, 0x3201)
+
//tmq
#define TSDB_CODE_TMQ_INVALID_MSG TAOS_DEF_ERROR_CODE(0, 0x4000)
diff --git a/include/util/tconfig.h b/include/util/tconfig.h
index 06fa9fd9aaf351f59b761a57cc96a4f3529ecf91..102656da2bdb17b4c347b3a8e9bbcf85e0e030ca 100644
--- a/include/util/tconfig.h
+++ b/include/util/tconfig.h
@@ -33,7 +33,8 @@ typedef enum {
CFG_STYPE_ENV_CMD,
CFG_STYPE_APOLLO_URL,
CFG_STYPE_ARG_LIST,
- CFG_STYPE_TAOS_OPTIONS
+ CFG_STYPE_TAOS_OPTIONS,
+ CFG_STYPE_ALTER_CMD,
} ECfgSrcType;
typedef enum {
@@ -104,6 +105,8 @@ int32_t cfgAddTimezone(SConfig *pCfg, const char *name, const char *defaultVal);
const char *cfgStypeStr(ECfgSrcType type);
const char *cfgDtypeStr(ECfgDataType type);
+void cfgDumpItemValue(SConfigItem *pItem, char* buf, int32_t bufSize, int32_t* pLen);
+
void cfgDumpCfg(SConfig *pCfg, bool tsc, bool dump);
int32_t cfgGetApollUrl(const char **envCmd, const char *envFile, char* apolloUrl);
diff --git a/include/util/tdef.h b/include/util/tdef.h
index c5a8b95a08cc37e4d665e01f5de01eca97b16087..55194d8647c210409088433834236f5b9051925a 100644
--- a/include/util/tdef.h
+++ b/include/util/tdef.h
@@ -49,12 +49,12 @@ extern const int32_t TYPE_BYTES[16];
#define TSDB_DATA_BOOL_NULL 0x02
#define TSDB_DATA_TINYINT_NULL 0x80
#define TSDB_DATA_SMALLINT_NULL 0x8000
-#define TSDB_DATA_INT_NULL 0x80000000L
-#define TSDB_DATA_BIGINT_NULL 0x8000000000000000L
+#define TSDB_DATA_INT_NULL 0x80000000LL
+#define TSDB_DATA_BIGINT_NULL 0x8000000000000000LL
#define TSDB_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
-#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000L // an NAN
+#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
#define TSDB_DATA_BINARY_NULL 0xFF
@@ -108,8 +108,8 @@ extern const int32_t TYPE_BYTES[16];
#define TSDB_INS_USER_STABLES_DBNAME_COLID 2
#define TSDB_TICK_PER_SECOND(precision) \
- ((int64_t)((precision) == TSDB_TIME_PRECISION_MILLI ? 1e3L \
- : ((precision) == TSDB_TIME_PRECISION_MICRO ? 1e6L : 1e9L)))
+ ((int64_t)((precision) == TSDB_TIME_PRECISION_MILLI ? 1000LL \
+ : ((precision) == TSDB_TIME_PRECISION_MICRO ? 1000000LL : 1000000000LL)))
#define T_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#define T_APPEND_MEMBER(dst, ptr, type, member) \
@@ -134,7 +134,7 @@ typedef enum EOperatorType {
OP_TYPE_MINUS,
OP_TYPE_ASSIGN,
- // bit operator
+ // bitwise operator
OP_TYPE_BIT_AND,
OP_TYPE_BIT_OR,
@@ -287,7 +287,7 @@ typedef enum ELogicConditionType {
#define TSDB_MULTI_TABLEMETA_MAX_NUM 100000 // maximum batch size allowed to load table meta
#define TSDB_MIN_VNODES_PER_DB 1
-#define TSDB_MAX_VNODES_PER_DB 4096
+#define TSDB_MAX_VNODES_PER_DB 1024
#define TSDB_DEFAULT_VN_PER_DB 2
#define TSDB_MIN_BUFFER_PER_VNODE 3 // unit MB
#define TSDB_MAX_BUFFER_PER_VNODE 16384 // unit MB
@@ -331,9 +331,12 @@ typedef enum ELogicConditionType {
#define TSDB_DB_STRICT_OFF 0
#define TSDB_DB_STRICT_ON 1
#define TSDB_DEFAULT_DB_STRICT 0
-#define TSDB_MIN_DB_CACHE_LAST_ROW 0
-#define TSDB_MAX_DB_CACHE_LAST_ROW 3
-#define TSDB_DEFAULT_CACHE_LAST_ROW 0
+#define TSDB_MIN_DB_CACHE_LAST 0
+#define TSDB_MAX_DB_CACHE_LAST 3
+#define TSDB_DEFAULT_CACHE_LAST 0
+#define TSDB_MIN_DB_CACHE_LAST_SIZE 1 // MB
+#define TSDB_MAX_DB_CACHE_LAST_SIZE 65536
+#define TSDB_DEFAULT_CACHE_LAST_SIZE 1
#define TSDB_DB_STREAM_MODE_OFF 0
#define TSDB_DB_STREAM_MODE_ON 1
#define TSDB_DEFAULT_DB_STREAM_MODE 0
@@ -443,8 +446,8 @@ enum {
#define VNODE_HANDLE -3
#define BNODE_HANDLE -4
-#define TSDB_CONFIG_OPTION_LEN 16
-#define TSDB_CONIIG_VALUE_LEN 48
+#define TSDB_CONFIG_OPTION_LEN 32
+#define TSDB_CONFIG_VALUE_LEN 64
#define TSDB_CONFIG_NUMBER 8
#define QUERY_ID_SIZE 20
diff --git a/include/util/tencode.h b/include/util/tencode.h
index a13afd44480eef8397befb42c2fe2a12c322b01e..ad642cd612db4d1bb31f57b7a49d977e90978ee5 100644
--- a/include/util/tencode.h
+++ b/include/util/tencode.h
@@ -440,7 +440,7 @@ static FORCE_INLINE bool tDecodeIsEnd(SDecoder* pCoder) { return (pCoder->size =
static FORCE_INLINE void* tEncoderMalloc(SEncoder* pCoder, int32_t size) {
void* p = NULL;
- SCoderMem* pMem = (SCoderMem*)taosMemoryMalloc(sizeof(*pMem) + size);
+ SCoderMem* pMem = (SCoderMem*)taosMemoryCalloc(1, sizeof(*pMem) + size);
if (pMem) {
pMem->next = pCoder->mList;
pCoder->mList = pMem;
@@ -451,7 +451,7 @@ static FORCE_INLINE void* tEncoderMalloc(SEncoder* pCoder, int32_t size) {
static FORCE_INLINE void* tDecoderMalloc(SDecoder* pCoder, int32_t size) {
void* p = NULL;
- SCoderMem* pMem = (SCoderMem*)taosMemoryMalloc(sizeof(*pMem) + size);
+ SCoderMem* pMem = (SCoderMem*)taosMemoryCalloc(1, sizeof(*pMem) + size);
if (pMem) {
pMem->next = pCoder->mList;
pCoder->mList = pMem;
@@ -477,22 +477,6 @@ static FORCE_INLINE void* tDecoderMalloc(SDecoder* pCoder, int32_t size) {
return n; \
} while (0)
-#define tGetV(p, v) \
- do { \
- int32_t n = 0; \
- if (v) *v = 0; \
- for (;;) { \
- if (p[n] <= 0x7f) { \
- if (v) (*v) |= (p[n] << (7 * n)); \
- n++; \
- break; \
- } \
- if (v) (*v) |= ((p[n] & 0x7f) << (7 * n)); \
- n++; \
- } \
- return n; \
- } while (0)
-
// PUT
static FORCE_INLINE int32_t tPutU8(uint8_t* p, uint8_t v) {
if (p) ((uint8_t*)p)[0] = v;
@@ -607,7 +591,22 @@ static FORCE_INLINE int32_t tGetI64(uint8_t* p, int64_t* v) {
return sizeof(int64_t);
}
-static FORCE_INLINE int32_t tGetU16v(uint8_t* p, uint16_t* v) { tGetV(p, v); }
+static FORCE_INLINE int32_t tGetU16v(uint8_t* p, uint16_t* v) {
+ int32_t n = 0;
+
+ if (v) *v = 0;
+ for (;;) {
+ if (p[n] <= 0x7f) {
+ if (v) (*v) |= (((uint16_t)p[n]) << (7 * n));
+ n++;
+ break;
+ }
+ if (v) (*v) |= (((uint16_t)(p[n] & 0x7f)) << (7 * n));
+ n++;
+ }
+
+ return n;
+}
static FORCE_INLINE int32_t tGetI16v(uint8_t* p, int16_t* v) {
int32_t n;
@@ -619,7 +618,22 @@ static FORCE_INLINE int32_t tGetI16v(uint8_t* p, int16_t* v) {
return n;
}
-static FORCE_INLINE int32_t tGetU32v(uint8_t* p, uint32_t* v) { tGetV(p, v); }
+static FORCE_INLINE int32_t tGetU32v(uint8_t* p, uint32_t* v) {
+ int32_t n = 0;
+
+ if (v) *v = 0;
+ for (;;) {
+ if (p[n] <= 0x7f) {
+ if (v) (*v) |= (((uint32_t)p[n]) << (7 * n));
+ n++;
+ break;
+ }
+ if (v) (*v) |= (((uint32_t)(p[n] & 0x7f)) << (7 * n));
+ n++;
+ }
+
+ return n;
+}
static FORCE_INLINE int32_t tGetI32v(uint8_t* p, int32_t* v) {
int32_t n;
@@ -631,7 +645,22 @@ static FORCE_INLINE int32_t tGetI32v(uint8_t* p, int32_t* v) {
return n;
}
-static FORCE_INLINE int32_t tGetU64v(uint8_t* p, uint64_t* v) { tGetV(p, v); }
+static FORCE_INLINE int32_t tGetU64v(uint8_t* p, uint64_t* v) {
+ int32_t n = 0;
+
+ if (v) *v = 0;
+ for (;;) {
+ if (p[n] <= 0x7f) {
+ if (v) (*v) |= (((uint64_t)p[n]) << (7 * n));
+ n++;
+ break;
+ }
+ if (v) (*v) |= (((uint64_t)(p[n] & 0x7f)) << (7 * n));
+ n++;
+ }
+
+ return n;
+}
static FORCE_INLINE int32_t tGetI64v(uint8_t* p, int64_t* v) {
int32_t n;
diff --git a/include/util/thash.h b/include/util/thash.h
index fc8785a8fb51ac781355b4e10d9f1dec63a1732e..781c22a56aaba0d449d1f711b32fe4bd75a39003 100644
--- a/include/util/thash.h
+++ b/include/util/thash.h
@@ -188,7 +188,7 @@ void *taosHashGetKey(void *data, size_t* keyLen);
void *taosHashAcquire(SHashObj *pHashObj, const void *key, size_t keyLen);
/**
- * release the prevous acquired obj
+ * release the previous acquired obj
*
* @param pHashObj
* @param data
diff --git a/include/util/tlockfree.h b/include/util/tlockfree.h
index 44e43f81cf79aab5c646fc30b81f014932eb0b06..8db6be88609baff3d95b63410ad694ca833a4418 100644
--- a/include/util/tlockfree.h
+++ b/include/util/tlockfree.h
@@ -71,11 +71,11 @@ typedef void (*_ref_fn_t)(const void *pObj);
// single writer multiple reader lock
typedef volatile int32_t SRWLatch;
-void taosInitRWLatch(SRWLatch *pLatch);
-void taosWLockLatch(SRWLatch *pLatch);
-void taosWUnLockLatch(SRWLatch *pLatch);
-void taosRLockLatch(SRWLatch *pLatch);
-void taosRUnLockLatch(SRWLatch *pLatch);
+void taosInitRWLatch(SRWLatch *pLatch);
+void taosWLockLatch(SRWLatch *pLatch);
+void taosWUnLockLatch(SRWLatch *pLatch);
+void taosRLockLatch(SRWLatch *pLatch);
+void taosRUnLockLatch(SRWLatch *pLatch);
int32_t taosWTryLockLatch(SRWLatch *pLatch);
// copy on read
diff --git a/include/util/tlog.h b/include/util/tlog.h
index 988d9c6890832d17a7e9acd2b496e3ef6ba63d90..d186c328412d5eb25983103afced9d3e00c8dccd 100644
--- a/include/util/tlog.h
+++ b/include/util/tlog.h
@@ -60,7 +60,7 @@ extern int32_t tsdbDebugFlag;
extern int32_t tqDebugFlag;
extern int32_t fsDebugFlag;
extern int32_t metaDebugFlag;
-extern int32_t fnDebugFlag;
+extern int32_t udfDebugFlag;
extern int32_t smaDebugFlag;
extern int32_t idxDebugFlag;
@@ -94,7 +94,7 @@ void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, cons
#define pError(...) { taosPrintLog("APP ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }
#define pPrint(...) { taosPrintLog("APP ", DEBUG_INFO, 255, __VA_ARGS__); }
// clang-format on
-
+//#define BUF_PAGE_DEBUG
#ifdef __cplusplus
}
#endif
diff --git a/include/util/tmallocator.h b/include/util/tmallocator.h
deleted file mode 100644
index e9eb3e1b727755fdcf34f5b9c78771362d6a0b6e..0000000000000000000000000000000000000000
--- a/include/util/tmallocator.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _TD_UTIL_MALLOCATOR_H_
-#define _TD_UTIL_MALLOCATOR_H_
-
-#include "os.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Memory allocator
-#define TD_MEM_ALCT(TYPE) \
- struct { \
- void *(*malloc_)(struct TYPE *, uint64_t size); \
- void (*free_)(struct TYPE *, void *ptr); \
- }
-#define TD_MA_MALLOC_FUNC(TMA) (TMA)->malloc_
-#define TD_MA_FREE_FUNC(TMA) (TMA)->free_
-
-#define TD_MA_MALLOC(TMA, SIZE) (*((TMA)->malloc_))(TMA, (SIZE))
-#define TD_MA_FREE(TMA, PTR) (*((TMA)->free_))(TMA, (PTR))
-
-typedef struct SMemAllocator {
- void *impl;
- TD_MEM_ALCT(SMemAllocator);
-} SMemAllocator;
-
-#define tMalloc(pMA, SIZE) TD_MA_MALLOC(PMA, SIZE)
-#define tFree(pMA, PTR) TD_MA_FREE(PMA, PTR)
-
-typedef struct SMemAllocatorFactory {
- void *impl;
- SMemAllocator *(*create)(struct SMemAllocatorFactory *);
- void (*destroy)(struct SMemAllocatorFactory *, SMemAllocator *);
-} SMemAllocatorFactory;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_TD_UTIL_MALLOCATOR_H_*/
\ No newline at end of file
diff --git a/include/util/tpagedbuf.h b/include/util/tpagedbuf.h
index af82e29ec500aec1d5519d59cb5f184bf736d0e4..ef266068cbaff046ec6ebcf0bf02d0b44ee9d3a2 100644
--- a/include/util/tpagedbuf.h
+++ b/include/util/tpagedbuf.h
@@ -28,7 +28,7 @@ typedef struct SArray* SIDList;
typedef struct SPageInfo SPageInfo;
typedef struct SDiskbasedBuf SDiskbasedBuf;
-#define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) // in bytes
+#define DEFAULT_INTERN_BUF_PAGE_SIZE (1024LL) // in bytes
typedef struct SFilePage {
int32_t num;
diff --git a/include/util/tqueue.h b/include/util/tqueue.h
index 466c577c0079d07774722ff2efdd30bf207e0fc3..0f4f1db9eee4c1b57e25464cd947c1c96218fbec 100644
--- a/include/util/tqueue.h
+++ b/include/util/tqueue.h
@@ -44,6 +44,8 @@ typedef struct STaosQset STaosQset;
typedef struct STaosQall STaosQall;
typedef struct {
void *ahandle;
+ void *fp;
+ void *queue;
int32_t workerId;
int32_t threadNum;
int64_t timestamp;
@@ -65,6 +67,7 @@ void taosFreeQitem(void *pItem);
void taosWriteQitem(STaosQueue *queue, void *pItem);
int32_t taosReadQitem(STaosQueue *queue, void **ppItem);
bool taosQueueEmpty(STaosQueue *queue);
+void taosUpdateItemSize(STaosQueue *queue, int32_t items);
int32_t taosQueueItemSize(STaosQueue *queue);
int64_t taosQueueMemorySize(STaosQueue *queue);
@@ -81,8 +84,8 @@ int32_t taosAddIntoQset(STaosQset *qset, STaosQueue *queue, void *ahandle);
void taosRemoveFromQset(STaosQset *qset, STaosQueue *queue);
int32_t taosGetQueueNumber(STaosQset *qset);
-int32_t taosReadQitemFromQset(STaosQset *qset, void **ppItem, int64_t *ts, void **ahandle, FItem *itemFp);
-int32_t taosReadAllQitemsFromQset(STaosQset *qset, STaosQall *qall, void **ahandle, FItems *itemsFp);
+int32_t taosReadQitemFromQset(STaosQset *qset, void **ppItem, SQueueInfo *qinfo);
+int32_t taosReadAllQitemsFromQset(STaosQset *qset, STaosQall *qall, SQueueInfo *qinfo);
void taosResetQsetThread(STaosQset *qset, void *pItem);
extern int64_t tsRpcQueueMemoryAllowed;
diff --git a/include/util/ttrace.h b/include/util/ttrace.h
index 206cbbf28d9a785873333e3d32d7a67a0115d603..579768228a6086fda8656b0dca1430e7da06f9a6 100644
--- a/include/util/ttrace.h
+++ b/include/util/ttrace.h
@@ -45,9 +45,11 @@ typedef struct STraceId {
#define TRACE_GET_MSGID(traceId) (traceId)->msgId
-#define TRACE_TO_STR(traceId, buf) \
- do { \
- sprintf(buf, "0x%" PRIx64 ":0x%" PRIx64 "", traceId->rootId, traceId->msgId); \
+#define TRACE_TO_STR(traceId, buf) \
+ do { \
+ int64_t rootId = (traceId) != NULL ? (traceId)->rootId : 0; \
+ int64_t msgId = (traceId) != NULL ? (traceId)->msgId : 0; \
+ sprintf(buf, "0x%" PRIx64 ":0x%" PRIx64 "", rootId, msgId); \
} while (0)
#ifdef __cplusplus
diff --git a/include/util/tutil.h b/include/util/tutil.h
index b29e1f7cfa889944b53b3603bd0c8fefc8ece1f0..2e96c5b88e239b8ba6df3dbe4fc07040639e6cdb 100644
--- a/include/util/tutil.h
+++ b/include/util/tutil.h
@@ -44,6 +44,9 @@ uint32_t ip2uint(const char *const ip_addr);
void taosIp2String(uint32_t ip, char *str);
void taosIpPort2String(uint32_t ip, uint16_t port, char *str);
+void *tmemmem(const char *haystack, int hlen, const char *needle, int nlen);
+char *strDupUnquo(const char *src);
+
static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, size_t inLen, char *target) {
T_MD5_CTX context;
tMD5Init(&context);
@@ -59,10 +62,10 @@ static FORCE_INLINE void taosEncryptPass_c(uint8_t *inBuf, size_t len, char *tar
tMD5Final(&context);
char buf[TSDB_PASSWORD_LEN + 1];
- sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0],
- context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5],
- context.digest[6], context.digest[7], context.digest[8], context.digest[9], context.digest[10],
- context.digest[11], context.digest[12], context.digest[13], context.digest[14], context.digest[15]);
+ sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0], context.digest[1],
+ context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6],
+ context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11],
+ context.digest[12], context.digest[13], context.digest[14], context.digest[15]);
memcpy(target, buf, TSDB_PASSWORD_LEN);
}
diff --git a/include/util/types.h b/include/util/types.h
index d48995418e530646e8ef540bfb0630fc90cd9636..1360307156ab726b274f45e18dc607798941804f 100644
--- a/include/util/types.h
+++ b/include/util/types.h
@@ -32,7 +32,7 @@ extern "C" {
#define GET_UINT64_VAL(x) (*(uint64_t *)(x))
static FORCE_INLINE float taos_align_get_float(const char *pBuf) {
-#if __STDC_VERSION__ >= 201112L
+#if __STDC_VERSION__ >= 201112LL
static_assert(sizeof(float) == sizeof(uint32_t), "sizeof(float) must equal to sizeof(uint32_t)");
#else
assert(sizeof(float) == sizeof(uint32_t));
@@ -43,7 +43,7 @@ static FORCE_INLINE float taos_align_get_float(const char *pBuf) {
}
static FORCE_INLINE double taos_align_get_double(const char *pBuf) {
-#if __STDC_VERSION__ >= 201112L
+#if __STDC_VERSION__ >= 201112LL
static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) must equal to sizeof(uint64_t)");
#else
assert(sizeof(double) == sizeof(uint64_t));
@@ -83,6 +83,7 @@ typedef uint16_t VarDataLenT; // maxVarDataLen: 32767
#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)
diff --git a/packaging/cfg/tarbitratord.service b/packaging/cfg/tarbitratord.service
deleted file mode 100644
index d60cb536b094fe6b6c472d55076dc4d1db669d68..0000000000000000000000000000000000000000
--- a/packaging/cfg/tarbitratord.service
+++ /dev/null
@@ -1,20 +0,0 @@
-[Unit]
-Description=TDengine arbitrator service
-After=network-online.target
-Wants=network-online.target
-
-[Service]
-Type=simple
-ExecStart=/usr/bin/tarbitrator
-TimeoutStopSec=1000000s
-LimitNOFILE=infinity
-LimitNPROC=infinity
-LimitCORE=infinity
-TimeoutStartSec=0
-StandardOutput=null
-Restart=always
-StartLimitBurst=3
-StartLimitInterval=60s
-
-[Install]
-WantedBy=multi-user.target
diff --git a/packaging/check_package.sh b/packaging/check_package.sh
index 81abff57a586d116ead0137f96697ece04250d6b..e728c6455abdb149d43a4e46d2b7730511b8800d 100644
--- a/packaging/check_package.sh
+++ b/packaging/check_package.sh
@@ -170,7 +170,7 @@ function check_lib_path() {
function check_header_path() {
# check all header
- header_dir=("taos.h" "taosdef.h" "taoserror.h")
+ header_dir=("taos.h" "taosdef.h" "taoserror.h" "taosudf.h")
for i in "${header_dir[@]}";do
check_link ${inc_link_dir}/$i
done
diff --git a/packaging/deb/DEBIAN/preinst b/packaging/deb/DEBIAN/preinst
index 5217a8229571bf993c6c3df8f82beb1ed67c3e96..c9957fc89c9570f9195e7ab0859db4583cbce0cf 100644
--- a/packaging/deb/DEBIAN/preinst
+++ b/packaging/deb/DEBIAN/preinst
@@ -37,4 +37,5 @@ if [ -f "${install_main_dir}/taosadapter.service" ]; then
fi
# there can not libtaos.so*, otherwise ln -s error
-${csudo}rm -f ${install_main_dir}/driver/libtaos* || :
+${csudo}rm -f ${install_main_dir}/driver/libtaos.* || :
+${csudo}rm -f ${install_main_dir}/driver/libtaosws.* || :
diff --git a/packaging/deb/DEBIAN/prerm b/packaging/deb/DEBIAN/prerm
index c01db74701f99e52cc45b589d8fe7b07c4c8afe1..5ff970bb700f32ff2848183feef2395f55910ae7 100644
--- a/packaging/deb/DEBIAN/prerm
+++ b/packaging/deb/DEBIAN/prerm
@@ -29,7 +29,12 @@ else
${csudo}rm -f ${bin_link_dir}/taosdemo || :
${csudo}rm -f ${cfg_link_dir}/* || :
${csudo}rm -f ${inc_link_dir}/taos.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosdef.h || :
+ ${csudo}rm -f ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosudf.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosws.h || :
${csudo}rm -f ${lib_link_dir}/libtaos.* || :
+ ${csudo}rm -f ${lib_link_dir}/libtaosws.* || :
${csudo}rm -f ${log_link_dir} || :
${csudo}rm -f ${data_link_dir} || :
diff --git a/packaging/deb/makedeb.sh b/packaging/deb/makedeb.sh
index 5a14aea4ec14d64913845cf7efb0615abd7b6f93..1a4131ec6f059d25be409976246f767b6c3ec840 100755
--- a/packaging/deb/makedeb.sh
+++ b/packaging/deb/makedeb.sh
@@ -30,6 +30,7 @@ mkdir -p ${pkg_dir}
cd ${pkg_dir}
libfile="libtaos.so.${tdengine_ver}"
+wslibfile="libtaosws.so"
# create install dir
install_home_path="/usr/local/taos"
@@ -67,9 +68,12 @@ fi
cp ${compile_dir}/build/bin/taos ${pkg_dir}${install_home_path}/bin
cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_path}/driver
+cp ${compile_dir}/build/lib/${wslibfile} ${pkg_dir}${install_home_path}/driver ||:
cp ${compile_dir}/../include/client/taos.h ${pkg_dir}${install_home_path}/include
cp ${compile_dir}/../include/common/taosdef.h ${pkg_dir}${install_home_path}/include
cp ${compile_dir}/../include/util/taoserror.h ${pkg_dir}${install_home_path}/include
+cp ${compile_dir}/../include/libs/function/taosudf.h ${pkg_dir}${install_home_path}/include
+cp ${compile_dir}/../src/inc/taosws.h ${pkg_dir}${install_home_path}/include ||:
cp -r ${top_dir}/examples/* ${pkg_dir}${install_home_path}/examples
#cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector
#cp -r ${top_dir}/src/connector/go ${pkg_dir}${install_home_path}/connector
diff --git a/packaging/deb/tarbitratord b/packaging/deb/tarbitratord
deleted file mode 100644
index 3f97c3c0c2143817ad4ecbb13fabd8c09fb44c69..0000000000000000000000000000000000000000
--- a/packaging/deb/tarbitratord
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-#
-# Modified from original source: Elastic Search
-# https://github.com/elasticsearch/elasticsearch
-# Thank you to the Elastic Search authors
-#
-# chkconfig: 2345 99 01
-#
-### BEGIN INIT INFO
-# Provides: taoscluster
-# Required-Start: $local_fs $network $syslog
-# Required-Stop: $local_fs $network $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Starts taoscluster tarbitrator
-# Description: Starts taoscluster tarbitrator, a arbitrator
-### END INIT INFO
-
-set -e
-
-PATH="/bin:/usr/bin:/sbin:/usr/sbin"
-NAME="taoscluster"
-USER="root"
-GROUP="root"
-DAEMON="/usr/local/taos/bin/tarbitrator"
-DAEMON_OPTS=""
-PID_FILE="/var/run/$NAME.pid"
-APPARGS=""
-
-# Maximum number of open files
-MAX_OPEN_FILES=65535
-
-. /lib/lsb/init-functions
-
-case "$1" in
- start)
-
- log_action_begin_msg "Starting tarbitrator..."
- if start-stop-daemon --test --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile "$PID_FILE" --exec "$DAEMON" -- $APPARGS &> /dev/null; then
-
- touch "$PID_FILE" && chown "$USER":"$GROUP" "$PID_FILE"
-
- if [ -n "$MAX_OPEN_FILES" ]; then
- ulimit -n $MAX_OPEN_FILES
- fi
-
- start-stop-daemon --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile "$PID_FILE" --exec "$DAEMON" -- $APPARGS
-
- log_end_msg $?
- fi
- ;;
-
- stop)
- log_action_begin_msg "Stopping tarbitrator..."
- set +e
- if [ -f "$PID_FILE" ]; then
- start-stop-daemon --stop --pidfile "$PID_FILE" --user "$USER" --retry=TERM/120/KILL/5 > /dev/null
- if [ $? -eq 1 ]; then
- log_action_cont_msg "TSD is not running but pid file exists, cleaning up"
- elif [ $? -eq 3 ]; then
- PID="`cat $PID_FILE`"
- log_failure_msg "Failed to stop tarbitrator (pid $PID)"
- exit 1
- fi
- rm -f "$PID_FILE"
- else
- log_action_cont_msg "tarbitrator was not running"
- fi
- log_action_end_msg 0
- set -e
- ;;
-
- restart|force-reload)
- if [ -f "$PID_FILE" ]; then
- $0 stop
- sleep 1
- fi
- $0 start
- ;;
- status)
- status_of_proc -p "$PID_FILE" "$DAEMON" "$NAME"
- ;;
- *)
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/packaging/release.sh b/packaging/release.sh
index 00a4ad7009d9b5293bc5b0ee0efd566159c69450..3426c2856d03573cb6ed6ec6078c38dfa6371cb0 100755
--- a/packaging/release.sh
+++ b/packaging/release.sh
@@ -111,9 +111,9 @@ else
fi
csudo=""
-if command -v sudo > /dev/null; then
- csudo="sudo "
-fi
+#if command -v sudo > /dev/null; then
+# csudo="sudo "
+#fi
function is_valid_version() {
[ -z $1 ] && return 1 || :
@@ -182,14 +182,10 @@ cd "${curr_dir}"
# 2. cmake executable file
compile_dir="${top_dir}/debug"
if [ -d ${compile_dir} ]; then
- ${csudo}rm -rf ${compile_dir}
+ rm -rf ${compile_dir}
fi
-if [ "$osType" != "Darwin" ]; then
- ${csudo}mkdir -p ${compile_dir}
-else
- mkdir -p ${compile_dir}
-fi
+mkdir -p ${compile_dir}
cd ${compile_dir}
if [[ "$allocator" == "jemalloc" ]]; then
@@ -255,18 +251,18 @@ if [ "$osType" != "Darwin" ]; then
echo "====do deb package for the ubuntu system===="
output_dir="${top_dir}/debs"
if [ -d ${output_dir} ]; then
- ${csudo}rm -rf ${output_dir}
+ rm -rf ${output_dir}
fi
- ${csudo}mkdir -p ${output_dir}
+ mkdir -p ${output_dir}
cd ${script_dir}/deb
${csudo}./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
if [[ "$pagMode" == "full" ]]; then
if [ -d ${top_dir}/tools/taos-tools/packaging/deb ]; then
cd ${top_dir}/tools/taos-tools/packaging/deb
+ taos_tools_ver=$(git describe --tags | sed -e 's/ver-//g' | awk -F '-' '{print $1}')
[ -z "$taos_tools_ver" ] && taos_tools_ver="0.1.0"
- taos_tools_ver=$(git describe --tags | sed -e 's/ver-//g' | awk -F '-' '{print $1}')
${csudo}./make-taos-tools-deb.sh ${top_dir} \
${compile_dir} ${output_dir} ${taos_tools_ver} ${cpuType} ${osType} ${verMode} ${verType}
fi
@@ -280,18 +276,18 @@ if [ "$osType" != "Darwin" ]; then
echo "====do rpm package for the centos system===="
output_dir="${top_dir}/rpms"
if [ -d ${output_dir} ]; then
- ${csudo}rm -rf ${output_dir}
+ rm -rf ${output_dir}
fi
- ${csudo}mkdir -p ${output_dir}
+ mkdir -p ${output_dir}
cd ${script_dir}/rpm
${csudo}./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
if [[ "$pagMode" == "full" ]]; then
if [ -d ${top_dir}/tools/taos-tools/packaging/rpm ]; then
cd ${top_dir}/tools/taos-tools/packaging/rpm
+ taos_tools_ver=$(git describe --tags | sed -e 's/ver-//g' | awk -F '-' '{print $1}' | sed -e 's/-/_/g')
[ -z "$taos_tools_ver" ] && taos_tools_ver="0.1.0"
- taos_tools_ver=$(git describe --tags | sed -e 's/ver-//g' | awk -F '-' '{print $1}' | sed -e 's/-/_/g')
${csudo}./make-taos-tools-rpm.sh ${top_dir} \
${compile_dir} ${output_dir} ${taos_tools_ver} ${cpuType} ${osType} ${verMode} ${verType}
fi
@@ -306,7 +302,6 @@ if [ "$osType" != "Darwin" ]; then
${csudo}./makepkg.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${verNumberComp} ${dbName}
${csudo}./makeclient.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${dbName}
- # ${csudo}./makearbi.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode}
else
# only make client for Darwin
diff --git a/packaging/rpm/makerpm.sh b/packaging/rpm/makerpm.sh
old mode 100644
new mode 100755
diff --git a/packaging/rpm/tarbitratord b/packaging/rpm/tarbitratord
deleted file mode 100644
index 68138f5c1d5d4491b5fda52b08cfd51a039ffc64..0000000000000000000000000000000000000000
--- a/packaging/rpm/tarbitratord
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/bin/bash
-#
-# tarbitratord This shell script takes care of starting and stopping tarbitrator.
-#
-# chkconfig: 2345 99 01
-# description: tarbitrator is a arbitrator used in TDengine cluster.
-#
-#
-### BEGIN INIT INFO
-# Provides: taoscluster
-# Required-Start: $network $local_fs $remote_fs
-# Required-Stop: $network $local_fs $remote_fs
-# Short-Description: start and stop tarbitrator
-# Description: tarbitrator is a arbitrator used in TDengine cluster.
-### END INIT INFO
-
-# Source init functions
-. /etc/init.d/functions
-
-# Maximum number of open files
-MAX_OPEN_FILES=65535
-
-# Default program options
-NAME=tarbitrator
-PROG=/usr/local/taos/bin/tarbitrator
-USER=root
-GROUP=root
-
-# Default directories
-LOCK_DIR=/var/lock/subsys
-PID_DIR=/var/run/$NAME
-
-# Set file names
-LOCK_FILE=$LOCK_DIR/$NAME
-PID_FILE=$PID_DIR/$NAME.pid
-
-[ -e $PID_DIR ] || mkdir -p $PID_DIR
-
-PROG_OPTS=""
-
-start() {
- echo -n "Starting ${NAME}: "
- # check identity
- curid="`id -u -n`"
- if [ "$curid" != root ] && [ "$curid" != "$USER" ] ; then
- echo "Must be run as root or $USER, but was run as $curid"
- return 1
- fi
- # Sets the maximum number of open file descriptors allowed.
- ulimit -n $MAX_OPEN_FILES
- curulimit="`ulimit -n`"
- if [ "$curulimit" -lt $MAX_OPEN_FILES ] ; then
- echo "'ulimit -n' must be greater than or equal to $MAX_OPEN_FILES, is $curulimit"
- return 1
- fi
-
- if [ "`id -u -n`" == root ] ; then
- # Changes the owner of the lock, and the pid files to allow
- # non-root OpenTSDB daemons to run /usr/share/opentsdb/bin/opentsdb_restart.py.
- touch $LOCK_FILE && chown $USER:$GROUP $LOCK_FILE
- touch $PID_FILE && chown $USER:$GROUP $PID_FILE
- daemon --user $USER --pidfile $PID_FILE "$PROG $PROG_OPTS &> /dev/null &"
- else
- # Don't have to change user.
- daemon --pidfile $PID_FILE "$PROG $PROG_OPTS &> /dev/null &"
- fi
- retval=$?
- sleep 2
- echo
- [ $retval -eq 0 ] && (findproc > $PID_FILE && touch $LOCK_FILE)
- return $retval
-}
-
-stop() {
- echo -n "Stopping ${NAME}: "
- killproc -p $PID_FILE $NAME
- retval=$?
- echo
- # Non-root users don't have enough permission to remove pid and lock files.
- # So, the opentsdb_restart.py cannot get rid of the files, and the command
- # "service opentsdb status" will complain about the existing pid file.
- # Makes the pid file empty.
- echo > $PID_FILE
- [ $retval -eq 0 ] && (rm -f $PID_FILE && rm -f $LOCK_FILE)
- return $retval
-}
-
-restart() {
- stop
- start
-}
-
-reload() {
- restart
-}
-
-force_reload() {
- restart
-}
-
-rh_status() {
- # run checks to determine if the service is running or use generic status
- status -p $PID_FILE -l $LOCK_FILE $NAME
-}
-
-rh_status_q() {
- rh_status >/dev/null 2>&1
-}
-
-case "$1" in
- start)
- rh_status_q && exit 0
- $1
- ;;
- stop)
- rh_status_q || exit 0
- $1
- ;;
- restart)
- $1
- ;;
- reload)
- rh_status_q || exit 7
- $1
- ;;
- force-reload)
- force_reload
- ;;
- status)
- rh_status
- ;;
- condrestart|try-restart)
- rh_status_q || exit 0
- restart
- ;;
- *)
- echo "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
- exit 2
-esac
-
-exit $?
diff --git a/packaging/rpm/tdengine.spec b/packaging/rpm/tdengine.spec
index d61d12932f219e16911a998125518205b91664d2..02e7e9b5e5ba5587f7cc102a42aa6991c8ea2c8a 100644
--- a/packaging/rpm/tdengine.spec
+++ b/packaging/rpm/tdengine.spec
@@ -42,6 +42,7 @@ echo version: %{_version}
echo buildroot: %{buildroot}
libfile="libtaos.so.%{_version}"
+wslibfile="libtaosws.so"
# create install path, and cp file
mkdir -p %{buildroot}%{homepath}/bin
@@ -74,9 +75,12 @@ if [ -f %{_compiledir}/build/bin/taosadapter ]; then
cp %{_compiledir}/build/bin/taosadapter %{buildroot}%{homepath}/bin ||:
fi
cp %{_compiledir}/build/lib/${libfile} %{buildroot}%{homepath}/driver
+cp %{_compiledir}/build/lib/${wslibfile} %{buildroot}%{homepath}/driver ||:
cp %{_compiledir}/../include/client/taos.h %{buildroot}%{homepath}/include
cp %{_compiledir}/../include/common/taosdef.h %{buildroot}%{homepath}/include
cp %{_compiledir}/../include/util/taoserror.h %{buildroot}%{homepath}/include
+cp %{_compiledir}/../include/libs/function/taosudf.h %{buildroot}%{homepath}/include
+cp %{_compiledir}/../src/inc/taosws.h %{buildroot}%{homepath}/include ||:
#cp -r %{_compiledir}/../src/connector/python %{buildroot}%{homepath}/connector
#cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector
#cp -r %{_compiledir}/../src/connector/nodejs %{buildroot}%{homepath}/connector
@@ -201,6 +205,7 @@ if [ $1 -eq 0 ];then
${csudo}rm -f ${inc_link_dir}/taos.h || :
${csudo}rm -f ${inc_link_dir}/taosdef.h || :
${csudo}rm -f ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosudf.h || :
${csudo}rm -f ${lib_link_dir}/libtaos.* || :
${csudo}rm -f ${log_link_dir} || :
diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh
index f07705ff442b65f1295431e59b48ef50a76cadc0..f40983409172e496ca864eae3f7c045b89f63486 100755
--- a/packaging/tools/install.sh
+++ b/packaging/tools/install.sh
@@ -30,6 +30,7 @@ configDir="/etc/taos"
installDir="/usr/local/taos"
adapterName="taosadapter"
benchmarkName="taosBenchmark"
+tmqName="tmq_sim"
dumpName="taosdump"
demoName="taosdemo"
@@ -194,9 +195,7 @@ function install_bin() {
${csudo}rm -f ${bin_link_dir}/${serverName} || :
${csudo}rm -f ${bin_link_dir}/${adapterName} || :
${csudo}rm -f ${bin_link_dir}/${uninstallScript} || :
- ${csudo}rm -f ${bin_link_dir}/tarbitrator || :
${csudo}rm -f ${bin_link_dir}/set_core || :
- ${csudo}rm -f ${bin_link_dir}/run_${serverName}_and_${adapterName}.sh || :
${csudo}rm -f ${bin_link_dir}/TDinsight.sh || :
${csudo}cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo}chmod 0555 ${install_main_dir}/bin/*
@@ -207,12 +206,11 @@ function install_bin() {
[ -x ${install_main_dir}/bin/${adapterName} ] && ${csudo}ln -s ${install_main_dir}/bin/${adapterName} ${bin_link_dir}/${adapterName} || :
[ -x ${install_main_dir}/bin/${benchmarkName} ] && ${csudo}ln -s ${install_main_dir}/bin/${benchmarkName} ${bin_link_dir}/${demoName} || :
[ -x ${install_main_dir}/bin/${benchmarkName} ] && ${csudo}ln -s ${install_main_dir}/bin/${benchmarkName} ${bin_link_dir}/${benchmarkName} || :
+ [ -x ${install_main_dir}/bin/${tmqName} ] && ${csudo}ln -s ${install_main_dir}/bin/${tmqName} ${bin_link_dir}/${tmqName} || :
[ -x ${install_main_dir}/bin/${dumpName} ] && ${csudo}ln -s ${install_main_dir}/bin/${dumpName} ${bin_link_dir}/${dumpName} || :
[ -x ${install_main_dir}/bin/TDinsight.sh ] && ${csudo}ln -s ${install_main_dir}/bin/TDinsight.sh ${bin_link_dir}/TDinsight.sh || :
[ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || :
[ -x ${install_main_dir}/bin/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || :
- [ -x ${install_main_dir}/bin/run_${serverName}_and_${adapterName}.sh ] && ${csudo}ln -s ${install_main_dir}/bin/run_${serverName}_and_${adapterName}.sh ${bin_link_dir}/run_${serverName}_and_${adapterName}.sh || :
- [ -x ${install_main_dir}/bin/tarbitrator ] && ${csudo}ln -s ${install_main_dir}/bin/tarbitrator ${bin_link_dir}/tarbitrator || :
if [ "$verMode" == "cluster" ]; then
${csudo}cp -r ${script_dir}/nginxd/* ${nginx_dir} && ${csudo}chmod 0555 ${nginx_dir}/*
@@ -231,9 +229,13 @@ function install_lib() {
${csudo}ln -s ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1
${csudo}ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
+ ${csudo}ln -s ${lib_link_dir}/libtaosws.so ${lib_link_dir}/libtaosws.so || :
+
if [[ -d ${lib64_link_dir} && ! -e ${lib64_link_dir}/libtaos.so ]]; then
${csudo}ln -s ${install_main_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1 || :
${csudo}ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || :
+
+ ${csudo}ln -s ${lib64_link_dir}/libtaosws.so ${lib64_link_dir}/libtaosws.so || :
fi
${csudo}ldconfig
@@ -316,11 +318,17 @@ function install_jemalloc() {
}
function install_header() {
- ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h ${inc_link_dir}/taosudf.h || :
+
+ ${csudo}rm -f ${inc_link_dir}/taosws.h || :
+
${csudo}cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/*
${csudo}ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo}ln -s ${install_main_dir}/include/taosdef.h ${inc_link_dir}/taosdef.h
${csudo}ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
+ ${csudo}ln -s ${install_main_dir}/include/taosudf.h ${inc_link_dir}/taosudf.h
+
+ [ -f ${install_main_dir}/include/taosws.h ] && ${csudo}ln -s ${install_main_dir}/include/taosws.h ${inc_link_dir}/taosws.h || :
}
function add_newHostname_to_hosts() {
@@ -607,28 +615,19 @@ function install_service_on_sysvinit() {
if ((${os_type} == 1)); then
# ${csudo}cp -f ${script_dir}/init.d/${serverName}.deb ${install_main_dir}/init.d/${serverName}
${csudo}cp ${script_dir}/init.d/${serverName}.deb ${service_config_dir}/${serverName} && ${csudo}chmod a+x ${service_config_dir}/${serverName}
- # ${csudo}cp -f ${script_dir}/init.d/tarbitratord.deb ${install_main_dir}/init.d/tarbitratord
- ${csudo}cp ${script_dir}/init.d/tarbitratord.deb ${service_config_dir}/tarbitratord && ${csudo}chmod a+x ${service_config_dir}/tarbitratord
elif ((${os_type} == 2)); then
# ${csudo}cp -f ${script_dir}/init.d/${serverName}.rpm ${install_main_dir}/init.d/${serverName}
${csudo}cp ${script_dir}/init.d/${serverName}.rpm ${service_config_dir}/${serverName} && ${csudo}chmod a+x ${service_config_dir}/${serverName}
- # ${csudo}cp -f ${script_dir}/init.d/tarbitratord.rpm ${install_main_dir}/init.d/tarbitratord
- ${csudo}cp ${script_dir}/init.d/tarbitratord.rpm ${service_config_dir}/tarbitratord && ${csudo}chmod a+x ${service_config_dir}/tarbitratord
fi
if ((${initd_mod} == 1)); then
${csudo}chkconfig --add ${serverName} || :
${csudo}chkconfig --level 2345 ${serverName} on || :
- ${csudo}chkconfig --add tarbitratord || :
- ${csudo}chkconfig --level 2345 tarbitratord on || :
elif ((${initd_mod} == 2)); then
${csudo}insserv ${serverName} || :
${csudo}insserv -d ${serverName} || :
- ${csudo}insserv tarbitratord || :
- ${csudo}insserv -d tarbitratord || :
elif ((${initd_mod} == 3)); then
${csudo}update-rc.d ${serverName} defaults || :
- ${csudo}update-rc.d tarbitratord defaults || :
fi
}
@@ -670,9 +669,6 @@ function install_service_on_systemd() {
${csudo}systemctl enable ${serverName}
- [ -f ${script_dir}/cfg/tarbitratord.service ] &&
- ${csudo}cp ${script_dir}/cfg/tarbitratord.service \
- ${service_config_dir}/ || :
${csudo}systemctl daemon-reload
if [ "$verMode" == "cluster" ]; then
diff --git a/packaging/tools/install_arbi.sh b/packaging/tools/install_arbi.sh
deleted file mode 100755
index e3c63965d4beee31cea91d2f8fd84e3d2bdd00d3..0000000000000000000000000000000000000000
--- a/packaging/tools/install_arbi.sh
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/bin/bash
-#
-# This file is used to install database on linux systems. The operating system
-# is required to use systemd to manage services at boot
-
-set -e
-#set -x
-
-# -----------------------Variables definition---------------------
-script_dir=$(dirname $(readlink -f "$0"))
-
-bin_link_dir="/usr/bin"
-#inc_link_dir="/usr/include"
-
-#install main path
-install_main_dir="/usr/local/tarbitrator"
-
-# old bin dir
-bin_dir="/usr/local/tarbitrator/bin"
-
-service_config_dir="/etc/systemd/system"
-
-# Color setting
-RED='\033[0;31m'
-GREEN='\033[1;32m'
-GREEN_DARK='\033[0;32m'
-GREEN_UNDERLINE='\033[4;32m'
-NC='\033[0m'
-
-csudo=""
-if command -v sudo >/dev/null; then
- csudo="sudo "
-fi
-
-update_flag=0
-
-initd_mod=0
-service_mod=2
-if pidof systemd &>/dev/null; then
- service_mod=0
-elif $(which service &>/dev/null); then
- service_mod=1
- service_config_dir="/etc/init.d"
- if $(which chkconfig &>/dev/null); then
- initd_mod=1
- elif $(which insserv &>/dev/null); then
- initd_mod=2
- elif $(which update-rc.d &>/dev/null); then
- initd_mod=3
- else
- service_mod=2
- fi
-else
- service_mod=2
-fi
-
-# get the operating system type for using the corresponding init file
-# ubuntu/debian(deb), centos/fedora(rpm), others: opensuse, redhat, ..., no verification
-#osinfo=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
-if [[ -e /etc/os-release ]]; then
- osinfo=$(cat /etc/os-release | grep "NAME" | cut -d '"' -f2) || :
-else
- osinfo=""
-fi
-#echo "osinfo: ${osinfo}"
-os_type=0
-if echo $osinfo | grep -qwi "ubuntu"; then
- # echo "This is ubuntu system"
- os_type=1
-elif echo $osinfo | grep -qwi "debian"; then
- # echo "This is debian system"
- os_type=1
-elif echo $osinfo | grep -qwi "Kylin"; then
- # echo "This is Kylin system"
- os_type=1
-elif echo $osinfo | grep -qwi "centos"; then
- # echo "This is centos system"
- os_type=2
-elif echo $osinfo | grep -qwi "fedora"; then
- # echo "This is fedora system"
- os_type=2
-else
- echo " osinfo: ${osinfo}"
- echo " This is an officially unverified linux system,"
- echo " if there are any problems with the installation and operation, "
- echo " please feel free to contact taosdata.com for support."
- os_type=1
-fi
-
-function kill_tarbitrator() {
- pid=$(ps -ef | grep "tarbitrator" | grep -v "grep" | awk '{print $2}')
- if [ -n "$pid" ]; then
- ${csudo}kill -9 $pid || :
- fi
-}
-
-function install_main_path() {
- #create install main dir and all sub dir
- ${csudo}rm -rf ${install_main_dir} || :
- ${csudo}mkdir -p ${install_main_dir}
- ${csudo}mkdir -p ${install_main_dir}/bin
- #${csudo}mkdir -p ${install_main_dir}/include
- ${csudo}mkdir -p ${install_main_dir}/init.d
-}
-
-function install_bin() {
- # Remove links
- ${csudo}rm -f ${bin_link_dir}/rmtarbitrator || :
- ${csudo}rm -f ${bin_link_dir}/tarbitrator || :
- ${csudo}cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo}chmod 0555 ${install_main_dir}/bin/*
-
- #Make link
- [ -x ${install_main_dir}/bin/remove_arbi.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove_arbi.sh ${bin_link_dir}/rmtarbitrator || :
- [ -x ${install_main_dir}/bin/tarbitrator ] && ${csudo}ln -s ${install_main_dir}/bin/tarbitrator ${bin_link_dir}/tarbitrator || :
-}
-
-function install_header() {
- ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h || :
- ${csudo}cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/*
- ${csudo}ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
- ${csudo}ln -s ${install_main_dir}/include/taosdef.h ${inc_link_dir}/taosdef.h
- ${csudo}ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
-}
-
-function install_jemalloc() {
- jemalloc_dir=${script_dir}/jemalloc
-
- if [ -d ${jemalloc_dir} ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/bin
-
- if [ -f ${jemalloc_dir}/bin/jemalloc-config ]; then
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jemalloc-config /usr/local/bin
- fi
- if [ -f ${jemalloc_dir}/bin/jemalloc.sh ]; then
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jemalloc.sh /usr/local/bin
- fi
- if [ -f ${jemalloc_dir}/bin/jeprof ]; then
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jeprof /usr/local/bin
- fi
- if [ -f ${jemalloc_dir}/include/jemalloc/jemalloc.h ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/include/jemalloc
- ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/include/jemalloc/jemalloc.h /usr/local/include/jemalloc
- fi
- if [ -f ${jemalloc_dir}/lib/libjemalloc.so.2 ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/lib
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc.so.2 /usr/local/lib
- ${csudo}ln -sf libjemalloc.so.2 /usr/local/lib/libjemalloc.so
- ${csudo}/usr/bin/install -c -d /usr/local/lib
- if [ -f ${jemalloc_dir}/lib/libjemalloc.a ]; then
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc.a /usr/local/lib
- fi
- if [ -f ${jemalloc_dir}/lib/libjemalloc_pic.a ]; then
- ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc_pic.a /usr/local/lib
- fi
- if [ -f ${jemalloc_dir}/lib/libjemalloc_pic.a ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/lib/pkgconfig
- ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/lib/pkgconfig/jemalloc.pc /usr/local/lib/pkgconfig
- fi
- fi
- if [ -f ${jemalloc_dir}/share/doc/jemalloc/jemalloc.html ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/share/doc/jemalloc
- ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/share/doc/jemalloc/jemalloc.html /usr/local/share/doc/jemalloc
- fi
- if [ -f ${jemalloc_dir}/share/man/man3/jemalloc.3 ]; then
- ${csudo}/usr/bin/install -c -d /usr/local/share/man/man3
- ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/share/man/man3/jemalloc.3 /usr/local/share/man/man3
- fi
-
- if [ -d /etc/ld.so.conf.d ]; then
- echo "/usr/local/lib" | ${csudo}tee /etc/ld.so.conf.d/jemalloc.conf >/dev/null || echo -e "failed to write /etc/ld.so.conf.d/jemalloc.conf"
- ${csudo}ldconfig
- else
- echo "/etc/ld.so.conf.d not found!"
- fi
- fi
-}
-
-function clean_service_on_sysvinit() {
- if pidof tarbitrator &>/dev/null; then
- ${csudo}service tarbitratord stop || :
- fi
-
- if ((${initd_mod} == 1)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}chkconfig --del tarbitratord || :
- fi
- elif ((${initd_mod} == 2)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}insserv -r tarbitratord || :
- fi
- elif ((${initd_mod} == 3)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}update-rc.d -f tarbitratord remove || :
- fi
- fi
-
- ${csudo}rm -f ${service_config_dir}/tarbitratord || :
-
- if $(which init &>/dev/null); then
- ${csudo}init q || :
- fi
-}
-
-function install_service_on_sysvinit() {
- clean_service_on_sysvinit
- sleep 1
-
- if ((${os_type} == 1)); then
- ${csudo}cp -f ${script_dir}/init.d/tarbitratord.deb ${install_main_dir}/init.d/tarbitratord
- ${csudo}cp ${script_dir}/init.d/tarbitratord.deb ${service_config_dir}/tarbitratord && ${csudo}chmod a+x ${service_config_dir}/tarbitratord
- elif ((${os_type} == 2)); then
- ${csudo}cp -f ${script_dir}/init.d/tarbitratord.rpm ${install_main_dir}/init.d/tarbitratord
- ${csudo}cp ${script_dir}/init.d/tarbitratord.rpm ${service_config_dir}/tarbitratord && ${csudo}chmod a+x ${service_config_dir}/tarbitratord
- fi
-
- if ((${initd_mod} == 1)); then
- ${csudo}chkconfig --add tarbitratord || :
- ${csudo}chkconfig --level 2345 tarbitratord on || :
- elif ((${initd_mod} == 2)); then
- ${csudo}insserv tarbitratord || :
- ${csudo}insserv -d tarbitratord || :
- elif ((${initd_mod} == 3)); then
- ${csudo}update-rc.d tarbitratord defaults || :
- fi
-}
-
-function clean_service_on_systemd() {
- tarbitratord_service_config="${service_config_dir}/tarbitratord.service"
- if systemctl is-active --quiet tarbitratord; then
- echo "tarbitrator is running, stopping it..."
- ${csudo}systemctl stop tarbitratord &>/dev/null || echo &>/dev/null
- fi
- ${csudo}systemctl disable tarbitratord &>/dev/null || echo &>/dev/null
-
- ${csudo}rm -f ${tarbitratord_service_config}
-}
-
-function install_service_on_systemd() {
- clean_service_on_systemd
-
- tarbitratord_service_config="${service_config_dir}/tarbitratord.service"
-
- ${csudo}bash -c "echo '[Unit]' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'Description=TDengine arbitrator service' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'After=network-online.target' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'Wants=network-online.target' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo '[Service]' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'Type=simple' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'ExecStart=/usr/bin/tarbitrator' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'TimeoutStopSec=1000000s' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'LimitNOFILE=infinity' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'LimitNPROC=infinity' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'LimitCORE=infinity' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'TimeoutStartSec=0' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'StandardOutput=null' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'Restart=always' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'StartLimitBurst=3' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'StartLimitInterval=60s' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo '[Install]' >> ${tarbitratord_service_config}"
- ${csudo}bash -c "echo 'WantedBy=multi-user.target' >> ${tarbitratord_service_config}"
- ${csudo}systemctl enable tarbitratord
-}
-
-function install_service() {
- if ((${service_mod} == 0)); then
- install_service_on_systemd
- elif ((${service_mod} == 1)); then
- install_service_on_sysvinit
- else
- kill_tarbitrator
- fi
-}
-
-function update_TDengine() {
- # Start to update
- echo -e "${GREEN}Start to update TDengine's arbitrator ...${NC}"
- # Stop the service if running
- if pidof tarbitrator &>/dev/null; then
- if ((${service_mod} == 0)); then
- ${csudo}systemctl stop tarbitratord || :
- elif ((${service_mod} == 1)); then
- ${csudo}service tarbitratord stop || :
- else
- kill_tarbitrator
- fi
- sleep 1
- fi
-
- install_main_path
- #install_header
- install_bin
- install_service
- install_jemalloc
-
- echo
- if ((${service_mod} == 0)); then
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: ${csudo}systemctl start tarbitratord${NC}"
- elif ((${service_mod} == 1)); then
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: ${csudo}service tarbitratord start${NC}"
- else
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: ./tarbitrator${NC}"
- fi
- echo
- echo -e "\033[44;32;1mTDengine's arbitrator is updated successfully!${NC}"
-}
-
-function install_TDengine() {
- # Start to install
- echo -e "${GREEN}Start to install TDengine's arbitrator ...${NC}"
-
- install_main_path
- #install_header
- install_bin
- install_service
- install_jemalloc
-
- echo
- if ((${service_mod} == 0)); then
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: ${csudo}systemctl start tarbitratord${NC}"
- elif ((${service_mod} == 1)); then
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: ${csudo}service tarbitratord start${NC}"
- else
- echo -e "${GREEN_DARK}To start arbitrator ${NC}: tarbitrator${NC}"
- fi
-
- echo -e "\033[44;32;1mTDengine's arbitrator is installed successfully!${NC}"
- echo
-}
-
-## ==============================Main program starts from here============================
-# Install server and client
-if [ -x ${bin_dir}/tarbitrator ]; then
- update_flag=1
- update_TDengine
-else
- install_TDengine
-fi
diff --git a/packaging/tools/install_client.sh b/packaging/tools/install_client.sh
index 5f449e5d91122522d595eb2ccfb948aa4f8a66fe..0c86877c999e521f519fb303373827ffbaca6a30 100755
--- a/packaging/tools/install_client.sh
+++ b/packaging/tools/install_client.sh
@@ -148,11 +148,12 @@ function install_lib() {
}
function install_header() {
- ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h ${inc_link_dir}/taosudf.h || :
${csudo}cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/*
${csudo}ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo}ln -s ${install_main_dir}/include/taosdef.h ${inc_link_dir}/taosdef.h
${csudo}ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
+ ${csudo}ln -s ${install_main_dir}/include/taosudf.h ${inc_link_dir}/taosudf.h
}
function install_jemalloc() {
diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh
index 31cb5e87b99a5ac61fef740bb8c9393c032ef75a..680fa6736b16d3a12bd76e578a25648a9bd1f227 100755
--- a/packaging/tools/make_install.sh
+++ b/packaging/tools/make_install.sh
@@ -176,7 +176,6 @@ function install_bin() {
if [ "$osType" != "Darwin" ]; then
${csudo}rm -f ${bin_link_dir}/perfMonitor || :
${csudo}rm -f ${bin_link_dir}/set_core || :
- ${csudo}rm -f ${bin_link_dir}/run_taosd_and_taosadapter.sh || :
${csudo}rm -f ${bin_link_dir}/${uninstallScript} || :
${csudo}cp -r ${binary_dir}/build/bin/${clientName} ${install_main_dir}/bin || :
@@ -186,12 +185,10 @@ function install_bin() {
[ -f ${binary_dir}/build/bin/taosadapter ] && ${csudo}cp -r ${binary_dir}/build/bin/taosadapter ${install_main_dir}/bin || :
[ -f ${binary_dir}/build/bin/udfd ] && ${csudo}cp -r ${binary_dir}/build/bin/udfd ${install_main_dir}/bin || :
${csudo}cp -r ${binary_dir}/build/bin/${serverName} ${install_main_dir}/bin || :
- # ${csudo}cp -r ${binary_dir}/build/bin/tarbitrator ${install_main_dir}/bin || :
${csudo}cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_dir}/bin || :
${csudo}cp -r ${script_dir}/remove.sh ${install_main_dir}/bin || :
${csudo}cp -r ${script_dir}/set_core.sh ${install_main_dir}/bin || :
- ${csudo}cp -r ${script_dir}/run_taosd_and_taosadapter.sh ${install_main_dir}/bin || :
${csudo}cp -r ${script_dir}/startPre.sh ${install_main_dir}/bin || :
${csudo}chmod 0555 ${install_main_dir}/bin/*
@@ -204,7 +201,6 @@ function install_bin() {
[ -x ${install_main_dir}/bin/taosdemo ] && ${csudo}ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || :
[ -x ${install_main_dir}/bin/perfMonitor ] && ${csudo}ln -s ${install_main_dir}/bin/perfMonitor ${bin_link_dir}/perfMonitor || :
[ -x ${install_main_dir}/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || :
- [ -x ${install_main_dir}/run_taosd_and_taosadapter.sh ] && ${csudo}ln -s ${install_main_dir}/bin/run_taosd_and_taosadapter.sh ${bin_link_dir}/run_taosd_and_taosadapter.sh || :
[ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || :
else
@@ -298,21 +294,34 @@ function install_avro() {
function install_lib() {
# Remove links
${csudo}rm -f ${lib_link_dir}/libtaos.* || :
+ ${csudo}rm -f ${lib_link_dir}/libtaosws.* || :
if [ "$osType" != "Darwin" ]; then
${csudo}rm -f ${lib64_link_dir}/libtaos.* || :
+ ${csudo}rm -f ${lib64_link_dir}/libtaosws.* || :
fi
if [ "$osType" != "Darwin" ]; then
${csudo}cp ${binary_dir}/build/lib/libtaos.so.${verNumber} \
${install_main_dir}/driver &&
- ${csudo}chmod 777 ${install_main_dir}/driver/*
+ ${csudo}chmod 777 ${install_main_dir}/driver/libtaos.so.${verNumber}
${csudo}ln -sf ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1
${csudo}ln -sf ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
-
if [ -d "${lib64_link_dir}" ]; then
- ${csudo}ln -sf ${install_main_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1
- ${csudo}ln -sf ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so
+ ${csudo}ln -sf ${install_main_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1
+ ${csudo}ln -sf ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so
+ fi
+
+ if [ -f ${binary_dir}/build/lib/libtaosws.so ]; then
+ ${csudo}cp ${binary_dir}/build/lib/libtaosws.so \
+ ${install_main_dir}/driver &&
+ ${csudo}chmod 777 ${install_main_dir}/driver/libtaosws.so ||:
+
+ ${csudo}ln -sf ${install_main_dir}/driver/libtaosws.so ${lib_link_dir}/libtaosws.so || :
+
+ if [ -d "${lib64_link_dir}" ]; then
+ ${csudo}ln -sf ${lib64_link_dir}/libtaosws.so ${lib64_link_dir}/libtaosws.so || :
+ fi
fi
else
${csudo}cp -Rf ${binary_dir}/build/lib/libtaos.${verNumber}.dylib \
@@ -341,8 +350,8 @@ function install_lib() {
fi
install_jemalloc
- install_avro lib
- install_avro lib64
+ #install_avro lib
+ #install_avro lib64
if [ "$osType" != "Darwin" ]; then
${csudo}ldconfig
@@ -352,18 +361,27 @@ function install_lib() {
function install_header() {
if [ "$osType" != "Darwin" ]; then
- ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h || :
- ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h \
+ ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h ${inc_link_dir}/taosudf.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosws.h ||:
+ ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \
${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/*
+
+ if [ -f ${binary_dir}/build/include/taosws.h ]; then
+ ${csudo}cp -f ${binary_dir}/build/include/taosws.h ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/taosws.h ||:
+ ${csudo}ln -s ${install_main_dir}/include/taosws.h ${inc_link_dir}/taosws.h ||:
+ fi
+
${csudo}ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo}ln -s ${install_main_dir}/include/taosdef.h ${inc_link_dir}/taosdef.h
${csudo}ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
+ ${csudo}ln -s ${install_main_dir}/include/taosudf.h ${inc_link_dir}/taosudf.h
+
else
- ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h \
+ ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \
${install_main_dir}/include ||
- ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h \
+ ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \
${install_main_2_dir}/include &&
- ${csudo}chmod 644 ${install_main_dir}/include/* ||
+ ${csudo}chmod 644 ${install_main_dir}/include/* ||:
${csudo}chmod 644 ${install_main_2_dir}/include/*
fi
}
diff --git a/packaging/tools/makearbi.sh b/packaging/tools/makearbi.sh
deleted file mode 100755
index 65a6dae9a4d558da06a3f49bb9e6aa478c762916..0000000000000000000000000000000000000000
--- a/packaging/tools/makearbi.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/bash
-#
-# Generate arbitrator's tar.gz setup package for all os system
-
-set -e
-#set -x
-
-curr_dir=$(pwd)
-compile_dir=$1
-version=$2
-build_time=$3
-cpuType=$4
-osType=$5
-verMode=$6
-verType=$7
-pagMode=$8
-
-script_dir="$(dirname $(readlink -f $0))"
-top_dir="$(readlink -f ${script_dir}/../..)"
-
-productName="TDengine"
-
-# create compressed install file.
-build_dir="${compile_dir}/build"
-code_dir="${top_dir}"
-release_dir="${top_dir}/release"
-
-#package_name='linux'
-if [ "$verMode" == "cluster" ]; then
- install_dir="${release_dir}/${productName}-enterprise-arbitrator-${version}"
-else
- install_dir="${release_dir}/${productName}-arbitrator-${version}"
-fi
-
-# Directories and files.
-bin_files="${build_dir}/bin/tarbitrator ${script_dir}/remove_arbi.sh"
-install_files="${script_dir}/install_arbi.sh"
-
-#header_files="${code_dir}/include/client/taos.h ${code_dir}/include/common/taosdef.h ${code_dir}/include/util/taoserror.h"
-init_file_tarbitrator_deb=${script_dir}/../deb/tarbitratord
-init_file_tarbitrator_rpm=${script_dir}/../rpm/tarbitratord
-
-# make directories.
-mkdir -p ${install_dir} && cp ${install_files} ${install_dir} && chmod a+x ${install_dir}/install_arbi.sh || :
-#mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc || :
-mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/* || :
-mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_deb} ${install_dir}/init.d/tarbitratord.deb || :
-mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_rpm} ${install_dir}/init.d/tarbitratord.rpm || :
-
-cd ${release_dir}
-
-# install_dir has been distinguishes cluster from edege, so comments this code
-pkg_name=${install_dir}-${osType}-${cpuType}
-
-if [[ "$verType" == "beta" ]] || [[ "$verType" == "preRelease" ]]; then
- pkg_name=${install_dir}-${verType}-${osType}-${cpuType}
-elif [ "$verType" == "stable" ]; then
- pkg_name=${pkg_name}
-else
- echo "unknow verType, nor stabel or beta"
- exit 1
-fi
-
-tar -zcv -f "$(basename ${pkg_name}).tar.gz" $(basename ${install_dir}) --remove-files || :
-exitcode=$?
-if [ "$exitcode" != "0" ]; then
- echo "tar ${pkg_name}.tar.gz error !!!"
- exit $exitcode
-fi
-
-cd ${curr_dir}
diff --git a/packaging/tools/makeclient.sh b/packaging/tools/makeclient.sh
index 9e7f01300602ec01656c7862b2a918b5889a53b2..ca3a9a19be14f9d935ee6afcc7063a5cd612c9fb 100755
--- a/packaging/tools/makeclient.sh
+++ b/packaging/tools/makeclient.sh
@@ -62,7 +62,7 @@ else
lib_files="${build_dir}/lib/libtaos.${version}.dylib"
fi
-header_files="${code_dir}/include/client/taos.h ${code_dir}/include/common/taosdef.h ${code_dir}/include/util/taoserror.h"
+header_files="${code_dir}/include/client/taos.h ${code_dir}/include/common/taosdef.h ${code_dir}/include/util/taoserror.h ${code_dir}/include/libs/function/taosudf.h"
if [ "$dbName" != "taos" ]; then
cfg_dir="${top_dir}/../enterprise/packaging/cfg"
else
@@ -161,13 +161,11 @@ if [[ $productName == "TDengine" ]]; then
mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
if [ "$osType" != "Darwin" ]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector || :
- fi
- if find ${connector_dir}/go -mindepth 1 -maxdepth 1 | read; then
- cp -r ${connector_dir}/go ${install_dir}/connector
- else
- echo "WARNING: go connector not found, please check if want to use it!"
+ [ -f ${build_dir}/lib/*.jar ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || :
fi
+ git clone --depth 1 https://github.com/taosdata/driver-go ${install_dir}/connector/go
+ rm -rf ${install_dir}/connector/go/.git ||:
+
git clone --depth 1 https://github.com/taosdata/taos-connector-python ${install_dir}/connector/python
rm -rf ${install_dir}/connector/python/.git ||:
# cp -r ${connector_dir}/python ${install_dir}/connector
diff --git a/packaging/tools/makepkg.sh b/packaging/tools/makepkg.sh
index ea8ebba4509f14f59be2a711c540c06e3a00702c..c37397005c22386bdf1187ba3104f3b9656ff9d0 100755
--- a/packaging/tools/makepkg.sh
+++ b/packaging/tools/makepkg.sh
@@ -60,7 +60,7 @@ if [ "$pagMode" == "lite" ]; then
strip ${build_dir}/bin/${serverName}
strip ${build_dir}/bin/${clientName}
# lite version doesn't include taosadapter, which will lead to no restful interface
- bin_files="${build_dir}/bin/${serverName} ${build_dir}/bin/${clientName} ${script_dir}/remove.sh ${script_dir}/startPre.sh ${build_dir}/bin/taosBenchmark"
+ bin_files="${build_dir}/bin/${serverName} ${build_dir}/bin/${clientName} ${script_dir}/remove.sh ${script_dir}/startPre.sh ${build_dir}/bin/taosBenchmark ${build_dir}/bin/tmq_sim"
taostools_bin_files=""
else
@@ -78,6 +78,7 @@ else
taostools_bin_files=" ${build_dir}/bin/taosdump \
${build_dir}/bin/taosBenchmark \
+ ${build_dir}/bin/tmq_sim \
${build_dir}/bin/TDinsight.sh \
$tdinsight_caches"
@@ -85,16 +86,17 @@ else
${build_dir}/bin/${clientName} \
${taostools_bin_files} \
${build_dir}/bin/taosadapter \
- ${build_dir}/bin/tarbitrator\
${script_dir}/remove.sh \
${script_dir}/set_core.sh \
- ${script_dir}/run_taosd_and_taosadapter.sh \
${script_dir}/startPre.sh \
${script_dir}/taosd-dump-cfg.gdb"
fi
lib_files="${build_dir}/lib/libtaos.so.${version}"
-header_files="${code_dir}/include/client/taos.h ${code_dir}/include/common/taosdef.h ${code_dir}/include/util/taoserror.h"
+wslib_files="${build_dir}/lib/libtaosws.so."
+header_files="${code_dir}/include/client/taos.h ${code_dir}/include/common/taosdef.h ${code_dir}/include/util/taoserror.h ${code_dir}/include/libs/function/taosudf.h"
+
+wsheader_files="${code_dir}/inc/taosws.h"
if [ "$dbName" != "taos" ]; then
cfg_dir="${top_dir}/../enterprise/packaging/cfg"
@@ -107,12 +109,13 @@ nginx_dir="${top_dir}/../enterprise/src/plugins/web"
init_file_deb=${script_dir}/../deb/taosd
init_file_rpm=${script_dir}/../rpm/taosd
-init_file_tarbitrator_deb=${script_dir}/../deb/tarbitratord
-init_file_tarbitrator_rpm=${script_dir}/../rpm/tarbitratord
# make directories.
mkdir -p ${install_dir}
mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc
+
+${wsheader_files} ${install_dir}/inc || :
+
mkdir -p ${install_dir}/cfg && cp ${cfg_dir}/${configFile} ${install_dir}/cfg/${configFile}
if [ -f "${compile_dir}/test/cfg/taosadapter.toml" ]; then
@@ -127,10 +130,6 @@ if [ -f "${cfg_dir}/${serverName}.service" ]; then
cp ${cfg_dir}/${serverName}.service ${install_dir}/cfg || :
fi
-if [ -f "${top_dir}/packaging/cfg/tarbitratord.service" ]; then
- cp ${top_dir}/packaging/cfg/tarbitratord.service ${install_dir}/cfg || :
-fi
-
if [ -f "${top_dir}/packaging/cfg/nginxd.service" ]; then
cp ${top_dir}/packaging/cfg/nginxd.service ${install_dir}/cfg || :
fi
@@ -138,8 +137,6 @@ fi
mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/* || :
mkdir -p ${install_dir}/init.d && cp ${init_file_deb} ${install_dir}/init.d/${serverName}.deb
mkdir -p ${install_dir}/init.d && cp ${init_file_rpm} ${install_dir}/init.d/${serverName}.rpm
-mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_deb} ${install_dir}/init.d/tarbitratord.deb || :
-mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_rpm} ${install_dir}/init.d/tarbitratord.rpm || :
if [ $adapterName != "taosadapter" ]; then
mv ${install_dir}/cfg/taosadapter.toml ${install_dir}/cfg/$adapterName.toml
@@ -152,7 +149,6 @@ if [ $adapterName != "taosadapter" ]; then
sed -i "s/taosadapter/${adapterName}/g" ${install_dir}/cfg/$adapterName.service
mv ${install_dir}/bin/taosadapter ${install_dir}/bin/${adapterName}
- mv ${install_dir}/bin/run_taosd_and_taosadapter.sh ${install_dir}/bin/run_${serverName}_and_${adapterName}.sh
mv ${install_dir}/bin/taosd-dump-cfg.gdb ${install_dir}/bin/${serverName}-dump-cfg.gdb
fi
@@ -294,18 +290,17 @@ fi
# Copy driver
mkdir -p ${install_dir}/driver && cp ${lib_files} ${install_dir}/driver && echo "${versionComp}" >${install_dir}/driver/vercomp.txt
+[ -f ${wslib_files} ] && cp ${wslib_files} ${install_dir}/driver || :
# Copy connector
if [ "$verMode" == "cluster" ]; then
connector_dir="${code_dir}/connector"
mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector || :
- if find ${connector_dir}/go -mindepth 1 -maxdepth 1 | read; then
- cp -r ${connector_dir}/go ${install_dir}/connector
- else
- echo "WARNING: go connector not found, please check if want to use it!"
- fi
+ [ -f ${build_dir}/lib/*.jar ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || :
+ git clone --depth 1 https://github.com/taosdata/driver-go ${install_dir}/connector/go
+ rm -rf ${install_dir}/connector/go/.git ||:
+
git clone --depth 1 https://github.com/taosdata/taos-connector-python ${install_dir}/connector/python
rm -rf ${install_dir}/connector/python/.git ||:
@@ -317,6 +312,7 @@ if [ "$verMode" == "cluster" ]; then
git clone --depth 1 https://github.com/taosdata/libtaos-rs ${install_dir}/connector/rust
rm -rf ${install_dir}/connector/rust/.git ||:
+
# cp -r ${connector_dir}/python ${install_dir}/connector
# cp -r ${connector_dir}/nodejs ${install_dir}/connector
fi
diff --git a/packaging/tools/post.sh b/packaging/tools/post.sh
index 93849dd4ebef00512854b4dfff8b57f4b44f7797..2d744233bafc8bc1787622a7158dbabfd492f5cd 100755
--- a/packaging/tools/post.sh
+++ b/packaging/tools/post.sh
@@ -81,10 +81,11 @@ function kill_taosd() {
}
function install_include() {
- ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h|| :
+ ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h ${inc_link_dir}/taosudf.h || :
${csudo}ln -s ${inc_dir}/taos.h ${inc_link_dir}/taos.h
${csudo}ln -s ${inc_dir}/taosdef.h ${inc_link_dir}/taosdef.h
${csudo}ln -s ${inc_dir}/taoserror.h ${inc_link_dir}/taoserror.h
+ ${csudo}ln -s ${inc_dir}/taosudf.h ${inc_link_dir}/taosudf.h
}
function install_lib() {
diff --git a/packaging/tools/preun.sh b/packaging/tools/preun.sh
index 2f35e41a48a438d86a7dc6ca71511ce967ba7ebf..8dee9da9889b33437e96c1ba11ae57947db1c738 100755
--- a/packaging/tools/preun.sh
+++ b/packaging/tools/preun.sh
@@ -128,6 +128,7 @@ ${csudo}rm -f ${cfg_link_dir}/*.new || :
${csudo}rm -f ${inc_link_dir}/taos.h || :
${csudo}rm -f ${inc_link_dir}/taosdef.h || :
${csudo}rm -f ${inc_link_dir}/taoserror.h || :
+${csudo}rm -f ${inc_link_dir}/taosudf.h || :
${csudo}rm -f ${lib_link_dir}/libtaos.* || :
${csudo}rm -f ${lib64_link_dir}/libtaos.* || :
diff --git a/packaging/tools/remove.sh b/packaging/tools/remove.sh
index 3b043f44a330199640af34f550afa40c6e12e111..1bd5ed3ea4482c36df1dfbe8a12b23ab22b63cd8 100755
--- a/packaging/tools/remove.sh
+++ b/packaging/tools/remove.sh
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Script to stop the service and uninstall TDengine, but retain the config, data and log files.
+# Script to stop and uninstall the service, but retain the config, data and log files.
set -e
#set -x
@@ -11,120 +11,222 @@ RED='\033[0;31m'
GREEN='\033[1;32m'
NC='\033[0m'
+installDir="/usr/local/taos"
+serverName="taosd"
+clientName="taos"
+uninstallScript="rmtaos"
+productName="TDengine"
+
#install main path
-install_main_dir="/usr/local/taos"
-data_link_dir="/usr/local/taos/data"
-log_link_dir="/usr/local/taos/log"
-cfg_link_dir="/usr/local/taos/cfg"
+install_main_dir=${installDir}
+data_link_dir=${installDir}/data
+log_link_dir=${installDir}/log
+cfg_link_dir=${installDir}/cfg
bin_link_dir="/usr/bin"
+local_bin_link_dir="/usr/local/bin"
lib_link_dir="/usr/lib"
lib64_link_dir="/usr/lib64"
inc_link_dir="/usr/include"
+install_nginxd_dir="/usr/local/nginxd"
service_config_dir="/etc/systemd/system"
-taos_service_name="taosd"
-
+taos_service_name=${serverName}
+taosadapter_service_name="taosadapter"
+tarbitrator_service_name="tarbitratord"
+nginx_service_name="nginxd"
csudo=""
-if command -v sudo > /dev/null; then
- csudo="sudo"
+if command -v sudo >/dev/null; then
+ csudo="sudo "
fi
initd_mod=0
service_mod=2
-if pidof systemd &> /dev/null; then
- service_mod=0
-elif $(which service &> /dev/null); then
- service_mod=1
- service_config_dir="/etc/init.d"
- if $(which chkconfig &> /dev/null); then
- initd_mod=1
- elif $(which insserv &> /dev/null); then
- initd_mod=2
- elif $(which update-rc.d &> /dev/null); then
- initd_mod=3
- else
- service_mod=2
- fi
-else
+if pidof systemd &>/dev/null; then
+ service_mod=0
+elif $(which service &>/dev/null); then
+ service_mod=1
+ service_config_dir="/etc/init.d"
+ if $(which chkconfig &>/dev/null); then
+ initd_mod=1
+ elif $(which insserv &>/dev/null); then
+ initd_mod=2
+ elif $(which update-rc.d &>/dev/null); then
+ initd_mod=3
+ else
service_mod=2
+ fi
+else
+ service_mod=2
fi
+function kill_taosadapter() {
+ pid=$(ps -ef | grep "taosadapter" | grep -v "grep" | awk '{print $2}')
+ if [ -n "$pid" ]; then
+ ${csudo}kill -9 $pid || :
+ fi
+}
function kill_taosd() {
- pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
+ pid=$(ps -ef | grep ${serverName} | grep -v "grep" | awk '{print $2}')
if [ -n "$pid" ]; then
- ${csudo} kill -9 $pid || :
+ ${csudo}kill -9 $pid || :
fi
}
+function kill_tarbitrator() {
+ pid=$(ps -ef | grep "tarbitrator" | grep -v "grep" | awk '{print $2}')
+ if [ -n "$pid" ]; then
+ ${csudo}kill -9 $pid || :
+ fi
+}
function clean_bin() {
- # Remove link
- ${csudo} rm -f ${bin_link_dir}/taos || :
- ${csudo} rm -f ${bin_link_dir}/taosd || :
- ${csudo} rm -f ${bin_link_dir}/create_table || :
- ${csudo} rm -f ${bin_link_dir}/tmq_sim || :
- ${csudo} rm -f ${bin_link_dir}/taosdemo || :
- ${csudo} rm -f ${bin_link_dir}/taosdump || :
- ${csudo} rm -f ${bin_link_dir}/rmtaos || :
- #${csudo} rm -f ${bin_link_dir}/set_core || :
+ # Remove link
+ ${csudo}rm -f ${bin_link_dir}/${clientName} || :
+ ${csudo}rm -f ${bin_link_dir}/${serverName} || :
+ ${csudo}rm -f ${bin_link_dir}/taosadapter || :
+ ${csudo}rm -f ${bin_link_dir}/taosBenchmark || :
+ ${csudo}rm -f ${bin_link_dir}/taosdemo || :
+ ${csudo}rm -f ${bin_link_dir}/taosdump || :
+ ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || :
+ ${csudo}rm -f ${bin_link_dir}/tarbitrator || :
+ ${csudo}rm -f ${bin_link_dir}/set_core || :
+ ${csudo}rm -f ${bin_link_dir}/TDinsight.sh || :
+}
+
+function clean_local_bin() {
+ ${csudo}rm -f ${local_bin_link_dir}/taosBenchmark || :
+ ${csudo}rm -f ${local_bin_link_dir}/taosdemo || :
}
function clean_lib() {
- # Remove link
- ${csudo} rm -f ${lib_link_dir}/libtaos.* || :
- ${csudo} rm -f ${lib64_link_dir}/libtaos.* || :
-
- ${csudo} rm -f ${lib_link_dir}/libtdb.* || :
- ${csudo} rm -f ${lib64_link_dir}/libtdb.* || :
+ # Remove link
+ ${csudo}rm -f ${lib_link_dir}/libtaos.* || :
+ ${csudo}rm -f ${lib_link_dir}/libtaosws.* || :
+
+ ${csudo}rm -f ${lib64_link_dir}/libtaos.* || :
+ ${csudo}rm -f ${lib64_link_dir}/libtaosws.* || :
+ #${csudo}rm -rf ${v15_java_app_dir} || :
}
function clean_header() {
- # Remove link
- ${csudo} rm -f ${inc_link_dir}/taos.h || :
- ${csudo} rm -f ${inc_link_dir}/taosdef.h || :
- ${csudo} rm -f ${inc_link_dir}/taoserror.h || :
+ # Remove link
+ ${csudo}rm -f ${inc_link_dir}/taos.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosdef.h || :
+ ${csudo}rm -f ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosudf.h || :
+
+ ${csudo}rm -f ${inc_link_dir}/taosws.h || :
}
function clean_config() {
- # Remove link
- ${csudo} rm -f ${cfg_link_dir}/* || :
+ # Remove link
+ ${csudo}rm -f ${cfg_link_dir}/* || :
}
function clean_log() {
- # Remove link
- ${csudo} rm -rf ${log_link_dir} || :
+ # Remove link
+ ${csudo}rm -rf ${log_link_dir} || :
}
function clean_service_on_systemd() {
- taosd_service_config="${service_config_dir}/${taos_service_name}.service"
- if systemctl is-active --quiet ${taos_service_name}; then
- echo "TDengine taosd is running, stopping it..."
- ${csudo} systemctl stop ${taos_service_name} &> /dev/null || echo &> /dev/null
+ taosd_service_config="${service_config_dir}/${taos_service_name}.service"
+ if systemctl is-active --quiet ${taos_service_name}; then
+ echo "${productName} ${serverName} is running, stopping it..."
+ ${csudo}systemctl stop ${taos_service_name} &>/dev/null || echo &>/dev/null
+ fi
+ ${csudo}systemctl disable ${taos_service_name} &>/dev/null || echo &>/dev/null
+ ${csudo}rm -f ${taosd_service_config}
+
+ taosadapter_service_config="${service_config_dir}/taosadapter.service"
+ if systemctl is-active --quiet ${taosadapter_service_name}; then
+ echo "${productName} taosAdapter is running, stopping it..."
+ ${csudo}systemctl stop ${taosadapter_service_name} &>/dev/null || echo &>/dev/null
+ fi
+ ${csudo}systemctl disable ${taosadapter_service_name} &>/dev/null || echo &>/dev/null
+ [ -f ${taosadapter_service_config} ] && ${csudo}rm -f ${taosadapter_service_config}
+
+ tarbitratord_service_config="${service_config_dir}/${tarbitrator_service_name}.service"
+ if systemctl is-active --quiet ${tarbitrator_service_name}; then
+ echo "${productName} tarbitrator is running, stopping it..."
+ ${csudo}systemctl stop ${tarbitrator_service_name} &>/dev/null || echo &>/dev/null
+ fi
+ ${csudo}systemctl disable ${tarbitrator_service_name} &>/dev/null || echo &>/dev/null
+ ${csudo}rm -f ${tarbitratord_service_config}
+
+ if [ "$verMode" == "cluster" ]; then
+ nginx_service_config="${service_config_dir}/${nginx_service_name}.service"
+ if [ -d ${install_nginxd_dir} ]; then
+ if systemctl is-active --quiet ${nginx_service_name}; then
+ echo "Nginx for ${productName} is running, stopping it..."
+ ${csudo}systemctl stop ${nginx_service_name} &>/dev/null || echo &>/dev/null
+ fi
+ ${csudo}systemctl disable ${nginx_service_name} &>/dev/null || echo &>/dev/null
+ ${csudo}rm -f ${nginx_service_config}
fi
- ${csudo} systemctl disable ${taos_service_name} &> /dev/null || echo &> /dev/null
- ${csudo} rm -f ${taosd_service_config}
+ fi
}
function clean_service_on_sysvinit() {
- echo " "
+ if pidof ${serverName} &>/dev/null; then
+ echo "${productName} ${serverName} is running, stopping it..."
+ ${csudo}service ${serverName} stop || :
+ fi
+
+ if pidof tarbitrator &>/dev/null; then
+ echo "${productName} tarbitrator is running, stopping it..."
+ ${csudo}service tarbitratord stop || :
+ fi
+
+ if ((${initd_mod} == 1)); then
+ if [ -e ${service_config_dir}/${serverName} ]; then
+ ${csudo}chkconfig --del ${serverName} || :
+ fi
+ if [ -e ${service_config_dir}/tarbitratord ]; then
+ ${csudo}chkconfig --del tarbitratord || :
+ fi
+ elif ((${initd_mod} == 2)); then
+ if [ -e ${service_config_dir}/${serverName} ]; then
+ ${csudo}insserv -r ${serverName} || :
+ fi
+ if [ -e ${service_config_dir}/tarbitratord ]; then
+ ${csudo}insserv -r tarbitratord || :
+ fi
+ elif ((${initd_mod} == 3)); then
+ if [ -e ${service_config_dir}/${serverName} ]; then
+ ${csudo}update-rc.d -f ${serverName} remove || :
+ fi
+ if [ -e ${service_config_dir}/tarbitratord ]; then
+ ${csudo}update-rc.d -f tarbitratord remove || :
+ fi
+ fi
+
+ ${csudo}rm -f ${service_config_dir}/${serverName} || :
+ ${csudo}rm -f ${service_config_dir}/tarbitratord || :
+
+ if $(which init &>/dev/null); then
+ ${csudo}init q || :
+ fi
}
function clean_service() {
- if ((${service_mod}==0)); then
- clean_service_on_systemd
- elif ((${service_mod}==1)); then
- clean_service_on_sysvinit
- else
- # must manual stop taosd
- kill_taosd
- fi
+ if ((${service_mod} == 0)); then
+ clean_service_on_systemd
+ elif ((${service_mod} == 1)); then
+ clean_service_on_sysvinit
+ else
+ kill_taosadapter
+ kill_taosd
+ kill_tarbitrator
+ fi
}
# Stop service and disable booting start.
clean_service
# Remove binary file and links
clean_bin
+# Remove links of local bin
+clean_local_bin
# Remove header file.
clean_header
# Remove lib file
@@ -134,15 +236,26 @@ clean_log
# Remove link configuration file
clean_config
# Remove data link directory
-${csudo} rm -rf ${data_link_dir} || :
-
-${csudo} rm -rf ${install_main_dir}
+${csudo}rm -rf ${data_link_dir} || :
+${csudo}rm -rf ${install_main_dir}
+${csudo}rm -rf ${install_nginxd_dir}
if [[ -e /etc/os-release ]]; then
osinfo=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
else
osinfo=""
fi
-echo -e "${GREEN}TDengine is removed successfully!${NC}"
+if echo $osinfo | grep -qwi "ubuntu"; then
+ # echo "this is ubuntu system"
+ ${csudo}dpkg --force-all -P tdengine >/dev/null 2>&1 || :
+elif echo $osinfo | grep -qwi "debian"; then
+ # echo "this is debian system"
+ ${csudo}dpkg --force-all -P tdengine >/dev/null 2>&1 || :
+elif echo $osinfo | grep -qwi "centos"; then
+ # echo "this is centos system"
+ ${csudo}rpm -e --noscripts tdengine >/dev/null 2>&1 || :
+fi
+
+echo -e "${GREEN}${productName} is removed successfully!${NC}"
echo
diff --git a/packaging/tools/remove_arbi.sh b/packaging/tools/remove_arbi.sh
deleted file mode 100755
index 0a1162cd7a6793d8542ad5079b8c8cce1659724a..0000000000000000000000000000000000000000
--- a/packaging/tools/remove_arbi.sh
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/bash
-#
-# Script to stop the service and uninstall TDengine's arbitrator
-
-set -e
-#set -x
-
-verMode=edge
-
-RED='\033[0;31m'
-GREEN='\033[1;32m'
-NC='\033[0m'
-
-#install main path
-install_main_dir="/usr/local/tarbitrator"
-bin_link_dir="/usr/bin"
-#inc_link_dir="/usr/include"
-
-service_config_dir="/etc/systemd/system"
-tarbitrator_service_name="tarbitratord"
-csudo=""
-if command -v sudo > /dev/null; then
- csudo="sudo "
-fi
-
-initd_mod=0
-service_mod=2
-if pidof systemd &> /dev/null; then
- service_mod=0
-elif $(which service &> /dev/null); then
- service_mod=1
- service_config_dir="/etc/init.d"
- if $(which chkconfig &> /dev/null); then
- initd_mod=1
- elif $(which insserv &> /dev/null); then
- initd_mod=2
- elif $(which update-rc.d &> /dev/null); then
- initd_mod=3
- else
- service_mod=2
- fi
-else
- service_mod=2
-fi
-
-function kill_tarbitrator() {
- pid=$(ps -ef | grep "tarbitrator" | grep -v "grep" | awk '{print $2}')
- if [ -n "$pid" ]; then
- ${csudo}kill -9 $pid || :
- fi
-}
-function clean_bin() {
- # Remove link
- ${csudo}rm -f ${bin_link_dir}/tarbitrator || :
-}
-
-function clean_header() {
- # Remove link
- ${csudo}rm -f ${inc_link_dir}/taos.h || :
- ${csudo}rm -f ${inc_link_dir}/taosdef.h || :
- ${csudo}rm -f ${inc_link_dir}/taoserror.h || :
-}
-
-function clean_log() {
- # Remove link
- ${csudo}rm -rf /arbitrator.log || :
-}
-
-function clean_service_on_systemd() {
- tarbitratord_service_config="${service_config_dir}/${tarbitrator_service_name}.service"
-
- if systemctl is-active --quiet ${tarbitrator_service_name}; then
- echo "TDengine tarbitrator is running, stopping it..."
- ${csudo}systemctl stop ${tarbitrator_service_name} &> /dev/null || echo &> /dev/null
- fi
- ${csudo}systemctl disable ${tarbitrator_service_name} &> /dev/null || echo &> /dev/null
-
- ${csudo}rm -f ${tarbitratord_service_config}
-}
-
-function clean_service_on_sysvinit() {
- if pidof tarbitrator &> /dev/null; then
- echo "TDengine's tarbitrator is running, stopping it..."
- ${csudo}service tarbitratord stop || :
- fi
-
- if ((${initd_mod}==1)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}chkconfig --del tarbitratord || :
- fi
- elif ((${initd_mod}==2)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}insserv -r tarbitratord || :
- fi
- elif ((${initd_mod}==3)); then
- if [ -e ${service_config_dir}/tarbitratord ]; then
- ${csudo}update-rc.d -f tarbitratord remove || :
- fi
- fi
-
- ${csudo}rm -f ${service_config_dir}/tarbitratord || :
-
- if $(which init &> /dev/null); then
- ${csudo}init q || :
- fi
-}
-
-function clean_service() {
- if ((${service_mod}==0)); then
- clean_service_on_systemd
- elif ((${service_mod}==1)); then
- clean_service_on_sysvinit
- else
- # must manual stop
- kill_tarbitrator
- fi
-}
-
-# Stop service and disable booting start.
-clean_service
-# Remove binary file and links
-clean_bin
-# Remove header file.
-##clean_header
-# Remove log file
-clean_log
-
-${csudo}rm -rf ${install_main_dir}
-
-echo -e "${GREEN}TDengine's arbitrator is removed successfully!${NC}"
diff --git a/packaging/tools/remove_client.sh b/packaging/tools/remove_client.sh
index f2cbccb45f738c058236e5625a86fc40c161f488..54f7a949f3abf34c49be63ffae5e43efdf773e8d 100755
--- a/packaging/tools/remove_client.sh
+++ b/packaging/tools/remove_client.sh
@@ -54,6 +54,7 @@ function clean_header() {
${csudo}rm -f ${inc_link_dir}/taos.h || :
${csudo}rm -f ${inc_link_dir}/taosdef.h || :
${csudo}rm -f ${inc_link_dir}/taoserror.h || :
+ ${csudo}rm -f ${inc_link_dir}/taosudf.h || :
}
function clean_config() {
diff --git a/packaging/tools/run_taosd_and_taosadapter.sh b/packaging/tools/run_taosd_and_taosadapter.sh
deleted file mode 100755
index 9ab9eb484a4a5bbc4e3d3994d97b61e0f4bd328d..0000000000000000000000000000000000000000
--- a/packaging/tools/run_taosd_and_taosadapter.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-[[ -x /usr/bin/taosadapter ]] && /usr/bin/taosadapter &
-taosd
diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt
index d3adc12df1674c1c4f7ba5d4d03221d6a97256cc..129e20e5de89caf1ad892205b98106d33a14ab19 100644
--- a/source/client/CMakeLists.txt
+++ b/source/client/CMakeLists.txt
@@ -1,9 +1,13 @@
aux_source_directory(src CLIENT_SRC)
+
if(TD_WINDOWS)
add_library(taos SHARED ${CLIENT_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/src/taos.rc.in)
else()
add_library(taos SHARED ${CLIENT_SRC})
-endif ()
+endif()
+
+INCLUDE_DIRECTORIES(jni)
+
target_include_directories(
taos
PUBLIC "${TD_SOURCE_DIR}/include/client"
@@ -14,13 +18,19 @@ target_link_libraries(
INTERFACE api
PRIVATE os util common transport nodes parser command planner catalog scheduler function qcom
)
+
if(TD_WINDOWS)
- set_target_properties(taos
- PROPERTIES
- LINK_FLAGS
+ set_target_properties(taos
+ PROPERTIES
+ LINK_FLAGS
/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/taos.def
)
-endif ()
+ INCLUDE_DIRECTORIES(jni/windows)
+ INCLUDE_DIRECTORIES(jni/windows/win32)
+ INCLUDE_DIRECTORIES(jni/windows/win32/bridge)
+else()
+ INCLUDE_DIRECTORIES(jni/linux)
+endif()
set_target_properties(
taos
diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h
index c39b492620c4c9bb0922438c1e895b8b4661326d..367e656f064a200ace8a051a88a554808f7dae61 100644
--- a/source/client/inc/clientInt.h
+++ b/source/client/inc/clientInt.h
@@ -20,9 +20,9 @@
extern "C" {
#endif
+#include "catalog.h"
#include "parser.h"
#include "planner.h"
-#include "catalog.h"
#include "query.h"
#include "taos.h"
#include "tcommon.h"
@@ -51,10 +51,16 @@ extern "C" {
enum {
RES_TYPE__QUERY = 1,
RES_TYPE__TMQ,
+ RES_TYPE__TMQ_META,
};
-#define TD_RES_QUERY(res) (*(int8_t*)res == RES_TYPE__QUERY)
-#define TD_RES_TMQ(res) (*(int8_t*)res == RES_TYPE__TMQ)
+#define SHOW_VARIABLES_RESULT_COLS 2
+#define SHOW_VARIABLES_RESULT_FIELD1_LEN (TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE)
+#define SHOW_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE)
+
+#define TD_RES_QUERY(res) (*(int8_t*)res == RES_TYPE__QUERY)
+#define TD_RES_TMQ(res) (*(int8_t*)res == RES_TYPE__TMQ)
+#define TD_RES_TMQ_META(res) (*(int8_t*)res == RES_TYPE__TMQ_META)
typedef struct SAppInstInfo SAppInstInfo;
@@ -66,9 +72,9 @@ typedef struct {
int64_t reportBytes; // not implemented
int64_t startTime;
// ctl
- SRWLatch lock; // lock is used in serialization
+ SRWLatch lock; // lock is used in serialization
SAppInstInfo* pAppInstInfo;
- SHashObj* activeInfo; // hash
+ SHashObj* activeInfo; // hash
} SAppHbMgr;
typedef int32_t (*FHbRspHandle)(SAppHbMgr* pAppHbMgr, SClientHbRsp* pRsp);
@@ -76,13 +82,13 @@ typedef int32_t (*FHbRspHandle)(SAppHbMgr* pAppHbMgr, SClientHbRsp* pRsp);
typedef int32_t (*FHbReqHandle)(SClientHbKey* connKey, void* param, SClientHbReq* req);
typedef struct {
- int8_t inited;
- int64_t appId;
+ int8_t inited;
+ int64_t appId;
// ctl
int8_t threadStop;
TdThread thread;
- TdThreadMutex lock; // used when app init and cleanup
- SHashObj *appSummary;
+ TdThreadMutex lock; // used when app init and cleanup
+ SHashObj* appSummary;
SArray* appHbMgrs; // SArray one for each cluster
FHbReqHandle reqHandle[CONN_TYPE__MAX];
FHbRspHandle rspHandle[CONN_TYPE__MAX];
@@ -102,6 +108,8 @@ typedef struct SHeartBeatInfo {
struct SAppInstInfo {
int64_t numOfConns;
SCorEpSet mgmtEp;
+ int32_t totalDnodes;
+ int32_t onlineDnodes;
TdThreadMutex qnodeMutex;
SArray* pQnodeList;
SAppClusterSummary summary;
@@ -109,6 +117,7 @@ struct SAppInstInfo {
uint64_t clusterId;
void* pTransporter;
SAppHbMgr* pAppHbMgr;
+ char* instKey;
};
typedef struct SAppInfo {
@@ -125,11 +134,12 @@ typedef struct STscObj {
char user[TSDB_USER_LEN];
char pass[TSDB_PASSWORD_LEN];
char db[TSDB_DB_FNAME_LEN];
- char ver[128];
+ char sVer[TSDB_VERSION_LEN];
+ char sDetailVer[128];
int8_t connType;
int32_t acctId;
uint32_t connId;
- TAOS *id; // ref ID returned by taosAddRef
+ int64_t id; // ref ID returned by taosAddRef
TdThreadMutex mutex; // used to protect the operation on db
int32_t numOfReqs; // number of sqlObj bound to this connection
SAppInstInfo* pAppInfo;
@@ -146,7 +156,7 @@ typedef struct SResultColumn {
} SResultColumn;
typedef struct SReqResultInfo {
- SQueryExecRes execRes;
+ SExecResult execRes;
const char* pRspMsg;
const char* pData;
TAOS_FIELD* fields; // todo, column names are not needed.
@@ -159,6 +169,7 @@ typedef struct SReqResultInfo {
uint32_t numOfRows;
uint64_t totalRows;
uint32_t current;
+ bool localResultFetched;
bool completed;
int32_t precision;
bool convertUcs4;
@@ -167,14 +178,15 @@ typedef struct SReqResultInfo {
} SReqResultInfo;
typedef struct SRequestSendRecvBody {
- tsem_t rspSem; // not used now
- __taos_async_fn_t queryFp;
- __taos_async_fn_t fetchFp;
- void* param;
- SDataBuf requestMsg;
- int64_t queryJob; // query job, created according to sql query DAG.
- struct SQueryPlan* pDag; // the query dag, generated according to the sql statement.
- SReqResultInfo resInfo;
+ tsem_t rspSem; // not used now
+ __taos_async_fn_t queryFp;
+ __taos_async_fn_t fetchFp;
+ EQueryExecMode execMode;
+ void* param;
+ SDataBuf requestMsg;
+ int64_t queryJob; // query job, created according to sql query DAG.
+ int32_t subplanNum;
+ SReqResultInfo resInfo;
} SRequestSendRecvBody;
typedef struct {
@@ -184,10 +196,18 @@ typedef struct {
int32_t vgId;
SSchemaWrapper schema;
int32_t resIter;
- SMqDataBlkRsp rsp;
+ SMqDataRsp rsp;
SReqResultInfo resInfo;
} SMqRspObj;
+typedef struct {
+ int8_t resType;
+ char topic[TSDB_TOPIC_FNAME_LEN];
+ char db[TSDB_DB_FNAME_LEN];
+ int32_t vgId;
+ SMqMetaRsp metaRsp;
+} SMqMetaRspObj;
+
typedef struct SRequestObj {
int8_t resType; // query or tmq
uint64_t requestId;
@@ -204,11 +224,12 @@ typedef struct SRequestObj {
SArray* tableList;
SQueryExecMetric metric;
SRequestSendRecvBody body;
- bool stableQuery;
+ 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;
+ bool killed;
+ uint32_t prevCode; // previous error code: todo refactor, add update flag for catalog
+ uint32_t retry;
} SRequestObj;
typedef struct SSyncQueryParam {
@@ -216,8 +237,8 @@ typedef struct SSyncQueryParam {
SRequestObj* pRequest;
} SSyncQueryParam;
-void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
-void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
+void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
+void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
void doSetOneRowPtr(SReqResultInfo* pResultInfo);
void setResPrecision(SReqResultInfo* pResInfo, int32_t precision);
@@ -225,7 +246,12 @@ int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableR
bool freeAfterUse);
void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols);
void doFreeReqResultInfo(SReqResultInfo* pResInfo);
-SRequestObj* execQuery(STscObj* pTscObj, const char* sql, int sqlLen);
+int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName, SArray** pReq);
+void syncCatalogFn(SMetaData* pResult, void* param, int32_t code);
+
+SRequestObj* execQuery(uint64_t connId, const char* sql, int sqlLen, bool validateOnly);
+TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly);
+void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly);
static FORCE_INLINE SReqResultInfo* tmqGetCurResInfo(TAOS_RES* res) {
SMqRspObj* msg = (SMqRspObj*)res;
@@ -260,6 +286,7 @@ static FORCE_INLINE SReqResultInfo* tscGetCurResInfo(TAOS_RES* res) {
extern SAppInfo appInfo;
extern int32_t clientReqRefPool;
extern int32_t clientConnRefPool;
+extern void* tscQhandle;
__async_send_cb_fn_t getMsgRspHandle(int32_t msgType);
@@ -272,10 +299,12 @@ int32_t releaseTscObj(int64_t rid);
uint64_t generateRequestId();
-void* createRequest(STscObj* pObj, int32_t type);
+void* createRequest(uint64_t connId, int32_t type);
void destroyRequest(SRequestObj* pRequest);
SRequestObj* acquireRequest(int64_t rid);
int32_t releaseRequest(int64_t rid);
+int32_t removeRequest(int64_t rid);
+void doDestroyRequest(void* p);
char* getDbOfConnection(STscObj* pObj);
void setConnectionDB(STscObj* pTscObj, const char* db);
@@ -289,17 +318,18 @@ bool persistConnForSpecificMsg(void* parenct, tmsg_t msgType);
void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet);
STscObj* taos_connect_internal(const char* ip, const char* user, const char* pass, const char* auth, const char* db,
- uint16_t port, int connType);
+ uint16_t port, int connType);
-SRequestObj* launchQuery(STscObj* pTscObj, const char* sql, int sqlLen);
+SRequestObj* launchQuery(uint64_t connId, const char* sql, int sqlLen, bool validateOnly);
int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtCallback* pStmtCb);
int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArray* pNodeList);
-int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj** pRequest);
+int32_t buildRequest(uint64_t connId, const char* sql, int sqlLen, void* param, bool validateSql,
+ SRequestObj** pRequest);
-void taos_close_internal(void *taos);
+void taos_close_internal(void* taos);
// --- heartbeat
// global, called by mgmt
@@ -310,6 +340,9 @@ int hbHandleRsp(SClientHbBatchRsp* hbRsp);
// cluster level
SAppHbMgr* appHbMgrInit(SAppInstInfo* pAppInstInfo, char* key);
void appHbMgrCleanup(void);
+void hbRemoveAppHbMrg(SAppHbMgr** pAppHbMgr);
+void destroyAllRequests(SHashObj* pRequests);
+void stopAllRequests(SHashObj* pRequests);
// conn level
int hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType);
@@ -320,12 +353,12 @@ void hbMgrInitMqHbRspHandle();
SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res);
int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList);
-void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData *pResultMeta);
+void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta);
int32_t refreshMeta(STscObj* pTscObj, SRequestObj* pRequest);
int32_t updateQnodeList(SAppInstInfo* pInfo, SArray* pNodeList);
void doAsyncQuery(SRequestObj* pRequest, bool forceUpdateMeta);
-int32_t removeMeta(STscObj* pTscObj, SArray* tbList);// todo move to clientImpl.c and become a static function
-int32_t handleAlterTbExecRes(void* res, struct SCatalog* pCatalog);// todo move to xxx
+int32_t removeMeta(STscObj* pTscObj, SArray* tbList); // todo move to clientImpl.c and become a static function
+int32_t handleAlterTbExecRes(void* res, struct SCatalog* pCatalog); // todo move to xxx
bool qnodeRequired(SRequestObj* pRequest);
#ifdef __cplusplus
diff --git a/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b728a31429aea1c695268a1dcb21ad67f79771c
--- /dev/null
+++ b/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+/* Header for class com_taosdata_jdbc_TSDBJNIConnector */
+
+#ifndef _Included_com_taosdata_jdbc_TSDBJNIConnector
+#define _Included_com_taosdata_jdbc_TSDBJNIConnector
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE
+#define com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE 0LL
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: initImp
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: setOptions
+ * Signature: (ILjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *, jclass, jint, jstring);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: setConfigImp
+ * Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException;
+ */
+JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp(JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getTsCharset
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(JNIEnv *, jclass);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getResultTimePrecisionImp
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecisionImp(JNIEnv *, jobject, jlong,
+ jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: connectImp
+ * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *, jobject, jstring, jint, jstring,
+ jstring, jstring);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: executeQueryImp
+ * Signature: ([BJ)I
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(JNIEnv *, jobject, jbyteArray, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getErrCodeImp
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getErrMsgImp
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getResultSetImp
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: isUpdateQueryImp
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: freeResultSetImp
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getAffectedRowsImp
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: getSchemaMetaDataImp
+ * Signature: (JJLjava/util/List;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp(JNIEnv *, jobject, jlong, jlong,
+ jobject);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: fetchRowImp
+ * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetRowData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEnv *, jobject, jlong, jlong, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: fetchBlockImp
+ * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *, jobject, jlong, jlong, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: closeConnectionImp
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: subscribeImp
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JI)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNIEnv *, jobject, jlong, jboolean,
+ jstring, jstring, jint);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: consumeImp
+ * Signature: (J)Lcom/taosdata/jdbc/TSDBResultSetRowData;
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: unsubscribeImp
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_unsubscribeImp(JNIEnv *, jobject, jlong, jboolean);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: validateCreateTableSqlImp
+ * Signature: (J[B)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTableSqlImp(JNIEnv *, jobject, jlong,
+ jbyteArray);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: prepareStmtImp
+ * Signature: ([BJ)I
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *, jobject, jbyteArray, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: setBindTableNameImp
+ * Signature: (JLjava/lang/String;J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp(JNIEnv *, jobject, jlong, jstring,
+ jlong);
+
+/**
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: setTableNameTagsImp
+ * Signature: (JLjava/lang/String;I[B[B[B[BJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp(JNIEnv *, jobject, jlong, jstring,
+ jint, jbyteArray, jbyteArray,
+ jbyteArray, jbyteArray, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: bindColDataImp
+ * Signature: (J[B[B[BIIIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(JNIEnv *, jobject, jlong, jbyteArray,
+ jbyteArray, jbyteArray, jint, jint, jint,
+ jint, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: stmt_add_batch
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: executeBatchImp
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: closeStmt
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: stmt_errstr
+ * Signature: (JJ)I
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: insertLinesImp
+ * Signature: ([Ljava/lang/String;JII)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *, jobject, jobjectArray, jlong,
+ jint, jint);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: schemalessInsertImp
+ * Signature: (J[B[B[BIIIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp(JNIEnv *, jobject, jobjectArray,
+ jlong, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h b/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3b098e460ea7897e9a99c252e5ba0812eb94fa7
--- /dev/null
+++ b/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+/* Header for class com_taosdata_jdbc_tmq_TMQConnector */
+
+#ifndef _Included_com_taosdata_jdbc_tmq_TMQConnector
+#define _Included_com_taosdata_jdbc_tmq_TMQConnector
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConfNewImp
+ * Signature: (Lcom/taosdata/jdbc/tmq/TAOSConsumer;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfNewImp(JNIEnv *, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConfSetImp
+ * Signature: (JLjava/lang/String;Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfSetImp(JNIEnv *, jobject, jlong, jstring,
+ jstring);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConfDestroyImp
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfDestroyImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConsumerNewImp
+ * Signature: (JLcom/taosdata/jdbc/tmq/TMQConnector;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerNewImp(JNIEnv *, jobject, jlong, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqTopicNewImp
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicNewImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqTopicAppendImp
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicAppendImp(JNIEnv *, jobject, jlong, jstring);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqTopicDestroyImp
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicDestroyImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqSubscribeImp
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSubscribeImp(JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqSubscriptionImp
+ * Signature: (JLcom/taosdata/jdbc/tmq/TMQConnector;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSubscriptionImp(JNIEnv *, jobject, jlong, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqCommitSync
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitSync(JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqCommitAsync
+ * Signature: (JJLcom/taosdata/jdbc/tmq/TAOSConsumer;)V
+ */
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JNIEnv *, jobject, jlong, jlong, jobject);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqUnsubscribeImp
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqUnsubscribeImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConsumerCloseImp
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerCloseImp(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: getErrMsgImp
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_getErrMsgImp(JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqConsumerPoll
+ * Signature: (JJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerPoll(JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqGetTopicName
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTopicName(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqGetDbName
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetDbName(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqGetVgroupId
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetVgroupId(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: tmqGetTableName
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTableName(JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_taosdata_jdbc_tmq_TMQConnector
+ * Method: fetchBlockImp
+ * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;ILjava/util/List;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(JNIEnv *, jobject, jlong, jlong,
+ jobject, jint, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/source/client/jni/jniCommon.h b/source/client/jni/jniCommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..d620487ad2710b7ed1462c1a73cb6333b2f40db3
--- /dev/null
+++ b/source/client/jni/jniCommon.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include "taoserror.h"
+#include "tdef.h"
+#include "tlog.h"
+#include "ttypes.h"
+
+#ifndef TDENGINE_JNICOMMON_H
+#define TDENGINE_JNICOMMON_H
+
+#define jniFatal(...) \
+ { \
+ if (jniDebugFlag & DEBUG_FATAL) { \
+ taosPrintLog("JNI FATAL ", DEBUG_FATAL, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define jniError(...) \
+ { \
+ if (jniDebugFlag & DEBUG_ERROR) { \
+ taosPrintLog("JNI ERROR ", DEBUG_ERROR, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define jniWarn(...) \
+ { \
+ if (jniDebugFlag & DEBUG_WARN) { \
+ taosPrintLog("JNI WARN ", DEBUG_WARN, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define jniInfo(...) \
+ { \
+ if (jniDebugFlag & DEBUG_INFO) { \
+ taosPrintLog("JNI ", DEBUG_INFO, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define jniDebug(...) \
+ { \
+ if (jniDebugFlag & DEBUG_DEBUG) { \
+ taosPrintLog("JNI ", DEBUG_DEBUG, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define jniTrace(...) \
+ { \
+ if (jniDebugFlag & DEBUG_TRACE) { \
+ taosPrintLog("JNI ", DEBUG_TRACE, jniDebugFlag, __VA_ARGS__); \
+ } \
+ }
+
+extern jclass g_arrayListClass;
+extern jmethodID g_arrayListConstructFp;
+extern jmethodID g_arrayListAddFp;
+
+extern jclass g_metadataClass;
+extern jmethodID g_metadataConstructFp;
+extern jfieldID g_metadataColtypeField;
+extern jfieldID g_metadataColnameField;
+extern jfieldID g_metadataColsizeField;
+extern jfieldID g_metadataColindexField;
+
+extern jclass g_rowdataClass;
+extern jmethodID g_rowdataConstructor;
+extern jmethodID g_rowdataClearFp;
+extern jmethodID g_rowdataSetBooleanFp;
+extern jmethodID g_rowdataSetByteFp;
+extern jmethodID g_rowdataSetShortFp;
+extern jmethodID g_rowdataSetIntFp;
+extern jmethodID g_rowdataSetLongFp;
+extern jmethodID g_rowdataSetFloatFp;
+extern jmethodID g_rowdataSetDoubleFp;
+extern jmethodID g_rowdataSetStringFp;
+extern jmethodID g_rowdataSetTimestampFp;
+extern jmethodID g_rowdataSetByteArrayFp;
+
+extern jmethodID g_blockdataSetByteArrayFp;
+extern jmethodID g_blockdataSetNumOfRowsFp;
+extern jmethodID g_blockdataSetNumOfColsFp;
+
+extern jclass g_tmqClass;
+extern jmethodID g_createConsumerErrorCallback;
+extern jmethodID g_topicListCallback;
+
+extern jclass g_consumerClass;
+extern jmethodID g_commitCallback;
+
+jstring jniFromNCharToByteArray(JNIEnv *, char *, int32_t);
+
+#define JNI_SUCCESS 0
+#define JNI_TDENGINE_ERROR -1
+#define JNI_CONNECTION_NULL -2
+#define JNI_RESULT_SET_NULL -3
+#define JNI_NUM_OF_FIELDS_0 -4
+#define JNI_SQL_NULL -5
+#define JNI_FETCH_END -6
+#define JNI_OUT_OF_MEMORY -7
+
+#define TMQ_CONF_NULL -100;
+#define TMQ_CONF_KEY_NULL -101;
+#define TMQ_CONF_VALUE_NULL -102;
+#define TMQ_TOPIC_NULL -110;
+#define TMQ_TOPIC_NAME_NULL -111;
+#define TMQ_CONSUMER_NULL -120;
+#define TMQ_CONSUMER_CREATE_ERROR -121;
+
+extern JavaVM *g_vm;
+
+void jniGetGlobalMethod(JNIEnv *env);
+
+int32_t check_for_params(jobject jobj, jlong conn, jlong res);
+
+#endif // TDENGINE_JNICOMMON_H
diff --git a/source/client/jni/linux/AWTCocoaComponent.h b/source/client/jni/linux/AWTCocoaComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4f5ace357588ccfe963f977f1a111cc3c1e3823
--- /dev/null
+++ b/source/client/jni/linux/AWTCocoaComponent.h
@@ -0,0 +1,15 @@
+//
+// AWTCocoaComponent.h
+//
+// Copyright (c) 2003 Apple Computer Inc. All rights reserved.
+//
+
+#import
+#import
+
+// This is implemented by a com.apple.eawt.CocoaComponent. It receives messages
+// from java safely on the AppKit thread. See the com.apple.eawt.CocoaComponent
+// java documentation for more information.
+@protocol AWTCocoaComponent
+-(void)awtMessage:(jint)messageID message:(jobject)message env:(JNIEnv*)env DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+@end
diff --git a/source/client/jni/linux/JDWP.h b/source/client/jni/linux/JDWP.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f9faeb09b528b9bbed2701850cd59da1dead9e8
--- /dev/null
+++ b/source/client/jni/linux/JDWP.h
@@ -0,0 +1,53 @@
+/*
+ * @(#)JDWP.h 1.33 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef JDWP_JDWP_H
+#define JDWP_JDWP_H
+
+#include "JDWPCommands.h"
+
+/*
+ * JDWPCommands.h is the javah'ed version of all the constants defined
+ * com.sun.tools.jdi.JDWP and all its nested classes. Since the names are
+ * very long, the macros below are provided for convenience.
+ */
+
+#define JDWP_COMMAND_SET(name) JDWP_ ## name
+#define JDWP_COMMAND(set, name) JDWP_ ## set ## _ ## name
+#define JDWP_REQUEST_MODIFIER(name) \
+ JDWP_EventRequest_Set_Out_modifiers_Modifier_ ## name
+#define JDWP_EVENT(name) \
+ JDWP_EventKind_ ## name
+#define JDWP_THREAD_STATUS(name) \
+ JDWP_ThreadStatus_ ## name
+#define JDWP_SUSPEND_STATUS(name) \
+ JDWP_SuspendStatus_SUSPEND_STATUS_ ## name
+#define JDWP_CLASS_STATUS(name) \
+ JDWP_ClassStatus_ ## name
+#define JDWP_TYPE_TAG(name) \
+ JDWP_TypeTag_ ## name
+#define JDWP_TAG(name) \
+ JDWP_Tag_ ## name
+#define JDWP_STEP_DEPTH(name) \
+ JDWP_StepDepth_ ## name
+#define JDWP_STEP_SIZE(name) \
+ JDWP_StepSize_ ## name
+#define JDWP_SUSPEND_POLICY(name) \
+ JDWP_SuspendPolicy_ ## name
+#define JDWP_INVOKE_OPTIONS(name) \
+ JDWP_InvokeOptions_INVOKE_ ## name
+#define JDWP_ERROR(name) \
+ JDWP_Error_ ## name
+#define JDWP_HIGHEST_COMMAND_SET 17
+#define JDWP_REQUEST_NONE -1
+
+/* This typedef helps keep the event and error types straight. */
+typedef unsigned short jdwpError;
+typedef unsigned char jdwpEvent;
+typedef jint jdwpThreadStatus;
+
+#endif
diff --git a/source/client/jni/linux/JDWPCommands.h b/source/client/jni/linux/JDWPCommands.h
new file mode 100644
index 0000000000000000000000000000000000000000..afad997021d3d5992469051a7f91660f7f5b6d81
--- /dev/null
+++ b/source/client/jni/linux/JDWPCommands.h
@@ -0,0 +1,257 @@
+#define JDWP_VirtualMachine 1
+#define JDWP_VirtualMachine_Version 1
+#define JDWP_VirtualMachine_ClassesBySignature 2
+#define JDWP_VirtualMachine_AllClasses 3
+#define JDWP_VirtualMachine_AllThreads 4
+#define JDWP_VirtualMachine_TopLevelThreadGroups 5
+#define JDWP_VirtualMachine_Dispose 6
+#define JDWP_VirtualMachine_IDSizes 7
+#define JDWP_VirtualMachine_Suspend 8
+#define JDWP_VirtualMachine_Resume 9
+#define JDWP_VirtualMachine_Exit 10
+#define JDWP_VirtualMachine_CreateString 11
+#define JDWP_VirtualMachine_Capabilities 12
+#define JDWP_VirtualMachine_ClassPaths 13
+#define JDWP_VirtualMachine_DisposeObjects 14
+#define JDWP_VirtualMachine_HoldEvents 15
+#define JDWP_VirtualMachine_ReleaseEvents 16
+#define JDWP_VirtualMachine_CapabilitiesNew 17
+#define JDWP_VirtualMachine_RedefineClasses 18
+#define JDWP_VirtualMachine_SetDefaultStratum 19
+#define JDWP_VirtualMachine_AllClassesWithGeneric 20
+#define JDWP_VirtualMachine_InstanceCounts 21
+#define JDWP_ReferenceType 2
+#define JDWP_ReferenceType_Signature 1
+#define JDWP_ReferenceType_ClassLoader 2
+#define JDWP_ReferenceType_Modifiers 3
+#define JDWP_ReferenceType_Fields 4
+#define JDWP_ReferenceType_Methods 5
+#define JDWP_ReferenceType_GetValues 6
+#define JDWP_ReferenceType_SourceFile 7
+#define JDWP_ReferenceType_NestedTypes 8
+#define JDWP_ReferenceType_Status 9
+#define JDWP_ReferenceType_Interfaces 10
+#define JDWP_ReferenceType_ClassObject 11
+#define JDWP_ReferenceType_SourceDebugExtension 12
+#define JDWP_ReferenceType_SignatureWithGeneric 13
+#define JDWP_ReferenceType_FieldsWithGeneric 14
+#define JDWP_ReferenceType_MethodsWithGeneric 15
+#define JDWP_ReferenceType_Instances 16
+#define JDWP_ReferenceType_ClassFileVersion 17
+#define JDWP_ReferenceType_ConstantPool 18
+#define JDWP_ClassType 3
+#define JDWP_ClassType_Superclass 1
+#define JDWP_ClassType_SetValues 2
+#define JDWP_ClassType_InvokeMethod 3
+#define JDWP_ClassType_NewInstance 4
+#define JDWP_ArrayType 4
+#define JDWP_ArrayType_NewInstance 1
+#define JDWP_InterfaceType 5
+#define JDWP_Method 6
+#define JDWP_Method_LineTable 1
+#define JDWP_Method_VariableTable 2
+#define JDWP_Method_Bytecodes 3
+#define JDWP_Method_IsObsolete 4
+#define JDWP_Method_VariableTableWithGeneric 5
+#define JDWP_Field 8
+#define JDWP_ObjectReference 9
+#define JDWP_ObjectReference_ReferenceType 1
+#define JDWP_ObjectReference_GetValues 2
+#define JDWP_ObjectReference_SetValues 3
+#define JDWP_ObjectReference_MonitorInfo 5
+#define JDWP_ObjectReference_InvokeMethod 6
+#define JDWP_ObjectReference_DisableCollection 7
+#define JDWP_ObjectReference_EnableCollection 8
+#define JDWP_ObjectReference_IsCollected 9
+#define JDWP_ObjectReference_ReferringObjects 10
+#define JDWP_StringReference 10
+#define JDWP_StringReference_Value 1
+#define JDWP_ThreadReference 11
+#define JDWP_ThreadReference_Name 1
+#define JDWP_ThreadReference_Suspend 2
+#define JDWP_ThreadReference_Resume 3
+#define JDWP_ThreadReference_Status 4
+#define JDWP_ThreadReference_ThreadGroup 5
+#define JDWP_ThreadReference_Frames 6
+#define JDWP_ThreadReference_FrameCount 7
+#define JDWP_ThreadReference_OwnedMonitors 8
+#define JDWP_ThreadReference_CurrentContendedMonitor 9
+#define JDWP_ThreadReference_Stop 10
+#define JDWP_ThreadReference_Interrupt 11
+#define JDWP_ThreadReference_SuspendCount 12
+#define JDWP_ThreadReference_OwnedMonitorsStackDepthInfo 13
+#define JDWP_ThreadReference_ForceEarlyReturn 14
+#define JDWP_ThreadGroupReference 12
+#define JDWP_ThreadGroupReference_Name 1
+#define JDWP_ThreadGroupReference_Parent 2
+#define JDWP_ThreadGroupReference_Children 3
+#define JDWP_ArrayReference 13
+#define JDWP_ArrayReference_Length 1
+#define JDWP_ArrayReference_GetValues 2
+#define JDWP_ArrayReference_SetValues 3
+#define JDWP_ClassLoaderReference 14
+#define JDWP_ClassLoaderReference_VisibleClasses 1
+#define JDWP_EventRequest 15
+#define JDWP_EventRequest_Set 1
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Count 1
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Conditional 2
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ThreadOnly 3
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassOnly 4
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassMatch 5
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassExclude 6
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly 7
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ExceptionOnly 8
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_FieldOnly 9
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Step 10
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_InstanceOnly 11
+#define JDWP_EventRequest_Set_Out_modifiers_Modifier_SourceNameMatch 12
+#define JDWP_EventRequest_Clear 2
+#define JDWP_EventRequest_ClearAllBreakpoints 3
+#define JDWP_StackFrame 16
+#define JDWP_StackFrame_GetValues 1
+#define JDWP_StackFrame_SetValues 2
+#define JDWP_StackFrame_ThisObject 3
+#define JDWP_StackFrame_PopFrames 4
+#define JDWP_ClassObjectReference 17
+#define JDWP_ClassObjectReference_ReflectedType 1
+#define JDWP_Event 64
+#define JDWP_Event_Composite 100
+#define JDWP_Event_Composite_Event_events_Events_VMStart JDWP.EventKind.VM_START
+#define JDWP_Event_Composite_Event_events_Events_SingleStep JDWP.EventKind.SINGLE_STEP
+#define JDWP_Event_Composite_Event_events_Events_Breakpoint JDWP.EventKind.BREAKPOINT
+#define JDWP_Event_Composite_Event_events_Events_MethodEntry JDWP.EventKind.METHOD_ENTRY
+#define JDWP_Event_Composite_Event_events_Events_MethodExit JDWP.EventKind.METHOD_EXIT
+#define JDWP_Event_Composite_Event_events_Events_MethodExitWithReturnValue JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE
+#define JDWP_Event_Composite_Event_events_Events_MonitorContendedEnter JDWP.EventKind.MONITOR_CONTENDED_ENTER
+#define JDWP_Event_Composite_Event_events_Events_MonitorContendedEntered JDWP.EventKind.MONITOR_CONTENDED_ENTERED
+#define JDWP_Event_Composite_Event_events_Events_MonitorWait JDWP.EventKind.MONITOR_WAIT
+#define JDWP_Event_Composite_Event_events_Events_MonitorWaited JDWP.EventKind.MONITOR_WAITED
+#define JDWP_Event_Composite_Event_events_Events_Exception JDWP.EventKind.EXCEPTION
+#define JDWP_Event_Composite_Event_events_Events_ThreadStart JDWP.EventKind.THREAD_START
+#define JDWP_Event_Composite_Event_events_Events_ThreadDeath JDWP.EventKind.THREAD_DEATH
+#define JDWP_Event_Composite_Event_events_Events_ClassPrepare JDWP.EventKind.CLASS_PREPARE
+#define JDWP_Event_Composite_Event_events_Events_ClassUnload JDWP.EventKind.CLASS_UNLOAD
+#define JDWP_Event_Composite_Event_events_Events_FieldAccess JDWP.EventKind.FIELD_ACCESS
+#define JDWP_Event_Composite_Event_events_Events_FieldModification JDWP.EventKind.FIELD_MODIFICATION
+#define JDWP_Event_Composite_Event_events_Events_VMDeath JDWP.EventKind.VM_DEATH
+#define JDWP_Error_NONE 0
+#define JDWP_Error_INVALID_THREAD 10
+#define JDWP_Error_INVALID_THREAD_GROUP 11
+#define JDWP_Error_INVALID_PRIORITY 12
+#define JDWP_Error_THREAD_NOT_SUSPENDED 13
+#define JDWP_Error_THREAD_SUSPENDED 14
+#define JDWP_Error_THREAD_NOT_ALIVE 15
+#define JDWP_Error_INVALID_OBJECT 20
+#define JDWP_Error_INVALID_CLASS 21
+#define JDWP_Error_CLASS_NOT_PREPARED 22
+#define JDWP_Error_INVALID_METHODID 23
+#define JDWP_Error_INVALID_LOCATION 24
+#define JDWP_Error_INVALID_FIELDID 25
+#define JDWP_Error_INVALID_FRAMEID 30
+#define JDWP_Error_NO_MORE_FRAMES 31
+#define JDWP_Error_OPAQUE_FRAME 32
+#define JDWP_Error_NOT_CURRENT_FRAME 33
+#define JDWP_Error_TYPE_MISMATCH 34
+#define JDWP_Error_INVALID_SLOT 35
+#define JDWP_Error_DUPLICATE 40
+#define JDWP_Error_NOT_FOUND 41
+#define JDWP_Error_INVALID_MONITOR 50
+#define JDWP_Error_NOT_MONITOR_OWNER 51
+#define JDWP_Error_INTERRUPT 52
+#define JDWP_Error_INVALID_CLASS_FORMAT 60
+#define JDWP_Error_CIRCULAR_CLASS_DEFINITION 61
+#define JDWP_Error_FAILS_VERIFICATION 62
+#define JDWP_Error_ADD_METHOD_NOT_IMPLEMENTED 63
+#define JDWP_Error_SCHEMA_CHANGE_NOT_IMPLEMENTED 64
+#define JDWP_Error_INVALID_TYPESTATE 65
+#define JDWP_Error_HIERARCHY_CHANGE_NOT_IMPLEMENTED 66
+#define JDWP_Error_DELETE_METHOD_NOT_IMPLEMENTED 67
+#define JDWP_Error_UNSUPPORTED_VERSION 68
+#define JDWP_Error_NAMES_DONT_MATCH 69
+#define JDWP_Error_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED 70
+#define JDWP_Error_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED 71
+#define JDWP_Error_NOT_IMPLEMENTED 99
+#define JDWP_Error_NULL_POINTER 100
+#define JDWP_Error_ABSENT_INFORMATION 101
+#define JDWP_Error_INVALID_EVENT_TYPE 102
+#define JDWP_Error_ILLEGAL_ARGUMENT 103
+#define JDWP_Error_OUT_OF_MEMORY 110
+#define JDWP_Error_ACCESS_DENIED 111
+#define JDWP_Error_VM_DEAD 112
+#define JDWP_Error_INTERNAL 113
+#define JDWP_Error_UNATTACHED_THREAD 115
+#define JDWP_Error_INVALID_TAG 500
+#define JDWP_Error_ALREADY_INVOKING 502
+#define JDWP_Error_INVALID_INDEX 503
+#define JDWP_Error_INVALID_LENGTH 504
+#define JDWP_Error_INVALID_STRING 506
+#define JDWP_Error_INVALID_CLASS_LOADER 507
+#define JDWP_Error_INVALID_ARRAY 508
+#define JDWP_Error_TRANSPORT_LOAD 509
+#define JDWP_Error_TRANSPORT_INIT 510
+#define JDWP_Error_NATIVE_METHOD 511
+#define JDWP_Error_INVALID_COUNT 512
+#define JDWP_EventKind_SINGLE_STEP 1
+#define JDWP_EventKind_BREAKPOINT 2
+#define JDWP_EventKind_FRAME_POP 3
+#define JDWP_EventKind_EXCEPTION 4
+#define JDWP_EventKind_USER_DEFINED 5
+#define JDWP_EventKind_THREAD_START 6
+#define JDWP_EventKind_THREAD_DEATH 7
+#define JDWP_EventKind_THREAD_END 7
+#define JDWP_EventKind_CLASS_PREPARE 8
+#define JDWP_EventKind_CLASS_UNLOAD 9
+#define JDWP_EventKind_CLASS_LOAD 10
+#define JDWP_EventKind_FIELD_ACCESS 20
+#define JDWP_EventKind_FIELD_MODIFICATION 21
+#define JDWP_EventKind_EXCEPTION_CATCH 30
+#define JDWP_EventKind_METHOD_ENTRY 40
+#define JDWP_EventKind_METHOD_EXIT 41
+#define JDWP_EventKind_METHOD_EXIT_WITH_RETURN_VALUE 42
+#define JDWP_EventKind_MONITOR_CONTENDED_ENTER 43
+#define JDWP_EventKind_MONITOR_CONTENDED_ENTERED 44
+#define JDWP_EventKind_MONITOR_WAIT 45
+#define JDWP_EventKind_MONITOR_WAITED 46
+#define JDWP_EventKind_VM_START 90
+#define JDWP_EventKind_VM_INIT 90
+#define JDWP_EventKind_VM_DEATH 99
+#define JDWP_EventKind_VM_DISCONNECTED 100
+#define JDWP_ThreadStatus_ZOMBIE 0
+#define JDWP_ThreadStatus_RUNNING 1
+#define JDWP_ThreadStatus_SLEEPING 2
+#define JDWP_ThreadStatus_MONITOR 3
+#define JDWP_ThreadStatus_WAIT 4
+#define JDWP_SuspendStatus_SUSPEND_STATUS_SUSPENDED 0x1
+#define JDWP_ClassStatus_VERIFIED 1
+#define JDWP_ClassStatus_PREPARED 2
+#define JDWP_ClassStatus_INITIALIZED 4
+#define JDWP_ClassStatus_ERROR 8
+#define JDWP_TypeTag_CLASS 1
+#define JDWP_TypeTag_INTERFACE 2
+#define JDWP_TypeTag_ARRAY 3
+#define JDWP_Tag_ARRAY 91
+#define JDWP_Tag_BYTE 66
+#define JDWP_Tag_CHAR 67
+#define JDWP_Tag_OBJECT 76
+#define JDWP_Tag_FLOAT 70
+#define JDWP_Tag_DOUBLE 68
+#define JDWP_Tag_INT 73
+#define JDWP_Tag_LONG 74
+#define JDWP_Tag_SHORT 83
+#define JDWP_Tag_VOID 86
+#define JDWP_Tag_BOOLEAN 90
+#define JDWP_Tag_STRING 115
+#define JDWP_Tag_THREAD 116
+#define JDWP_Tag_THREAD_GROUP 103
+#define JDWP_Tag_CLASS_LOADER 108
+#define JDWP_Tag_CLASS_OBJECT 99
+#define JDWP_StepDepth_INTO 0
+#define JDWP_StepDepth_OVER 1
+#define JDWP_StepDepth_OUT 2
+#define JDWP_StepSize_MIN 0
+#define JDWP_StepSize_LINE 1
+#define JDWP_SuspendPolicy_NONE 0
+#define JDWP_SuspendPolicy_EVENT_THREAD 1
+#define JDWP_SuspendPolicy_ALL 2
+#define JDWP_InvokeOptions_INVOKE_SINGLE_THREADED 0x01
+#define JDWP_InvokeOptions_INVOKE_NONVIRTUAL 0x02
diff --git a/source/client/jni/linux/JavaVM.h b/source/client/jni/linux/JavaVM.h
new file mode 100644
index 0000000000000000000000000000000000000000..50a5361edb5cdf879c538fc28b1f1bd0d6210019
--- /dev/null
+++ b/source/client/jni/linux/JavaVM.h
@@ -0,0 +1,11 @@
+/*
+ * JavaVM.h
+ *
+ * Copyright (C) 1997-2001, Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ */
+
+#import
+#import
+
diff --git a/source/client/jni/linux/NSJavaConfiguration.h b/source/client/jni/linux/NSJavaConfiguration.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ddd5ff432b9cf1316eee05c8768e30f0bc5f549
--- /dev/null
+++ b/source/client/jni/linux/NSJavaConfiguration.h
@@ -0,0 +1,79 @@
+/*
+ * NSJavaConfiguration.h
+ *
+ * Copyright (c) 1997-2001, Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ * LaurentR- April, 2000
+ * - added:
+ * NSDefaultJavaLibraryKey
+ * NSDefaultJavaDebugLibraryKey
+ * NSDefaultObjCJavaLibraryKey
+ * NSDefaultObjCJavaDebugLibraryKey
+ * NSJavaVMArgumentsKey
+ */
+
+#import
+
+// The configuration dictionary contains a set of vendor-specific key/value
+// pairs and a set of default key/value pairs. If no vendor is specified,
+// NSJavaConfiguration uses the NSDefaultJavaVendorKey key to determine which
+// vendor-specific dictionary should be searched before the top-level dictionary// is searched. eg.:
+/*
+ {
+ Vendor = sun;
+ default = {
+ DefaultClasspath = "/NextLibrary/Java";
+ };
+ next = {
+ Compiler = "/usr/bin/javac";
+ VM = "/usr/bin/java";
+ };
+ sun = {
+ Compiler = "/NextLibrary/JDK/bin/javac";
+ VM = "/NextLibrary/JDK/bin/java";
+ };
+ }
+*/
+// In this case, if no vendor is specified, the `sun' mappings will be searched
+// first. The value for `VM' would be "/NextLibrary/JDK/bin/java" and the value
+// for `DefaultClasspath' would be "/NextLibrary/Java".
+//
+// This search patter is applied to three dictionaries, in order:
+// - the JavaConfiguration dictionary in the defaults for the application
+// - the dictionary in the "JavaConfiguration" domain of the user defaults
+// - the configuration file (/NextLibrary/Java/JavaConfig.plist).
+// This permits per-application, per-user and per-system specifications.
+
+
+extern NSString *NSDefaultJavaVendorKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+extern NSString *NSDefaultJavaVMKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultJavaCompilerKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultJavaClassPathKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultJavaLibraryKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultJavaDebugLibraryKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultObjCJavaLibraryKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSDefaultObjCJavaDebugLibraryKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+extern NSString *NSJavaVMArgumentsKey DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+@interface NSJavaConfiguration : NSObject
+{
+ NSString *_vendorName;
+}
+
++ (NSJavaConfiguration *) defaultConfiguration DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
++ (NSJavaConfiguration *) configurationForVendor:(NSString *)vendorName DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
++ (NSArray *) vendorNames DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+- init DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+- initWithVendor:(NSString *)vendorName DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+- (NSString *) vendorName DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+- valueForKey:(NSString *)keyName DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+- valueForKey:(NSString *)keyName expandEnvironmentVariables:(BOOL)flag DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+@end
+
diff --git a/source/client/jni/linux/NSJavaVirtualMachine.h b/source/client/jni/linux/NSJavaVirtualMachine.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3a6708d7283bee232b2bf257822c2088193758b
--- /dev/null
+++ b/source/client/jni/linux/NSJavaVirtualMachine.h
@@ -0,0 +1,61 @@
+/*
+ * NSJavaVirtualMachine.h
+ *
+ * Copyright (c) 1997-2001, Apple Computer, Inc.
+ * All Rights Reserved.
+ */
+
+#import
+
+@interface NSJavaVirtualMachine : NSObject
+{
+@private
+ void *_vmdata;
+}
+
+
+// Returns the default virtual machine - if necessary, calls alloc + init
+
++ (id) defaultVirtualMachine DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+// Returns a class path. First checks NSProcessInfo for an environment variable
+// called CLASSPATH and if that doesn't exist, uses NSJavaConfiguration to find
+// the default class path.
+
++ (NSString *) defaultClassPath DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+// Note that any NSThreads spawned after this method returns will automatically
+// be attached to the virtual machine. Likewise, it is not necessary to attach
+// the thread that is actually creating the virtual machine. If you spawn a
+// thread before creating the virtual machine, or if you use the cthread/pthread
+// or any other non-NSThread api for creating a thread, you must explicitly
+// attach those threads before messaging any Java object from that thread.
+// This is most easily done by using the -attachCurrentThread method.
+// Use -detachCurrentThread to detach explicitly attached threads when done.
+
+- initWithClassPath:(NSString *)classPath DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+- (void) attachCurrentThread DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+- (void) detachCurrentThread DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+- (Class)findClass:(NSString *)className DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+- (Class)defineClass:(NSData *)javaClassData withName:(NSString *)className DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+@end
+
+
+@interface NSObject (InstantiatingJavaObjects)
+
+// Instantiating java objects for when no -init/constructor mapping works.
+// The class these methods are invoked on *must* be a class returned by the
+// -findClass: method (or NSClassFromString() function), otherwise
+// NSInvalidJavaClassException is raised. The signature is specified using the
+// rather counter-intuitive format defined by the Java Virtual Machine
+// specification. Try looking in JavaVM/vm-interface.h for help.
+
++ (id) newWithSignature:(NSString *)signature, ... DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
++ (id) newWithSignature:(NSString *)signature arguments:(va_list)args DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+@end
+
+extern NSString *NSInvalidJavaClassException DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER;
diff --git a/source/client/jni/linux/jawt.h b/source/client/jni/linux/jawt.h
new file mode 100644
index 0000000000000000000000000000000000000000..b62fe666fe4c181cd9487905bd41aeb1944484ba
--- /dev/null
+++ b/source/client/jni/linux/jawt.h
@@ -0,0 +1,278 @@
+/*
+ * @(#)jawt.h 1.11 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JAWT_H_
+#define _JAVASOFT_JAWT_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * AWT native interface (new in JDK 1.3)
+ *
+ * The AWT native interface allows a native C or C++ application a means
+ * by which to access native structures in AWT. This is to facilitate moving
+ * legacy C and C++ applications to Java and to target the needs of the
+ * community who, at present, wish to do their own native rendering to canvases
+ * for performance reasons. Standard extensions such as Java3D also require a
+ * means to access the underlying native data structures of AWT.
+ *
+ * There may be future extensions to this API depending on demand.
+ *
+ * A VM does not have to implement this API in order to pass the JCK.
+ * It is recommended, however, that this API is implemented on VMs that support
+ * standard extensions, such as Java3D.
+ *
+ * Since this is a native API, any program which uses it cannot be considered
+ * 100% pure java.
+ */
+
+/*
+ * AWT Native Drawing Surface (JAWT_DrawingSurface).
+ *
+ * For each platform, there is a native drawing surface structure. This
+ * platform-specific structure can be found in jawt_md.h. It is recommended
+ * that additional platforms follow the same model. It is also recommended
+ * that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
+ *
+ *******************
+ * EXAMPLE OF USAGE:
+ *******************
+ *
+ * In Win32, a programmer wishes to access the HWND of a canvas to perform
+ * native rendering into it. The programmer has declared the paint() method
+ * for their canvas subclass to be native:
+ *
+ *
+ * MyCanvas.java:
+ *
+ * import java.awt.*;
+ *
+ * public class MyCanvas extends Canvas {
+ *
+ * static {
+ * System.loadLibrary("mylib");
+ * }
+ *
+ * public native void paint(Graphics g);
+ * }
+ *
+ *
+ * myfile.c:
+ *
+ * #include "jawt_md.h"
+ * #include
+ *
+ * JNIEXPORT void JNICALL
+ * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
+ * {
+ * JAWT awt;
+ * JAWT_DrawingSurface* ds;
+ * JAWT_DrawingSurfaceInfo* dsi;
+ * JAWT_Win32DrawingSurfaceInfo* dsi_win;
+ * jboolean result;
+ * jint lock;
+ *
+ * // Get the AWT
+ * awt.version = JAWT_VERSION_1_3;
+ * result = JAWT_GetAWT(env, &awt);
+ * assert(result != JNI_FALSE);
+ *
+ * // Get the drawing surface
+ * ds = awt.GetDrawingSurface(env, canvas);
+ * assert(ds != NULL);
+ *
+ * // Lock the drawing surface
+ * lock = ds->Lock(ds);
+ * assert((lock & JAWT_LOCK_ERROR) == 0);
+ *
+ * // Get the drawing surface info
+ * dsi = ds->GetDrawingSurfaceInfo(ds);
+ *
+ * // Get the platform-specific drawing info
+ * dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+ *
+ * //////////////////////////////
+ * // !!! DO PAINTING HERE !!! //
+ * //////////////////////////////
+ *
+ * // Free the drawing surface info
+ * ds->FreeDrawingSurfaceInfo(dsi);
+ *
+ * // Unlock the drawing surface
+ * ds->Unlock(ds);
+ *
+ * // Free the drawing surface
+ * awt.FreeDrawingSurface(ds);
+ * }
+ *
+ */
+
+/*
+ * JAWT_Rectangle
+ * Structure for a native rectangle.
+ */
+typedef struct jawt_Rectangle {
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+} JAWT_Rectangle;
+
+struct jawt_DrawingSurface;
+
+/*
+ * JAWT_DrawingSurfaceInfo
+ * Structure for containing the underlying drawing information of a component.
+ */
+typedef struct jawt_DrawingSurfaceInfo {
+ /*
+ * Pointer to the platform-specific information. This can be safely
+ * cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
+ * JAWT_X11DrawingSurfaceInfo on Solaris. See jawt_md.h for details.
+ */
+ void* platformInfo;
+ /* Cached pointer to the underlying drawing surface */
+ struct jawt_DrawingSurface* ds;
+ /* Bounding rectangle of the drawing surface */
+ JAWT_Rectangle bounds;
+ /* Number of rectangles in the clip */
+ jint clipSize;
+ /* Clip rectangle array */
+ JAWT_Rectangle* clip;
+} JAWT_DrawingSurfaceInfo;
+
+#define JAWT_LOCK_ERROR 0x00000001
+#define JAWT_LOCK_CLIP_CHANGED 0x00000002
+#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
+#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
+
+/*
+ * JAWT_DrawingSurface
+ * Structure for containing the underlying drawing information of a component.
+ * All operations on a JAWT_DrawingSurface MUST be performed from the same
+ * thread as the call to GetDrawingSurface.
+ */
+typedef struct jawt_DrawingSurface {
+ /*
+ * Cached reference to the Java environment of the calling thread.
+ * If Lock(), Unlock(), GetDrawingSurfaceInfo() or
+ * FreeDrawingSurfaceInfo() are called from a different thread,
+ * this data member should be set before calling those functions.
+ */
+ JNIEnv* env;
+ /* Cached reference to the target object */
+ jobject target;
+ /*
+ * Lock the surface of the target component for native rendering.
+ * When finished drawing, the surface must be unlocked with
+ * Unlock(). This function returns a bitmask with one or more of the
+ * following values:
+ *
+ * JAWT_LOCK_ERROR - When an error has occurred and the surface could not
+ * be locked.
+ *
+ * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
+ *
+ * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
+ *
+ * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
+ */
+ jint (JNICALL *Lock)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Get the drawing surface info.
+ * The value returned may be cached, but the values may change if
+ * additional calls to Lock() or Unlock() are made.
+ * Lock() must be called before this can return a valid value.
+ * Returns NULL if an error has occurred.
+ * When finished with the returned value, FreeDrawingSurfaceInfo must be
+ * called.
+ */
+ JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Free the drawing surface info.
+ */
+ void (JNICALL *FreeDrawingSurfaceInfo)
+ (JAWT_DrawingSurfaceInfo* dsi);
+ /*
+ * Unlock the drawing surface of the target component for native rendering.
+ */
+ void (JNICALL *Unlock)
+ (struct jawt_DrawingSurface* ds);
+} JAWT_DrawingSurface;
+
+/*
+ * JAWT
+ * Structure for containing native AWT functions.
+ */
+typedef struct jawt {
+ /*
+ * Version of this structure. This must always be set before
+ * calling JAWT_GetAWT()
+ */
+ jint version;
+ /*
+ * Return a drawing surface from a target jobject. This value
+ * may be cached.
+ * Returns NULL if an error has occurred.
+ * Target must be a java.awt.Component (should be a Canvas
+ * or Window for native rendering).
+ * FreeDrawingSurface() must be called when finished with the
+ * returned JAWT_DrawingSurface.
+ */
+ JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
+ (JNIEnv* env, jobject target);
+ /*
+ * Free the drawing surface allocated in GetDrawingSurface.
+ */
+ void (JNICALL *FreeDrawingSurface)
+ (JAWT_DrawingSurface* ds);
+ /*
+ * Since 1.4
+ * Locks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Lock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Unlocks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Unlock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Returns a reference to a java.awt.Component from a native
+ * platform handle. On Windows, this corresponds to an HWND;
+ * on Solaris and Linux, this is a Drawable. For other platforms,
+ * see the appropriate machine-dependent header file for a description.
+ * The reference returned by this function is a local
+ * reference that is only valid in this environment.
+ * This function returns a NULL reference if no component could be
+ * found with matching platform information.
+ */
+ jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
+
+} JAWT;
+
+/*
+ * Get the AWT native structure. This function returns JNI_FALSE if
+ * an error occurs.
+ */
+_JNI_IMPORT_OR_EXPORT_ __attribute__((deprecated))
+jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
+
+#define JAWT_VERSION_1_3 0x00010003
+#define JAWT_VERSION_1_4 0x00010004
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* !_JAVASOFT_JAWT_H_ */
diff --git a/source/client/jni/linux/jawt_md.h b/source/client/jni/linux/jawt_md.h
new file mode 100644
index 0000000000000000000000000000000000000000..f52353f17b2edb8cc642cf999ff5621d5f561e31
--- /dev/null
+++ b/source/client/jni/linux/jawt_md.h
@@ -0,0 +1,66 @@
+//
+// jawt_md.h
+// Copyright (c) 2002-2010 Apple Inc. All rights reserved.
+//
+
+#ifndef _JAVASOFT_JAWT_MD_H_
+#define _JAVASOFT_JAWT_MD_H_
+
+#include "jawt.h"
+
+#import
+#import
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JAWT on Mac OS X has two rendering models; legacy NSView, and CALayer.
+ *
+ * The CALayer based model returns an object conforming to the JAWT_SurfaceLayers
+ * protocol in it's JAWT_DrawingSurfaceInfo->platformInfo pointer. A CALayer
+ * assigned to the "layer" property overlays the rectangle of the java.awt.Component.
+ * The client CALayer traces the rect of the Java component as it is moved and resized.
+ *
+ * If there is a superlayer for the entire window, it is also accessible via
+ * the "windowLayer" property. This layer is useful for embedding the Java
+ * window in other layer graphs.
+ *
+ *
+ * The legacy NSView model provides raw access to the NSView hierarchy which
+ * mirrors the Java component hierarchy. The legacy NSView drawing model is deprecated,
+ * and will not be available in future versions of Java for Mac OS X.
+ *
+ * Clients can opt-into the CALayer model by OR'ing the JAWT_MACOSX_USE_CALAYER into the requested JAWT version.
+ *
+ * JAWT awt;
+ * awt.version = JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER;
+ * jboolean success = JAWT_GetAWT(env, &awt);
+ *
+ * Future versions of Java for Mac OS X will only support the CALayer model,
+ * and will not return a JAWT_MacOSXDrawingSurfaceInfo struct.
+ */
+
+#define JAWT_MACOSX_USE_CALAYER 0x80000000
+
+// CALayer-based rendering
+@protocol JAWT_SurfaceLayers
+@property (readwrite, retain) CALayer *layer;
+@property (readonly) CALayer *windowLayer;
+@end
+
+
+// Legacy NSView-based rendering
+typedef struct JAWT_MacOSXDrawingSurfaceInfo {
+ NSView *cocoaViewRef; // the view is guaranteed to be valid only for the duration of Component.paint method
+}
+JAWT_MacOSXDrawingSurfaceInfo;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_JAVASOFT_JAWT_MD_H_ */
diff --git a/source/client/jni/linux/jdwpTransport.h b/source/client/jni/linux/jdwpTransport.h
new file mode 100644
index 0000000000000000000000000000000000000000..30d88761ad96b10bf3335475c278a342113e607a
--- /dev/null
+++ b/source/client/jni/linux/jdwpTransport.h
@@ -0,0 +1,237 @@
+/*
+ * @(#)jdwpTransport.h 1.8 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/*
+ * Java Debug Wire Protocol Transport Service Provider Interface.
+ */
+
+#ifndef JDWPTRANSPORT_H
+#define JDWPTRANSPORT_H
+
+#include "jni.h"
+
+enum {
+ JDWPTRANSPORT_VERSION_1_0 = 0x00010000
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct jdwpTransportNativeInterface_;
+
+struct _jdwpTransportEnv;
+
+#ifdef __cplusplus
+typedef _jdwpTransportEnv jdwpTransportEnv;
+#else
+typedef const struct jdwpTransportNativeInterface_ *jdwpTransportEnv;
+#endif /* __cplusplus */
+
+/*
+ * Errors. Universal errors with JVMTI/JVMDI equivalents keep the
+ * values the same.
+ */
+typedef enum {
+ JDWPTRANSPORT_ERROR_NONE = 0,
+ JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103,
+ JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110,
+ JDWPTRANSPORT_ERROR_INTERNAL = 113,
+ JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201,
+ JDWPTRANSPORT_ERROR_IO_ERROR = 202,
+ JDWPTRANSPORT_ERROR_TIMEOUT = 203,
+ JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204
+} jdwpTransportError;
+
+
+/*
+ * Structure to define capabilities
+ */
+typedef struct {
+ unsigned int can_timeout_attach :1;
+ unsigned int can_timeout_accept :1;
+ unsigned int can_timeout_handshake :1;
+ unsigned int reserved3 :1;
+ unsigned int reserved4 :1;
+ unsigned int reserved5 :1;
+ unsigned int reserved6 :1;
+ unsigned int reserved7 :1;
+ unsigned int reserved8 :1;
+ unsigned int reserved9 :1;
+ unsigned int reserved10 :1;
+ unsigned int reserved11 :1;
+ unsigned int reserved12 :1;
+ unsigned int reserved13 :1;
+ unsigned int reserved14 :1;
+ unsigned int reserved15 :1;
+} JDWPTransportCapabilities;
+
+
+/*
+ * Structures to define packet layout.
+ *
+ * See: http://java.sun.com/j2se/1.5/docs/guide/jpda/jdwp-spec.html
+ */
+
+enum {
+ JDWPTRANSPORT_FLAGS_NONE = 0x0,
+ JDWPTRANSPORT_FLAGS_REPLY = 0x80
+};
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jbyte cmdSet;
+ jbyte cmd;
+ jbyte *data;
+} jdwpCmdPacket;
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jshort errorCode;
+ jbyte *data;
+} jdwpReplyPacket;
+
+typedef struct {
+ union {
+ jdwpCmdPacket cmd;
+ jdwpReplyPacket reply;
+ } type;
+} jdwpPacket;
+
+/*
+ * JDWP functions called by the transport.
+ */
+typedef struct jdwpTransportCallback {
+ void *(*alloc)(jint numBytes); /* Call this for all allocations */
+ void (*free)(void *buffer); /* Call this for all deallocations */
+} jdwpTransportCallback;
+
+typedef jint (JNICALL *jdwpTransport_OnLoad_t)(JavaVM *jvm,
+ jdwpTransportCallback *callback,
+ jint version,
+ jdwpTransportEnv** env);
+
+
+
+/* Function Interface */
+
+struct jdwpTransportNativeInterface_ {
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Get Capabilities */
+ jdwpTransportError (JNICALL *GetCapabilities)(jdwpTransportEnv* env,
+ JDWPTransportCapabilities *capabilities_ptr);
+
+ /* 3 : Attach */
+ jdwpTransportError (JNICALL *Attach)(jdwpTransportEnv* env,
+ const char* address,
+ jlong attach_timeout,
+ jlong handshake_timeout);
+
+ /* 4: StartListening */
+ jdwpTransportError (JNICALL *StartListening)(jdwpTransportEnv* env,
+ const char* address,
+ char** actual_address);
+
+ /* 5: StopListening */
+ jdwpTransportError (JNICALL *StopListening)(jdwpTransportEnv* env);
+
+ /* 6: Accept */
+ jdwpTransportError (JNICALL *Accept)(jdwpTransportEnv* env,
+ jlong accept_timeout,
+ jlong handshake_timeout);
+
+ /* 7: IsOpen */
+ jboolean (JNICALL *IsOpen)(jdwpTransportEnv* env);
+
+ /* 8: Close */
+ jdwpTransportError (JNICALL *Close)(jdwpTransportEnv* env);
+
+ /* 9: ReadPacket */
+ jdwpTransportError (JNICALL *ReadPacket)(jdwpTransportEnv* env,
+ jdwpPacket *pkt);
+
+ /* 10: Write Packet */
+ jdwpTransportError (JNICALL *WritePacket)(jdwpTransportEnv* env,
+ const jdwpPacket* pkt);
+
+ /* 11: GetLastError */
+ jdwpTransportError (JNICALL *GetLastError)(jdwpTransportEnv* env,
+ char** error);
+
+};
+
+
+/*
+ * Use inlined functions so that C++ code can use syntax such as
+ * env->Attach("mymachine:5000", 10*1000, 0);
+ *
+ * rather than using C's :-
+ *
+ * (*env)->Attach(env, "mymachine:5000", 10*1000, 0);
+ */
+struct _jdwpTransportEnv {
+ const struct jdwpTransportNativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jdwpTransportError GetCapabilities(JDWPTransportCapabilities *capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jdwpTransportError Attach(const char* address, jlong attach_timeout,
+ jlong handshake_timeout) {
+ return functions->Attach(this, address, attach_timeout, handshake_timeout);
+ }
+
+ jdwpTransportError StartListening(const char* address,
+ char** actual_address) {
+ return functions->StartListening(this, address, actual_address);
+ }
+
+ jdwpTransportError StopListening(void) {
+ return functions->StopListening(this);
+ }
+
+ jdwpTransportError Accept(jlong accept_timeout, jlong handshake_timeout) {
+ return functions->Accept(this, accept_timeout, handshake_timeout);
+ }
+
+ jboolean IsOpen(void) {
+ return functions->IsOpen(this);
+ }
+
+ jdwpTransportError Close(void) {
+ return functions->Close(this);
+ }
+
+ jdwpTransportError ReadPacket(jdwpPacket *pkt) {
+ return functions->ReadPacket(this, pkt);
+ }
+
+ jdwpTransportError WritePacket(const jdwpPacket* pkt) {
+ return functions->WritePacket(this, pkt);
+ }
+
+ jdwpTransportError GetLastError(char** error) {
+ return functions->GetLastError(this, error);
+ }
+
+
+#endif /* __cplusplus */
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* JDWPTRANSPORT_H */
+
diff --git a/source/client/jni/linux/jni.h b/source/client/jni/linux/jni.h
new file mode 100644
index 0000000000000000000000000000000000000000..fae147679a9679afdf6eff8c4f6ef242d176fd88
--- /dev/null
+++ b/source/client/jni/linux/jni.h
@@ -0,0 +1,1961 @@
+/*
+ * @(#)jni.h 1.62 06/02/02
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include
+#include
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+
+#if !TARGET_RT_MAC_CFM && defined(__ppc__)
+ void* cfm_vectors[225];
+#endif /* !TARGET_RT_MAC_CFM && defined(__ppc__) */
+
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+
+ /* New JNI 1.6 Features */
+
+ jobjectRefType (JNICALL *GetObjectRefType)
+ (JNIEnv* env, jobject obj);
+
+ #if TARGET_RT_MAC_CFM && defined(__ppc__)
+ void* real_functions[228];
+ #endif /* TARGET_RT_MAC_CFM && defined(__ppc__) */
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+ jobjectRefType GetObjectRefType(jobject obj) {
+ return functions->GetObjectRefType(this, obj);
+ }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+#if !TARGET_RT_MAC_CFM && defined(__ppc__)
+ void* cfm_vectors[4];
+#endif /* !TARGET_RT_MAC_CFM && defined(__ppc__) */
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+
+#if TARGET_RT_MAC_CFM && defined(__ppc__)
+ void* real_functions[5];
+#endif /* TARGET_RT_MAC_CFM && defined(__ppc__) */
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ __attribute__((deprecated)) jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ __attribute__((deprecated)) jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ __attribute__((deprecated)) jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
+
+
+
diff --git a/source/client/jni/linux/jni_md.h b/source/client/jni/linux/jni_md.h
new file mode 100644
index 0000000000000000000000000000000000000000..64a681d4f17b381cd45d6f0044e4693480a106ad
--- /dev/null
+++ b/source/client/jni/linux/jni_md.h
@@ -0,0 +1,23 @@
+/*
+ * @(#)jni_md.h 1.19 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT __attribute__((visibility("default")))
+#define JNIIMPORT
+#define JNICALL
+
+#if defined(__LP64__) && __LP64__ /* for -Wundef */
+typedef int jint;
+#else
+typedef long jint;
+#endif
+typedef long long jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/source/client/jni/linux/jvmti.h b/source/client/jni/linux/jvmti.h
new file mode 100644
index 0000000000000000000000000000000000000000..057490893942e333d57108b8adb483fb4ef61e23
--- /dev/null
+++ b/source/client/jni/linux/jvmti.h
@@ -0,0 +1,2504 @@
+#ifdef USE_PRAGMA_IDENT_HDR
+#pragma ident "@(#)jvmtiLib.xsl 1.38 06/08/02 23:22:31 JVM"
+#endif
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+ /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
+
+
+ /* Include file for the Java(tm) Virtual Machine Tool Interface */
+
+#ifndef _JAVA_JVMTI_H_
+#define _JAVA_JVMTI_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ JVMTI_VERSION_1 = 0x30010000,
+ JVMTI_VERSION_1_0 = 0x30010000,
+ JVMTI_VERSION_1_1 = 0x30010100,
+
+ JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (1 * 0x100) + 102 /* version: 1.1.102 */
+};
+
+JNIEXPORT jint JNICALL __attribute__((deprecated))
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
+
+JNIEXPORT jint JNICALL __attribute__((deprecated))
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
+
+JNIEXPORT void JNICALL __attribute__((deprecated))
+Agent_OnUnload(JavaVM *vm);
+
+ /* Forward declaration of the environment */
+
+struct _jvmtiEnv;
+
+struct jvmtiInterface_1_;
+
+#ifdef __cplusplus
+typedef _jvmtiEnv jvmtiEnv;
+#else
+typedef const struct jvmtiInterface_1_ *jvmtiEnv;
+#endif /* __cplusplus */
+
+/* Derived Base Types */
+
+typedef jobject jthread;
+typedef jobject jthreadGroup;
+typedef jlong jlocation;
+struct _jrawMonitorID;
+typedef struct _jrawMonitorID *jrawMonitorID;
+typedef struct JNINativeInterface_ jniNativeInterface;
+
+ /* Constants */
+
+
+ /* Thread State Flags */
+
+enum {
+ JVMTI_THREAD_STATE_ALIVE = 0x0001,
+ JVMTI_THREAD_STATE_TERMINATED = 0x0002,
+ JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
+ JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
+ JVMTI_THREAD_STATE_WAITING = 0x0080,
+ JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
+ JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
+ JVMTI_THREAD_STATE_SLEEPING = 0x0040,
+ JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
+ JVMTI_THREAD_STATE_PARKED = 0x0200,
+ JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
+ JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
+ JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
+ JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
+ JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
+ JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000
+};
+
+ /* java.lang.Thread.State Conversion Masks */
+
+enum {
+ JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
+ JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
+ JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
+ JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE,
+ JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
+ JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
+ JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
+};
+
+ /* Thread Priority Constants */
+
+enum {
+ JVMTI_THREAD_MIN_PRIORITY = 1,
+ JVMTI_THREAD_NORM_PRIORITY = 5,
+ JVMTI_THREAD_MAX_PRIORITY = 10
+};
+
+ /* Heap Filter Flags */
+
+enum {
+ JVMTI_HEAP_FILTER_TAGGED = 0x4,
+ JVMTI_HEAP_FILTER_UNTAGGED = 0x8,
+ JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10,
+ JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20
+};
+
+ /* Heap Visit Control Flags */
+
+enum {
+ JVMTI_VISIT_OBJECTS = 0x100,
+ JVMTI_VISIT_ABORT = 0x8000
+};
+
+ /* Heap Reference Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_REFERENCE_CLASS = 1,
+ JVMTI_HEAP_REFERENCE_FIELD = 2,
+ JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_HEAP_REFERENCE_SIGNERS = 5,
+ JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_HEAP_REFERENCE_INTERFACE = 7,
+ JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9,
+ JVMTI_HEAP_REFERENCE_SUPERCLASS = 10,
+ JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21,
+ JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22,
+ JVMTI_HEAP_REFERENCE_MONITOR = 23,
+ JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24,
+ JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25,
+ JVMTI_HEAP_REFERENCE_THREAD = 26,
+ JVMTI_HEAP_REFERENCE_OTHER = 27
+} jvmtiHeapReferenceKind;
+
+ /* Primitive Type Enumeration */
+
+typedef enum {
+ JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90,
+ JVMTI_PRIMITIVE_TYPE_BYTE = 66,
+ JVMTI_PRIMITIVE_TYPE_CHAR = 67,
+ JVMTI_PRIMITIVE_TYPE_SHORT = 83,
+ JVMTI_PRIMITIVE_TYPE_INT = 73,
+ JVMTI_PRIMITIVE_TYPE_LONG = 74,
+ JVMTI_PRIMITIVE_TYPE_FLOAT = 70,
+ JVMTI_PRIMITIVE_TYPE_DOUBLE = 68
+} jvmtiPrimitiveType;
+
+ /* Heap Object Filter Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_OBJECT_TAGGED = 1,
+ JVMTI_HEAP_OBJECT_UNTAGGED = 2,
+ JVMTI_HEAP_OBJECT_EITHER = 3
+} jvmtiHeapObjectFilter;
+
+ /* Heap Root Kind Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
+ JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
+ JVMTI_HEAP_ROOT_MONITOR = 3,
+ JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
+ JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
+ JVMTI_HEAP_ROOT_THREAD = 6,
+ JVMTI_HEAP_ROOT_OTHER = 7
+} jvmtiHeapRootKind;
+
+ /* Object Reference Enumeration */
+
+typedef enum {
+ JVMTI_REFERENCE_CLASS = 1,
+ JVMTI_REFERENCE_FIELD = 2,
+ JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_REFERENCE_SIGNERS = 5,
+ JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_REFERENCE_INTERFACE = 7,
+ JVMTI_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_REFERENCE_CONSTANT_POOL = 9
+} jvmtiObjectReferenceKind;
+
+ /* Iteration Control Enumeration */
+
+typedef enum {
+ JVMTI_ITERATION_CONTINUE = 1,
+ JVMTI_ITERATION_IGNORE = 2,
+ JVMTI_ITERATION_ABORT = 0
+} jvmtiIterationControl;
+
+ /* Class Status Flags */
+
+enum {
+ JVMTI_CLASS_STATUS_VERIFIED = 1,
+ JVMTI_CLASS_STATUS_PREPARED = 2,
+ JVMTI_CLASS_STATUS_INITIALIZED = 4,
+ JVMTI_CLASS_STATUS_ERROR = 8,
+ JVMTI_CLASS_STATUS_ARRAY = 16,
+ JVMTI_CLASS_STATUS_PRIMITIVE = 32
+};
+
+ /* Event Enable/Disable */
+
+typedef enum {
+ JVMTI_ENABLE = 1,
+ JVMTI_DISABLE = 0
+} jvmtiEventMode;
+
+ /* Extension Function/Event Parameter Types */
+
+typedef enum {
+ JVMTI_TYPE_JBYTE = 101,
+ JVMTI_TYPE_JCHAR = 102,
+ JVMTI_TYPE_JSHORT = 103,
+ JVMTI_TYPE_JINT = 104,
+ JVMTI_TYPE_JLONG = 105,
+ JVMTI_TYPE_JFLOAT = 106,
+ JVMTI_TYPE_JDOUBLE = 107,
+ JVMTI_TYPE_JBOOLEAN = 108,
+ JVMTI_TYPE_JOBJECT = 109,
+ JVMTI_TYPE_JTHREAD = 110,
+ JVMTI_TYPE_JCLASS = 111,
+ JVMTI_TYPE_JVALUE = 112,
+ JVMTI_TYPE_JFIELDID = 113,
+ JVMTI_TYPE_JMETHODID = 114,
+ JVMTI_TYPE_CCHAR = 115,
+ JVMTI_TYPE_CVOID = 116,
+ JVMTI_TYPE_JNIENV = 117
+} jvmtiParamTypes;
+
+ /* Extension Function/Event Parameter Kinds */
+
+typedef enum {
+ JVMTI_KIND_IN = 91,
+ JVMTI_KIND_IN_PTR = 92,
+ JVMTI_KIND_IN_BUF = 93,
+ JVMTI_KIND_ALLOC_BUF = 94,
+ JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
+ JVMTI_KIND_OUT = 96,
+ JVMTI_KIND_OUT_BUF = 97
+} jvmtiParamKind;
+
+ /* Timer Kinds */
+
+typedef enum {
+ JVMTI_TIMER_USER_CPU = 30,
+ JVMTI_TIMER_TOTAL_CPU = 31,
+ JVMTI_TIMER_ELAPSED = 32
+} jvmtiTimerKind;
+
+ /* Phases of execution */
+
+typedef enum {
+ JVMTI_PHASE_ONLOAD = 1,
+ JVMTI_PHASE_PRIMORDIAL = 2,
+ JVMTI_PHASE_START = 6,
+ JVMTI_PHASE_LIVE = 4,
+ JVMTI_PHASE_DEAD = 8
+} jvmtiPhase;
+
+ /* Version Interface Types */
+
+enum {
+ JVMTI_VERSION_INTERFACE_JNI = 0x00000000,
+ JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000
+};
+
+ /* Version Masks */
+
+enum {
+ JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000,
+ JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000,
+ JVMTI_VERSION_MASK_MINOR = 0x0000FF00,
+ JVMTI_VERSION_MASK_MICRO = 0x000000FF
+};
+
+ /* Version Shifts */
+
+enum {
+ JVMTI_VERSION_SHIFT_MAJOR = 16,
+ JVMTI_VERSION_SHIFT_MINOR = 8,
+ JVMTI_VERSION_SHIFT_MICRO = 0
+};
+
+ /* Verbose Flag Enumeration */
+
+typedef enum {
+ JVMTI_VERBOSE_OTHER = 0,
+ JVMTI_VERBOSE_GC = 1,
+ JVMTI_VERBOSE_CLASS = 2,
+ JVMTI_VERBOSE_JNI = 4
+} jvmtiVerboseFlag;
+
+ /* JLocation Format Enumeration */
+
+typedef enum {
+ JVMTI_JLOCATION_JVMBCI = 1,
+ JVMTI_JLOCATION_MACHINEPC = 2,
+ JVMTI_JLOCATION_OTHER = 0
+} jvmtiJlocationFormat;
+
+ /* Resource Exhaustion Flags */
+
+enum {
+ JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001,
+ JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002,
+ JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004
+};
+
+ /* Errors */
+
+typedef enum {
+ JVMTI_ERROR_NONE = 0,
+ JVMTI_ERROR_INVALID_THREAD = 10,
+ JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
+ JVMTI_ERROR_INVALID_PRIORITY = 12,
+ JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
+ JVMTI_ERROR_THREAD_SUSPENDED = 14,
+ JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
+ JVMTI_ERROR_INVALID_OBJECT = 20,
+ JVMTI_ERROR_INVALID_CLASS = 21,
+ JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
+ JVMTI_ERROR_INVALID_METHODID = 23,
+ JVMTI_ERROR_INVALID_LOCATION = 24,
+ JVMTI_ERROR_INVALID_FIELDID = 25,
+ JVMTI_ERROR_NO_MORE_FRAMES = 31,
+ JVMTI_ERROR_OPAQUE_FRAME = 32,
+ JVMTI_ERROR_TYPE_MISMATCH = 34,
+ JVMTI_ERROR_INVALID_SLOT = 35,
+ JVMTI_ERROR_DUPLICATE = 40,
+ JVMTI_ERROR_NOT_FOUND = 41,
+ JVMTI_ERROR_INVALID_MONITOR = 50,
+ JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
+ JVMTI_ERROR_INTERRUPT = 52,
+ JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
+ JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
+ JVMTI_ERROR_FAILS_VERIFICATION = 62,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
+ JVMTI_ERROR_INVALID_TYPESTATE = 65,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
+ JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
+ JVMTI_ERROR_NAMES_DONT_MATCH = 69,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
+ JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
+ JVMTI_ERROR_NOT_AVAILABLE = 98,
+ JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
+ JVMTI_ERROR_NULL_POINTER = 100,
+ JVMTI_ERROR_ABSENT_INFORMATION = 101,
+ JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
+ JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
+ JVMTI_ERROR_NATIVE_METHOD = 104,
+ JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106,
+ JVMTI_ERROR_OUT_OF_MEMORY = 110,
+ JVMTI_ERROR_ACCESS_DENIED = 111,
+ JVMTI_ERROR_WRONG_PHASE = 112,
+ JVMTI_ERROR_INTERNAL = 113,
+ JVMTI_ERROR_UNATTACHED_THREAD = 115,
+ JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
+ JVMTI_ERROR_MAX = 116
+} jvmtiError;
+
+ /* Event IDs */
+
+typedef enum {
+ JVMTI_MIN_EVENT_TYPE_VAL = 50,
+ JVMTI_EVENT_VM_INIT = 50,
+ JVMTI_EVENT_VM_DEATH = 51,
+ JVMTI_EVENT_THREAD_START = 52,
+ JVMTI_EVENT_THREAD_END = 53,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
+ JVMTI_EVENT_CLASS_LOAD = 55,
+ JVMTI_EVENT_CLASS_PREPARE = 56,
+ JVMTI_EVENT_VM_START = 57,
+ JVMTI_EVENT_EXCEPTION = 58,
+ JVMTI_EVENT_EXCEPTION_CATCH = 59,
+ JVMTI_EVENT_SINGLE_STEP = 60,
+ JVMTI_EVENT_FRAME_POP = 61,
+ JVMTI_EVENT_BREAKPOINT = 62,
+ JVMTI_EVENT_FIELD_ACCESS = 63,
+ JVMTI_EVENT_FIELD_MODIFICATION = 64,
+ JVMTI_EVENT_METHOD_ENTRY = 65,
+ JVMTI_EVENT_METHOD_EXIT = 66,
+ JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
+ JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
+ JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
+ JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
+ JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
+ JVMTI_EVENT_MONITOR_WAIT = 73,
+ JVMTI_EVENT_MONITOR_WAITED = 74,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
+ JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
+ JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
+ JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
+ JVMTI_EVENT_OBJECT_FREE = 83,
+ JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
+ JVMTI_MAX_EVENT_TYPE_VAL = 84
+} jvmtiEvent;
+
+
+ /* Pre-Declarations */
+struct _jvmtiThreadInfo;
+typedef struct _jvmtiThreadInfo jvmtiThreadInfo;
+struct _jvmtiMonitorStackDepthInfo;
+typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo;
+struct _jvmtiThreadGroupInfo;
+typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo;
+struct _jvmtiFrameInfo;
+typedef struct _jvmtiFrameInfo jvmtiFrameInfo;
+struct _jvmtiStackInfo;
+typedef struct _jvmtiStackInfo jvmtiStackInfo;
+struct _jvmtiHeapReferenceInfoField;
+typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField;
+struct _jvmtiHeapReferenceInfoArray;
+typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray;
+struct _jvmtiHeapReferenceInfoConstantPool;
+typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool;
+struct _jvmtiHeapReferenceInfoStackLocal;
+typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal;
+struct _jvmtiHeapReferenceInfoJniLocal;
+typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal;
+struct _jvmtiHeapReferenceInfoReserved;
+typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved;
+union _jvmtiHeapReferenceInfo;
+typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo;
+struct _jvmtiHeapCallbacks;
+typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks;
+struct _jvmtiClassDefinition;
+typedef struct _jvmtiClassDefinition jvmtiClassDefinition;
+struct _jvmtiMonitorUsage;
+typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage;
+struct _jvmtiLineNumberEntry;
+typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry;
+struct _jvmtiLocalVariableEntry;
+typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry;
+struct _jvmtiParamInfo;
+typedef struct _jvmtiParamInfo jvmtiParamInfo;
+struct _jvmtiExtensionFunctionInfo;
+typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo;
+struct _jvmtiExtensionEventInfo;
+typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo;
+struct _jvmtiTimerInfo;
+typedef struct _jvmtiTimerInfo jvmtiTimerInfo;
+struct _jvmtiAddrLocationMap;
+typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
+
+ /* Function Types */
+
+typedef void (JNICALL *jvmtiStartFunction)
+ (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
+
+typedef jint (JNICALL *jvmtiHeapIterationCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiHeapReferenceCallback)
+ (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
+ (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
+
+typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
+
+typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);
+
+typedef jint (JNICALL *jvmtiReservedCallback)
+ ();
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
+ (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
+
+typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
+ (jvmtiEnv* jvmti_env, ...);
+
+typedef void (JNICALL *jvmtiExtensionEvent)
+ (jvmtiEnv* jvmti_env, ...);
+
+
+ /* Structure Types */
+struct _jvmtiThreadInfo {
+ char* name;
+ jint priority;
+ jboolean is_daemon;
+ jthreadGroup thread_group;
+ jobject context_class_loader;
+};
+struct _jvmtiMonitorStackDepthInfo {
+ jobject monitor;
+ jint stack_depth;
+};
+struct _jvmtiThreadGroupInfo {
+ jthreadGroup parent;
+ char* name;
+ jint max_priority;
+ jboolean is_daemon;
+};
+struct _jvmtiFrameInfo {
+ jmethodID method;
+ jlocation location;
+};
+struct _jvmtiStackInfo {
+ jthread thread;
+ jint state;
+ jvmtiFrameInfo* frame_buffer;
+ jint frame_count;
+};
+struct _jvmtiHeapReferenceInfoField {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoArray {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoConstantPool {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoStackLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+ jlocation location;
+ jint slot;
+};
+struct _jvmtiHeapReferenceInfoJniLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+};
+struct _jvmtiHeapReferenceInfoReserved {
+ jlong reserved1;
+ jlong reserved2;
+ jlong reserved3;
+ jlong reserved4;
+ jlong reserved5;
+ jlong reserved6;
+ jlong reserved7;
+ jlong reserved8;
+};
+union _jvmtiHeapReferenceInfo {
+ jvmtiHeapReferenceInfoField field;
+ jvmtiHeapReferenceInfoArray array;
+ jvmtiHeapReferenceInfoConstantPool constant_pool;
+ jvmtiHeapReferenceInfoStackLocal stack_local;
+ jvmtiHeapReferenceInfoJniLocal jni_local;
+ jvmtiHeapReferenceInfoReserved other;
+};
+struct _jvmtiHeapCallbacks {
+ jvmtiHeapIterationCallback heap_iteration_callback;
+ jvmtiHeapReferenceCallback heap_reference_callback;
+ jvmtiPrimitiveFieldCallback primitive_field_callback;
+ jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
+ jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
+ jvmtiReservedCallback reserved5;
+ jvmtiReservedCallback reserved6;
+ jvmtiReservedCallback reserved7;
+ jvmtiReservedCallback reserved8;
+ jvmtiReservedCallback reserved9;
+ jvmtiReservedCallback reserved10;
+ jvmtiReservedCallback reserved11;
+ jvmtiReservedCallback reserved12;
+ jvmtiReservedCallback reserved13;
+ jvmtiReservedCallback reserved14;
+ jvmtiReservedCallback reserved15;
+};
+struct _jvmtiClassDefinition {
+ jclass klass;
+ jint class_byte_count;
+ const unsigned char* class_bytes;
+};
+struct _jvmtiMonitorUsage {
+ jthread owner;
+ jint entry_count;
+ jint waiter_count;
+ jthread* waiters;
+ jint notify_waiter_count;
+ jthread* notify_waiters;
+};
+struct _jvmtiLineNumberEntry {
+ jlocation start_location;
+ jint line_number;
+};
+struct _jvmtiLocalVariableEntry {
+ jlocation start_location;
+ jint length;
+ char* name;
+ char* signature;
+ char* generic_signature;
+ jint slot;
+};
+struct _jvmtiParamInfo {
+ char* name;
+ jvmtiParamKind kind;
+ jvmtiParamTypes base_type;
+ jboolean null_ok;
+};
+struct _jvmtiExtensionFunctionInfo {
+ jvmtiExtensionFunction func;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+ jint error_count;
+ jvmtiError* errors;
+};
+struct _jvmtiExtensionEventInfo {
+ jint extension_event_index;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+};
+struct _jvmtiTimerInfo {
+ jlong max_value;
+ jboolean may_skip_forward;
+ jboolean may_skip_backward;
+ jvmtiTimerKind kind;
+ jlong reserved1;
+ jlong reserved2;
+};
+struct _jvmtiAddrLocationMap {
+ const void* start_address;
+ jlocation location;
+};
+
+typedef struct {
+ unsigned int can_tag_objects : 1;
+ unsigned int can_generate_field_modification_events : 1;
+ unsigned int can_generate_field_access_events : 1;
+ unsigned int can_get_bytecodes : 1;
+ unsigned int can_get_synthetic_attribute : 1;
+ unsigned int can_get_owned_monitor_info : 1;
+ unsigned int can_get_current_contended_monitor : 1;
+ unsigned int can_get_monitor_info : 1;
+ unsigned int can_pop_frame : 1;
+ unsigned int can_redefine_classes : 1;
+ unsigned int can_signal_thread : 1;
+ unsigned int can_get_source_file_name : 1;
+ unsigned int can_get_line_numbers : 1;
+ unsigned int can_get_source_debug_extension : 1;
+ unsigned int can_access_local_variables : 1;
+ unsigned int can_maintain_original_method_order : 1;
+ unsigned int can_generate_single_step_events : 1;
+ unsigned int can_generate_exception_events : 1;
+ unsigned int can_generate_frame_pop_events : 1;
+ unsigned int can_generate_breakpoint_events : 1;
+ unsigned int can_suspend : 1;
+ unsigned int can_redefine_any_class : 1;
+ unsigned int can_get_current_thread_cpu_time : 1;
+ unsigned int can_get_thread_cpu_time : 1;
+ unsigned int can_generate_method_entry_events : 1;
+ unsigned int can_generate_method_exit_events : 1;
+ unsigned int can_generate_all_class_hook_events : 1;
+ unsigned int can_generate_compiled_method_load_events : 1;
+ unsigned int can_generate_monitor_events : 1;
+ unsigned int can_generate_vm_object_alloc_events : 1;
+ unsigned int can_generate_native_method_bind_events : 1;
+ unsigned int can_generate_garbage_collection_events : 1;
+ unsigned int can_generate_object_free_events : 1;
+ unsigned int can_force_early_return : 1;
+ unsigned int can_get_owned_monitor_stack_depth_info : 1;
+ unsigned int can_get_constant_pool : 1;
+ unsigned int can_set_native_method_prefix : 1;
+ unsigned int can_retransform_classes : 1;
+ unsigned int can_retransform_any_class : 1;
+ unsigned int can_generate_resource_exhaustion_heap_events : 1;
+ unsigned int can_generate_resource_exhaustion_threads_events : 1;
+ unsigned int : 7;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+} jvmtiCapabilities;
+
+
+ /* Event Definitions */
+
+typedef void (JNICALL *jvmtiEventReserved)(void);
+
+
+typedef void (JNICALL *jvmtiEventBreakpoint)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventClassFileLoadHook)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jclass class_being_redefined,
+ jobject loader,
+ const char* name,
+ jobject protection_domain,
+ jint class_data_len,
+ const unsigned char* class_data,
+ jint* new_class_data_len,
+ unsigned char** new_class_data);
+
+typedef void (JNICALL *jvmtiEventClassLoad)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassPrepare)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ jint code_size,
+ const void* code_addr,
+ jint map_length,
+ const jvmtiAddrLocationMap* map,
+ const void* compile_info);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ const void* code_addr);
+
+typedef void (JNICALL *jvmtiEventDataDumpRequest)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
+ (jvmtiEnv *jvmti_env,
+ const char* name,
+ const void* address,
+ jint length);
+
+typedef void (JNICALL *jvmtiEventException)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception,
+ jmethodID catch_method,
+ jlocation catch_location);
+
+typedef void (JNICALL *jvmtiEventExceptionCatch)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception);
+
+typedef void (JNICALL *jvmtiEventFieldAccess)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field);
+
+typedef void (JNICALL *jvmtiEventFieldModification)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field,
+ char signature_type,
+ jvalue new_value);
+
+typedef void (JNICALL *jvmtiEventFramePop)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventMethodEntry)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method);
+
+typedef void (JNICALL *jvmtiEventMethodExit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception,
+ jvalue return_value);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorWait)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jlong timeout);
+
+typedef void (JNICALL *jvmtiEventMonitorWaited)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jboolean timed_out);
+
+typedef void (JNICALL *jvmtiEventNativeMethodBind)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ void* address,
+ void** new_address_ptr);
+
+typedef void (JNICALL *jvmtiEventObjectFree)
+ (jvmtiEnv *jvmti_env,
+ jlong tag);
+
+typedef void (JNICALL *jvmtiEventResourceExhausted)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jint flags,
+ const void* reserved,
+ const char* description);
+
+typedef void (JNICALL *jvmtiEventSingleStep)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventThreadEnd)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventThreadStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMDeath)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+typedef void (JNICALL *jvmtiEventVMInit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMObjectAlloc)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jclass object_klass,
+ jlong size);
+
+typedef void (JNICALL *jvmtiEventVMStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+ /* Event Callback Structure */
+
+typedef struct {
+ /* 50 : VM Initialization Event */
+ jvmtiEventVMInit VMInit;
+ /* 51 : VM Death Event */
+ jvmtiEventVMDeath VMDeath;
+ /* 52 : Thread Start */
+ jvmtiEventThreadStart ThreadStart;
+ /* 53 : Thread End */
+ jvmtiEventThreadEnd ThreadEnd;
+ /* 54 : Class File Load Hook */
+ jvmtiEventClassFileLoadHook ClassFileLoadHook;
+ /* 55 : Class Load */
+ jvmtiEventClassLoad ClassLoad;
+ /* 56 : Class Prepare */
+ jvmtiEventClassPrepare ClassPrepare;
+ /* 57 : VM Start Event */
+ jvmtiEventVMStart VMStart;
+ /* 58 : Exception */
+ jvmtiEventException Exception;
+ /* 59 : Exception Catch */
+ jvmtiEventExceptionCatch ExceptionCatch;
+ /* 60 : Single Step */
+ jvmtiEventSingleStep SingleStep;
+ /* 61 : Frame Pop */
+ jvmtiEventFramePop FramePop;
+ /* 62 : Breakpoint */
+ jvmtiEventBreakpoint Breakpoint;
+ /* 63 : Field Access */
+ jvmtiEventFieldAccess FieldAccess;
+ /* 64 : Field Modification */
+ jvmtiEventFieldModification FieldModification;
+ /* 65 : Method Entry */
+ jvmtiEventMethodEntry MethodEntry;
+ /* 66 : Method Exit */
+ jvmtiEventMethodExit MethodExit;
+ /* 67 : Native Method Bind */
+ jvmtiEventNativeMethodBind NativeMethodBind;
+ /* 68 : Compiled Method Load */
+ jvmtiEventCompiledMethodLoad CompiledMethodLoad;
+ /* 69 : Compiled Method Unload */
+ jvmtiEventCompiledMethodUnload CompiledMethodUnload;
+ /* 70 : Dynamic Code Generated */
+ jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
+ /* 71 : Data Dump Request */
+ jvmtiEventDataDumpRequest DataDumpRequest;
+ /* 72 */
+ jvmtiEventReserved reserved72;
+ /* 73 : Monitor Wait */
+ jvmtiEventMonitorWait MonitorWait;
+ /* 74 : Monitor Waited */
+ jvmtiEventMonitorWaited MonitorWaited;
+ /* 75 : Monitor Contended Enter */
+ jvmtiEventMonitorContendedEnter MonitorContendedEnter;
+ /* 76 : Monitor Contended Entered */
+ jvmtiEventMonitorContendedEntered MonitorContendedEntered;
+ /* 77 */
+ jvmtiEventReserved reserved77;
+ /* 78 */
+ jvmtiEventReserved reserved78;
+ /* 79 */
+ jvmtiEventReserved reserved79;
+ /* 80 : Resource Exhausted */
+ jvmtiEventResourceExhausted ResourceExhausted;
+ /* 81 : Garbage Collection Start */
+ jvmtiEventGarbageCollectionStart GarbageCollectionStart;
+ /* 82 : Garbage Collection Finish */
+ jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
+ /* 83 : Object Free */
+ jvmtiEventObjectFree ObjectFree;
+ /* 84 : VM Object Allocation */
+ jvmtiEventVMObjectAlloc VMObjectAlloc;
+} jvmtiEventCallbacks;
+
+
+ /* Function Interface */
+
+typedef struct jvmtiInterface_1_ {
+
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Set Event Notification Mode */
+ jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
+ jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...);
+
+ /* 3 : RESERVED */
+ void *reserved3;
+
+ /* 4 : Get All Threads */
+ jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
+ jint* threads_count_ptr,
+ jthread** threads_ptr);
+
+ /* 5 : Suspend Thread */
+ jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 6 : Resume Thread */
+ jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 7 : Stop Thread */
+ jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
+ jthread thread,
+ jobject exception);
+
+ /* 8 : Interrupt Thread */
+ jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 9 : Get Thread Info */
+ jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiThreadInfo* info_ptr);
+
+ /* 10 : Get Owned Monitor Info */
+ jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr);
+
+ /* 11 : Get Current Contended Monitor */
+ jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
+ jthread thread,
+ jobject* monitor_ptr);
+
+ /* 12 : Run Agent Thread */
+ jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority);
+
+ /* 13 : Get Top Thread Groups */
+ jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 14 : Get Thread Group Info */
+ jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
+ jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr);
+
+ /* 15 : Get Thread Group Children */
+ jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
+ jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 16 : Get Frame Count */
+ jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
+ jthread thread,
+ jint* count_ptr);
+
+ /* 17 : Get Thread State */
+ jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
+ jthread thread,
+ jint* thread_state_ptr);
+
+ /* 18 : Get Current Thread */
+ jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
+ jthread* thread_ptr);
+
+ /* 19 : Get Frame Location */
+ jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr);
+
+ /* 20 : Notify Frame Pop */
+ jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
+ jthread thread,
+ jint depth);
+
+ /* 21 : Get Local Variable - Object */
+ jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr);
+
+ /* 22 : Get Local Variable - Int */
+ jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr);
+
+ /* 23 : Get Local Variable - Long */
+ jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr);
+
+ /* 24 : Get Local Variable - Float */
+ jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr);
+
+ /* 25 : Get Local Variable - Double */
+ jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr);
+
+ /* 26 : Set Local Variable - Object */
+ jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject value);
+
+ /* 27 : Set Local Variable - Int */
+ jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint value);
+
+ /* 28 : Set Local Variable - Long */
+ jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong value);
+
+ /* 29 : Set Local Variable - Float */
+ jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value);
+
+ /* 30 : Set Local Variable - Double */
+ jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value);
+
+ /* 31 : Create Raw Monitor */
+ jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
+ const char* name,
+ jrawMonitorID* monitor_ptr);
+
+ /* 32 : Destroy Raw Monitor */
+ jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 33 : Raw Monitor Enter */
+ jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 34 : Raw Monitor Exit */
+ jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 35 : Raw Monitor Wait */
+ jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
+ jrawMonitorID monitor,
+ jlong millis);
+
+ /* 36 : Raw Monitor Notify */
+ jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 37 : Raw Monitor Notify All */
+ jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 38 : Set Breakpoint */
+ jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 39 : Clear Breakpoint */
+ jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 40 : RESERVED */
+ void *reserved40;
+
+ /* 41 : Set Field Access Watch */
+ jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 42 : Clear Field Access Watch */
+ jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 43 : Set Field Modification Watch */
+ jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 44 : Clear Field Modification Watch */
+ jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 45 : Is Modifiable Class */
+ jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_modifiable_class_ptr);
+
+ /* 46 : Allocate */
+ jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
+ jlong size,
+ unsigned char** mem_ptr);
+
+ /* 47 : Deallocate */
+ jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
+ unsigned char* mem);
+
+ /* 48 : Get Class Signature */
+ jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
+ jclass klass,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 49 : Get Class Status */
+ jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
+ jclass klass,
+ jint* status_ptr);
+
+ /* 50 : Get Source File Name */
+ jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
+ jclass klass,
+ char** source_name_ptr);
+
+ /* 51 : Get Class Modifiers */
+ jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jint* modifiers_ptr);
+
+ /* 52 : Get Class Methods */
+ jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
+ jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr);
+
+ /* 53 : Get Class Fields */
+ jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
+ jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr);
+
+ /* 54 : Get Implemented Interfaces */
+ jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
+ jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr);
+
+ /* 55 : Is Interface */
+ jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_interface_ptr);
+
+ /* 56 : Is Array Class */
+ jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_array_class_ptr);
+
+ /* 57 : Get Class Loader */
+ jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
+ jclass klass,
+ jobject* classloader_ptr);
+
+ /* 58 : Get Object Hash Code */
+ jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
+ jobject object,
+ jint* hash_code_ptr);
+
+ /* 59 : Get Object Monitor Usage */
+ jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
+ jobject object,
+ jvmtiMonitorUsage* info_ptr);
+
+ /* 60 : Get Field Name (and Signature) */
+ jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 61 : Get Field Declaring Class */
+ jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr);
+
+ /* 62 : Get Field Modifiers */
+ jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr);
+
+ /* 63 : Is Field Synthetic */
+ jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr);
+
+ /* 64 : Get Method Name (and Signature) */
+ jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
+ jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 65 : Get Method Declaring Class */
+ jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
+ jmethodID method,
+ jclass* declaring_class_ptr);
+
+ /* 66 : Get Method Modifiers */
+ jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
+ jmethodID method,
+ jint* modifiers_ptr);
+
+ /* 67 : RESERVED */
+ void *reserved67;
+
+ /* 68 : Get Max Locals */
+ jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
+ jmethodID method,
+ jint* max_ptr);
+
+ /* 69 : Get Arguments Size */
+ jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
+ jmethodID method,
+ jint* size_ptr);
+
+ /* 70 : Get Line Number Table */
+ jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr);
+
+ /* 71 : Get Method Location */
+ jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr);
+
+ /* 72 : Get Local Variable Table */
+ jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr);
+
+ /* 73 : Set Native Method Prefix */
+ jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
+ const char* prefix);
+
+ /* 74 : Set Native Method Prefixes */
+ jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
+ jint prefix_count,
+ char** prefixes);
+
+ /* 75 : Get Bytecodes */
+ jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
+ jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr);
+
+ /* 76 : Is Method Native */
+ jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_native_ptr);
+
+ /* 77 : Is Method Synthetic */
+ jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_synthetic_ptr);
+
+ /* 78 : Get Loaded Classes */
+ jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 79 : Get Classloader Classes */
+ jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
+ jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 80 : Pop Frame */
+ jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 81 : Force Early Return - Object */
+ jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
+ jthread thread,
+ jobject value);
+
+ /* 82 : Force Early Return - Int */
+ jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
+ jthread thread,
+ jint value);
+
+ /* 83 : Force Early Return - Long */
+ jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
+ jthread thread,
+ jlong value);
+
+ /* 84 : Force Early Return - Float */
+ jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
+ jthread thread,
+ jfloat value);
+
+ /* 85 : Force Early Return - Double */
+ jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
+ jthread thread,
+ jdouble value);
+
+ /* 86 : Force Early Return - Void */
+ jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 87 : Redefine Classes */
+ jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jvmtiClassDefinition* class_definitions);
+
+ /* 88 : Get Version Number */
+ jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
+ jint* version_ptr);
+
+ /* 89 : Get Capabilities */
+ jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 90 : Get Source Debug Extension */
+ jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
+ jclass klass,
+ char** source_debug_extension_ptr);
+
+ /* 91 : Is Method Obsolete */
+ jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_obsolete_ptr);
+
+ /* 92 : Suspend Thread List */
+ jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 93 : Resume Thread List */
+ jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 94 : RESERVED */
+ void *reserved94;
+
+ /* 95 : RESERVED */
+ void *reserved95;
+
+ /* 96 : RESERVED */
+ void *reserved96;
+
+ /* 97 : RESERVED */
+ void *reserved97;
+
+ /* 98 : RESERVED */
+ void *reserved98;
+
+ /* 99 : RESERVED */
+ void *reserved99;
+
+ /* 100 : Get All Stack Traces */
+ jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr);
+
+ /* 101 : Get Thread List Stack Traces */
+ jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
+ jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr);
+
+ /* 102 : Get Thread Local Storage */
+ jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ void** data_ptr);
+
+ /* 103 : Set Thread Local Storage */
+ jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ const void* data);
+
+ /* 104 : Get Stack Trace */
+ jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
+ jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr);
+
+ /* 105 : RESERVED */
+ void *reserved105;
+
+ /* 106 : Get Tag */
+ jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong* tag_ptr);
+
+ /* 107 : Set Tag */
+ jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong tag);
+
+ /* 108 : Force Garbage Collection */
+ jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
+
+ /* 109 : Iterate Over Objects Reachable From Object */
+ jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
+ jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data);
+
+ /* 110 : Iterate Over Reachable Objects */
+ jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
+ jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data);
+
+ /* 111 : Iterate Over Heap */
+ jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 112 : Iterate Over Instances Of Class */
+ jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
+ jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 113 : RESERVED */
+ void *reserved113;
+
+ /* 114 : Get Objects With Tags */
+ jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
+ jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr);
+
+ /* 115 : Follow References */
+ jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 116 : Iterate Through Heap */
+ jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 117 : RESERVED */
+ void *reserved117;
+
+ /* 118 : RESERVED */
+ void *reserved118;
+
+ /* 119 : RESERVED */
+ void *reserved119;
+
+ /* 120 : Set JNI Function Table */
+ jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
+ const jniNativeInterface* function_table);
+
+ /* 121 : Get JNI Function Table */
+ jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
+ jniNativeInterface** function_table);
+
+ /* 122 : Set Event Callbacks */
+ jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
+ const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks);
+
+ /* 123 : Generate Events */
+ jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
+ jvmtiEvent event_type);
+
+ /* 124 : Get Extension Functions */
+ jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions);
+
+ /* 125 : Get Extension Events */
+ jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions);
+
+ /* 126 : Set Extension Event Callback */
+ jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
+ jint extension_event_index,
+ jvmtiExtensionEvent callback);
+
+ /* 127 : Dispose Environment */
+ jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
+
+ /* 128 : Get Error Name */
+ jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
+ jvmtiError error,
+ char** name_ptr);
+
+ /* 129 : Get JLocation Format */
+ jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
+ jvmtiJlocationFormat* format_ptr);
+
+ /* 130 : Get System Properties */
+ jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
+ jint* count_ptr,
+ char*** property_ptr);
+
+ /* 131 : Get System Property */
+ jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ char** value_ptr);
+
+ /* 132 : Set System Property */
+ jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ const char* value);
+
+ /* 133 : Get Phase */
+ jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
+ jvmtiPhase* phase_ptr);
+
+ /* 134 : Get Current Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 135 : Get Current Thread CPU Time */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 136 : Get Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 137 : Get Thread CPU Time */
+ jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
+ jthread thread,
+ jlong* nanos_ptr);
+
+ /* 138 : Get Timer Information */
+ jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 139 : Get Time */
+ jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 140 : Get Potential Capabilities */
+ jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 141 : RESERVED */
+ void *reserved141;
+
+ /* 142 : Add Capabilities */
+ jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 143 : Relinquish Capabilities */
+ jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 144 : Get Available Processors */
+ jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
+ jint* processor_count_ptr);
+
+ /* 145 : Get Class Version Numbers */
+ jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
+ jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr);
+
+ /* 146 : Get Constant Pool */
+ jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
+ jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr);
+
+ /* 147 : Get Environment Local Storage */
+ jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
+ void** data_ptr);
+
+ /* 148 : Set Environment Local Storage */
+ jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
+ const void* data);
+
+ /* 149 : Add To Bootstrap Class Loader Search */
+ jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 150 : Set Verbose Flag */
+ jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
+ jvmtiVerboseFlag flag,
+ jboolean value);
+
+ /* 151 : Add To System Class Loader Search */
+ jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 152 : Retransform Classes */
+ jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jclass* classes);
+
+ /* 153 : Get Owned Monitor Stack Depth Info */
+ jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr);
+
+ /* 154 : Get Object Size */
+ jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
+ jobject object,
+ jlong* size_ptr);
+
+} jvmtiInterface_1;
+
+struct _jvmtiEnv {
+ const struct jvmtiInterface_1_ *functions;
+#ifdef __cplusplus
+
+
+ jvmtiError Allocate(jlong size,
+ unsigned char** mem_ptr) {
+ return functions->Allocate(this, size, mem_ptr);
+ }
+
+ jvmtiError Deallocate(unsigned char* mem) {
+ return functions->Deallocate(this, mem);
+ }
+
+ jvmtiError GetThreadState(jthread thread,
+ jint* thread_state_ptr) {
+ return functions->GetThreadState(this, thread, thread_state_ptr);
+ }
+
+ jvmtiError GetCurrentThread(jthread* thread_ptr) {
+ return functions->GetCurrentThread(this, thread_ptr);
+ }
+
+ jvmtiError GetAllThreads(jint* threads_count_ptr,
+ jthread** threads_ptr) {
+ return functions->GetAllThreads(this, threads_count_ptr, threads_ptr);
+ }
+
+ jvmtiError SuspendThread(jthread thread) {
+ return functions->SuspendThread(this, thread);
+ }
+
+ jvmtiError SuspendThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->SuspendThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError ResumeThread(jthread thread) {
+ return functions->ResumeThread(this, thread);
+ }
+
+ jvmtiError ResumeThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->ResumeThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError StopThread(jthread thread,
+ jobject exception) {
+ return functions->StopThread(this, thread, exception);
+ }
+
+ jvmtiError InterruptThread(jthread thread) {
+ return functions->InterruptThread(this, thread);
+ }
+
+ jvmtiError GetThreadInfo(jthread thread,
+ jvmtiThreadInfo* info_ptr) {
+ return functions->GetThreadInfo(this, thread, info_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorInfo(jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr) {
+ return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
+ return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr);
+ }
+
+ jvmtiError GetCurrentContendedMonitor(jthread thread,
+ jobject* monitor_ptr) {
+ return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr);
+ }
+
+ jvmtiError RunAgentThread(jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority) {
+ return functions->RunAgentThread(this, thread, proc, arg, priority);
+ }
+
+ jvmtiError SetThreadLocalStorage(jthread thread,
+ const void* data) {
+ return functions->SetThreadLocalStorage(this, thread, data);
+ }
+
+ jvmtiError GetThreadLocalStorage(jthread thread,
+ void** data_ptr) {
+ return functions->GetThreadLocalStorage(this, thread, data_ptr);
+ }
+
+ jvmtiError GetTopThreadGroups(jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetThreadGroupInfo(jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr) {
+ return functions->GetThreadGroupInfo(this, group, info_ptr);
+ }
+
+ jvmtiError GetThreadGroupChildren(jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetStackTrace(jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr) {
+ return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr);
+ }
+
+ jvmtiError GetAllStackTraces(jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr) {
+ return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr);
+ }
+
+ jvmtiError GetThreadListStackTraces(jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr) {
+ return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr);
+ }
+
+ jvmtiError GetFrameCount(jthread thread,
+ jint* count_ptr) {
+ return functions->GetFrameCount(this, thread, count_ptr);
+ }
+
+ jvmtiError PopFrame(jthread thread) {
+ return functions->PopFrame(this, thread);
+ }
+
+ jvmtiError GetFrameLocation(jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr) {
+ return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr);
+ }
+
+ jvmtiError NotifyFramePop(jthread thread,
+ jint depth) {
+ return functions->NotifyFramePop(this, thread, depth);
+ }
+
+ jvmtiError ForceEarlyReturnObject(jthread thread,
+ jobject value) {
+ return functions->ForceEarlyReturnObject(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnInt(jthread thread,
+ jint value) {
+ return functions->ForceEarlyReturnInt(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnLong(jthread thread,
+ jlong value) {
+ return functions->ForceEarlyReturnLong(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnFloat(jthread thread,
+ jfloat value) {
+ return functions->ForceEarlyReturnFloat(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnDouble(jthread thread,
+ jdouble value) {
+ return functions->ForceEarlyReturnDouble(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnVoid(jthread thread) {
+ return functions->ForceEarlyReturnVoid(this, thread);
+ }
+
+ jvmtiError FollowReferences(jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data);
+ }
+
+ jvmtiError IterateThroughHeap(jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data);
+ }
+
+ jvmtiError GetTag(jobject object,
+ jlong* tag_ptr) {
+ return functions->GetTag(this, object, tag_ptr);
+ }
+
+ jvmtiError SetTag(jobject object,
+ jlong tag) {
+ return functions->SetTag(this, object, tag);
+ }
+
+ jvmtiError GetObjectsWithTags(jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr) {
+ return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr);
+ }
+
+ jvmtiError ForceGarbageCollection() {
+ return functions->ForceGarbageCollection(this);
+ }
+
+ jvmtiError IterateOverObjectsReachableFromObject(jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data) {
+ return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data);
+ }
+
+ jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data) {
+ return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
+ }
+
+ jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError IterateOverInstancesOfClass(jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError GetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr) {
+ return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr) {
+ return functions->GetLocalInt(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr) {
+ return functions->GetLocalLong(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr) {
+ return functions->GetLocalFloat(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr) {
+ return functions->GetLocalDouble(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError SetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject value) {
+ return functions->SetLocalObject(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint value) {
+ return functions->SetLocalInt(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong value) {
+ return functions->SetLocalLong(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value) {
+ return functions->SetLocalFloat(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value) {
+ return functions->SetLocalDouble(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->SetBreakpoint(this, method, location);
+ }
+
+ jvmtiError ClearBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->ClearBreakpoint(this, method, location);
+ }
+
+ jvmtiError SetFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError SetFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError GetLoadedClasses(jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassLoaderClasses(jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassSignature(jclass klass,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetClassStatus(jclass klass,
+ jint* status_ptr) {
+ return functions->GetClassStatus(this, klass, status_ptr);
+ }
+
+ jvmtiError GetSourceFileName(jclass klass,
+ char** source_name_ptr) {
+ return functions->GetSourceFileName(this, klass, source_name_ptr);
+ }
+
+ jvmtiError GetClassModifiers(jclass klass,
+ jint* modifiers_ptr) {
+ return functions->GetClassModifiers(this, klass, modifiers_ptr);
+ }
+
+ jvmtiError GetClassMethods(jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr) {
+ return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr);
+ }
+
+ jvmtiError GetClassFields(jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr) {
+ return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr);
+ }
+
+ jvmtiError GetImplementedInterfaces(jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr) {
+ return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr);
+ }
+
+ jvmtiError GetClassVersionNumbers(jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr) {
+ return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr);
+ }
+
+ jvmtiError GetConstantPool(jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr) {
+ return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr);
+ }
+
+ jvmtiError IsInterface(jclass klass,
+ jboolean* is_interface_ptr) {
+ return functions->IsInterface(this, klass, is_interface_ptr);
+ }
+
+ jvmtiError IsArrayClass(jclass klass,
+ jboolean* is_array_class_ptr) {
+ return functions->IsArrayClass(this, klass, is_array_class_ptr);
+ }
+
+ jvmtiError IsModifiableClass(jclass klass,
+ jboolean* is_modifiable_class_ptr) {
+ return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr);
+ }
+
+ jvmtiError GetClassLoader(jclass klass,
+ jobject* classloader_ptr) {
+ return functions->GetClassLoader(this, klass, classloader_ptr);
+ }
+
+ jvmtiError GetSourceDebugExtension(jclass klass,
+ char** source_debug_extension_ptr) {
+ return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr);
+ }
+
+ jvmtiError RetransformClasses(jint class_count,
+ const jclass* classes) {
+ return functions->RetransformClasses(this, class_count, classes);
+ }
+
+ jvmtiError RedefineClasses(jint class_count,
+ const jvmtiClassDefinition* class_definitions) {
+ return functions->RedefineClasses(this, class_count, class_definitions);
+ }
+
+ jvmtiError GetObjectSize(jobject object,
+ jlong* size_ptr) {
+ return functions->GetObjectSize(this, object, size_ptr);
+ }
+
+ jvmtiError GetObjectHashCode(jobject object,
+ jint* hash_code_ptr) {
+ return functions->GetObjectHashCode(this, object, hash_code_ptr);
+ }
+
+ jvmtiError GetObjectMonitorUsage(jobject object,
+ jvmtiMonitorUsage* info_ptr) {
+ return functions->GetObjectMonitorUsage(this, object, info_ptr);
+ }
+
+ jvmtiError GetFieldName(jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetFieldDeclaringClass(jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr) {
+ return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr);
+ }
+
+ jvmtiError GetFieldModifiers(jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr) {
+ return functions->GetFieldModifiers(this, klass, field, modifiers_ptr);
+ }
+
+ jvmtiError IsFieldSynthetic(jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr);
+ }
+
+ jvmtiError GetMethodName(jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetMethodDeclaringClass(jmethodID method,
+ jclass* declaring_class_ptr) {
+ return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr);
+ }
+
+ jvmtiError GetMethodModifiers(jmethodID method,
+ jint* modifiers_ptr) {
+ return functions->GetMethodModifiers(this, method, modifiers_ptr);
+ }
+
+ jvmtiError GetMaxLocals(jmethodID method,
+ jint* max_ptr) {
+ return functions->GetMaxLocals(this, method, max_ptr);
+ }
+
+ jvmtiError GetArgumentsSize(jmethodID method,
+ jint* size_ptr) {
+ return functions->GetArgumentsSize(this, method, size_ptr);
+ }
+
+ jvmtiError GetLineNumberTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr) {
+ return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetMethodLocation(jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr) {
+ return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr);
+ }
+
+ jvmtiError GetLocalVariableTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr) {
+ return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetBytecodes(jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr) {
+ return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr);
+ }
+
+ jvmtiError IsMethodNative(jmethodID method,
+ jboolean* is_native_ptr) {
+ return functions->IsMethodNative(this, method, is_native_ptr);
+ }
+
+ jvmtiError IsMethodSynthetic(jmethodID method,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsMethodSynthetic(this, method, is_synthetic_ptr);
+ }
+
+ jvmtiError IsMethodObsolete(jmethodID method,
+ jboolean* is_obsolete_ptr) {
+ return functions->IsMethodObsolete(this, method, is_obsolete_ptr);
+ }
+
+ jvmtiError SetNativeMethodPrefix(const char* prefix) {
+ return functions->SetNativeMethodPrefix(this, prefix);
+ }
+
+ jvmtiError SetNativeMethodPrefixes(jint prefix_count,
+ char** prefixes) {
+ return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes);
+ }
+
+ jvmtiError CreateRawMonitor(const char* name,
+ jrawMonitorID* monitor_ptr) {
+ return functions->CreateRawMonitor(this, name, monitor_ptr);
+ }
+
+ jvmtiError DestroyRawMonitor(jrawMonitorID monitor) {
+ return functions->DestroyRawMonitor(this, monitor);
+ }
+
+ jvmtiError RawMonitorEnter(jrawMonitorID monitor) {
+ return functions->RawMonitorEnter(this, monitor);
+ }
+
+ jvmtiError RawMonitorExit(jrawMonitorID monitor) {
+ return functions->RawMonitorExit(this, monitor);
+ }
+
+ jvmtiError RawMonitorWait(jrawMonitorID monitor,
+ jlong millis) {
+ return functions->RawMonitorWait(this, monitor, millis);
+ }
+
+ jvmtiError RawMonitorNotify(jrawMonitorID monitor) {
+ return functions->RawMonitorNotify(this, monitor);
+ }
+
+ jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) {
+ return functions->RawMonitorNotifyAll(this, monitor);
+ }
+
+ jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) {
+ return functions->SetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) {
+ return functions->GetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks) {
+ return functions->SetEventCallbacks(this, callbacks, size_of_callbacks);
+ }
+
+ jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...) {
+ return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
+ }
+
+ jvmtiError GenerateEvents(jvmtiEvent event_type) {
+ return functions->GenerateEvents(this, event_type);
+ }
+
+ jvmtiError GetExtensionFunctions(jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions) {
+ return functions->GetExtensionFunctions(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError GetExtensionEvents(jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions) {
+ return functions->GetExtensionEvents(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError SetExtensionEventCallback(jint extension_event_index,
+ jvmtiExtensionEvent callback) {
+ return functions->SetExtensionEventCallback(this, extension_event_index, callback);
+ }
+
+ jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetPotentialCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->AddCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->RelinquishCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) {
+ return functions->GetCurrentThreadCpuTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetThreadCpuTime(jthread thread,
+ jlong* nanos_ptr) {
+ return functions->GetThreadCpuTime(this, thread, nanos_ptr);
+ }
+
+ jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetTime(jlong* nanos_ptr) {
+ return functions->GetTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetAvailableProcessors(jint* processor_count_ptr) {
+ return functions->GetAvailableProcessors(this, processor_count_ptr);
+ }
+
+ jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) {
+ return functions->AddToBootstrapClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError AddToSystemClassLoaderSearch(const char* segment) {
+ return functions->AddToSystemClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError GetSystemProperties(jint* count_ptr,
+ char*** property_ptr) {
+ return functions->GetSystemProperties(this, count_ptr, property_ptr);
+ }
+
+ jvmtiError GetSystemProperty(const char* property,
+ char** value_ptr) {
+ return functions->GetSystemProperty(this, property, value_ptr);
+ }
+
+ jvmtiError SetSystemProperty(const char* property,
+ const char* value) {
+ return functions->SetSystemProperty(this, property, value);
+ }
+
+ jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
+ return functions->GetPhase(this, phase_ptr);
+ }
+
+ jvmtiError DisposeEnvironment() {
+ return functions->DisposeEnvironment(this);
+ }
+
+ jvmtiError SetEnvironmentLocalStorage(const void* data) {
+ return functions->SetEnvironmentLocalStorage(this, data);
+ }
+
+ jvmtiError GetEnvironmentLocalStorage(void** data_ptr) {
+ return functions->GetEnvironmentLocalStorage(this, data_ptr);
+ }
+
+ jvmtiError GetVersionNumber(jint* version_ptr) {
+ return functions->GetVersionNumber(this, version_ptr);
+ }
+
+ jvmtiError GetErrorName(jvmtiError error,
+ char** name_ptr) {
+ return functions->GetErrorName(this, error, name_ptr);
+ }
+
+ jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag,
+ jboolean value) {
+ return functions->SetVerboseFlag(this, flag, value);
+ }
+
+ jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
+ return functions->GetJLocationFormat(this, format_ptr);
+ }
+
+#endif /* __cplusplus */
+};
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVA_JVMTI_H_ */
+
diff --git a/source/client/jni/windows/classfile_constants.h b/source/client/jni/windows/classfile_constants.h
new file mode 100644
index 0000000000000000000000000000000000000000..b84790613cec30a3e840ab52c8c12b0207c50de9
--- /dev/null
+++ b/source/client/jni/windows/classfile_constants.h
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef CLASSFILE_CONSTANTS_H
+#define CLASSFILE_CONSTANTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Classfile version number for this information */
+#define JVM_CLASSFILE_MAJOR_VERSION 52
+#define JVM_CLASSFILE_MINOR_VERSION 0
+
+/* Flags */
+
+enum {
+ JVM_ACC_PUBLIC = 0x0001,
+ JVM_ACC_PRIVATE = 0x0002,
+ JVM_ACC_PROTECTED = 0x0004,
+ JVM_ACC_STATIC = 0x0008,
+ JVM_ACC_FINAL = 0x0010,
+ JVM_ACC_SYNCHRONIZED = 0x0020,
+ JVM_ACC_SUPER = 0x0020,
+ JVM_ACC_VOLATILE = 0x0040,
+ JVM_ACC_BRIDGE = 0x0040,
+ JVM_ACC_TRANSIENT = 0x0080,
+ JVM_ACC_VARARGS = 0x0080,
+ JVM_ACC_NATIVE = 0x0100,
+ JVM_ACC_INTERFACE = 0x0200,
+ JVM_ACC_ABSTRACT = 0x0400,
+ JVM_ACC_STRICT = 0x0800,
+ JVM_ACC_SYNTHETIC = 0x1000,
+ JVM_ACC_ANNOTATION = 0x2000,
+ JVM_ACC_ENUM = 0x4000
+};
+
+/* Used in newarray instruction. */
+
+enum {
+ JVM_T_BOOLEAN = 4,
+ JVM_T_CHAR = 5,
+ JVM_T_FLOAT = 6,
+ JVM_T_DOUBLE = 7,
+ JVM_T_BYTE = 8,
+ JVM_T_SHORT = 9,
+ JVM_T_INT = 10,
+ JVM_T_LONG = 11
+};
+
+/* Constant Pool Entries */
+
+enum {
+ JVM_CONSTANT_Utf8 = 1,
+ JVM_CONSTANT_Unicode = 2, /* unused */
+ JVM_CONSTANT_Integer = 3,
+ JVM_CONSTANT_Float = 4,
+ JVM_CONSTANT_Long = 5,
+ JVM_CONSTANT_Double = 6,
+ JVM_CONSTANT_Class = 7,
+ JVM_CONSTANT_String = 8,
+ JVM_CONSTANT_Fieldref = 9,
+ JVM_CONSTANT_Methodref = 10,
+ JVM_CONSTANT_InterfaceMethodref = 11,
+ JVM_CONSTANT_NameAndType = 12,
+ JVM_CONSTANT_MethodHandle = 15, // JSR 292
+ JVM_CONSTANT_MethodType = 16, // JSR 292
+ JVM_CONSTANT_InvokeDynamic = 18
+};
+
+/* JVM_CONSTANT_MethodHandle subtypes */
+enum {
+ JVM_REF_getField = 1,
+ JVM_REF_getStatic = 2,
+ JVM_REF_putField = 3,
+ JVM_REF_putStatic = 4,
+ JVM_REF_invokeVirtual = 5,
+ JVM_REF_invokeStatic = 6,
+ JVM_REF_invokeSpecial = 7,
+ JVM_REF_newInvokeSpecial = 8,
+ JVM_REF_invokeInterface = 9
+};
+
+/* StackMapTable type item numbers */
+
+enum {
+ JVM_ITEM_Top = 0,
+ JVM_ITEM_Integer = 1,
+ JVM_ITEM_Float = 2,
+ JVM_ITEM_Double = 3,
+ JVM_ITEM_Long = 4,
+ JVM_ITEM_Null = 5,
+ JVM_ITEM_UninitializedThis = 6,
+ JVM_ITEM_Object = 7,
+ JVM_ITEM_Uninitialized = 8
+};
+
+/* Type signatures */
+
+enum {
+ JVM_SIGNATURE_ARRAY = '[',
+ JVM_SIGNATURE_BYTE = 'B',
+ JVM_SIGNATURE_CHAR = 'C',
+ JVM_SIGNATURE_CLASS = 'L',
+ JVM_SIGNATURE_ENDCLASS = ';',
+ JVM_SIGNATURE_ENUM = 'E',
+ JVM_SIGNATURE_FLOAT = 'F',
+ JVM_SIGNATURE_DOUBLE = 'D',
+ JVM_SIGNATURE_FUNC = '(',
+ JVM_SIGNATURE_ENDFUNC = ')',
+ JVM_SIGNATURE_INT = 'I',
+ JVM_SIGNATURE_LONG = 'J',
+ JVM_SIGNATURE_SHORT = 'S',
+ JVM_SIGNATURE_VOID = 'V',
+ JVM_SIGNATURE_BOOLEAN = 'Z'
+};
+
+/* Opcodes */
+
+enum {
+ JVM_OPC_nop = 0,
+ JVM_OPC_aconst_null = 1,
+ JVM_OPC_iconst_m1 = 2,
+ JVM_OPC_iconst_0 = 3,
+ JVM_OPC_iconst_1 = 4,
+ JVM_OPC_iconst_2 = 5,
+ JVM_OPC_iconst_3 = 6,
+ JVM_OPC_iconst_4 = 7,
+ JVM_OPC_iconst_5 = 8,
+ JVM_OPC_lconst_0 = 9,
+ JVM_OPC_lconst_1 = 10,
+ JVM_OPC_fconst_0 = 11,
+ JVM_OPC_fconst_1 = 12,
+ JVM_OPC_fconst_2 = 13,
+ JVM_OPC_dconst_0 = 14,
+ JVM_OPC_dconst_1 = 15,
+ JVM_OPC_bipush = 16,
+ JVM_OPC_sipush = 17,
+ JVM_OPC_ldc = 18,
+ JVM_OPC_ldc_w = 19,
+ JVM_OPC_ldc2_w = 20,
+ JVM_OPC_iload = 21,
+ JVM_OPC_lload = 22,
+ JVM_OPC_fload = 23,
+ JVM_OPC_dload = 24,
+ JVM_OPC_aload = 25,
+ JVM_OPC_iload_0 = 26,
+ JVM_OPC_iload_1 = 27,
+ JVM_OPC_iload_2 = 28,
+ JVM_OPC_iload_3 = 29,
+ JVM_OPC_lload_0 = 30,
+ JVM_OPC_lload_1 = 31,
+ JVM_OPC_lload_2 = 32,
+ JVM_OPC_lload_3 = 33,
+ JVM_OPC_fload_0 = 34,
+ JVM_OPC_fload_1 = 35,
+ JVM_OPC_fload_2 = 36,
+ JVM_OPC_fload_3 = 37,
+ JVM_OPC_dload_0 = 38,
+ JVM_OPC_dload_1 = 39,
+ JVM_OPC_dload_2 = 40,
+ JVM_OPC_dload_3 = 41,
+ JVM_OPC_aload_0 = 42,
+ JVM_OPC_aload_1 = 43,
+ JVM_OPC_aload_2 = 44,
+ JVM_OPC_aload_3 = 45,
+ JVM_OPC_iaload = 46,
+ JVM_OPC_laload = 47,
+ JVM_OPC_faload = 48,
+ JVM_OPC_daload = 49,
+ JVM_OPC_aaload = 50,
+ JVM_OPC_baload = 51,
+ JVM_OPC_caload = 52,
+ JVM_OPC_saload = 53,
+ JVM_OPC_istore = 54,
+ JVM_OPC_lstore = 55,
+ JVM_OPC_fstore = 56,
+ JVM_OPC_dstore = 57,
+ JVM_OPC_astore = 58,
+ JVM_OPC_istore_0 = 59,
+ JVM_OPC_istore_1 = 60,
+ JVM_OPC_istore_2 = 61,
+ JVM_OPC_istore_3 = 62,
+ JVM_OPC_lstore_0 = 63,
+ JVM_OPC_lstore_1 = 64,
+ JVM_OPC_lstore_2 = 65,
+ JVM_OPC_lstore_3 = 66,
+ JVM_OPC_fstore_0 = 67,
+ JVM_OPC_fstore_1 = 68,
+ JVM_OPC_fstore_2 = 69,
+ JVM_OPC_fstore_3 = 70,
+ JVM_OPC_dstore_0 = 71,
+ JVM_OPC_dstore_1 = 72,
+ JVM_OPC_dstore_2 = 73,
+ JVM_OPC_dstore_3 = 74,
+ JVM_OPC_astore_0 = 75,
+ JVM_OPC_astore_1 = 76,
+ JVM_OPC_astore_2 = 77,
+ JVM_OPC_astore_3 = 78,
+ JVM_OPC_iastore = 79,
+ JVM_OPC_lastore = 80,
+ JVM_OPC_fastore = 81,
+ JVM_OPC_dastore = 82,
+ JVM_OPC_aastore = 83,
+ JVM_OPC_bastore = 84,
+ JVM_OPC_castore = 85,
+ JVM_OPC_sastore = 86,
+ JVM_OPC_pop = 87,
+ JVM_OPC_pop2 = 88,
+ JVM_OPC_dup = 89,
+ JVM_OPC_dup_x1 = 90,
+ JVM_OPC_dup_x2 = 91,
+ JVM_OPC_dup2 = 92,
+ JVM_OPC_dup2_x1 = 93,
+ JVM_OPC_dup2_x2 = 94,
+ JVM_OPC_swap = 95,
+ JVM_OPC_iadd = 96,
+ JVM_OPC_ladd = 97,
+ JVM_OPC_fadd = 98,
+ JVM_OPC_dadd = 99,
+ JVM_OPC_isub = 100,
+ JVM_OPC_lsub = 101,
+ JVM_OPC_fsub = 102,
+ JVM_OPC_dsub = 103,
+ JVM_OPC_imul = 104,
+ JVM_OPC_lmul = 105,
+ JVM_OPC_fmul = 106,
+ JVM_OPC_dmul = 107,
+ JVM_OPC_idiv = 108,
+ JVM_OPC_ldiv = 109,
+ JVM_OPC_fdiv = 110,
+ JVM_OPC_ddiv = 111,
+ JVM_OPC_irem = 112,
+ JVM_OPC_lrem = 113,
+ JVM_OPC_frem = 114,
+ JVM_OPC_drem = 115,
+ JVM_OPC_ineg = 116,
+ JVM_OPC_lneg = 117,
+ JVM_OPC_fneg = 118,
+ JVM_OPC_dneg = 119,
+ JVM_OPC_ishl = 120,
+ JVM_OPC_lshl = 121,
+ JVM_OPC_ishr = 122,
+ JVM_OPC_lshr = 123,
+ JVM_OPC_iushr = 124,
+ JVM_OPC_lushr = 125,
+ JVM_OPC_iand = 126,
+ JVM_OPC_land = 127,
+ JVM_OPC_ior = 128,
+ JVM_OPC_lor = 129,
+ JVM_OPC_ixor = 130,
+ JVM_OPC_lxor = 131,
+ JVM_OPC_iinc = 132,
+ JVM_OPC_i2l = 133,
+ JVM_OPC_i2f = 134,
+ JVM_OPC_i2d = 135,
+ JVM_OPC_l2i = 136,
+ JVM_OPC_l2f = 137,
+ JVM_OPC_l2d = 138,
+ JVM_OPC_f2i = 139,
+ JVM_OPC_f2l = 140,
+ JVM_OPC_f2d = 141,
+ JVM_OPC_d2i = 142,
+ JVM_OPC_d2l = 143,
+ JVM_OPC_d2f = 144,
+ JVM_OPC_i2b = 145,
+ JVM_OPC_i2c = 146,
+ JVM_OPC_i2s = 147,
+ JVM_OPC_lcmp = 148,
+ JVM_OPC_fcmpl = 149,
+ JVM_OPC_fcmpg = 150,
+ JVM_OPC_dcmpl = 151,
+ JVM_OPC_dcmpg = 152,
+ JVM_OPC_ifeq = 153,
+ JVM_OPC_ifne = 154,
+ JVM_OPC_iflt = 155,
+ JVM_OPC_ifge = 156,
+ JVM_OPC_ifgt = 157,
+ JVM_OPC_ifle = 158,
+ JVM_OPC_if_icmpeq = 159,
+ JVM_OPC_if_icmpne = 160,
+ JVM_OPC_if_icmplt = 161,
+ JVM_OPC_if_icmpge = 162,
+ JVM_OPC_if_icmpgt = 163,
+ JVM_OPC_if_icmple = 164,
+ JVM_OPC_if_acmpeq = 165,
+ JVM_OPC_if_acmpne = 166,
+ JVM_OPC_goto = 167,
+ JVM_OPC_jsr = 168,
+ JVM_OPC_ret = 169,
+ JVM_OPC_tableswitch = 170,
+ JVM_OPC_lookupswitch = 171,
+ JVM_OPC_ireturn = 172,
+ JVM_OPC_lreturn = 173,
+ JVM_OPC_freturn = 174,
+ JVM_OPC_dreturn = 175,
+ JVM_OPC_areturn = 176,
+ JVM_OPC_return = 177,
+ JVM_OPC_getstatic = 178,
+ JVM_OPC_putstatic = 179,
+ JVM_OPC_getfield = 180,
+ JVM_OPC_putfield = 181,
+ JVM_OPC_invokevirtual = 182,
+ JVM_OPC_invokespecial = 183,
+ JVM_OPC_invokestatic = 184,
+ JVM_OPC_invokeinterface = 185,
+ JVM_OPC_invokedynamic = 186,
+ JVM_OPC_new = 187,
+ JVM_OPC_newarray = 188,
+ JVM_OPC_anewarray = 189,
+ JVM_OPC_arraylength = 190,
+ JVM_OPC_athrow = 191,
+ JVM_OPC_checkcast = 192,
+ JVM_OPC_instanceof = 193,
+ JVM_OPC_monitorenter = 194,
+ JVM_OPC_monitorexit = 195,
+ JVM_OPC_wide = 196,
+ JVM_OPC_multianewarray = 197,
+ JVM_OPC_ifnull = 198,
+ JVM_OPC_ifnonnull = 199,
+ JVM_OPC_goto_w = 200,
+ JVM_OPC_jsr_w = 201,
+ JVM_OPC_MAX = 201
+};
+
+/* Opcode length initializer, use with something like:
+ * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER;
+ */
+#define JVM_OPCODE_LENGTH_INITIALIZER { \
+ 1, /* nop */ \
+ 1, /* aconst_null */ \
+ 1, /* iconst_m1 */ \
+ 1, /* iconst_0 */ \
+ 1, /* iconst_1 */ \
+ 1, /* iconst_2 */ \
+ 1, /* iconst_3 */ \
+ 1, /* iconst_4 */ \
+ 1, /* iconst_5 */ \
+ 1, /* lconst_0 */ \
+ 1, /* lconst_1 */ \
+ 1, /* fconst_0 */ \
+ 1, /* fconst_1 */ \
+ 1, /* fconst_2 */ \
+ 1, /* dconst_0 */ \
+ 1, /* dconst_1 */ \
+ 2, /* bipush */ \
+ 3, /* sipush */ \
+ 2, /* ldc */ \
+ 3, /* ldc_w */ \
+ 3, /* ldc2_w */ \
+ 2, /* iload */ \
+ 2, /* lload */ \
+ 2, /* fload */ \
+ 2, /* dload */ \
+ 2, /* aload */ \
+ 1, /* iload_0 */ \
+ 1, /* iload_1 */ \
+ 1, /* iload_2 */ \
+ 1, /* iload_3 */ \
+ 1, /* lload_0 */ \
+ 1, /* lload_1 */ \
+ 1, /* lload_2 */ \
+ 1, /* lload_3 */ \
+ 1, /* fload_0 */ \
+ 1, /* fload_1 */ \
+ 1, /* fload_2 */ \
+ 1, /* fload_3 */ \
+ 1, /* dload_0 */ \
+ 1, /* dload_1 */ \
+ 1, /* dload_2 */ \
+ 1, /* dload_3 */ \
+ 1, /* aload_0 */ \
+ 1, /* aload_1 */ \
+ 1, /* aload_2 */ \
+ 1, /* aload_3 */ \
+ 1, /* iaload */ \
+ 1, /* laload */ \
+ 1, /* faload */ \
+ 1, /* daload */ \
+ 1, /* aaload */ \
+ 1, /* baload */ \
+ 1, /* caload */ \
+ 1, /* saload */ \
+ 2, /* istore */ \
+ 2, /* lstore */ \
+ 2, /* fstore */ \
+ 2, /* dstore */ \
+ 2, /* astore */ \
+ 1, /* istore_0 */ \
+ 1, /* istore_1 */ \
+ 1, /* istore_2 */ \
+ 1, /* istore_3 */ \
+ 1, /* lstore_0 */ \
+ 1, /* lstore_1 */ \
+ 1, /* lstore_2 */ \
+ 1, /* lstore_3 */ \
+ 1, /* fstore_0 */ \
+ 1, /* fstore_1 */ \
+ 1, /* fstore_2 */ \
+ 1, /* fstore_3 */ \
+ 1, /* dstore_0 */ \
+ 1, /* dstore_1 */ \
+ 1, /* dstore_2 */ \
+ 1, /* dstore_3 */ \
+ 1, /* astore_0 */ \
+ 1, /* astore_1 */ \
+ 1, /* astore_2 */ \
+ 1, /* astore_3 */ \
+ 1, /* iastore */ \
+ 1, /* lastore */ \
+ 1, /* fastore */ \
+ 1, /* dastore */ \
+ 1, /* aastore */ \
+ 1, /* bastore */ \
+ 1, /* castore */ \
+ 1, /* sastore */ \
+ 1, /* pop */ \
+ 1, /* pop2 */ \
+ 1, /* dup */ \
+ 1, /* dup_x1 */ \
+ 1, /* dup_x2 */ \
+ 1, /* dup2 */ \
+ 1, /* dup2_x1 */ \
+ 1, /* dup2_x2 */ \
+ 1, /* swap */ \
+ 1, /* iadd */ \
+ 1, /* ladd */ \
+ 1, /* fadd */ \
+ 1, /* dadd */ \
+ 1, /* isub */ \
+ 1, /* lsub */ \
+ 1, /* fsub */ \
+ 1, /* dsub */ \
+ 1, /* imul */ \
+ 1, /* lmul */ \
+ 1, /* fmul */ \
+ 1, /* dmul */ \
+ 1, /* idiv */ \
+ 1, /* ldiv */ \
+ 1, /* fdiv */ \
+ 1, /* ddiv */ \
+ 1, /* irem */ \
+ 1, /* lrem */ \
+ 1, /* frem */ \
+ 1, /* drem */ \
+ 1, /* ineg */ \
+ 1, /* lneg */ \
+ 1, /* fneg */ \
+ 1, /* dneg */ \
+ 1, /* ishl */ \
+ 1, /* lshl */ \
+ 1, /* ishr */ \
+ 1, /* lshr */ \
+ 1, /* iushr */ \
+ 1, /* lushr */ \
+ 1, /* iand */ \
+ 1, /* land */ \
+ 1, /* ior */ \
+ 1, /* lor */ \
+ 1, /* ixor */ \
+ 1, /* lxor */ \
+ 3, /* iinc */ \
+ 1, /* i2l */ \
+ 1, /* i2f */ \
+ 1, /* i2d */ \
+ 1, /* l2i */ \
+ 1, /* l2f */ \
+ 1, /* l2d */ \
+ 1, /* f2i */ \
+ 1, /* f2l */ \
+ 1, /* f2d */ \
+ 1, /* d2i */ \
+ 1, /* d2l */ \
+ 1, /* d2f */ \
+ 1, /* i2b */ \
+ 1, /* i2c */ \
+ 1, /* i2s */ \
+ 1, /* lcmp */ \
+ 1, /* fcmpl */ \
+ 1, /* fcmpg */ \
+ 1, /* dcmpl */ \
+ 1, /* dcmpg */ \
+ 3, /* ifeq */ \
+ 3, /* ifne */ \
+ 3, /* iflt */ \
+ 3, /* ifge */ \
+ 3, /* ifgt */ \
+ 3, /* ifle */ \
+ 3, /* if_icmpeq */ \
+ 3, /* if_icmpne */ \
+ 3, /* if_icmplt */ \
+ 3, /* if_icmpge */ \
+ 3, /* if_icmpgt */ \
+ 3, /* if_icmple */ \
+ 3, /* if_acmpeq */ \
+ 3, /* if_acmpne */ \
+ 3, /* goto */ \
+ 3, /* jsr */ \
+ 2, /* ret */ \
+ 99, /* tableswitch */ \
+ 99, /* lookupswitch */ \
+ 1, /* ireturn */ \
+ 1, /* lreturn */ \
+ 1, /* freturn */ \
+ 1, /* dreturn */ \
+ 1, /* areturn */ \
+ 1, /* return */ \
+ 3, /* getstatic */ \
+ 3, /* putstatic */ \
+ 3, /* getfield */ \
+ 3, /* putfield */ \
+ 3, /* invokevirtual */ \
+ 3, /* invokespecial */ \
+ 3, /* invokestatic */ \
+ 5, /* invokeinterface */ \
+ 5, /* invokedynamic */ \
+ 3, /* new */ \
+ 2, /* newarray */ \
+ 3, /* anewarray */ \
+ 1, /* arraylength */ \
+ 1, /* athrow */ \
+ 3, /* checkcast */ \
+ 3, /* instanceof */ \
+ 1, /* monitorenter */ \
+ 1, /* monitorexit */ \
+ 0, /* wide */ \
+ 4, /* multianewarray */ \
+ 3, /* ifnull */ \
+ 3, /* ifnonnull */ \
+ 5, /* goto_w */ \
+ 5 /* jsr_w */ \
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* CLASSFILE_CONSTANTS */
diff --git a/source/client/jni/windows/jawt.h b/source/client/jni/windows/jawt.h
new file mode 100644
index 0000000000000000000000000000000000000000..231c292dc882da95dba958bcadfd011879cebbcb
--- /dev/null
+++ b/source/client/jni/windows/jawt.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JAWT_H_
+#define _JAVASOFT_JAWT_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * AWT native interface (new in JDK 1.3)
+ *
+ * The AWT native interface allows a native C or C++ application a means
+ * by which to access native structures in AWT. This is to facilitate moving
+ * legacy C and C++ applications to Java and to target the needs of the
+ * community who, at present, wish to do their own native rendering to canvases
+ * for performance reasons. Standard extensions such as Java3D also require a
+ * means to access the underlying native data structures of AWT.
+ *
+ * There may be future extensions to this API depending on demand.
+ *
+ * A VM does not have to implement this API in order to pass the JCK.
+ * It is recommended, however, that this API is implemented on VMs that support
+ * standard extensions, such as Java3D.
+ *
+ * Since this is a native API, any program which uses it cannot be considered
+ * 100% pure java.
+ */
+
+/*
+ * AWT Native Drawing Surface (JAWT_DrawingSurface).
+ *
+ * For each platform, there is a native drawing surface structure. This
+ * platform-specific structure can be found in jawt_md.h. It is recommended
+ * that additional platforms follow the same model. It is also recommended
+ * that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
+ *
+ *******************
+ * EXAMPLE OF USAGE:
+ *******************
+ *
+ * In Win32, a programmer wishes to access the HWND of a canvas to perform
+ * native rendering into it. The programmer has declared the paint() method
+ * for their canvas subclass to be native:
+ *
+ *
+ * MyCanvas.java:
+ *
+ * import java.awt.*;
+ *
+ * public class MyCanvas extends Canvas {
+ *
+ * static {
+ * System.loadLibrary("mylib");
+ * }
+ *
+ * public native void paint(Graphics g);
+ * }
+ *
+ *
+ * myfile.c:
+ *
+ * #include "jawt_md.h"
+ * #include
+ *
+ * JNIEXPORT void JNICALL
+ * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
+ * {
+ * JAWT awt;
+ * JAWT_DrawingSurface* ds;
+ * JAWT_DrawingSurfaceInfo* dsi;
+ * JAWT_Win32DrawingSurfaceInfo* dsi_win;
+ * jboolean result;
+ * jint lock;
+ *
+ * // Get the AWT
+ * awt.version = JAWT_VERSION_1_3;
+ * result = JAWT_GetAWT(env, &awt);
+ * assert(result != JNI_FALSE);
+ *
+ * // Get the drawing surface
+ * ds = awt.GetDrawingSurface(env, canvas);
+ * assert(ds != NULL);
+ *
+ * // Lock the drawing surface
+ * lock = ds->Lock(ds);
+ * assert((lock & JAWT_LOCK_ERROR) == 0);
+ *
+ * // Get the drawing surface info
+ * dsi = ds->GetDrawingSurfaceInfo(ds);
+ *
+ * // Get the platform-specific drawing info
+ * dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+ *
+ * //////////////////////////////
+ * // !!! DO PAINTING HERE !!! //
+ * //////////////////////////////
+ *
+ * // Free the drawing surface info
+ * ds->FreeDrawingSurfaceInfo(dsi);
+ *
+ * // Unlock the drawing surface
+ * ds->Unlock(ds);
+ *
+ * // Free the drawing surface
+ * awt.FreeDrawingSurface(ds);
+ * }
+ *
+ */
+
+/*
+ * JAWT_Rectangle
+ * Structure for a native rectangle.
+ */
+typedef struct jawt_Rectangle {
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+} JAWT_Rectangle;
+
+struct jawt_DrawingSurface;
+
+/*
+ * JAWT_DrawingSurfaceInfo
+ * Structure for containing the underlying drawing information of a component.
+ */
+typedef struct jawt_DrawingSurfaceInfo {
+ /*
+ * Pointer to the platform-specific information. This can be safely
+ * cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
+ * JAWT_X11DrawingSurfaceInfo on Solaris. On Mac OS X this is a
+ * pointer to a NSObject that conforms to the JAWT_SurfaceLayers
+ * protocol. See jawt_md.h for details.
+ */
+ void* platformInfo;
+ /* Cached pointer to the underlying drawing surface */
+ struct jawt_DrawingSurface* ds;
+ /* Bounding rectangle of the drawing surface */
+ JAWT_Rectangle bounds;
+ /* Number of rectangles in the clip */
+ jint clipSize;
+ /* Clip rectangle array */
+ JAWT_Rectangle* clip;
+} JAWT_DrawingSurfaceInfo;
+
+#define JAWT_LOCK_ERROR 0x00000001
+#define JAWT_LOCK_CLIP_CHANGED 0x00000002
+#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
+#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
+
+/*
+ * JAWT_DrawingSurface
+ * Structure for containing the underlying drawing information of a component.
+ * All operations on a JAWT_DrawingSurface MUST be performed from the same
+ * thread as the call to GetDrawingSurface.
+ */
+typedef struct jawt_DrawingSurface {
+ /*
+ * Cached reference to the Java environment of the calling thread.
+ * If Lock(), Unlock(), GetDrawingSurfaceInfo() or
+ * FreeDrawingSurfaceInfo() are called from a different thread,
+ * this data member should be set before calling those functions.
+ */
+ JNIEnv* env;
+ /* Cached reference to the target object */
+ jobject target;
+ /*
+ * Lock the surface of the target component for native rendering.
+ * When finished drawing, the surface must be unlocked with
+ * Unlock(). This function returns a bitmask with one or more of the
+ * following values:
+ *
+ * JAWT_LOCK_ERROR - When an error has occurred and the surface could not
+ * be locked.
+ *
+ * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
+ *
+ * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
+ *
+ * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
+ */
+ jint (JNICALL *Lock)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Get the drawing surface info.
+ * The value returned may be cached, but the values may change if
+ * additional calls to Lock() or Unlock() are made.
+ * Lock() must be called before this can return a valid value.
+ * Returns NULL if an error has occurred.
+ * When finished with the returned value, FreeDrawingSurfaceInfo must be
+ * called.
+ */
+ JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Free the drawing surface info.
+ */
+ void (JNICALL *FreeDrawingSurfaceInfo)
+ (JAWT_DrawingSurfaceInfo* dsi);
+ /*
+ * Unlock the drawing surface of the target component for native rendering.
+ */
+ void (JNICALL *Unlock)
+ (struct jawt_DrawingSurface* ds);
+} JAWT_DrawingSurface;
+
+/*
+ * JAWT
+ * Structure for containing native AWT functions.
+ */
+typedef struct jawt {
+ /*
+ * Version of this structure. This must always be set before
+ * calling JAWT_GetAWT()
+ */
+ jint version;
+ /*
+ * Return a drawing surface from a target jobject. This value
+ * may be cached.
+ * Returns NULL if an error has occurred.
+ * Target must be a java.awt.Component (should be a Canvas
+ * or Window for native rendering).
+ * FreeDrawingSurface() must be called when finished with the
+ * returned JAWT_DrawingSurface.
+ */
+ JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
+ (JNIEnv* env, jobject target);
+ /*
+ * Free the drawing surface allocated in GetDrawingSurface.
+ */
+ void (JNICALL *FreeDrawingSurface)
+ (JAWT_DrawingSurface* ds);
+ /*
+ * Since 1.4
+ * Locks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Lock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Unlocks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Unlock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Returns a reference to a java.awt.Component from a native
+ * platform handle. On Windows, this corresponds to an HWND;
+ * on Solaris and Linux, this is a Drawable. For other platforms,
+ * see the appropriate machine-dependent header file for a description.
+ * The reference returned by this function is a local
+ * reference that is only valid in this environment.
+ * This function returns a NULL reference if no component could be
+ * found with matching platform information.
+ */
+ jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
+
+} JAWT;
+
+/*
+ * Get the AWT native structure. This function returns JNI_FALSE if
+ * an error occurs.
+ */
+_JNI_IMPORT_OR_EXPORT_
+jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
+
+#define JAWT_VERSION_1_3 0x00010003
+#define JAWT_VERSION_1_4 0x00010004
+#define JAWT_VERSION_1_7 0x00010007
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* !_JAVASOFT_JAWT_H_ */
diff --git a/source/client/jni/windows/jdwpTransport.h b/source/client/jni/windows/jdwpTransport.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2b9d9049c4ab17af09dce7d6be447f5f898e0c9
--- /dev/null
+++ b/source/client/jni/windows/jdwpTransport.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Java Debug Wire Protocol Transport Service Provider Interface.
+ */
+
+#ifndef JDWPTRANSPORT_H
+#define JDWPTRANSPORT_H
+
+#include "jni.h"
+
+enum {
+ JDWPTRANSPORT_VERSION_1_0 = 0x00010000
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct jdwpTransportNativeInterface_;
+
+struct _jdwpTransportEnv;
+
+#ifdef __cplusplus
+typedef _jdwpTransportEnv jdwpTransportEnv;
+#else
+typedef const struct jdwpTransportNativeInterface_ *jdwpTransportEnv;
+#endif /* __cplusplus */
+
+/*
+ * Errors. Universal errors with JVMTI/JVMDI equivalents keep the
+ * values the same.
+ */
+typedef enum {
+ JDWPTRANSPORT_ERROR_NONE = 0,
+ JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103,
+ JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110,
+ JDWPTRANSPORT_ERROR_INTERNAL = 113,
+ JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201,
+ JDWPTRANSPORT_ERROR_IO_ERROR = 202,
+ JDWPTRANSPORT_ERROR_TIMEOUT = 203,
+ JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204
+} jdwpTransportError;
+
+
+/*
+ * Structure to define capabilities
+ */
+typedef struct {
+ unsigned int can_timeout_attach :1;
+ unsigned int can_timeout_accept :1;
+ unsigned int can_timeout_handshake :1;
+ unsigned int reserved3 :1;
+ unsigned int reserved4 :1;
+ unsigned int reserved5 :1;
+ unsigned int reserved6 :1;
+ unsigned int reserved7 :1;
+ unsigned int reserved8 :1;
+ unsigned int reserved9 :1;
+ unsigned int reserved10 :1;
+ unsigned int reserved11 :1;
+ unsigned int reserved12 :1;
+ unsigned int reserved13 :1;
+ unsigned int reserved14 :1;
+ unsigned int reserved15 :1;
+} JDWPTransportCapabilities;
+
+
+/*
+ * Structures to define packet layout.
+ *
+ * See: http://java.sun.com/j2se/1.5/docs/guide/jpda/jdwp-spec.html
+ */
+
+enum {
+ /*
+ * If additional flags are added that apply to jdwpCmdPacket,
+ * then debugLoop.c: reader() will need to be updated to
+ * accept more than JDWPTRANSPORT_FLAGS_NONE.
+ */
+ JDWPTRANSPORT_FLAGS_NONE = 0x0,
+ JDWPTRANSPORT_FLAGS_REPLY = 0x80
+};
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jbyte cmdSet;
+ jbyte cmd;
+ jbyte *data;
+} jdwpCmdPacket;
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jshort errorCode;
+ jbyte *data;
+} jdwpReplyPacket;
+
+typedef struct {
+ union {
+ jdwpCmdPacket cmd;
+ jdwpReplyPacket reply;
+ } type;
+} jdwpPacket;
+
+/*
+ * JDWP functions called by the transport.
+ */
+typedef struct jdwpTransportCallback {
+ void *(*alloc)(jint numBytes); /* Call this for all allocations */
+ void (*free)(void *buffer); /* Call this for all deallocations */
+} jdwpTransportCallback;
+
+typedef jint (JNICALL *jdwpTransport_OnLoad_t)(JavaVM *jvm,
+ jdwpTransportCallback *callback,
+ jint version,
+ jdwpTransportEnv** env);
+
+
+
+/* Function Interface */
+
+struct jdwpTransportNativeInterface_ {
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Get Capabilities */
+ jdwpTransportError (JNICALL *GetCapabilities)(jdwpTransportEnv* env,
+ JDWPTransportCapabilities *capabilities_ptr);
+
+ /* 3 : Attach */
+ jdwpTransportError (JNICALL *Attach)(jdwpTransportEnv* env,
+ const char* address,
+ jlong attach_timeout,
+ jlong handshake_timeout);
+
+ /* 4: StartListening */
+ jdwpTransportError (JNICALL *StartListening)(jdwpTransportEnv* env,
+ const char* address,
+ char** actual_address);
+
+ /* 5: StopListening */
+ jdwpTransportError (JNICALL *StopListening)(jdwpTransportEnv* env);
+
+ /* 6: Accept */
+ jdwpTransportError (JNICALL *Accept)(jdwpTransportEnv* env,
+ jlong accept_timeout,
+ jlong handshake_timeout);
+
+ /* 7: IsOpen */
+ jboolean (JNICALL *IsOpen)(jdwpTransportEnv* env);
+
+ /* 8: Close */
+ jdwpTransportError (JNICALL *Close)(jdwpTransportEnv* env);
+
+ /* 9: ReadPacket */
+ jdwpTransportError (JNICALL *ReadPacket)(jdwpTransportEnv* env,
+ jdwpPacket *pkt);
+
+ /* 10: Write Packet */
+ jdwpTransportError (JNICALL *WritePacket)(jdwpTransportEnv* env,
+ const jdwpPacket* pkt);
+
+ /* 11: GetLastError */
+ jdwpTransportError (JNICALL *GetLastError)(jdwpTransportEnv* env,
+ char** error);
+
+};
+
+
+/*
+ * Use inlined functions so that C++ code can use syntax such as
+ * env->Attach("mymachine:5000", 10*1000, 0);
+ *
+ * rather than using C's :-
+ *
+ * (*env)->Attach(env, "mymachine:5000", 10*1000, 0);
+ */
+struct _jdwpTransportEnv {
+ const struct jdwpTransportNativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jdwpTransportError GetCapabilities(JDWPTransportCapabilities *capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jdwpTransportError Attach(const char* address, jlong attach_timeout,
+ jlong handshake_timeout) {
+ return functions->Attach(this, address, attach_timeout, handshake_timeout);
+ }
+
+ jdwpTransportError StartListening(const char* address,
+ char** actual_address) {
+ return functions->StartListening(this, address, actual_address);
+ }
+
+ jdwpTransportError StopListening(void) {
+ return functions->StopListening(this);
+ }
+
+ jdwpTransportError Accept(jlong accept_timeout, jlong handshake_timeout) {
+ return functions->Accept(this, accept_timeout, handshake_timeout);
+ }
+
+ jboolean IsOpen(void) {
+ return functions->IsOpen(this);
+ }
+
+ jdwpTransportError Close(void) {
+ return functions->Close(this);
+ }
+
+ jdwpTransportError ReadPacket(jdwpPacket *pkt) {
+ return functions->ReadPacket(this, pkt);
+ }
+
+ jdwpTransportError WritePacket(const jdwpPacket* pkt) {
+ return functions->WritePacket(this, pkt);
+ }
+
+ jdwpTransportError GetLastError(char** error) {
+ return functions->GetLastError(this, error);
+ }
+
+
+#endif /* __cplusplus */
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* JDWPTRANSPORT_H */
diff --git a/source/client/jni/windows/jni.h b/source/client/jni/windows/jni.h
new file mode 100644
index 0000000000000000000000000000000000000000..424dca56428b021195a45e3060418d6e47a48ef9
--- /dev/null
+++ b/source/client/jni/windows/jni.h
@@ -0,0 +1,1960 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include
+#include
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+
+ /* New JNI 1.6 Features */
+
+ jobjectRefType (JNICALL *GetObjectRefType)
+ (JNIEnv* env, jobject obj);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+ jobjectRefType GetObjectRefType(jobject obj) {
+ return functions->GetObjectRefType(this, obj);
+ }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+#define JNI_VERSION_1_8 0x00010008
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
diff --git a/source/client/jni/windows/jvmti.h b/source/client/jni/windows/jvmti.h
new file mode 100644
index 0000000000000000000000000000000000000000..10df7dadc1620fcbe62134697224c76ea898f7ff
--- /dev/null
+++ b/source/client/jni/windows/jvmti.h
@@ -0,0 +1,2534 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
+
+
+ /* Include file for the Java(tm) Virtual Machine Tool Interface */
+
+#ifndef _JAVA_JVMTI_H_
+#define _JAVA_JVMTI_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ JVMTI_VERSION_1 = 0x30010000,
+ JVMTI_VERSION_1_0 = 0x30010000,
+ JVMTI_VERSION_1_1 = 0x30010100,
+ JVMTI_VERSION_1_2 = 0x30010200,
+
+ JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */
+};
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
+
+JNIEXPORT void JNICALL
+Agent_OnUnload(JavaVM *vm);
+
+ /* Forward declaration of the environment */
+
+struct _jvmtiEnv;
+
+struct jvmtiInterface_1_;
+
+#ifdef __cplusplus
+typedef _jvmtiEnv jvmtiEnv;
+#else
+typedef const struct jvmtiInterface_1_ *jvmtiEnv;
+#endif /* __cplusplus */
+
+/* Derived Base Types */
+
+typedef jobject jthread;
+typedef jobject jthreadGroup;
+typedef jlong jlocation;
+struct _jrawMonitorID;
+typedef struct _jrawMonitorID *jrawMonitorID;
+typedef struct JNINativeInterface_ jniNativeInterface;
+
+ /* Constants */
+
+
+ /* Thread State Flags */
+
+enum {
+ JVMTI_THREAD_STATE_ALIVE = 0x0001,
+ JVMTI_THREAD_STATE_TERMINATED = 0x0002,
+ JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
+ JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
+ JVMTI_THREAD_STATE_WAITING = 0x0080,
+ JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
+ JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
+ JVMTI_THREAD_STATE_SLEEPING = 0x0040,
+ JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
+ JVMTI_THREAD_STATE_PARKED = 0x0200,
+ JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
+ JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
+ JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
+ JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
+ JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
+ JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000
+};
+
+ /* java.lang.Thread.State Conversion Masks */
+
+enum {
+ JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
+ JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
+ JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
+ JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE,
+ JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
+ JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
+ JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
+};
+
+ /* Thread Priority Constants */
+
+enum {
+ JVMTI_THREAD_MIN_PRIORITY = 1,
+ JVMTI_THREAD_NORM_PRIORITY = 5,
+ JVMTI_THREAD_MAX_PRIORITY = 10
+};
+
+ /* Heap Filter Flags */
+
+enum {
+ JVMTI_HEAP_FILTER_TAGGED = 0x4,
+ JVMTI_HEAP_FILTER_UNTAGGED = 0x8,
+ JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10,
+ JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20
+};
+
+ /* Heap Visit Control Flags */
+
+enum {
+ JVMTI_VISIT_OBJECTS = 0x100,
+ JVMTI_VISIT_ABORT = 0x8000
+};
+
+ /* Heap Reference Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_REFERENCE_CLASS = 1,
+ JVMTI_HEAP_REFERENCE_FIELD = 2,
+ JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_HEAP_REFERENCE_SIGNERS = 5,
+ JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_HEAP_REFERENCE_INTERFACE = 7,
+ JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9,
+ JVMTI_HEAP_REFERENCE_SUPERCLASS = 10,
+ JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21,
+ JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22,
+ JVMTI_HEAP_REFERENCE_MONITOR = 23,
+ JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24,
+ JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25,
+ JVMTI_HEAP_REFERENCE_THREAD = 26,
+ JVMTI_HEAP_REFERENCE_OTHER = 27
+} jvmtiHeapReferenceKind;
+
+ /* Primitive Type Enumeration */
+
+typedef enum {
+ JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90,
+ JVMTI_PRIMITIVE_TYPE_BYTE = 66,
+ JVMTI_PRIMITIVE_TYPE_CHAR = 67,
+ JVMTI_PRIMITIVE_TYPE_SHORT = 83,
+ JVMTI_PRIMITIVE_TYPE_INT = 73,
+ JVMTI_PRIMITIVE_TYPE_LONG = 74,
+ JVMTI_PRIMITIVE_TYPE_FLOAT = 70,
+ JVMTI_PRIMITIVE_TYPE_DOUBLE = 68
+} jvmtiPrimitiveType;
+
+ /* Heap Object Filter Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_OBJECT_TAGGED = 1,
+ JVMTI_HEAP_OBJECT_UNTAGGED = 2,
+ JVMTI_HEAP_OBJECT_EITHER = 3
+} jvmtiHeapObjectFilter;
+
+ /* Heap Root Kind Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
+ JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
+ JVMTI_HEAP_ROOT_MONITOR = 3,
+ JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
+ JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
+ JVMTI_HEAP_ROOT_THREAD = 6,
+ JVMTI_HEAP_ROOT_OTHER = 7
+} jvmtiHeapRootKind;
+
+ /* Object Reference Enumeration */
+
+typedef enum {
+ JVMTI_REFERENCE_CLASS = 1,
+ JVMTI_REFERENCE_FIELD = 2,
+ JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_REFERENCE_SIGNERS = 5,
+ JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_REFERENCE_INTERFACE = 7,
+ JVMTI_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_REFERENCE_CONSTANT_POOL = 9
+} jvmtiObjectReferenceKind;
+
+ /* Iteration Control Enumeration */
+
+typedef enum {
+ JVMTI_ITERATION_CONTINUE = 1,
+ JVMTI_ITERATION_IGNORE = 2,
+ JVMTI_ITERATION_ABORT = 0
+} jvmtiIterationControl;
+
+ /* Class Status Flags */
+
+enum {
+ JVMTI_CLASS_STATUS_VERIFIED = 1,
+ JVMTI_CLASS_STATUS_PREPARED = 2,
+ JVMTI_CLASS_STATUS_INITIALIZED = 4,
+ JVMTI_CLASS_STATUS_ERROR = 8,
+ JVMTI_CLASS_STATUS_ARRAY = 16,
+ JVMTI_CLASS_STATUS_PRIMITIVE = 32
+};
+
+ /* Event Enable/Disable */
+
+typedef enum {
+ JVMTI_ENABLE = 1,
+ JVMTI_DISABLE = 0
+} jvmtiEventMode;
+
+ /* Extension Function/Event Parameter Types */
+
+typedef enum {
+ JVMTI_TYPE_JBYTE = 101,
+ JVMTI_TYPE_JCHAR = 102,
+ JVMTI_TYPE_JSHORT = 103,
+ JVMTI_TYPE_JINT = 104,
+ JVMTI_TYPE_JLONG = 105,
+ JVMTI_TYPE_JFLOAT = 106,
+ JVMTI_TYPE_JDOUBLE = 107,
+ JVMTI_TYPE_JBOOLEAN = 108,
+ JVMTI_TYPE_JOBJECT = 109,
+ JVMTI_TYPE_JTHREAD = 110,
+ JVMTI_TYPE_JCLASS = 111,
+ JVMTI_TYPE_JVALUE = 112,
+ JVMTI_TYPE_JFIELDID = 113,
+ JVMTI_TYPE_JMETHODID = 114,
+ JVMTI_TYPE_CCHAR = 115,
+ JVMTI_TYPE_CVOID = 116,
+ JVMTI_TYPE_JNIENV = 117
+} jvmtiParamTypes;
+
+ /* Extension Function/Event Parameter Kinds */
+
+typedef enum {
+ JVMTI_KIND_IN = 91,
+ JVMTI_KIND_IN_PTR = 92,
+ JVMTI_KIND_IN_BUF = 93,
+ JVMTI_KIND_ALLOC_BUF = 94,
+ JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
+ JVMTI_KIND_OUT = 96,
+ JVMTI_KIND_OUT_BUF = 97
+} jvmtiParamKind;
+
+ /* Timer Kinds */
+
+typedef enum {
+ JVMTI_TIMER_USER_CPU = 30,
+ JVMTI_TIMER_TOTAL_CPU = 31,
+ JVMTI_TIMER_ELAPSED = 32
+} jvmtiTimerKind;
+
+ /* Phases of execution */
+
+typedef enum {
+ JVMTI_PHASE_ONLOAD = 1,
+ JVMTI_PHASE_PRIMORDIAL = 2,
+ JVMTI_PHASE_START = 6,
+ JVMTI_PHASE_LIVE = 4,
+ JVMTI_PHASE_DEAD = 8
+} jvmtiPhase;
+
+ /* Version Interface Types */
+
+enum {
+ JVMTI_VERSION_INTERFACE_JNI = 0x00000000,
+ JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000
+};
+
+ /* Version Masks */
+
+enum {
+ JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000,
+ JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000,
+ JVMTI_VERSION_MASK_MINOR = 0x0000FF00,
+ JVMTI_VERSION_MASK_MICRO = 0x000000FF
+};
+
+ /* Version Shifts */
+
+enum {
+ JVMTI_VERSION_SHIFT_MAJOR = 16,
+ JVMTI_VERSION_SHIFT_MINOR = 8,
+ JVMTI_VERSION_SHIFT_MICRO = 0
+};
+
+ /* Verbose Flag Enumeration */
+
+typedef enum {
+ JVMTI_VERBOSE_OTHER = 0,
+ JVMTI_VERBOSE_GC = 1,
+ JVMTI_VERBOSE_CLASS = 2,
+ JVMTI_VERBOSE_JNI = 4
+} jvmtiVerboseFlag;
+
+ /* JLocation Format Enumeration */
+
+typedef enum {
+ JVMTI_JLOCATION_JVMBCI = 1,
+ JVMTI_JLOCATION_MACHINEPC = 2,
+ JVMTI_JLOCATION_OTHER = 0
+} jvmtiJlocationFormat;
+
+ /* Resource Exhaustion Flags */
+
+enum {
+ JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001,
+ JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002,
+ JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004
+};
+
+ /* Errors */
+
+typedef enum {
+ JVMTI_ERROR_NONE = 0,
+ JVMTI_ERROR_INVALID_THREAD = 10,
+ JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
+ JVMTI_ERROR_INVALID_PRIORITY = 12,
+ JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
+ JVMTI_ERROR_THREAD_SUSPENDED = 14,
+ JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
+ JVMTI_ERROR_INVALID_OBJECT = 20,
+ JVMTI_ERROR_INVALID_CLASS = 21,
+ JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
+ JVMTI_ERROR_INVALID_METHODID = 23,
+ JVMTI_ERROR_INVALID_LOCATION = 24,
+ JVMTI_ERROR_INVALID_FIELDID = 25,
+ JVMTI_ERROR_NO_MORE_FRAMES = 31,
+ JVMTI_ERROR_OPAQUE_FRAME = 32,
+ JVMTI_ERROR_TYPE_MISMATCH = 34,
+ JVMTI_ERROR_INVALID_SLOT = 35,
+ JVMTI_ERROR_DUPLICATE = 40,
+ JVMTI_ERROR_NOT_FOUND = 41,
+ JVMTI_ERROR_INVALID_MONITOR = 50,
+ JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
+ JVMTI_ERROR_INTERRUPT = 52,
+ JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
+ JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
+ JVMTI_ERROR_FAILS_VERIFICATION = 62,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
+ JVMTI_ERROR_INVALID_TYPESTATE = 65,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
+ JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
+ JVMTI_ERROR_NAMES_DONT_MATCH = 69,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
+ JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
+ JVMTI_ERROR_NOT_AVAILABLE = 98,
+ JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
+ JVMTI_ERROR_NULL_POINTER = 100,
+ JVMTI_ERROR_ABSENT_INFORMATION = 101,
+ JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
+ JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
+ JVMTI_ERROR_NATIVE_METHOD = 104,
+ JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106,
+ JVMTI_ERROR_OUT_OF_MEMORY = 110,
+ JVMTI_ERROR_ACCESS_DENIED = 111,
+ JVMTI_ERROR_WRONG_PHASE = 112,
+ JVMTI_ERROR_INTERNAL = 113,
+ JVMTI_ERROR_UNATTACHED_THREAD = 115,
+ JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
+ JVMTI_ERROR_MAX = 116
+} jvmtiError;
+
+ /* Event IDs */
+
+typedef enum {
+ JVMTI_MIN_EVENT_TYPE_VAL = 50,
+ JVMTI_EVENT_VM_INIT = 50,
+ JVMTI_EVENT_VM_DEATH = 51,
+ JVMTI_EVENT_THREAD_START = 52,
+ JVMTI_EVENT_THREAD_END = 53,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
+ JVMTI_EVENT_CLASS_LOAD = 55,
+ JVMTI_EVENT_CLASS_PREPARE = 56,
+ JVMTI_EVENT_VM_START = 57,
+ JVMTI_EVENT_EXCEPTION = 58,
+ JVMTI_EVENT_EXCEPTION_CATCH = 59,
+ JVMTI_EVENT_SINGLE_STEP = 60,
+ JVMTI_EVENT_FRAME_POP = 61,
+ JVMTI_EVENT_BREAKPOINT = 62,
+ JVMTI_EVENT_FIELD_ACCESS = 63,
+ JVMTI_EVENT_FIELD_MODIFICATION = 64,
+ JVMTI_EVENT_METHOD_ENTRY = 65,
+ JVMTI_EVENT_METHOD_EXIT = 66,
+ JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
+ JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
+ JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
+ JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
+ JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
+ JVMTI_EVENT_MONITOR_WAIT = 73,
+ JVMTI_EVENT_MONITOR_WAITED = 74,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
+ JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
+ JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
+ JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
+ JVMTI_EVENT_OBJECT_FREE = 83,
+ JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
+ JVMTI_MAX_EVENT_TYPE_VAL = 84
+} jvmtiEvent;
+
+
+ /* Pre-Declarations */
+struct _jvmtiThreadInfo;
+typedef struct _jvmtiThreadInfo jvmtiThreadInfo;
+struct _jvmtiMonitorStackDepthInfo;
+typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo;
+struct _jvmtiThreadGroupInfo;
+typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo;
+struct _jvmtiFrameInfo;
+typedef struct _jvmtiFrameInfo jvmtiFrameInfo;
+struct _jvmtiStackInfo;
+typedef struct _jvmtiStackInfo jvmtiStackInfo;
+struct _jvmtiHeapReferenceInfoField;
+typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField;
+struct _jvmtiHeapReferenceInfoArray;
+typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray;
+struct _jvmtiHeapReferenceInfoConstantPool;
+typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool;
+struct _jvmtiHeapReferenceInfoStackLocal;
+typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal;
+struct _jvmtiHeapReferenceInfoJniLocal;
+typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal;
+struct _jvmtiHeapReferenceInfoReserved;
+typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved;
+union _jvmtiHeapReferenceInfo;
+typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo;
+struct _jvmtiHeapCallbacks;
+typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks;
+struct _jvmtiClassDefinition;
+typedef struct _jvmtiClassDefinition jvmtiClassDefinition;
+struct _jvmtiMonitorUsage;
+typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage;
+struct _jvmtiLineNumberEntry;
+typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry;
+struct _jvmtiLocalVariableEntry;
+typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry;
+struct _jvmtiParamInfo;
+typedef struct _jvmtiParamInfo jvmtiParamInfo;
+struct _jvmtiExtensionFunctionInfo;
+typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo;
+struct _jvmtiExtensionEventInfo;
+typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo;
+struct _jvmtiTimerInfo;
+typedef struct _jvmtiTimerInfo jvmtiTimerInfo;
+struct _jvmtiAddrLocationMap;
+typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
+
+ /* Function Types */
+
+typedef void (JNICALL *jvmtiStartFunction)
+ (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
+
+typedef jint (JNICALL *jvmtiHeapIterationCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiHeapReferenceCallback)
+ (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
+ (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
+
+typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
+
+typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);
+
+typedef jint (JNICALL *jvmtiReservedCallback)
+ ();
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
+ (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
+
+typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
+ (jvmtiEnv* jvmti_env, ...);
+
+typedef void (JNICALL *jvmtiExtensionEvent)
+ (jvmtiEnv* jvmti_env, ...);
+
+
+ /* Structure Types */
+struct _jvmtiThreadInfo {
+ char* name;
+ jint priority;
+ jboolean is_daemon;
+ jthreadGroup thread_group;
+ jobject context_class_loader;
+};
+struct _jvmtiMonitorStackDepthInfo {
+ jobject monitor;
+ jint stack_depth;
+};
+struct _jvmtiThreadGroupInfo {
+ jthreadGroup parent;
+ char* name;
+ jint max_priority;
+ jboolean is_daemon;
+};
+struct _jvmtiFrameInfo {
+ jmethodID method;
+ jlocation location;
+};
+struct _jvmtiStackInfo {
+ jthread thread;
+ jint state;
+ jvmtiFrameInfo* frame_buffer;
+ jint frame_count;
+};
+struct _jvmtiHeapReferenceInfoField {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoArray {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoConstantPool {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoStackLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+ jlocation location;
+ jint slot;
+};
+struct _jvmtiHeapReferenceInfoJniLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+};
+struct _jvmtiHeapReferenceInfoReserved {
+ jlong reserved1;
+ jlong reserved2;
+ jlong reserved3;
+ jlong reserved4;
+ jlong reserved5;
+ jlong reserved6;
+ jlong reserved7;
+ jlong reserved8;
+};
+union _jvmtiHeapReferenceInfo {
+ jvmtiHeapReferenceInfoField field;
+ jvmtiHeapReferenceInfoArray array;
+ jvmtiHeapReferenceInfoConstantPool constant_pool;
+ jvmtiHeapReferenceInfoStackLocal stack_local;
+ jvmtiHeapReferenceInfoJniLocal jni_local;
+ jvmtiHeapReferenceInfoReserved other;
+};
+struct _jvmtiHeapCallbacks {
+ jvmtiHeapIterationCallback heap_iteration_callback;
+ jvmtiHeapReferenceCallback heap_reference_callback;
+ jvmtiPrimitiveFieldCallback primitive_field_callback;
+ jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
+ jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
+ jvmtiReservedCallback reserved5;
+ jvmtiReservedCallback reserved6;
+ jvmtiReservedCallback reserved7;
+ jvmtiReservedCallback reserved8;
+ jvmtiReservedCallback reserved9;
+ jvmtiReservedCallback reserved10;
+ jvmtiReservedCallback reserved11;
+ jvmtiReservedCallback reserved12;
+ jvmtiReservedCallback reserved13;
+ jvmtiReservedCallback reserved14;
+ jvmtiReservedCallback reserved15;
+};
+struct _jvmtiClassDefinition {
+ jclass klass;
+ jint class_byte_count;
+ const unsigned char* class_bytes;
+};
+struct _jvmtiMonitorUsage {
+ jthread owner;
+ jint entry_count;
+ jint waiter_count;
+ jthread* waiters;
+ jint notify_waiter_count;
+ jthread* notify_waiters;
+};
+struct _jvmtiLineNumberEntry {
+ jlocation start_location;
+ jint line_number;
+};
+struct _jvmtiLocalVariableEntry {
+ jlocation start_location;
+ jint length;
+ char* name;
+ char* signature;
+ char* generic_signature;
+ jint slot;
+};
+struct _jvmtiParamInfo {
+ char* name;
+ jvmtiParamKind kind;
+ jvmtiParamTypes base_type;
+ jboolean null_ok;
+};
+struct _jvmtiExtensionFunctionInfo {
+ jvmtiExtensionFunction func;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+ jint error_count;
+ jvmtiError* errors;
+};
+struct _jvmtiExtensionEventInfo {
+ jint extension_event_index;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+};
+struct _jvmtiTimerInfo {
+ jlong max_value;
+ jboolean may_skip_forward;
+ jboolean may_skip_backward;
+ jvmtiTimerKind kind;
+ jlong reserved1;
+ jlong reserved2;
+};
+struct _jvmtiAddrLocationMap {
+ const void* start_address;
+ jlocation location;
+};
+
+typedef struct {
+ unsigned int can_tag_objects : 1;
+ unsigned int can_generate_field_modification_events : 1;
+ unsigned int can_generate_field_access_events : 1;
+ unsigned int can_get_bytecodes : 1;
+ unsigned int can_get_synthetic_attribute : 1;
+ unsigned int can_get_owned_monitor_info : 1;
+ unsigned int can_get_current_contended_monitor : 1;
+ unsigned int can_get_monitor_info : 1;
+ unsigned int can_pop_frame : 1;
+ unsigned int can_redefine_classes : 1;
+ unsigned int can_signal_thread : 1;
+ unsigned int can_get_source_file_name : 1;
+ unsigned int can_get_line_numbers : 1;
+ unsigned int can_get_source_debug_extension : 1;
+ unsigned int can_access_local_variables : 1;
+ unsigned int can_maintain_original_method_order : 1;
+ unsigned int can_generate_single_step_events : 1;
+ unsigned int can_generate_exception_events : 1;
+ unsigned int can_generate_frame_pop_events : 1;
+ unsigned int can_generate_breakpoint_events : 1;
+ unsigned int can_suspend : 1;
+ unsigned int can_redefine_any_class : 1;
+ unsigned int can_get_current_thread_cpu_time : 1;
+ unsigned int can_get_thread_cpu_time : 1;
+ unsigned int can_generate_method_entry_events : 1;
+ unsigned int can_generate_method_exit_events : 1;
+ unsigned int can_generate_all_class_hook_events : 1;
+ unsigned int can_generate_compiled_method_load_events : 1;
+ unsigned int can_generate_monitor_events : 1;
+ unsigned int can_generate_vm_object_alloc_events : 1;
+ unsigned int can_generate_native_method_bind_events : 1;
+ unsigned int can_generate_garbage_collection_events : 1;
+ unsigned int can_generate_object_free_events : 1;
+ unsigned int can_force_early_return : 1;
+ unsigned int can_get_owned_monitor_stack_depth_info : 1;
+ unsigned int can_get_constant_pool : 1;
+ unsigned int can_set_native_method_prefix : 1;
+ unsigned int can_retransform_classes : 1;
+ unsigned int can_retransform_any_class : 1;
+ unsigned int can_generate_resource_exhaustion_heap_events : 1;
+ unsigned int can_generate_resource_exhaustion_threads_events : 1;
+ unsigned int : 7;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+} jvmtiCapabilities;
+
+
+ /* Event Definitions */
+
+typedef void (JNICALL *jvmtiEventReserved)(void);
+
+
+typedef void (JNICALL *jvmtiEventBreakpoint)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventClassFileLoadHook)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jclass class_being_redefined,
+ jobject loader,
+ const char* name,
+ jobject protection_domain,
+ jint class_data_len,
+ const unsigned char* class_data,
+ jint* new_class_data_len,
+ unsigned char** new_class_data);
+
+typedef void (JNICALL *jvmtiEventClassLoad)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassPrepare)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ jint code_size,
+ const void* code_addr,
+ jint map_length,
+ const jvmtiAddrLocationMap* map,
+ const void* compile_info);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ const void* code_addr);
+
+typedef void (JNICALL *jvmtiEventDataDumpRequest)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
+ (jvmtiEnv *jvmti_env,
+ const char* name,
+ const void* address,
+ jint length);
+
+typedef void (JNICALL *jvmtiEventException)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception,
+ jmethodID catch_method,
+ jlocation catch_location);
+
+typedef void (JNICALL *jvmtiEventExceptionCatch)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception);
+
+typedef void (JNICALL *jvmtiEventFieldAccess)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field);
+
+typedef void (JNICALL *jvmtiEventFieldModification)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field,
+ char signature_type,
+ jvalue new_value);
+
+typedef void (JNICALL *jvmtiEventFramePop)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventMethodEntry)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method);
+
+typedef void (JNICALL *jvmtiEventMethodExit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception,
+ jvalue return_value);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorWait)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jlong timeout);
+
+typedef void (JNICALL *jvmtiEventMonitorWaited)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jboolean timed_out);
+
+typedef void (JNICALL *jvmtiEventNativeMethodBind)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ void* address,
+ void** new_address_ptr);
+
+typedef void (JNICALL *jvmtiEventObjectFree)
+ (jvmtiEnv *jvmti_env,
+ jlong tag);
+
+typedef void (JNICALL *jvmtiEventResourceExhausted)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jint flags,
+ const void* reserved,
+ const char* description);
+
+typedef void (JNICALL *jvmtiEventSingleStep)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventThreadEnd)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventThreadStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMDeath)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+typedef void (JNICALL *jvmtiEventVMInit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMObjectAlloc)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jclass object_klass,
+ jlong size);
+
+typedef void (JNICALL *jvmtiEventVMStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+ /* Event Callback Structure */
+
+typedef struct {
+ /* 50 : VM Initialization Event */
+ jvmtiEventVMInit VMInit;
+ /* 51 : VM Death Event */
+ jvmtiEventVMDeath VMDeath;
+ /* 52 : Thread Start */
+ jvmtiEventThreadStart ThreadStart;
+ /* 53 : Thread End */
+ jvmtiEventThreadEnd ThreadEnd;
+ /* 54 : Class File Load Hook */
+ jvmtiEventClassFileLoadHook ClassFileLoadHook;
+ /* 55 : Class Load */
+ jvmtiEventClassLoad ClassLoad;
+ /* 56 : Class Prepare */
+ jvmtiEventClassPrepare ClassPrepare;
+ /* 57 : VM Start Event */
+ jvmtiEventVMStart VMStart;
+ /* 58 : Exception */
+ jvmtiEventException Exception;
+ /* 59 : Exception Catch */
+ jvmtiEventExceptionCatch ExceptionCatch;
+ /* 60 : Single Step */
+ jvmtiEventSingleStep SingleStep;
+ /* 61 : Frame Pop */
+ jvmtiEventFramePop FramePop;
+ /* 62 : Breakpoint */
+ jvmtiEventBreakpoint Breakpoint;
+ /* 63 : Field Access */
+ jvmtiEventFieldAccess FieldAccess;
+ /* 64 : Field Modification */
+ jvmtiEventFieldModification FieldModification;
+ /* 65 : Method Entry */
+ jvmtiEventMethodEntry MethodEntry;
+ /* 66 : Method Exit */
+ jvmtiEventMethodExit MethodExit;
+ /* 67 : Native Method Bind */
+ jvmtiEventNativeMethodBind NativeMethodBind;
+ /* 68 : Compiled Method Load */
+ jvmtiEventCompiledMethodLoad CompiledMethodLoad;
+ /* 69 : Compiled Method Unload */
+ jvmtiEventCompiledMethodUnload CompiledMethodUnload;
+ /* 70 : Dynamic Code Generated */
+ jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
+ /* 71 : Data Dump Request */
+ jvmtiEventDataDumpRequest DataDumpRequest;
+ /* 72 */
+ jvmtiEventReserved reserved72;
+ /* 73 : Monitor Wait */
+ jvmtiEventMonitorWait MonitorWait;
+ /* 74 : Monitor Waited */
+ jvmtiEventMonitorWaited MonitorWaited;
+ /* 75 : Monitor Contended Enter */
+ jvmtiEventMonitorContendedEnter MonitorContendedEnter;
+ /* 76 : Monitor Contended Entered */
+ jvmtiEventMonitorContendedEntered MonitorContendedEntered;
+ /* 77 */
+ jvmtiEventReserved reserved77;
+ /* 78 */
+ jvmtiEventReserved reserved78;
+ /* 79 */
+ jvmtiEventReserved reserved79;
+ /* 80 : Resource Exhausted */
+ jvmtiEventResourceExhausted ResourceExhausted;
+ /* 81 : Garbage Collection Start */
+ jvmtiEventGarbageCollectionStart GarbageCollectionStart;
+ /* 82 : Garbage Collection Finish */
+ jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
+ /* 83 : Object Free */
+ jvmtiEventObjectFree ObjectFree;
+ /* 84 : VM Object Allocation */
+ jvmtiEventVMObjectAlloc VMObjectAlloc;
+} jvmtiEventCallbacks;
+
+
+ /* Function Interface */
+
+typedef struct jvmtiInterface_1_ {
+
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Set Event Notification Mode */
+ jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
+ jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...);
+
+ /* 3 : RESERVED */
+ void *reserved3;
+
+ /* 4 : Get All Threads */
+ jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
+ jint* threads_count_ptr,
+ jthread** threads_ptr);
+
+ /* 5 : Suspend Thread */
+ jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 6 : Resume Thread */
+ jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 7 : Stop Thread */
+ jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
+ jthread thread,
+ jobject exception);
+
+ /* 8 : Interrupt Thread */
+ jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 9 : Get Thread Info */
+ jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiThreadInfo* info_ptr);
+
+ /* 10 : Get Owned Monitor Info */
+ jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr);
+
+ /* 11 : Get Current Contended Monitor */
+ jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
+ jthread thread,
+ jobject* monitor_ptr);
+
+ /* 12 : Run Agent Thread */
+ jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority);
+
+ /* 13 : Get Top Thread Groups */
+ jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 14 : Get Thread Group Info */
+ jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
+ jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr);
+
+ /* 15 : Get Thread Group Children */
+ jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
+ jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 16 : Get Frame Count */
+ jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
+ jthread thread,
+ jint* count_ptr);
+
+ /* 17 : Get Thread State */
+ jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
+ jthread thread,
+ jint* thread_state_ptr);
+
+ /* 18 : Get Current Thread */
+ jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
+ jthread* thread_ptr);
+
+ /* 19 : Get Frame Location */
+ jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr);
+
+ /* 20 : Notify Frame Pop */
+ jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
+ jthread thread,
+ jint depth);
+
+ /* 21 : Get Local Variable - Object */
+ jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr);
+
+ /* 22 : Get Local Variable - Int */
+ jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr);
+
+ /* 23 : Get Local Variable - Long */
+ jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr);
+
+ /* 24 : Get Local Variable - Float */
+ jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr);
+
+ /* 25 : Get Local Variable - Double */
+ jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr);
+
+ /* 26 : Set Local Variable - Object */
+ jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject value);
+
+ /* 27 : Set Local Variable - Int */
+ jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint value);
+
+ /* 28 : Set Local Variable - Long */
+ jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong value);
+
+ /* 29 : Set Local Variable - Float */
+ jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value);
+
+ /* 30 : Set Local Variable - Double */
+ jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value);
+
+ /* 31 : Create Raw Monitor */
+ jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
+ const char* name,
+ jrawMonitorID* monitor_ptr);
+
+ /* 32 : Destroy Raw Monitor */
+ jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 33 : Raw Monitor Enter */
+ jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 34 : Raw Monitor Exit */
+ jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 35 : Raw Monitor Wait */
+ jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
+ jrawMonitorID monitor,
+ jlong millis);
+
+ /* 36 : Raw Monitor Notify */
+ jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 37 : Raw Monitor Notify All */
+ jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 38 : Set Breakpoint */
+ jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 39 : Clear Breakpoint */
+ jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 40 : RESERVED */
+ void *reserved40;
+
+ /* 41 : Set Field Access Watch */
+ jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 42 : Clear Field Access Watch */
+ jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 43 : Set Field Modification Watch */
+ jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 44 : Clear Field Modification Watch */
+ jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 45 : Is Modifiable Class */
+ jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_modifiable_class_ptr);
+
+ /* 46 : Allocate */
+ jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
+ jlong size,
+ unsigned char** mem_ptr);
+
+ /* 47 : Deallocate */
+ jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
+ unsigned char* mem);
+
+ /* 48 : Get Class Signature */
+ jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
+ jclass klass,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 49 : Get Class Status */
+ jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
+ jclass klass,
+ jint* status_ptr);
+
+ /* 50 : Get Source File Name */
+ jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
+ jclass klass,
+ char** source_name_ptr);
+
+ /* 51 : Get Class Modifiers */
+ jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jint* modifiers_ptr);
+
+ /* 52 : Get Class Methods */
+ jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
+ jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr);
+
+ /* 53 : Get Class Fields */
+ jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
+ jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr);
+
+ /* 54 : Get Implemented Interfaces */
+ jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
+ jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr);
+
+ /* 55 : Is Interface */
+ jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_interface_ptr);
+
+ /* 56 : Is Array Class */
+ jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_array_class_ptr);
+
+ /* 57 : Get Class Loader */
+ jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
+ jclass klass,
+ jobject* classloader_ptr);
+
+ /* 58 : Get Object Hash Code */
+ jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
+ jobject object,
+ jint* hash_code_ptr);
+
+ /* 59 : Get Object Monitor Usage */
+ jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
+ jobject object,
+ jvmtiMonitorUsage* info_ptr);
+
+ /* 60 : Get Field Name (and Signature) */
+ jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 61 : Get Field Declaring Class */
+ jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr);
+
+ /* 62 : Get Field Modifiers */
+ jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr);
+
+ /* 63 : Is Field Synthetic */
+ jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr);
+
+ /* 64 : Get Method Name (and Signature) */
+ jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
+ jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 65 : Get Method Declaring Class */
+ jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
+ jmethodID method,
+ jclass* declaring_class_ptr);
+
+ /* 66 : Get Method Modifiers */
+ jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
+ jmethodID method,
+ jint* modifiers_ptr);
+
+ /* 67 : RESERVED */
+ void *reserved67;
+
+ /* 68 : Get Max Locals */
+ jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
+ jmethodID method,
+ jint* max_ptr);
+
+ /* 69 : Get Arguments Size */
+ jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
+ jmethodID method,
+ jint* size_ptr);
+
+ /* 70 : Get Line Number Table */
+ jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr);
+
+ /* 71 : Get Method Location */
+ jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr);
+
+ /* 72 : Get Local Variable Table */
+ jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr);
+
+ /* 73 : Set Native Method Prefix */
+ jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
+ const char* prefix);
+
+ /* 74 : Set Native Method Prefixes */
+ jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
+ jint prefix_count,
+ char** prefixes);
+
+ /* 75 : Get Bytecodes */
+ jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
+ jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr);
+
+ /* 76 : Is Method Native */
+ jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_native_ptr);
+
+ /* 77 : Is Method Synthetic */
+ jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_synthetic_ptr);
+
+ /* 78 : Get Loaded Classes */
+ jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 79 : Get Classloader Classes */
+ jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
+ jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 80 : Pop Frame */
+ jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 81 : Force Early Return - Object */
+ jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
+ jthread thread,
+ jobject value);
+
+ /* 82 : Force Early Return - Int */
+ jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
+ jthread thread,
+ jint value);
+
+ /* 83 : Force Early Return - Long */
+ jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
+ jthread thread,
+ jlong value);
+
+ /* 84 : Force Early Return - Float */
+ jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
+ jthread thread,
+ jfloat value);
+
+ /* 85 : Force Early Return - Double */
+ jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
+ jthread thread,
+ jdouble value);
+
+ /* 86 : Force Early Return - Void */
+ jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 87 : Redefine Classes */
+ jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jvmtiClassDefinition* class_definitions);
+
+ /* 88 : Get Version Number */
+ jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
+ jint* version_ptr);
+
+ /* 89 : Get Capabilities */
+ jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 90 : Get Source Debug Extension */
+ jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
+ jclass klass,
+ char** source_debug_extension_ptr);
+
+ /* 91 : Is Method Obsolete */
+ jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_obsolete_ptr);
+
+ /* 92 : Suspend Thread List */
+ jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 93 : Resume Thread List */
+ jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 94 : RESERVED */
+ void *reserved94;
+
+ /* 95 : RESERVED */
+ void *reserved95;
+
+ /* 96 : RESERVED */
+ void *reserved96;
+
+ /* 97 : RESERVED */
+ void *reserved97;
+
+ /* 98 : RESERVED */
+ void *reserved98;
+
+ /* 99 : RESERVED */
+ void *reserved99;
+
+ /* 100 : Get All Stack Traces */
+ jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr);
+
+ /* 101 : Get Thread List Stack Traces */
+ jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
+ jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr);
+
+ /* 102 : Get Thread Local Storage */
+ jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ void** data_ptr);
+
+ /* 103 : Set Thread Local Storage */
+ jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ const void* data);
+
+ /* 104 : Get Stack Trace */
+ jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
+ jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr);
+
+ /* 105 : RESERVED */
+ void *reserved105;
+
+ /* 106 : Get Tag */
+ jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong* tag_ptr);
+
+ /* 107 : Set Tag */
+ jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong tag);
+
+ /* 108 : Force Garbage Collection */
+ jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
+
+ /* 109 : Iterate Over Objects Reachable From Object */
+ jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
+ jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data);
+
+ /* 110 : Iterate Over Reachable Objects */
+ jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
+ jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data);
+
+ /* 111 : Iterate Over Heap */
+ jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 112 : Iterate Over Instances Of Class */
+ jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
+ jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 113 : RESERVED */
+ void *reserved113;
+
+ /* 114 : Get Objects With Tags */
+ jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
+ jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr);
+
+ /* 115 : Follow References */
+ jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 116 : Iterate Through Heap */
+ jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 117 : RESERVED */
+ void *reserved117;
+
+ /* 118 : RESERVED */
+ void *reserved118;
+
+ /* 119 : RESERVED */
+ void *reserved119;
+
+ /* 120 : Set JNI Function Table */
+ jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
+ const jniNativeInterface* function_table);
+
+ /* 121 : Get JNI Function Table */
+ jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
+ jniNativeInterface** function_table);
+
+ /* 122 : Set Event Callbacks */
+ jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
+ const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks);
+
+ /* 123 : Generate Events */
+ jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
+ jvmtiEvent event_type);
+
+ /* 124 : Get Extension Functions */
+ jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions);
+
+ /* 125 : Get Extension Events */
+ jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions);
+
+ /* 126 : Set Extension Event Callback */
+ jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
+ jint extension_event_index,
+ jvmtiExtensionEvent callback);
+
+ /* 127 : Dispose Environment */
+ jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
+
+ /* 128 : Get Error Name */
+ jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
+ jvmtiError error,
+ char** name_ptr);
+
+ /* 129 : Get JLocation Format */
+ jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
+ jvmtiJlocationFormat* format_ptr);
+
+ /* 130 : Get System Properties */
+ jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
+ jint* count_ptr,
+ char*** property_ptr);
+
+ /* 131 : Get System Property */
+ jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ char** value_ptr);
+
+ /* 132 : Set System Property */
+ jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ const char* value);
+
+ /* 133 : Get Phase */
+ jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
+ jvmtiPhase* phase_ptr);
+
+ /* 134 : Get Current Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 135 : Get Current Thread CPU Time */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 136 : Get Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 137 : Get Thread CPU Time */
+ jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
+ jthread thread,
+ jlong* nanos_ptr);
+
+ /* 138 : Get Timer Information */
+ jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 139 : Get Time */
+ jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 140 : Get Potential Capabilities */
+ jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 141 : RESERVED */
+ void *reserved141;
+
+ /* 142 : Add Capabilities */
+ jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 143 : Relinquish Capabilities */
+ jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 144 : Get Available Processors */
+ jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
+ jint* processor_count_ptr);
+
+ /* 145 : Get Class Version Numbers */
+ jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
+ jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr);
+
+ /* 146 : Get Constant Pool */
+ jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
+ jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr);
+
+ /* 147 : Get Environment Local Storage */
+ jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
+ void** data_ptr);
+
+ /* 148 : Set Environment Local Storage */
+ jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
+ const void* data);
+
+ /* 149 : Add To Bootstrap Class Loader Search */
+ jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 150 : Set Verbose Flag */
+ jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
+ jvmtiVerboseFlag flag,
+ jboolean value);
+
+ /* 151 : Add To System Class Loader Search */
+ jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 152 : Retransform Classes */
+ jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jclass* classes);
+
+ /* 153 : Get Owned Monitor Stack Depth Info */
+ jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr);
+
+ /* 154 : Get Object Size */
+ jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
+ jobject object,
+ jlong* size_ptr);
+
+ /* 155 : Get Local Instance */
+ jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jobject* value_ptr);
+
+} jvmtiInterface_1;
+
+struct _jvmtiEnv {
+ const struct jvmtiInterface_1_ *functions;
+#ifdef __cplusplus
+
+
+ jvmtiError Allocate(jlong size,
+ unsigned char** mem_ptr) {
+ return functions->Allocate(this, size, mem_ptr);
+ }
+
+ jvmtiError Deallocate(unsigned char* mem) {
+ return functions->Deallocate(this, mem);
+ }
+
+ jvmtiError GetThreadState(jthread thread,
+ jint* thread_state_ptr) {
+ return functions->GetThreadState(this, thread, thread_state_ptr);
+ }
+
+ jvmtiError GetCurrentThread(jthread* thread_ptr) {
+ return functions->GetCurrentThread(this, thread_ptr);
+ }
+
+ jvmtiError GetAllThreads(jint* threads_count_ptr,
+ jthread** threads_ptr) {
+ return functions->GetAllThreads(this, threads_count_ptr, threads_ptr);
+ }
+
+ jvmtiError SuspendThread(jthread thread) {
+ return functions->SuspendThread(this, thread);
+ }
+
+ jvmtiError SuspendThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->SuspendThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError ResumeThread(jthread thread) {
+ return functions->ResumeThread(this, thread);
+ }
+
+ jvmtiError ResumeThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->ResumeThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError StopThread(jthread thread,
+ jobject exception) {
+ return functions->StopThread(this, thread, exception);
+ }
+
+ jvmtiError InterruptThread(jthread thread) {
+ return functions->InterruptThread(this, thread);
+ }
+
+ jvmtiError GetThreadInfo(jthread thread,
+ jvmtiThreadInfo* info_ptr) {
+ return functions->GetThreadInfo(this, thread, info_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorInfo(jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr) {
+ return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
+ return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr);
+ }
+
+ jvmtiError GetCurrentContendedMonitor(jthread thread,
+ jobject* monitor_ptr) {
+ return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr);
+ }
+
+ jvmtiError RunAgentThread(jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority) {
+ return functions->RunAgentThread(this, thread, proc, arg, priority);
+ }
+
+ jvmtiError SetThreadLocalStorage(jthread thread,
+ const void* data) {
+ return functions->SetThreadLocalStorage(this, thread, data);
+ }
+
+ jvmtiError GetThreadLocalStorage(jthread thread,
+ void** data_ptr) {
+ return functions->GetThreadLocalStorage(this, thread, data_ptr);
+ }
+
+ jvmtiError GetTopThreadGroups(jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetThreadGroupInfo(jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr) {
+ return functions->GetThreadGroupInfo(this, group, info_ptr);
+ }
+
+ jvmtiError GetThreadGroupChildren(jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetStackTrace(jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr) {
+ return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr);
+ }
+
+ jvmtiError GetAllStackTraces(jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr) {
+ return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr);
+ }
+
+ jvmtiError GetThreadListStackTraces(jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr) {
+ return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr);
+ }
+
+ jvmtiError GetFrameCount(jthread thread,
+ jint* count_ptr) {
+ return functions->GetFrameCount(this, thread, count_ptr);
+ }
+
+ jvmtiError PopFrame(jthread thread) {
+ return functions->PopFrame(this, thread);
+ }
+
+ jvmtiError GetFrameLocation(jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr) {
+ return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr);
+ }
+
+ jvmtiError NotifyFramePop(jthread thread,
+ jint depth) {
+ return functions->NotifyFramePop(this, thread, depth);
+ }
+
+ jvmtiError ForceEarlyReturnObject(jthread thread,
+ jobject value) {
+ return functions->ForceEarlyReturnObject(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnInt(jthread thread,
+ jint value) {
+ return functions->ForceEarlyReturnInt(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnLong(jthread thread,
+ jlong value) {
+ return functions->ForceEarlyReturnLong(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnFloat(jthread thread,
+ jfloat value) {
+ return functions->ForceEarlyReturnFloat(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnDouble(jthread thread,
+ jdouble value) {
+ return functions->ForceEarlyReturnDouble(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnVoid(jthread thread) {
+ return functions->ForceEarlyReturnVoid(this, thread);
+ }
+
+ jvmtiError FollowReferences(jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data);
+ }
+
+ jvmtiError IterateThroughHeap(jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data);
+ }
+
+ jvmtiError GetTag(jobject object,
+ jlong* tag_ptr) {
+ return functions->GetTag(this, object, tag_ptr);
+ }
+
+ jvmtiError SetTag(jobject object,
+ jlong tag) {
+ return functions->SetTag(this, object, tag);
+ }
+
+ jvmtiError GetObjectsWithTags(jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr) {
+ return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr);
+ }
+
+ jvmtiError ForceGarbageCollection() {
+ return functions->ForceGarbageCollection(this);
+ }
+
+ jvmtiError IterateOverObjectsReachableFromObject(jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data) {
+ return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data);
+ }
+
+ jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data) {
+ return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
+ }
+
+ jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError IterateOverInstancesOfClass(jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError GetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr) {
+ return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalInstance(jthread thread,
+ jint depth,
+ jobject* value_ptr) {
+ return functions->GetLocalInstance(this, thread, depth, value_ptr);
+ }
+
+ jvmtiError GetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr) {
+ return functions->GetLocalInt(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr) {
+ return functions->GetLocalLong(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr) {
+ return functions->GetLocalFloat(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr) {
+ return functions->GetLocalDouble(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError SetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject value) {
+ return functions->SetLocalObject(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint value) {
+ return functions->SetLocalInt(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong value) {
+ return functions->SetLocalLong(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value) {
+ return functions->SetLocalFloat(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value) {
+ return functions->SetLocalDouble(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->SetBreakpoint(this, method, location);
+ }
+
+ jvmtiError ClearBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->ClearBreakpoint(this, method, location);
+ }
+
+ jvmtiError SetFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError SetFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError GetLoadedClasses(jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassLoaderClasses(jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassSignature(jclass klass,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetClassStatus(jclass klass,
+ jint* status_ptr) {
+ return functions->GetClassStatus(this, klass, status_ptr);
+ }
+
+ jvmtiError GetSourceFileName(jclass klass,
+ char** source_name_ptr) {
+ return functions->GetSourceFileName(this, klass, source_name_ptr);
+ }
+
+ jvmtiError GetClassModifiers(jclass klass,
+ jint* modifiers_ptr) {
+ return functions->GetClassModifiers(this, klass, modifiers_ptr);
+ }
+
+ jvmtiError GetClassMethods(jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr) {
+ return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr);
+ }
+
+ jvmtiError GetClassFields(jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr) {
+ return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr);
+ }
+
+ jvmtiError GetImplementedInterfaces(jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr) {
+ return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr);
+ }
+
+ jvmtiError GetClassVersionNumbers(jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr) {
+ return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr);
+ }
+
+ jvmtiError GetConstantPool(jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr) {
+ return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr);
+ }
+
+ jvmtiError IsInterface(jclass klass,
+ jboolean* is_interface_ptr) {
+ return functions->IsInterface(this, klass, is_interface_ptr);
+ }
+
+ jvmtiError IsArrayClass(jclass klass,
+ jboolean* is_array_class_ptr) {
+ return functions->IsArrayClass(this, klass, is_array_class_ptr);
+ }
+
+ jvmtiError IsModifiableClass(jclass klass,
+ jboolean* is_modifiable_class_ptr) {
+ return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr);
+ }
+
+ jvmtiError GetClassLoader(jclass klass,
+ jobject* classloader_ptr) {
+ return functions->GetClassLoader(this, klass, classloader_ptr);
+ }
+
+ jvmtiError GetSourceDebugExtension(jclass klass,
+ char** source_debug_extension_ptr) {
+ return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr);
+ }
+
+ jvmtiError RetransformClasses(jint class_count,
+ const jclass* classes) {
+ return functions->RetransformClasses(this, class_count, classes);
+ }
+
+ jvmtiError RedefineClasses(jint class_count,
+ const jvmtiClassDefinition* class_definitions) {
+ return functions->RedefineClasses(this, class_count, class_definitions);
+ }
+
+ jvmtiError GetObjectSize(jobject object,
+ jlong* size_ptr) {
+ return functions->GetObjectSize(this, object, size_ptr);
+ }
+
+ jvmtiError GetObjectHashCode(jobject object,
+ jint* hash_code_ptr) {
+ return functions->GetObjectHashCode(this, object, hash_code_ptr);
+ }
+
+ jvmtiError GetObjectMonitorUsage(jobject object,
+ jvmtiMonitorUsage* info_ptr) {
+ return functions->GetObjectMonitorUsage(this, object, info_ptr);
+ }
+
+ jvmtiError GetFieldName(jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetFieldDeclaringClass(jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr) {
+ return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr);
+ }
+
+ jvmtiError GetFieldModifiers(jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr) {
+ return functions->GetFieldModifiers(this, klass, field, modifiers_ptr);
+ }
+
+ jvmtiError IsFieldSynthetic(jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr);
+ }
+
+ jvmtiError GetMethodName(jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetMethodDeclaringClass(jmethodID method,
+ jclass* declaring_class_ptr) {
+ return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr);
+ }
+
+ jvmtiError GetMethodModifiers(jmethodID method,
+ jint* modifiers_ptr) {
+ return functions->GetMethodModifiers(this, method, modifiers_ptr);
+ }
+
+ jvmtiError GetMaxLocals(jmethodID method,
+ jint* max_ptr) {
+ return functions->GetMaxLocals(this, method, max_ptr);
+ }
+
+ jvmtiError GetArgumentsSize(jmethodID method,
+ jint* size_ptr) {
+ return functions->GetArgumentsSize(this, method, size_ptr);
+ }
+
+ jvmtiError GetLineNumberTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr) {
+ return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetMethodLocation(jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr) {
+ return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr);
+ }
+
+ jvmtiError GetLocalVariableTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr) {
+ return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetBytecodes(jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr) {
+ return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr);
+ }
+
+ jvmtiError IsMethodNative(jmethodID method,
+ jboolean* is_native_ptr) {
+ return functions->IsMethodNative(this, method, is_native_ptr);
+ }
+
+ jvmtiError IsMethodSynthetic(jmethodID method,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsMethodSynthetic(this, method, is_synthetic_ptr);
+ }
+
+ jvmtiError IsMethodObsolete(jmethodID method,
+ jboolean* is_obsolete_ptr) {
+ return functions->IsMethodObsolete(this, method, is_obsolete_ptr);
+ }
+
+ jvmtiError SetNativeMethodPrefix(const char* prefix) {
+ return functions->SetNativeMethodPrefix(this, prefix);
+ }
+
+ jvmtiError SetNativeMethodPrefixes(jint prefix_count,
+ char** prefixes) {
+ return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes);
+ }
+
+ jvmtiError CreateRawMonitor(const char* name,
+ jrawMonitorID* monitor_ptr) {
+ return functions->CreateRawMonitor(this, name, monitor_ptr);
+ }
+
+ jvmtiError DestroyRawMonitor(jrawMonitorID monitor) {
+ return functions->DestroyRawMonitor(this, monitor);
+ }
+
+ jvmtiError RawMonitorEnter(jrawMonitorID monitor) {
+ return functions->RawMonitorEnter(this, monitor);
+ }
+
+ jvmtiError RawMonitorExit(jrawMonitorID monitor) {
+ return functions->RawMonitorExit(this, monitor);
+ }
+
+ jvmtiError RawMonitorWait(jrawMonitorID monitor,
+ jlong millis) {
+ return functions->RawMonitorWait(this, monitor, millis);
+ }
+
+ jvmtiError RawMonitorNotify(jrawMonitorID monitor) {
+ return functions->RawMonitorNotify(this, monitor);
+ }
+
+ jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) {
+ return functions->RawMonitorNotifyAll(this, monitor);
+ }
+
+ jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) {
+ return functions->SetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) {
+ return functions->GetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks) {
+ return functions->SetEventCallbacks(this, callbacks, size_of_callbacks);
+ }
+
+ jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...) {
+ return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
+ }
+
+ jvmtiError GenerateEvents(jvmtiEvent event_type) {
+ return functions->GenerateEvents(this, event_type);
+ }
+
+ jvmtiError GetExtensionFunctions(jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions) {
+ return functions->GetExtensionFunctions(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError GetExtensionEvents(jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions) {
+ return functions->GetExtensionEvents(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError SetExtensionEventCallback(jint extension_event_index,
+ jvmtiExtensionEvent callback) {
+ return functions->SetExtensionEventCallback(this, extension_event_index, callback);
+ }
+
+ jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetPotentialCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->AddCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->RelinquishCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) {
+ return functions->GetCurrentThreadCpuTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetThreadCpuTime(jthread thread,
+ jlong* nanos_ptr) {
+ return functions->GetThreadCpuTime(this, thread, nanos_ptr);
+ }
+
+ jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetTime(jlong* nanos_ptr) {
+ return functions->GetTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetAvailableProcessors(jint* processor_count_ptr) {
+ return functions->GetAvailableProcessors(this, processor_count_ptr);
+ }
+
+ jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) {
+ return functions->AddToBootstrapClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError AddToSystemClassLoaderSearch(const char* segment) {
+ return functions->AddToSystemClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError GetSystemProperties(jint* count_ptr,
+ char*** property_ptr) {
+ return functions->GetSystemProperties(this, count_ptr, property_ptr);
+ }
+
+ jvmtiError GetSystemProperty(const char* property,
+ char** value_ptr) {
+ return functions->GetSystemProperty(this, property, value_ptr);
+ }
+
+ jvmtiError SetSystemProperty(const char* property,
+ const char* value) {
+ return functions->SetSystemProperty(this, property, value);
+ }
+
+ jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
+ return functions->GetPhase(this, phase_ptr);
+ }
+
+ jvmtiError DisposeEnvironment() {
+ return functions->DisposeEnvironment(this);
+ }
+
+ jvmtiError SetEnvironmentLocalStorage(const void* data) {
+ return functions->SetEnvironmentLocalStorage(this, data);
+ }
+
+ jvmtiError GetEnvironmentLocalStorage(void** data_ptr) {
+ return functions->GetEnvironmentLocalStorage(this, data_ptr);
+ }
+
+ jvmtiError GetVersionNumber(jint* version_ptr) {
+ return functions->GetVersionNumber(this, version_ptr);
+ }
+
+ jvmtiError GetErrorName(jvmtiError error,
+ char** name_ptr) {
+ return functions->GetErrorName(this, error, name_ptr);
+ }
+
+ jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag,
+ jboolean value) {
+ return functions->SetVerboseFlag(this, flag, value);
+ }
+
+ jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
+ return functions->GetJLocationFormat(this, format_ptr);
+ }
+
+#endif /* __cplusplus */
+};
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVA_JVMTI_H_ */
+
diff --git a/source/client/jni/windows/jvmticmlr.h b/source/client/jni/windows/jvmticmlr.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a0591dd00378697295e412432010d963f47e7d3
--- /dev/null
+++ b/source/client/jni/windows/jvmticmlr.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * This header file defines the data structures sent by the VM
+ * through the JVMTI CompiledMethodLoad callback function via the
+ * "void * compile_info" parameter. The memory pointed to by the
+ * compile_info parameter may not be referenced after returning from
+ * the CompiledMethodLoad callback. These are VM implementation
+ * specific data structures that may evolve in future releases. A
+ * JVMTI agent should interpret a non-NULL compile_info as a pointer
+ * to a region of memory containing a list of records. In a typical
+ * usage scenario, a JVMTI agent would cast each record to a
+ * jvmtiCompiledMethodLoadRecordHeader, a struct that represents
+ * arbitrary information. This struct contains a kind field to indicate
+ * the kind of information being passed, and a pointer to the next
+ * record. If the kind field indicates inlining information, then the
+ * agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord.
+ * This record contains an array of PCStackInfo structs, which indicate
+ * for every pc address what are the methods on the invocation stack.
+ * The "methods" and "bcis" fields in each PCStackInfo struct specify a
+ * 1-1 mapping between these inlined methods and their bytecode indices.
+ * This can be used to derive the proper source lines of the inlined
+ * methods.
+ */
+
+#ifndef _JVMTI_CMLR_H_
+#define _JVMTI_CMLR_H_
+
+enum {
+ JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001,
+ JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000,
+
+ JVMTI_CMLR_MAJOR_VERSION = 0x00000001,
+ JVMTI_CMLR_MINOR_VERSION = 0x00000000
+
+ /*
+ * This comment is for the "JDK import from HotSpot" sanity check:
+ * version: 1.0.0
+ */
+};
+
+typedef enum {
+ JVMTI_CMLR_DUMMY = 1,
+ JVMTI_CMLR_INLINE_INFO = 2
+} jvmtiCMLRKind;
+
+/*
+ * Record that represents arbitrary information passed through JVMTI
+ * CompiledMethodLoadEvent void pointer.
+ */
+typedef struct _jvmtiCompiledMethodLoadRecordHeader {
+ jvmtiCMLRKind kind; /* id for the kind of info passed in the record */
+ jint majorinfoversion; /* major and minor info version values. Init'ed */
+ jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */
+
+ struct _jvmtiCompiledMethodLoadRecordHeader* next;
+} jvmtiCompiledMethodLoadRecordHeader;
+
+/*
+ * Record that gives information about the methods on the compile-time
+ * stack at a specific pc address of a compiled method. Each element in
+ * the methods array maps to same element in the bcis array.
+ */
+typedef struct _PCStackInfo {
+ void* pc; /* the pc address for this compiled method */
+ jint numstackframes; /* number of methods on the stack */
+ jmethodID* methods; /* array of numstackframes method ids */
+ jint* bcis; /* array of numstackframes bytecode indices */
+} PCStackInfo;
+
+/*
+ * Record that contains inlining information for each pc address of
+ * an nmethod.
+ */
+typedef struct _jvmtiCompiledMethodLoadInlineRecord {
+ jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
+ jint numpcs; /* number of pc descriptors in this nmethod */
+ PCStackInfo* pcinfo; /* array of numpcs pc descriptors */
+} jvmtiCompiledMethodLoadInlineRecord;
+
+/*
+ * Dummy record used to test that we can pass records with different
+ * information through the void pointer provided that they can be cast
+ * to a jvmtiCompiledMethodLoadRecordHeader.
+ */
+
+typedef struct _jvmtiCompiledMethodLoadDummyRecord {
+ jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
+ char message[50];
+} jvmtiCompiledMethodLoadDummyRecord;
+
+#endif
diff --git a/source/client/jni/windows/win32/bridge/AccessBridgeCallbacks.h b/source/client/jni/windows/win32/bridge/AccessBridgeCallbacks.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d55b3f497310ae104452574a9e0837a1977dc87
--- /dev/null
+++ b/source/client/jni/windows/win32/bridge/AccessBridgeCallbacks.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * AccessBridgeCallbacks.h 1.17 05/03/21
+ */
+
+/*
+ * Header file defining callback typedefs for Windows routines
+ * which are called from Java (responding to events, etc.).
+ */
+
+#ifndef __AccessBridgeCallbacks_H__
+#define __AccessBridgeCallbacks_H__
+
+#include
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*AccessBridge_PropertyChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *property, wchar_t *oldValue, wchar_t *newValue);
+
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+
+typedef void (*AccessBridge_FocusGainedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_FocusLostFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_CaretUpdateFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MouseClickedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseEnteredFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseExitedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MousePressedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseReleasedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuDeselectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuSelectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeInvisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeVisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_PropertyNameChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldName, wchar_t *newName);
+typedef void (*AccessBridge_PropertyDescriptionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldDescription, wchar_t *newDescription);
+typedef void (*AccessBridge_PropertyStateChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldState, wchar_t *newState);
+typedef void (*AccessBridge_PropertyValueChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldValue, wchar_t *newValue);
+typedef void (*AccessBridge_PropertySelectionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyTextChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyCaretChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ int oldPosition, int newPosition);
+typedef void (*AccessBridge_PropertyVisibleDataChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyChildChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ JOBJECT64 oldChild, JOBJECT64 newChild);
+typedef void (*AccessBridge_PropertyActiveDescendentChangeFP) (long vmID, JOBJECT64 event,
+ JOBJECT64 source,
+ JOBJECT64 oldActiveDescendent,
+ JOBJECT64 newActiveDescendent);
+
+typedef void (*AccessBridge_PropertyTableModelChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 src,
+ wchar_t *oldValue, wchar_t *newValue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/client/jni/windows/win32/bridge/AccessBridgeCalls.c b/source/client/jni/windows/win32/bridge/AccessBridgeCalls.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ed699f34faca966aebaa5841f313b5a3262d2d7
--- /dev/null
+++ b/source/client/jni/windows/win32/bridge/AccessBridgeCalls.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * @(#)AccessBridgeCalls.c 1.25 05/08/22
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+
+#include
+#include
+
+
+//#define ACCESSBRIDGE_32
+//#define ACCESSBRIDGE_64
+
+#include "AccessBridgeCalls.h"
+#include "AccessBridgeDebug.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ HINSTANCE theAccessBridgeInstance;
+ AccessBridgeFPs theAccessBridge;
+
+ BOOL theAccessBridgeInitializedFlag = FALSE;
+
+#define LOAD_FP(result, type, name) \
+ PrintDebugString("LOAD_FP loading: %s ...", name); \
+ if ((theAccessBridge.result = \
+ (type) GetProcAddress(theAccessBridgeInstance, name)) == (type) 0) { \
+ PrintDebugString("LOAD_FP failed: %s", name); \
+ return FALSE; \
+ }
+
+ BOOL initializeAccessBridge() {
+
+#ifdef ACCESSBRIDGE_ARCH_32 // For 32bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-32");
+#else
+#ifdef ACCESSBRIDGE_ARCH_64 // For 64bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-64");
+#else // legacy
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE");
+#endif
+#endif
+ if (theAccessBridgeInstance != 0) {
+ LOAD_FP(Windows_run, Windows_runFP, "Windows_run");
+
+ LOAD_FP(SetJavaShutdown, SetJavaShutdownFP, "setJavaShutdownFP");
+ LOAD_FP(SetFocusGained, SetFocusGainedFP, "setFocusGainedFP");
+ LOAD_FP(SetFocusLost, SetFocusLostFP, "setFocusLostFP");
+
+ LOAD_FP(SetCaretUpdate, SetCaretUpdateFP, "setCaretUpdateFP");
+
+ LOAD_FP(SetMouseClicked, SetMouseClickedFP, "setMouseClickedFP");
+ LOAD_FP(SetMouseEntered, SetMouseEnteredFP, "setMouseEnteredFP");
+ LOAD_FP(SetMouseExited, SetMouseExitedFP, "setMouseExitedFP");
+ LOAD_FP(SetMousePressed, SetMousePressedFP, "setMousePressedFP");
+ LOAD_FP(SetMouseReleased, SetMouseReleasedFP, "setMouseReleasedFP");
+
+ LOAD_FP(SetMenuCanceled, SetMenuCanceledFP, "setMenuCanceledFP");
+ LOAD_FP(SetMenuDeselected, SetMenuDeselectedFP, "setMenuDeselectedFP");
+ LOAD_FP(SetMenuSelected, SetMenuSelectedFP, "setMenuSelectedFP");
+ LOAD_FP(SetPopupMenuCanceled, SetPopupMenuCanceledFP, "setPopupMenuCanceledFP");
+ LOAD_FP(SetPopupMenuWillBecomeInvisible, SetPopupMenuWillBecomeInvisibleFP, "setPopupMenuWillBecomeInvisibleFP");
+ LOAD_FP(SetPopupMenuWillBecomeVisible, SetPopupMenuWillBecomeVisibleFP, "setPopupMenuWillBecomeVisibleFP");
+
+ LOAD_FP(SetPropertyNameChange, SetPropertyNameChangeFP, "setPropertyNameChangeFP");
+ LOAD_FP(SetPropertyDescriptionChange, SetPropertyDescriptionChangeFP, "setPropertyDescriptionChangeFP");
+ LOAD_FP(SetPropertyStateChange, SetPropertyStateChangeFP, "setPropertyStateChangeFP");
+ LOAD_FP(SetPropertyValueChange, SetPropertyValueChangeFP, "setPropertyValueChangeFP");
+ LOAD_FP(SetPropertySelectionChange, SetPropertySelectionChangeFP, "setPropertySelectionChangeFP");
+ LOAD_FP(SetPropertyTextChange, SetPropertyTextChangeFP, "setPropertyTextChangeFP");
+ LOAD_FP(SetPropertyCaretChange, SetPropertyCaretChangeFP, "setPropertyCaretChangeFP");
+ LOAD_FP(SetPropertyVisibleDataChange, SetPropertyVisibleDataChangeFP, "setPropertyVisibleDataChangeFP");
+ LOAD_FP(SetPropertyChildChange, SetPropertyChildChangeFP, "setPropertyChildChangeFP");
+ LOAD_FP(SetPropertyActiveDescendentChange, SetPropertyActiveDescendentChangeFP, "setPropertyActiveDescendentChangeFP");
+
+ LOAD_FP(SetPropertyTableModelChange, SetPropertyTableModelChangeFP, "setPropertyTableModelChangeFP");
+
+ LOAD_FP(ReleaseJavaObject, ReleaseJavaObjectFP, "releaseJavaObject");
+ LOAD_FP(GetVersionInfo, GetVersionInfoFP, "getVersionInfo");
+
+ LOAD_FP(IsJavaWindow, IsJavaWindowFP, "isJavaWindow");
+ LOAD_FP(IsSameObject, IsSameObjectFP, "isSameObject");
+ LOAD_FP(GetAccessibleContextFromHWND, GetAccessibleContextFromHWNDFP, "getAccessibleContextFromHWND");
+ LOAD_FP(getHWNDFromAccessibleContext, getHWNDFromAccessibleContextFP, "getHWNDFromAccessibleContext");
+
+ LOAD_FP(GetAccessibleContextAt, GetAccessibleContextAtFP, "getAccessibleContextAt");
+ LOAD_FP(GetAccessibleContextWithFocus, GetAccessibleContextWithFocusFP, "getAccessibleContextWithFocus");
+ LOAD_FP(GetAccessibleContextInfo, GetAccessibleContextInfoFP, "getAccessibleContextInfo");
+ LOAD_FP(GetAccessibleChildFromContext, GetAccessibleChildFromContextFP, "getAccessibleChildFromContext");
+ LOAD_FP(GetAccessibleParentFromContext, GetAccessibleParentFromContextFP, "getAccessibleParentFromContext");
+
+ /* begin AccessibleTable */
+ LOAD_FP(getAccessibleTableInfo, getAccessibleTableInfoFP, "getAccessibleTableInfo");
+ LOAD_FP(getAccessibleTableCellInfo, getAccessibleTableCellInfoFP, "getAccessibleTableCellInfo");
+
+ LOAD_FP(getAccessibleTableRowHeader, getAccessibleTableRowHeaderFP, "getAccessibleTableRowHeader");
+ LOAD_FP(getAccessibleTableColumnHeader, getAccessibleTableColumnHeaderFP, "getAccessibleTableColumnHeader");
+
+ LOAD_FP(getAccessibleTableRowDescription, getAccessibleTableRowDescriptionFP, "getAccessibleTableRowDescription");
+ LOAD_FP(getAccessibleTableColumnDescription, getAccessibleTableColumnDescriptionFP, "getAccessibleTableColumnDescription");
+
+ LOAD_FP(getAccessibleTableRowSelectionCount, getAccessibleTableRowSelectionCountFP,
+ "getAccessibleTableRowSelectionCount");
+ LOAD_FP(isAccessibleTableRowSelected, isAccessibleTableRowSelectedFP,
+ "isAccessibleTableRowSelected");
+ LOAD_FP(getAccessibleTableRowSelections, getAccessibleTableRowSelectionsFP,
+ "getAccessibleTableRowSelections");
+
+ LOAD_FP(getAccessibleTableColumnSelectionCount, getAccessibleTableColumnSelectionCountFP,
+ "getAccessibleTableColumnSelectionCount");
+ LOAD_FP(isAccessibleTableColumnSelected, isAccessibleTableColumnSelectedFP,
+ "isAccessibleTableColumnSelected");
+ LOAD_FP(getAccessibleTableColumnSelections, getAccessibleTableColumnSelectionsFP,
+ "getAccessibleTableColumnSelections");
+
+ LOAD_FP(getAccessibleTableRow, getAccessibleTableRowFP,
+ "getAccessibleTableRow");
+ LOAD_FP(getAccessibleTableColumn, getAccessibleTableColumnFP,
+ "getAccessibleTableColumn");
+ LOAD_FP(getAccessibleTableIndex, getAccessibleTableIndexFP,
+ "getAccessibleTableIndex");
+
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ LOAD_FP(getAccessibleRelationSet, getAccessibleRelationSetFP, "getAccessibleRelationSet");
+
+ /* AccessibleHypertext */
+ LOAD_FP(getAccessibleHypertext, getAccessibleHypertextFP, "getAccessibleHypertext");
+ LOAD_FP(activateAccessibleHyperlink, activateAccessibleHyperlinkFP, "activateAccessibleHyperlink");
+ LOAD_FP(getAccessibleHyperlinkCount, getAccessibleHyperlinkCountFP, "getAccessibleHyperlinkCount");
+ LOAD_FP(getAccessibleHypertextExt, getAccessibleHypertextExtFP, "getAccessibleHypertextExt");
+ LOAD_FP(getAccessibleHypertextLinkIndex, getAccessibleHypertextLinkIndexFP, "getAccessibleHypertextLinkIndex");
+ LOAD_FP(getAccessibleHyperlink, getAccessibleHyperlinkFP, "getAccessibleHyperlink");
+
+ /* Accessible KeyBinding, Icon and Action */
+ LOAD_FP(getAccessibleKeyBindings, getAccessibleKeyBindingsFP, "getAccessibleKeyBindings");
+ LOAD_FP(getAccessibleIcons, getAccessibleIconsFP, "getAccessibleIcons");
+ LOAD_FP(getAccessibleActions, getAccessibleActionsFP, "getAccessibleActions");
+ LOAD_FP(doAccessibleActions, doAccessibleActionsFP, "doAccessibleActions");
+
+ /* AccessibleText */
+ LOAD_FP(GetAccessibleTextInfo, GetAccessibleTextInfoFP, "getAccessibleTextInfo");
+ LOAD_FP(GetAccessibleTextItems, GetAccessibleTextItemsFP, "getAccessibleTextItems");
+ LOAD_FP(GetAccessibleTextSelectionInfo, GetAccessibleTextSelectionInfoFP, "getAccessibleTextSelectionInfo");
+ LOAD_FP(GetAccessibleTextAttributes, GetAccessibleTextAttributesFP, "getAccessibleTextAttributes");
+ LOAD_FP(GetAccessibleTextRect, GetAccessibleTextRectFP, "getAccessibleTextRect");
+ LOAD_FP(GetAccessibleTextLineBounds, GetAccessibleTextLineBoundsFP, "getAccessibleTextLineBounds");
+ LOAD_FP(GetAccessibleTextRange, GetAccessibleTextRangeFP, "getAccessibleTextRange");
+
+ LOAD_FP(GetCurrentAccessibleValueFromContext, GetCurrentAccessibleValueFromContextFP, "getCurrentAccessibleValueFromContext");
+ LOAD_FP(GetMaximumAccessibleValueFromContext, GetMaximumAccessibleValueFromContextFP, "getMaximumAccessibleValueFromContext");
+ LOAD_FP(GetMinimumAccessibleValueFromContext, GetMinimumAccessibleValueFromContextFP, "getMinimumAccessibleValueFromContext");
+
+ LOAD_FP(AddAccessibleSelectionFromContext, AddAccessibleSelectionFromContextFP, "addAccessibleSelectionFromContext");
+ LOAD_FP(ClearAccessibleSelectionFromContext, ClearAccessibleSelectionFromContextFP, "clearAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionFromContext, GetAccessibleSelectionFromContextFP, "getAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionCountFromContext, GetAccessibleSelectionCountFromContextFP, "getAccessibleSelectionCountFromContext");
+ LOAD_FP(IsAccessibleChildSelectedFromContext, IsAccessibleChildSelectedFromContextFP, "isAccessibleChildSelectedFromContext");
+ LOAD_FP(RemoveAccessibleSelectionFromContext, RemoveAccessibleSelectionFromContextFP, "removeAccessibleSelectionFromContext");
+ LOAD_FP(SelectAllAccessibleSelectionFromContext, SelectAllAccessibleSelectionFromContextFP, "selectAllAccessibleSelectionFromContext");
+
+ LOAD_FP(setTextContents, setTextContentsFP, "setTextContents");
+ LOAD_FP(getParentWithRole, getParentWithRoleFP, "getParentWithRole");
+ LOAD_FP(getTopLevelObject, getTopLevelObjectFP, "getTopLevelObject");
+ LOAD_FP(getParentWithRoleElseRoot, getParentWithRoleElseRootFP, "getParentWithRoleElseRoot");
+ LOAD_FP(getObjectDepth, getObjectDepthFP, "getObjectDepth");
+ LOAD_FP(getActiveDescendent, getActiveDescendentFP, "getActiveDescendent");
+
+ // additional methods for Teton
+ LOAD_FP(getVirtualAccessibleName, getVirtualAccessibleNameFP, "getVirtualAccessibleName");
+ LOAD_FP(requestFocus, requestFocusFP, "requestFocus");
+ LOAD_FP(selectTextRange, selectTextRangeFP, "selectTextRange");
+ LOAD_FP(getTextAttributesInRange, getTextAttributesInRangeFP, "getTextAttributesInRange");
+ LOAD_FP(getVisibleChildrenCount, getVisibleChildrenCountFP, "getVisibleChildrenCount");
+ LOAD_FP(getVisibleChildren, getVisibleChildrenFP, "getVisibleChildren");
+ LOAD_FP(setCaretPosition, setCaretPositionFP, "setCaretPosition");
+ LOAD_FP(getCaretLocation, getCaretLocationFP, "getCaretLocation");
+
+ LOAD_FP(getEventsWaiting, getEventsWaitingFP, "getEventsWaiting");
+
+ theAccessBridge.Windows_run();
+
+ theAccessBridgeInitializedFlag = TRUE;
+ PrintDebugString("theAccessBridgeInitializedFlag = TRUE");
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+
+ BOOL shutdownAccessBridge() {
+ BOOL result;
+ DWORD error;
+ theAccessBridgeInitializedFlag = FALSE;
+ if (theAccessBridgeInstance != (HANDLE) 0) {
+ result = FreeLibrary(theAccessBridgeInstance);
+ if (result != TRUE) {
+ error = GetLastError();
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetJavaShutdown(fp);
+ }
+ }
+
+ void SetFocusGained(AccessBridge_FocusGainedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusGained(fp);
+ }
+ }
+
+ void SetFocusLost(AccessBridge_FocusLostFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusLost(fp);
+ }
+ }
+
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetCaretUpdate(fp);
+ }
+ }
+
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseClicked(fp);
+ }
+ }
+
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseEntered(fp);
+ }
+ }
+
+ void SetMouseExited(AccessBridge_MouseExitedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseExited(fp);
+ }
+ }
+
+ void SetMousePressed(AccessBridge_MousePressedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMousePressed(fp);
+ }
+ }
+
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseReleased(fp);
+ }
+ }
+
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuCanceled(fp);
+ }
+ }
+
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuDeselected(fp);
+ }
+ }
+
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuSelected(fp);
+ }
+ }
+
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuCanceled(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeInvisible(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeVisible(fp);
+ }
+ }
+
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyNameChange(fp);
+ }
+ }
+
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyDescriptionChange(fp);
+ }
+ }
+
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyStateChange(fp);
+ }
+ }
+
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyValueChange(fp);
+ }
+ }
+
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertySelectionChange(fp);
+ }
+ }
+
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTextChange(fp);
+ }
+ }
+
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyCaretChange(fp);
+ }
+ }
+
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyVisibleDataChange(fp);
+ }
+ }
+
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyChildChange(fp);
+ }
+ }
+
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyActiveDescendentChange(fp);
+ }
+ }
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTableModelChange(fp);
+ }
+ }
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ReleaseJavaObject(vmID, object);
+ }
+ }
+
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetVersionInfo(vmID, info);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ BOOL ret ;
+ ret = theAccessBridge.IsJavaWindow(window);
+ return ret ;
+
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Returns the virtual machine ID and AccessibleContext for a top-level window
+ */
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextFromHWND(target, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the HWND from the AccessibleContext of a top-level window. Returns 0
+ * on error or if the AccessibleContext does not refer to a top-level window.
+ */
+ HWND getHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getHWNDFromAccessibleContext(vmID, accesibleContext);
+ }
+ return (HWND)0;
+ }
+
+ /**
+ * returns whether two objects are the same
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsSameObject(vmID, obj1, obj2);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setTextContents(vmID, accessibleContext, text);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRole(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRoleElseRoot(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTopLevelObject(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getObjectDepth(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getActiveDescendent(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextAt(vmID, acParent, x, y, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextWithFocus(window, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextInfo(vmID, ac, info);
+ }
+ return FALSE;
+ }
+
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleChildFromContext(vmID, ac, index);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleParentFromContext(vmID, ac);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ /* begin AccessibleTable routines */
+
+ /*
+ * get information about an AccessibleTable
+ */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableInfo(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable cell
+ */
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableCellInfo(vmID, accessibleTable, row, column, tableCellInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable row header
+ */
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable column header
+ */
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return a description of an AccessibleTable row header
+ */
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowDescription(vmID, acParent, row);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return a description of an AccessibleTable column header
+ */
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnDescription(vmID, acParent, column);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return the number of rows selected in an AccessibleTable
+ */
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a row is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableRowSelected(vmID, table, row);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of selected rows in an AccessibleTable
+ */
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the number of columns selected in an AccessibleTable
+ */
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a column is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableColumnSelected(vmID, table, column);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of columns selected in an AccessibleTable
+ */
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the row number for a cell at a given index
+ */
+ jint
+ getAccessibleTableRow(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRow(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the column number for a cell at a given index
+ */
+ jint
+ getAccessibleTableColumn(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumn(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the index of a cell at a given row and column
+ */
+ jint
+ getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableIndex(vmID, table, row, column);
+ }
+ return -1;
+ }
+
+ /* end AccessibleTable routines */
+
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextInfo(vmID, at, textInfo, x, y);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextItems(vmID, at, textItems, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextSelectionInfo(vmID, at, textSelection);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextAttributes(vmID, at, index, attributes);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRect(vmID, at, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextLineBounds(vmID, at, index, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRange(vmID, at, start, end, text, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleRelationSet routines
+ */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleRelationSet(vmID, accessibleContext, relationSetInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleHypertext routines
+ */
+
+ // Gets AccessibleHypertext for an AccessibleContext
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertext(vmID, accessibleContext, hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ // Activates an AccessibleHyperlink for an AccessibleContext
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.activateAccessibleHyperlink(vmID, accessibleContext, accessibleHyperlink);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlinkCount(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextExt(vmID,
+ accessibleContext,
+ nStartIndex,
+ hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document;
+ * Maps to AccessibleHypertext.getLinkIndex.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextLinkIndex(vmID,
+ hypertext,
+ nIndex);
+ }
+ return -1;
+ }
+
+ /*
+ * Returns the nth hyperlink in a document.
+ * Maps to AccessibleHypertext.getLink.
+ * Returns -1 on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlink(vmID,
+ hypertext,
+ nIndex,
+ hyperlinkInfo);
+ }
+ return FALSE;
+ }
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleKeyBindings(vmID, accessibleContext, keyBindings);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleIcons(vmID, accessibleContext, icons);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleActions(vmID, accessibleContext, actions);
+ }
+ return FALSE;
+ }
+
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.doAccessibleActions(vmID, accessibleContext, actionsToDo, failure);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetCurrentAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMaximumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMinimumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Accessible Selection routines
+ */
+ void addAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.AddAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void clearAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ClearAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionFromContext(vmID, as, i);
+ }
+ return (JOBJECT64) 0;
+ }
+
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionCountFromContext(vmID, as);
+ }
+ return -1;
+ }
+
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsAccessibleChildSelectedFromContext(vmID, as, i);
+ }
+ return FALSE;
+ }
+
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.RemoveAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SelectAllAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVirtualAccessibleName(vmID, accessibleContext, name, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.requestFocus(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.selectTextRange(vmID, accessibleContext, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTextAttributesInRange(vmID, accessibleContext, startIndex,
+ endIndex, attributes, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildrenCount(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful;
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *visibleChildrenInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildren(vmID, accessibleContext, startIndex,
+ visibleChildrenInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setCaretPosition(vmID, accessibleContext, position);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getCaretLocation(vmID, ac, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting() {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getEventsWaiting();
+ }
+ return FALSE;
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/client/jni/windows/win32/bridge/AccessBridgeCalls.h b/source/client/jni/windows/win32/bridge/AccessBridgeCalls.h
new file mode 100644
index 0000000000000000000000000000000000000000..d00de6d143d89e858e5b4e789195ecf2d9c497a1
--- /dev/null
+++ b/source/client/jni/windows/win32/bridge/AccessBridgeCalls.h
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+#include
+#include
+#include "AccessBridgeCallbacks.h"
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define null NULL
+
+ typedef JOBJECT64 AccessibleContext;
+ typedef JOBJECT64 AccessibleText;
+ typedef JOBJECT64 AccessibleValue;
+ typedef JOBJECT64 AccessibleSelection;
+ typedef JOBJECT64 Java_Object;
+ typedef JOBJECT64 PropertyChangeEvent;
+ typedef JOBJECT64 FocusEvent;
+ typedef JOBJECT64 CaretEvent;
+ typedef JOBJECT64 MouseEvent;
+ typedef JOBJECT64 MenuEvent;
+ typedef JOBJECT64 AccessibleTable;
+ typedef JOBJECT64 AccessibleHyperlink;
+ typedef JOBJECT64 AccessibleHypertext;
+
+
+ typedef void (*Windows_runFP) ();
+
+ typedef void (*SetPropertyChangeFP) (AccessBridge_PropertyChangeFP fp);
+
+ typedef void (*SetJavaShutdownFP) (AccessBridge_JavaShutdownFP fp);
+ typedef void (*SetFocusGainedFP) (AccessBridge_FocusGainedFP fp);
+ typedef void (*SetFocusLostFP) (AccessBridge_FocusLostFP fp);
+
+ typedef void (*SetCaretUpdateFP) (AccessBridge_CaretUpdateFP fp);
+
+ typedef void (*SetMouseClickedFP) (AccessBridge_MouseClickedFP fp);
+ typedef void (*SetMouseEnteredFP) (AccessBridge_MouseEnteredFP fp);
+ typedef void (*SetMouseExitedFP) (AccessBridge_MouseExitedFP fp);
+ typedef void (*SetMousePressedFP) (AccessBridge_MousePressedFP fp);
+ typedef void (*SetMouseReleasedFP) (AccessBridge_MouseReleasedFP fp);
+
+ typedef void (*SetMenuCanceledFP) (AccessBridge_MenuCanceledFP fp);
+ typedef void (*SetMenuDeselectedFP) (AccessBridge_MenuDeselectedFP fp);
+ typedef void (*SetMenuSelectedFP) (AccessBridge_MenuSelectedFP fp);
+ typedef void (*SetPopupMenuCanceledFP) (AccessBridge_PopupMenuCanceledFP fp);
+ typedef void (*SetPopupMenuWillBecomeInvisibleFP) (AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ typedef void (*SetPopupMenuWillBecomeVisibleFP) (AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ typedef void (*SetPropertyNameChangeFP) (AccessBridge_PropertyNameChangeFP fp);
+ typedef void (*SetPropertyDescriptionChangeFP) (AccessBridge_PropertyDescriptionChangeFP fp);
+ typedef void (*SetPropertyStateChangeFP) (AccessBridge_PropertyStateChangeFP fp);
+ typedef void (*SetPropertyValueChangeFP) (AccessBridge_PropertyValueChangeFP fp);
+ typedef void (*SetPropertySelectionChangeFP) (AccessBridge_PropertySelectionChangeFP fp);
+ typedef void (*SetPropertyTextChangeFP) (AccessBridge_PropertyTextChangeFP fp);
+ typedef void (*SetPropertyCaretChangeFP) (AccessBridge_PropertyCaretChangeFP fp);
+ typedef void (*SetPropertyVisibleDataChangeFP) (AccessBridge_PropertyVisibleDataChangeFP fp);
+ typedef void (*SetPropertyChildChangeFP) (AccessBridge_PropertyChildChangeFP fp);
+ typedef void (*SetPropertyActiveDescendentChangeFP) (AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ typedef void (*SetPropertyTableModelChangeFP) (AccessBridge_PropertyTableModelChangeFP fp);
+
+ typedef void (*ReleaseJavaObjectFP) (long vmID, Java_Object object);
+
+ typedef BOOL (*GetVersionInfoFP) (long vmID, AccessBridgeVersionInfo *info);
+
+ typedef BOOL (*IsJavaWindowFP) (HWND window);
+ typedef BOOL (*IsSameObjectFP) (long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+ typedef BOOL (*GetAccessibleContextFromHWNDFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef HWND (*getHWNDFromAccessibleContextFP) (long vmID, AccessibleContext ac);
+
+ typedef BOOL (*GetAccessibleContextAtFP) (long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextWithFocusFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextInfoFP) (long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ typedef AccessibleContext (*GetAccessibleChildFromContextFP) (long vmID, AccessibleContext ac, jint i);
+ typedef AccessibleContext (*GetAccessibleParentFromContextFP) (long vmID, AccessibleContext ac);
+
+ /* begin AccessibleTable */
+ typedef BOOL (*getAccessibleTableInfoFP) (long vmID, AccessibleContext ac, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableCellInfoFP) (long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo);
+
+ typedef BOOL (*getAccessibleTableRowHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableColumnHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ typedef AccessibleContext (*getAccessibleTableRowDescriptionFP) (long vmID, AccessibleContext acParent, jint row);
+ typedef AccessibleContext (*getAccessibleTableColumnDescriptionFP) (long vmID, AccessibleContext acParent, jint column);
+
+ typedef jint (*getAccessibleTableRowSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableRowSelectedFP) (long vmID, AccessibleTable table, jint row);
+ typedef BOOL (*getAccessibleTableRowSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableColumnSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableColumnSelectedFP) (long vmID, AccessibleTable table, jint column);
+ typedef BOOL (*getAccessibleTableColumnSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableRowFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableColumnFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableIndexFP) (long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ typedef BOOL (*getAccessibleRelationSetFP) (long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* AccessibleHypertext */
+ typedef BOOL (*getAccessibleHypertextFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef BOOL (*activateAccessibleHyperlinkFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ typedef jint (*getAccessibleHyperlinkCountFP)(const long vmID,
+ const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getAccessibleHypertextExtFP) (const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef jint (*getAccessibleHypertextLinkIndexFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ typedef BOOL (*getAccessibleHyperlinkFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ typedef BOOL (*getAccessibleKeyBindingsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ typedef BOOL (*getAccessibleIconsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ typedef BOOL (*getAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ typedef BOOL (*doAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+ /* AccessibleText */
+
+ typedef BOOL (*GetAccessibleTextInfoFP) (long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ typedef BOOL (*GetAccessibleTextItemsFP) (long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ typedef BOOL (*GetAccessibleTextSelectionInfoFP) (long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ typedef BOOL (*GetAccessibleTextAttributesFP) (long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ typedef BOOL (*GetAccessibleTextRectFP) (long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ typedef BOOL (*GetAccessibleTextLineBoundsFP) (long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ typedef BOOL (*GetAccessibleTextRangeFP) (long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ typedef BOOL (*GetCurrentAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMaximumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMinimumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ typedef void (*AddAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*ClearAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+ typedef JOBJECT64 (*GetAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef int (*GetAccessibleSelectionCountFromContextFP) (long vmID, AccessibleSelection as);
+ typedef BOOL (*IsAccessibleChildSelectedFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*RemoveAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*SelectAllAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+
+ /* Utility methods */
+
+ typedef BOOL (*setTextContentsFP) (const long vmID, const AccessibleContext ac, const wchar_t *text);
+ typedef AccessibleContext (*getParentWithRoleFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getParentWithRoleElseRootFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getTopLevelObjectFP) (const long vmID, const AccessibleContext ac);
+ typedef int (*getObjectDepthFP) (const long vmID, const AccessibleContext ac);
+ typedef AccessibleContext (*getActiveDescendentFP) (const long vmID, const AccessibleContext ac);
+
+
+ typedef BOOL (*getVirtualAccessibleNameFP) (const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ typedef BOOL (*requestFocusFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*selectTextRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex);
+
+ typedef BOOL (*getTextAttributesInRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ typedef int (*getVisibleChildrenCountFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getVisibleChildrenFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *children);
+
+ typedef BOOL (*setCaretPositionFP) (const long vmID, const AccessibleContext accessibleContext, const int position);
+
+ typedef BOOL (*getCaretLocationFP) (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index);
+
+ typedef int (*getEventsWaitingFP) ();
+
+ typedef struct AccessBridgeFPsTag {
+ Windows_runFP Windows_run;
+
+ SetPropertyChangeFP SetPropertyChange;
+
+ SetJavaShutdownFP SetJavaShutdown;
+ SetFocusGainedFP SetFocusGained;
+ SetFocusLostFP SetFocusLost;
+
+ SetCaretUpdateFP SetCaretUpdate;
+
+ SetMouseClickedFP SetMouseClicked;
+ SetMouseEnteredFP SetMouseEntered;
+ SetMouseExitedFP SetMouseExited;
+ SetMousePressedFP SetMousePressed;
+ SetMouseReleasedFP SetMouseReleased;
+
+ SetMenuCanceledFP SetMenuCanceled;
+ SetMenuDeselectedFP SetMenuDeselected;
+ SetMenuSelectedFP SetMenuSelected;
+ SetPopupMenuCanceledFP SetPopupMenuCanceled;
+ SetPopupMenuWillBecomeInvisibleFP SetPopupMenuWillBecomeInvisible;
+ SetPopupMenuWillBecomeVisibleFP SetPopupMenuWillBecomeVisible;
+
+ SetPropertyNameChangeFP SetPropertyNameChange;
+ SetPropertyDescriptionChangeFP SetPropertyDescriptionChange;
+ SetPropertyStateChangeFP SetPropertyStateChange;
+ SetPropertyValueChangeFP SetPropertyValueChange;
+ SetPropertySelectionChangeFP SetPropertySelectionChange;
+ SetPropertyTextChangeFP SetPropertyTextChange;
+ SetPropertyCaretChangeFP SetPropertyCaretChange;
+ SetPropertyVisibleDataChangeFP SetPropertyVisibleDataChange;
+ SetPropertyChildChangeFP SetPropertyChildChange;
+ SetPropertyActiveDescendentChangeFP SetPropertyActiveDescendentChange;
+
+ SetPropertyTableModelChangeFP SetPropertyTableModelChange;
+
+ ReleaseJavaObjectFP ReleaseJavaObject;
+ GetVersionInfoFP GetVersionInfo;
+
+ IsJavaWindowFP IsJavaWindow;
+ IsSameObjectFP IsSameObject;
+ GetAccessibleContextFromHWNDFP GetAccessibleContextFromHWND;
+ getHWNDFromAccessibleContextFP getHWNDFromAccessibleContext;
+
+ GetAccessibleContextAtFP GetAccessibleContextAt;
+ GetAccessibleContextWithFocusFP GetAccessibleContextWithFocus;
+ GetAccessibleContextInfoFP GetAccessibleContextInfo;
+ GetAccessibleChildFromContextFP GetAccessibleChildFromContext;
+ GetAccessibleParentFromContextFP GetAccessibleParentFromContext;
+
+ getAccessibleTableInfoFP getAccessibleTableInfo;
+ getAccessibleTableCellInfoFP getAccessibleTableCellInfo;
+
+ getAccessibleTableRowHeaderFP getAccessibleTableRowHeader;
+ getAccessibleTableColumnHeaderFP getAccessibleTableColumnHeader;
+
+ getAccessibleTableRowDescriptionFP getAccessibleTableRowDescription;
+ getAccessibleTableColumnDescriptionFP getAccessibleTableColumnDescription;
+
+ getAccessibleTableRowSelectionCountFP getAccessibleTableRowSelectionCount;
+ isAccessibleTableRowSelectedFP isAccessibleTableRowSelected;
+ getAccessibleTableRowSelectionsFP getAccessibleTableRowSelections;
+
+ getAccessibleTableColumnSelectionCountFP getAccessibleTableColumnSelectionCount;
+ isAccessibleTableColumnSelectedFP isAccessibleTableColumnSelected;
+ getAccessibleTableColumnSelectionsFP getAccessibleTableColumnSelections;
+
+ getAccessibleTableRowFP getAccessibleTableRow;
+ getAccessibleTableColumnFP getAccessibleTableColumn;
+ getAccessibleTableIndexFP getAccessibleTableIndex;
+
+ getAccessibleRelationSetFP getAccessibleRelationSet;
+
+ getAccessibleHypertextFP getAccessibleHypertext;
+ activateAccessibleHyperlinkFP activateAccessibleHyperlink;
+ getAccessibleHyperlinkCountFP getAccessibleHyperlinkCount;
+ getAccessibleHypertextExtFP getAccessibleHypertextExt;
+ getAccessibleHypertextLinkIndexFP getAccessibleHypertextLinkIndex;
+ getAccessibleHyperlinkFP getAccessibleHyperlink;
+
+ getAccessibleKeyBindingsFP getAccessibleKeyBindings;
+ getAccessibleIconsFP getAccessibleIcons;
+ getAccessibleActionsFP getAccessibleActions;
+ doAccessibleActionsFP doAccessibleActions;
+
+ GetAccessibleTextInfoFP GetAccessibleTextInfo;
+ GetAccessibleTextItemsFP GetAccessibleTextItems;
+ GetAccessibleTextSelectionInfoFP GetAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributesFP GetAccessibleTextAttributes;
+ GetAccessibleTextRectFP GetAccessibleTextRect;
+ GetAccessibleTextLineBoundsFP GetAccessibleTextLineBounds;
+ GetAccessibleTextRangeFP GetAccessibleTextRange;
+
+ GetCurrentAccessibleValueFromContextFP GetCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextFP GetMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextFP GetMinimumAccessibleValueFromContext;
+
+ AddAccessibleSelectionFromContextFP AddAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextFP ClearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextFP GetAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextFP GetAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextFP IsAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextFP RemoveAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextFP SelectAllAccessibleSelectionFromContext;
+
+ setTextContentsFP setTextContents;
+ getParentWithRoleFP getParentWithRole;
+ getTopLevelObjectFP getTopLevelObject;
+ getParentWithRoleElseRootFP getParentWithRoleElseRoot;
+ getObjectDepthFP getObjectDepth;
+ getActiveDescendentFP getActiveDescendent;
+
+ getVirtualAccessibleNameFP getVirtualAccessibleName;
+ requestFocusFP requestFocus;
+ selectTextRangeFP selectTextRange;
+ getTextAttributesInRangeFP getTextAttributesInRange;
+ getVisibleChildrenCountFP getVisibleChildrenCount;
+ getVisibleChildrenFP getVisibleChildren;
+ setCaretPositionFP setCaretPosition;
+ getCaretLocationFP getCaretLocation;
+
+ getEventsWaitingFP getEventsWaiting;
+
+ } AccessBridgeFPs;
+
+
+ /**
+ * Initialize the world
+ */
+ BOOL initializeAccessBridge();
+ BOOL shutdownAccessBridge();
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window);
+
+ // Returns the virtual machine ID and AccessibleContext for a top-level window
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac);
+
+ // Returns the HWND from the AccessibleContext of a top-level window
+ HWND getHWNDFromAccessibleContext(long vmID, AccessibleContext ac);
+
+
+ /**
+ * Event handling routines
+ */
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp);
+ void SetFocusGained(AccessBridge_FocusGainedFP fp);
+ void SetFocusLost(AccessBridge_FocusLostFP fp);
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp);
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp);
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp);
+ void SetMouseExited(AccessBridge_MouseExitedFP fp);
+ void SetMousePressed(AccessBridge_MousePressedFP fp);
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp);
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp);
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp);
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp);
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp);
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp);
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp);
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp);
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp);
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp);
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp);
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp);
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp);
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp);
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp);
+
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object);
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info);
+ HWND GetHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext);
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac);
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index);
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac);
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ /* begin AccessibleTable routines */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable, jint row, jint column,
+ AccessibleTableCellInfo *tableCellInfo);
+
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row);
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column);
+
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row);
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column);
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableRow(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableColumn(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* ----- AccessibleRelationSet routines */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* ----- AccessibleHypertext routines */
+
+ /*
+ * Returns hypertext information associated with a component.
+ */
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Requests that a hyperlink be activated.
+ */
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleHypertext hypertext);
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * Returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document; maps to AccessibleHypertext.getLinkIndex
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ /*
+ * Returns the nth hyperlink in a document
+ * Maps to AccessibleHypertext.getLink.
+ * Returns FALSE on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+ /* Accessible KeyBindings, Icons and Actions */
+
+ /*
+ * Returns a list of key bindings associated with a component.
+ */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ /*
+ * Returns a list of icons associate with a component.
+ */
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ /*
+ * Returns a list of actions that a component can perform.
+ */
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ /*
+ * Request that a list of AccessibleActions be performed by a component.
+ * Returns TRUE if all actions are performed. Returns FALSE
+ * when the first requested action fails in which case "failure"
+ * contains the index of the action that failed.
+ */
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+
+ /* Additional utility methods */
+
+ /*
+ * Returns whether two object references refer to the same object.
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length that can be set is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ /**
+ * Accessible Selection routines
+ */
+ void AddAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void ClearAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as);
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i);
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ /**
+ * Request focus for a component. Returns whether successful.
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful.
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext, const int startIndex,
+ const int endIndex);
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex,
+ VisibleChildrenInfo *visibleChildrenInfo);
+
+ /**
+ * Set the caret to a text position. Returns whether successful.
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position);
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac,
+ AccessibleTextRectInfo *rectInfo, jint index);
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/client/jni/windows/win32/bridge/AccessBridgePackages.h b/source/client/jni/windows/win32/bridge/AccessBridgePackages.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff21abaf57572477a9b2e5205cb6846667b24b9f
--- /dev/null
+++ b/source/client/jni/windows/win32/bridge/AccessBridgePackages.h
@@ -0,0 +1,2215 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Header file for packages of paramaters passed between Java Accessibility
+ * and native Assistive Technologies
+ */
+
+#ifndef __AccessBridgePackages_H__
+#define __AccessBridgePackages_H__
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef ACCESSBRIDGE_ARCH_LEGACY
+typedef jobject JOBJECT64;
+typedef HWND ABHWND64;
+#define ABHandleToLong
+#define ABLongToHandle
+#else
+typedef jlong JOBJECT64;
+typedef long ABHWND64;
+#define ABHandleToLong HandleToLong
+#define ABLongToHandle LongToHandle
+#endif
+
+#define MAX_BUFFER_SIZE 10240
+#define MAX_STRING_SIZE 1024
+#define SHORT_STRING_SIZE 256
+
+ // object types
+ typedef JOBJECT64 AccessibleContext;
+ typedef JOBJECT64 AccessibleText;
+ typedef JOBJECT64 AccessibleValue;
+ typedef JOBJECT64 AccessibleSelection;
+ typedef JOBJECT64 Java_Object;
+ typedef JOBJECT64 PropertyChangeEvent;
+ typedef JOBJECT64 FocusEvent;
+ typedef JOBJECT64 CaretEvent;
+ typedef JOBJECT64 MouseEvent;
+ typedef JOBJECT64 MenuEvent;
+ typedef JOBJECT64 AccessibleTable;
+ typedef JOBJECT64 AccessibleHyperlink;
+ typedef JOBJECT64 AccessibleHypertext;
+
+ /**
+ ******************************************************
+ * Java event types
+ ******************************************************
+ */
+
+#define cPropertyChangeEvent (jlong) 1 // 1
+#define cFocusGainedEvent (jlong) 2 // 2
+#define cFocusLostEvent (jlong) 4 // 4
+#define cCaretUpdateEvent (jlong) 8 // 8
+#define cMouseClickedEvent (jlong) 16 // 10
+#define cMouseEnteredEvent (jlong) 32 // 20
+#define cMouseExitedEvent (jlong) 64 // 40
+#define cMousePressedEvent (jlong) 128 // 80
+#define cMouseReleasedEvent (jlong) 256 // 100
+#define cMenuCanceledEvent (jlong) 512 // 200
+#define cMenuDeselectedEvent (jlong) 1024 // 400
+#define cMenuSelectedEvent (jlong) 2048 // 800
+#define cPopupMenuCanceledEvent (jlong) 4096 // 1000
+#define cPopupMenuWillBecomeInvisibleEvent (jlong) 8192 // 2000
+#define cPopupMenuWillBecomeVisibleEvent (jlong) 16384 // 4000
+#define cJavaShutdownEvent (jlong) 32768 // 8000
+
+ /**
+ ******************************************************
+ * Accessible Roles
+ * Defines all AccessibleRoles in Local.US
+ ******************************************************
+ */
+
+ /**
+ * Object is used to alert the user about something.
+ */
+#define ACCESSIBLE_ALERT L"alert"
+
+ /**
+ * The header for a column of data.
+ */
+#define ACCESSIBLE_COLUMN_HEADER L"column header"
+
+ /**
+ * Object that can be drawn into and is used to trap
+ * events.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_CANVAS L"canvas"
+
+ /**
+ * A list of choices the user can select from. Also optionally
+ * allows the user to enter a choice of their own.
+ */
+#define ACCESSIBLE_COMBO_BOX L"combo box"
+
+ /**
+ * An iconified internal frame in a DESKTOP_PANE.
+ * see ACCESSIBLE_DESKTOP_PANE
+ * see ACCESSIBLE_INTERNAL_FRAME
+ */
+#define ACCESSIBLE_DESKTOP_ICON L"desktop icon"
+
+ /**
+ * A frame-like object that is clipped by a desktop pane. The
+ * desktop pane, internal frame, and desktop icon objects are
+ * often used to create multiple document interfaces within an
+ * application.
+ * see ACCESSIBLE_DESKTOP_ICON
+ * see ACCESSIBLE_DESKTOP_PANE
+ * see ACCESSIBLE_FRAME
+ */
+#define ACCESSIBLE_INTERNAL_FRAME L"internal frame"
+
+ /**
+ * A pane that supports internal frames and
+ * iconified versions of those internal frames.
+ * see ACCESSIBLE_DESKTOP_ICON
+ * see ACCESSIBLE_INTERNAL_FRAME
+ */
+#define ACCESSIBLE_DESKTOP_PANE L"desktop pane"
+
+ /**
+ * A specialized pane whose primary use is inside a DIALOG
+ * see ACCESSIBLE_DIALOG
+ */
+#define ACCESSIBLE_OPTION_PANE L"option pane"
+
+ /**
+ * A top level window with no title or border.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_DIALOG
+ */
+#define ACCESSIBLE_WINDOW L"window"
+
+ /**
+ * A top level window with a title bar, border, menu bar, etc. It is
+ * often used as the primary window for an application.
+ * see ACCESSIBLE_DIALOG
+ * see ACCESSIBLE_CANVAS
+ * see ACCESSIBLE_WINDOW
+ */
+#define ACCESSIBLE_FRAME L"frame"
+
+ /**
+ * A top level window with title bar and a border. A dialog is similar
+ * to a frame, but it has fewer properties and is often used as a
+ * secondary window for an application.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_WINDOW
+ */
+#define ACCESSIBLE_DIALOG L"dialog"
+
+ /**
+ * A specialized dialog that lets the user choose a color.
+ */
+#define ACCESSIBLE_COLOR_CHOOSER L"color chooser"
+
+
+ /**
+ * A pane that allows the user to navigate through
+ * and select the contents of a directory. May be used
+ * by a file chooser.
+ * see ACCESSIBLE_FILE_CHOOSER
+ */
+#define ACCESSIBLE_DIRECTORY_PANE L"directory pane"
+
+ /**
+ * A specialized dialog that displays the files in the directory
+ * and lets the user select a file, browse a different directory,
+ * or specify a filename. May use the directory pane to show the
+ * contents of a directory.
+ * see ACCESSIBLE_DIRECTORY_PANE
+ */
+#define ACCESSIBLE_FILE_CHOOSER L"file chooser"
+
+ /**
+ * An object that fills up space in a user interface. It is often
+ * used in interfaces to tweak the spacing between components,
+ * but serves no other purpose.
+ */
+#define ACCESSIBLE_FILLER L"filler"
+
+ /**
+ * A hypertext anchor
+ */
+#define ACCESSIBLE_HYPERLINK L"hyperlink"
+
+ /**
+ * A small fixed size picture, typically used to decorate components.
+ */
+#define ACCESSIBLE_ICON L"icon"
+
+ /**
+ * An object used to present an icon or short string in an interface.
+ */
+#define ACCESSIBLE_LABEL L"label"
+
+ /**
+ * A specialized pane that has a glass pane and a layered pane as its
+ * children.
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_ROOT_PANE L"root pane"
+
+ /**
+ * A pane that is guaranteed to be painted on top
+ * of all panes beneath it.
+ * see ACCESSIBLE_ROOT_PANE
+ * see ACCESSIBLE_CANVAS
+ */
+#define ACCESSIBLE_GLASS_PANE L"glass pane"
+
+ /**
+ * A specialized pane that allows its children to be drawn in layers,
+ * providing a form of stacking order. This is usually the pane that
+ * holds the menu bar as well as the pane that contains most of the
+ * visual components in a window.
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_ROOT_PANE
+ */
+#define ACCESSIBLE_LAYERED_PANE L"layered pane"
+
+ /**
+ * An object that presents a list of objects to the user and allows the
+ * user to select one or more of them. A list is usually contained
+ * within a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ * see ACCESSIBLE_LIST_ITEM
+ */
+#define ACCESSIBLE_LIST L"list"
+
+ /**
+ * An object that presents an element in a list. A list is usually
+ * contained within a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ * see ACCESSIBLE_LIST
+ */
+#define ACCESSIBLE_LIST_ITEM L"list item"
+
+ /**
+ * An object usually drawn at the top of the primary dialog box of
+ * an application that contains a list of menus the user can choose
+ * from. For example, a menu bar might contain menus for "File,"
+ * "Edit," and "Help."
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_POPUP_MENU
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_MENU_BAR L"menu bar"
+
+ /**
+ * A temporary window that is usually used to offer the user a
+ * list of choices, and then hides when the user selects one of
+ * those choices.
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_MENU_ITEM
+ */
+#define ACCESSIBLE_POPUP_MENU L"popup menu"
+
+ /**
+ * An object usually found inside a menu bar that contains a list
+ * of actions the user can choose from. A menu can have any object
+ * as its children, but most often they are menu items, other menus,
+ * or rudimentary objects such as radio buttons, check boxes, or
+ * separators. For example, an application may have an "Edit" menu
+ * that contains menu items for "Cut" and "Paste."
+ * see ACCESSIBLE_MENU_BAR
+ * see ACCESSIBLE_MENU_ITEM
+ * see ACCESSIBLE_SEPARATOR
+ * see ACCESSIBLE_RADIO_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_POPUP_MENU
+ */
+#define ACCESSIBLE_MENU L"menu"
+
+ /**
+ * An object usually contained in a menu that presents an action
+ * the user can choose. For example, the "Cut" menu item in an
+ * "Edit" menu would be an action the user can select to cut the
+ * selected area of text in a document.
+ * see ACCESSIBLE_MENU_BAR
+ * see ACCESSIBLE_SEPARATOR
+ * see ACCESSIBLE_POPUP_MENU
+ */
+#define ACCESSIBLE_MENU_ITEM L"menu item"
+
+ /**
+ * An object usually contained in a menu to provide a visual
+ * and logical separation of the contents in a menu. For example,
+ * the "File" menu of an application might contain menu items for
+ * "Open," "Close," and "Exit," and will place a separator between
+ * "Close" and "Exit" menu items.
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_MENU_ITEM
+ */
+#define ACCESSIBLE_SEPARATOR L"separator"
+
+ /**
+ * An object that presents a series of panels (or page tabs), one at a
+ * time, through some mechanism provided by the object. The most common
+ * mechanism is a list of tabs at the top of the panel. The children of
+ * a page tab list are all page tabs.
+ * see ACCESSIBLE_PAGE_TAB
+ */
+#define ACCESSIBLE_PAGE_TAB_LIST L"page tab list"
+
+ /**
+ * An object that is a child of a page tab list. Its sole child is
+ * the panel that is to be presented to the user when the user
+ * selects the page tab from the list of tabs in the page tab list.
+ * see ACCESSIBLE_PAGE_TAB_LIST
+ */
+#define ACCESSIBLE_PAGE_TAB L"page tab"
+
+ /**
+ * A generic container that is often used to group objects.
+ */
+#define ACCESSIBLE_PANEL L"panel"
+
+ /**
+ * An object used to indicate how much of a task has been completed.
+ */
+#define ACCESSIBLE_PROGRESS_BAR L"progress bar"
+
+ /**
+ * A text object used for passwords, or other places where the
+ * text contents is not shown visibly to the user
+ */
+#define ACCESSIBLE_PASSWORD_TEXT L"password text"
+
+ /**
+ * An object the user can manipulate to tell the application to do
+ * something.
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_PUSH_BUTTON L"push button"
+
+ /**
+ * A specialized push button that can be checked or unchecked, but
+ * does not provide a separate indicator for the current state.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_TOGGLE_BUTTON L"toggle button"
+
+ /**
+ * A choice that can be checked or unchecked and provides a
+ * separate indicator for the current state.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_CHECK_BOX L"check box"
+
+ /**
+ * A specialized check box that will cause other radio buttons in the
+ * same group to become unchecked when this one is checked.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ */
+#define ACCESSIBLE_RADIO_BUTTON L"radio button"
+
+ /**
+ * The header for a row of data.
+ */
+#define ACCESSIBLE_ROW_HEADER L"row header"
+
+ /**
+ * An object that allows a user to incrementally view a large amount
+ * of information. Its children can include scroll bars and a viewport.
+ * see ACCESSIBLE_SCROLL_BAR
+ * see ACCESSIBLE_VIEWPORT
+ */
+#define ACCESSIBLE_SCROLL_PANE L"scroll pane"
+
+ /**
+ * An object usually used to allow a user to incrementally view a
+ * large amount of data. Usually used only by a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ */
+#define ACCESSIBLE_SCROLL_BAR L"scroll bar"
+
+ /**
+ * An object usually used in a scroll pane. It represents the portion
+ * of the entire data that the user can see. As the user manipulates
+ * the scroll bars, the contents of the viewport can change.
+ * see ACCESSIBLE_SCROLL_PANE
+ */
+#define ACCESSIBLE_VIEWPORT L"viewport"
+
+ /**
+ * An object that allows the user to select from a bounded range. For
+ * example, a slider might be used to select a number between 0 and 100.
+ */
+#define ACCESSIBLE_SLIDER L"slider"
+
+ /**
+ * A specialized panel that presents two other panels at the same time.
+ * Between the two panels is a divider the user can manipulate to make
+ * one panel larger and the other panel smaller.
+ */
+#define ACCESSIBLE_SPLIT_PANE L"split pane"
+
+ /**
+ * An object used to present information in terms of rows and columns.
+ * An example might include a spreadsheet application.
+ */
+#define ACCESSIBLE_TABLE L"table"
+
+ /**
+ * An object that presents text to the user. The text is usually
+ * editable by the user as opposed to a label.
+ * see ACCESSIBLE_LABEL
+ */
+#define ACCESSIBLE_TEXT L"text"
+
+ /**
+ * An object used to present hierarchical information to the user.
+ * The individual nodes in the tree can be collapsed and expanded
+ * to provide selective disclosure of the tree's contents.
+ */
+#define ACCESSIBLE_TREE L"tree"
+
+ /**
+ * A bar or palette usually composed of push buttons or toggle buttons.
+ * It is often used to provide the most frequently used functions for an
+ * application.
+ */
+#define ACCESSIBLE_TOOL_BAR L"tool bar"
+
+ /**
+ * An object that provides information about another object. The
+ * accessibleDescription property of the tool tip is often displayed
+ * to the user in a small L"help bubble" when the user causes the
+ * mouse to hover over the object associated with the tool tip.
+ */
+#define ACCESSIBLE_TOOL_TIP L"tool tip"
+
+ /**
+ * An AWT component, but nothing else is known about it.
+ * see ACCESSIBLE_SWING_COMPONENT
+ * see ACCESSIBLE_UNKNOWN
+ */
+#define ACCESSIBLE_AWT_COMPONENT L"awt component"
+
+ /**
+ * A Swing component, but nothing else is known about it.
+ * see ACCESSIBLE_AWT_COMPONENT
+ * see ACCESSIBLE_UNKNOWN
+ */
+#define ACCESSIBLE_SWING_COMPONENT L"swing component"
+
+ /**
+ * The object contains some Accessible information, but its role is
+ * not known.
+ * see ACCESSIBLE_AWT_COMPONENT
+ * see ACCESSIBLE_SWING_COMPONENT
+ */
+#define ACCESSIBLE_UNKNOWN L"unknown"
+
+ /**
+ * A STATUS_BAR is an simple component that can contain
+ * multiple labels of status information to the user.
+ */
+#define ACCESSIBLE_STATUS_BAR L"status bar"
+
+ /**
+ * A DATE_EDITOR is a component that allows users to edit
+ * java.util.Date and java.util.Time objects
+ */
+#define ACCESSIBLE_DATE_EDITOR L"date editor"
+
+ /**
+ * A SPIN_BOX is a simple spinner component and its main use
+ * is for simple numbers.
+ */
+#define ACCESSIBLE_SPIN_BOX L"spin box"
+
+ /**
+ * A FONT_CHOOSER is a component that lets the user pick various
+ * attributes for fonts.
+ */
+#define ACCESSIBLE_FONT_CHOOSER L"font chooser"
+
+ /**
+ * A GROUP_BOX is a simple container that contains a border
+ * around it and contains components inside it.
+ */
+#define ACCESSIBLE_GROUP_BOX L"group box"
+
+ /**
+ * A text header
+ */
+#define ACCESSIBLE_HEADER L"header"
+
+ /**
+ * A text footer
+ */
+#define ACCESSIBLE_FOOTER L"footer"
+
+ /**
+ * A text paragraph
+ */
+#define ACCESSIBLE_PARAGRAPH L"paragraph"
+
+ /**
+ * A ruler is an object used to measure distance
+ */
+#define ACCESSIBLE_RULER L"ruler"
+
+ /**
+ * A role indicating the object acts as a formula for
+ * calculating a value. An example is a formula in
+ * a spreadsheet cell.
+ */
+#define ACCESSIBLE_EDITBAR L"editbar"
+
+ /**
+ * A role indicating the object monitors the progress
+ * of some operation.
+ */
+#define PROGRESS_MONITOR L"progress monitor"
+
+
+ /**
+ ******************************************************
+ * Accessibility event types
+ ******************************************************
+ */
+
+#define cPropertyNameChangeEvent (jlong) 1 // 1
+#define cPropertyDescriptionChangeEvent (jlong) 2 // 2
+#define cPropertyStateChangeEvent (jlong) 4 // 4
+#define cPropertyValueChangeEvent (jlong) 8 // 8
+#define cPropertySelectionChangeEvent (jlong) 16 // 10
+#define cPropertyTextChangeEvent (jlong) 32 // 20
+#define cPropertyCaretChangeEvent (jlong) 64 // 40
+#define cPropertyVisibleDataChangeEvent (jlong) 128 // 80
+#define cPropertyChildChangeEvent (jlong) 256 // 100
+#define cPropertyActiveDescendentChangeEvent (jlong) 512 // 200
+#define cPropertyTableModelChangeEvent (jlong) 1024 // 400
+
+ /**
+ ******************************************************
+ * optional AccessibleContext interfaces
+ *
+ * This version of the bridge reuses the accessibleValue
+ * field in the AccessibleContextInfo struct to represent
+ * additional optional interfaces that are supported by
+ * the Java AccessibleContext. This is backwardly compatable
+ * because the old accessibleValue was set to the BOOL
+ * value TRUE (i.e., 1) if the AccessibleValue interface is
+ * supported.
+ ******************************************************
+ */
+
+#define cAccessibleValueInterface (jlong) 1 // 1 << 1 (TRUE)
+#define cAccessibleActionInterface (jlong) 2 // 1 << 2
+#define cAccessibleComponentInterface (jlong) 4 // 1 << 3
+#define cAccessibleSelectionInterface (jlong) 8 // 1 << 4
+#define cAccessibleTableInterface (jlong) 16 // 1 << 5
+#define cAccessibleTextInterface (jlong) 32 // 1 << 6
+#define cAccessibleHypertextInterface (jlong) 64 // 1 << 7
+
+
+ /**
+ ******************************************************
+ * Accessibility information bundles
+ ******************************************************
+ */
+
+ typedef struct AccessBridgeVersionInfoTag {
+ wchar_t VMversion[SHORT_STRING_SIZE]; // output of "java -version"
+ wchar_t bridgeJavaClassVersion[SHORT_STRING_SIZE]; // version of the AccessBridge.class
+ wchar_t bridgeJavaDLLVersion[SHORT_STRING_SIZE]; // version of JavaAccessBridge.dll
+ wchar_t bridgeWinDLLVersion[SHORT_STRING_SIZE]; // version of WindowsAccessBridge.dll
+ } AccessBridgeVersionInfo;
+
+
+ typedef struct AccessibleContextInfoTag {
+ wchar_t name[MAX_STRING_SIZE]; // the AccessibleName of the object
+ wchar_t description[MAX_STRING_SIZE]; // the AccessibleDescription of the object
+
+ wchar_t role[SHORT_STRING_SIZE]; // localized AccesibleRole string
+ wchar_t role_en_US[SHORT_STRING_SIZE]; // AccesibleRole string in the en_US locale
+ wchar_t states[SHORT_STRING_SIZE]; // localized AccesibleStateSet string (comma separated)
+ wchar_t states_en_US[SHORT_STRING_SIZE]; // AccesibleStateSet string in the en_US locale (comma separated)
+
+ jint indexInParent; // index of object in parent
+ jint childrenCount; // # of children, if any
+
+ jint x; // screen coords in pixels
+ jint y; // "
+ jint width; // pixel width of object
+ jint height; // pixel height of object
+
+ BOOL accessibleComponent; // flags for various additional
+ BOOL accessibleAction; // Java Accessibility interfaces
+ BOOL accessibleSelection; // FALSE if this object doesn't
+ BOOL accessibleText; // implement the additional interface
+ // in question
+
+ // BOOL accessibleValue; // old BOOL indicating whether AccessibleValue is supported
+ BOOL accessibleInterfaces; // new bitfield containing additional interface flags
+
+ } AccessibleContextInfo;
+
+
+
+ // AccessibleText packages
+ typedef struct AccessibleTextInfoTag {
+ jint charCount; // # of characters in this text object
+ jint caretIndex; // index of caret
+ jint indexAtPoint; // index at the passsed in point
+ } AccessibleTextInfo;
+
+ typedef struct AccessibleTextItemsInfoTag {
+ wchar_t letter;
+ wchar_t word[SHORT_STRING_SIZE];
+ wchar_t sentence[MAX_STRING_SIZE];
+ } AccessibleTextItemsInfo;
+
+ typedef struct AccessibleTextSelectionInfoTag {
+ jint selectionStartIndex;
+ jint selectionEndIndex;
+ wchar_t selectedText[MAX_STRING_SIZE];
+ } AccessibleTextSelectionInfo;
+
+ typedef struct AccessibleTextRectInfoTag {
+ jint x; // bounding rect of char at index
+ jint y; // "
+ jint width; // "
+ jint height; // "
+ } AccessibleTextRectInfo;
+
+ // standard attributes for text; note: tabstops are not supported
+ typedef struct AccessibleTextAttributesInfoTag {
+ BOOL bold;
+ BOOL italic;
+ BOOL underline;
+ BOOL strikethrough;
+ BOOL superscript;
+ BOOL subscript;
+
+ wchar_t backgroundColor[SHORT_STRING_SIZE];
+ wchar_t foregroundColor[SHORT_STRING_SIZE];
+ wchar_t fontFamily[SHORT_STRING_SIZE];
+ jint fontSize;
+
+ jint alignment;
+ jint bidiLevel;
+
+ jfloat firstLineIndent;
+ jfloat leftIndent;
+ jfloat rightIndent;
+ jfloat lineSpacing;
+ jfloat spaceAbove;
+ jfloat spaceBelow;
+
+ wchar_t fullAttributesString[MAX_STRING_SIZE];
+ } AccessibleTextAttributesInfo;
+
+ /**
+ ******************************************************
+ * IPC management typedefs
+ ******************************************************
+ */
+
+#define cMemoryMappedNameSize 255
+
+ /**
+ * sent by the WindowsDLL -> the memory-mapped file is setup
+ *
+ */
+ typedef struct MemoryMappedFileCreatedPackageTag {
+// HWND bridgeWindow; // redundant, but easier to get to here...
+ ABHWND64 bridgeWindow; // redundant, but easier to get to here...
+ char filename[cMemoryMappedNameSize];
+ } MemoryMappedFileCreatedPackage;
+
+
+
+
+ /**
+ * sent when a new JavaVM attaches to the Bridge
+ *
+ */
+ typedef struct JavaVMCreatedPackageTag {
+ ABHWND64 bridgeWindow;
+ long vmID;
+ } JavaVMCreatedPackage;
+
+ /**
+ * sent when a JavaVM detatches from the Bridge
+ *
+ */
+ typedef struct JavaVMDestroyedPackageTag {
+ ABHWND64 bridgeWindow;
+ } JavaVMDestroyedPackage;
+
+ /**
+ * sent when a new AT attaches to the Bridge
+ *
+ */
+ typedef struct WindowsATCreatedPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATCreatedPackage;
+
+ /**
+ * sent when an AT detatches from the Bridge
+ *
+ */
+ typedef struct WindowsATDestroyedPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATDestroyedPackage;
+
+
+ /**
+ * sent by JVM Bridges in response to a WindowsATCreate
+ * message; saying "howdy, welcome to the neighborhood"
+ *
+ */
+ typedef struct JavaVMPresentNotificationPackageTag {
+ ABHWND64 bridgeWindow;
+ long vmID;
+ } JavaVMPresentNotificationPackage;
+
+ /**
+ * sent by AT Bridges in response to a JavaVMCreate
+ * message; saying "howdy, welcome to the neighborhood"
+ *
+ */
+ typedef struct WindowsATPresentNotificationPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATPresentNotificationPackage;
+
+
+ /**
+ ******************************************************
+ * Core packages
+ ******************************************************
+ */
+
+ typedef struct ReleaseJavaObjectPackageTag {
+ long vmID;
+ JOBJECT64 object;
+ } ReleaseJavaObjectPackage;
+
+ typedef struct GetAccessBridgeVersionPackageTag {
+ long vmID; // can't get VM info w/out a VM!
+ AccessBridgeVersionInfo rVersionInfo;
+ } GetAccessBridgeVersionPackage;
+
+ typedef struct IsSameObjectPackageTag {
+ long vmID;
+ JOBJECT64 obj1;
+ JOBJECT64 obj2;
+ jboolean rResult;
+ } IsSameObjectPackage;
+
+ /**
+ ******************************************************
+ * Windows packages
+ ******************************************************
+ */
+
+ typedef struct IsJavaWindowPackageTag {
+ jint window;
+ jboolean rResult;
+ } IsJavaWindowPackage;
+
+ typedef struct GetAccessibleContextFromHWNDPackageTag {
+ jint window;
+ long rVMID;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextFromHWNDPackage;
+
+ typedef struct GetHWNDFromAccessibleContextPackageTag {
+ JOBJECT64 accessibleContext;
+ ABHWND64 rHWND;
+ } GetHWNDFromAccessibleContextPackage;
+
+ /**
+******************************************************
+* AccessibleContext packages
+******************************************************
+*/
+
+ typedef struct GetAccessibleContextAtPackageTag {
+ jint x;
+ jint y;
+ long vmID;
+ JOBJECT64 AccessibleContext; // look within this AC
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextAtPackage;
+
+ typedef struct GetAccessibleContextWithFocusPackageTag {
+ long rVMID;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextWithFocusPackage;
+
+ typedef struct GetAccessibleContextInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ AccessibleContextInfo rAccessibleContextInfo;
+ } GetAccessibleContextInfoPackage;
+
+ typedef struct GetAccessibleChildFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint childIndex;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleChildFromContextPackage;
+
+ typedef struct GetAccessibleParentFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleParentFromContextPackage;
+
+ /**
+******************************************************
+* AccessibleTable packages
+******************************************************
+*/
+
+#define MAX_TABLE_SELECTIONS 64
+
+ // table information
+ typedef struct AccessibleTableInfoTag {
+ JOBJECT64 caption; // AccesibleContext
+ JOBJECT64 summary; // AccessibleContext
+ jint rowCount;
+ jint columnCount;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 accessibleTable;
+ } AccessibleTableInfo;
+
+ typedef struct GetAccessibleTableInfoPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableInfoPackage;
+
+ // table cell information
+ typedef struct AccessibleTableCellInfoTag {
+ JOBJECT64 accessibleContext;
+ jint index;
+ jint row;
+ jint column;
+ jint rowExtent;
+ jint columnExtent;
+ jboolean isSelected;
+ } AccessibleTableCellInfo;
+
+ typedef struct GetAccessibleTableCellInfoPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jint column;
+ AccessibleTableCellInfo rTableCellInfo;
+ } GetAccessibleTableCellInfoPackage;
+
+ typedef struct GetAccessibleTableRowHeaderPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableRowHeaderPackage;
+
+ typedef struct GetAccessibleTableColumnHeaderPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableColumnHeaderPackage;
+
+ typedef struct GetAccessibleTableRowDescriptionPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint row;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleTableRowDescriptionPackage;
+
+ typedef struct GetAccessibleTableColumnDescriptionPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint column;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleTableColumnDescriptionPackage;
+
+ typedef struct GetAccessibleTableRowSelectionCountPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint rCount;
+ } GetAccessibleTableRowSelectionCountPackage;
+
+ typedef struct IsAccessibleTableRowSelectedPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jboolean rResult;
+ } IsAccessibleTableRowSelectedPackage;
+
+ typedef struct GetAccessibleTableRowSelectionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint count;
+ jint rSelections[MAX_TABLE_SELECTIONS];
+ } GetAccessibleTableRowSelectionsPackage;
+
+ typedef struct GetAccessibleTableColumnSelectionCountPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint rCount;
+ } GetAccessibleTableColumnSelectionCountPackage;
+
+ typedef struct IsAccessibleTableColumnSelectedPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint column;
+ jboolean rResult;
+ } IsAccessibleTableColumnSelectedPackage;
+
+ typedef struct GetAccessibleTableColumnSelectionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint count;
+ jint rSelections[MAX_TABLE_SELECTIONS];
+ } GetAccessibleTableColumnSelectionsPackage;
+
+
+ typedef struct GetAccessibleTableRowPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint index;
+ jint rRow;
+ } GetAccessibleTableRowPackage;
+
+ typedef struct GetAccessibleTableColumnPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint index;
+ jint rColumn;
+ } GetAccessibleTableColumnPackage;
+
+ typedef struct GetAccessibleTableIndexPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jint column;
+ jint rIndex;
+ } GetAccessibleTableIndexPackage;
+
+
+ /**
+ ******************************************************
+ * AccessibleRelationSet packages
+ ******************************************************
+ */
+
+#define MAX_RELATION_TARGETS 25
+#define MAX_RELATIONS 5
+
+ typedef struct AccessibleRelationInfoTag {
+ wchar_t key[SHORT_STRING_SIZE];
+ jint targetCount;
+ JOBJECT64 targets[MAX_RELATION_TARGETS]; // AccessibleContexts
+ } AccessibleRelationInfo;
+
+ typedef struct AccessibleRelationSetInfoTag {
+ jint relationCount;
+ AccessibleRelationInfo relations[MAX_RELATIONS];
+ } AccessibleRelationSetInfo;
+
+ typedef struct GetAccessibleRelationSetPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleRelationSetInfo rAccessibleRelationSetInfo;
+ } GetAccessibleRelationSetPackage;
+
+ /**
+ ******************************************************
+ * AccessibleHypertext packagess
+ ******************************************************
+ */
+
+#define MAX_HYPERLINKS 64 // maximum number of hyperlinks returned
+
+ // hyperlink information
+ typedef struct AccessibleHyperlinkInfoTag {
+ wchar_t text[SHORT_STRING_SIZE]; // the hyperlink text
+ jint startIndex; //index in the hypertext document where the link begins
+ jint endIndex; //index in the hypertext document where the link ends
+ JOBJECT64 accessibleHyperlink; // AccessibleHyperlink object
+ } AccessibleHyperlinkInfo;
+
+ // hypertext information
+ typedef struct AccessibleHypertextInfoTag {
+ jint linkCount; // number of hyperlinks
+ AccessibleHyperlinkInfo links[MAX_HYPERLINKS]; // the hyperlinks
+ JOBJECT64 accessibleHypertext; // AccessibleHypertext object
+ } AccessibleHypertextInfo;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ typedef struct GetAccessibleHypertextPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext with hypertext
+ AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext
+ } GetAccessibleHypertextPackage;
+
+ // struct for sending an message to activate a hyperlink
+ typedef struct ActivateAccessibleHyperlinkPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext containing the link
+ JOBJECT64 accessibleHyperlink; // the link to activate
+ BOOL rResult; // hyperlink activation return value
+ } ActivateAccessibleHyperlinkPackage;
+
+ // struct for sending a message to get the number of hyperlinks in a component
+ typedef struct GetAccessibleHyperlinkCountPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext containing AccessibleHypertext
+ jint rLinkCount; // link count return value
+ } GetAccessibleHyperlinkCountPackage;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ // starting at a specified index in the document
+ typedef struct GetAccessibleHypertextExtPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext with hypertext
+ jint startIndex; // start index in document
+ AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext
+ BOOL rSuccess; // whether call succeeded
+ } GetAccessibleHypertextExtPackage;
+
+ // struct for sending a message to get the nth hyperlink in a document;
+ // maps to AccessibleHypertext.getLink
+ typedef struct GetAccessibleHyperlinkPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 hypertext; // AccessibleHypertext
+ jint linkIndex; // hyperlink index
+ AccessibleHyperlinkInfo rAccessibleHyperlinkInfo; // returned hyperlink
+ } GetAccessibleHyperlinkPackage;
+
+ // struct for sending a message to get the index into an array
+ // of hyperlinks that is associated with a character index in a
+ // document; maps to AccessibleHypertext.getLinkIndex
+ typedef struct GetAccessibleHypertextLinkIndexPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 hypertext; // AccessibleHypertext
+ jint charIndex; // character index in document
+ jint rLinkIndex; // returned hyperlink index
+ } GetAccessibleHypertextLinkIndexPackage;
+
+ /**
+ ******************************************************
+ * Accessible Key Bindings packages
+ ******************************************************
+ */
+
+#define MAX_KEY_BINDINGS 10
+
+ // keyboard character modifiers
+#define ACCESSIBLE_SHIFT_KEYSTROKE 1
+#define ACCESSIBLE_CONTROL_KEYSTROKE 2
+#define ACCESSIBLE_META_KEYSTROKE 4
+#define ACCESSIBLE_ALT_KEYSTROKE 8
+#define ACCESSIBLE_ALT_GRAPH_KEYSTROKE 16
+#define ACCESSIBLE_BUTTON1_KEYSTROKE 32
+#define ACCESSIBLE_BUTTON2_KEYSTROKE 64
+#define ACCESSIBLE_BUTTON3_KEYSTROKE 128
+#define ACCESSIBLE_FKEY_KEYSTROKE 256 // F key pressed, character contains 1-24
+#define ACCESSIBLE_CONTROLCODE_KEYSTROKE 512 // Control code key pressed, character contains control code.
+
+// The supported control code keys are:
+#define ACCESSIBLE_VK_BACK_SPACE 8
+#define ACCESSIBLE_VK_DELETE 127
+#define ACCESSIBLE_VK_DOWN 40
+#define ACCESSIBLE_VK_END 35
+#define ACCESSIBLE_VK_HOME 36
+#define ACCESSIBLE_VK_INSERT 155
+#define ACCESSIBLE_VK_KP_DOWN 225
+#define ACCESSIBLE_VK_KP_LEFT 226
+#define ACCESSIBLE_VK_KP_RIGHT 227
+#define ACCESSIBLE_VK_KP_UP 224
+#define ACCESSIBLE_VK_LEFT 37
+#define ACCESSIBLE_VK_PAGE_DOWN 34
+#define ACCESSIBLE_VK_PAGE_UP 33
+#define ACCESSIBLE_VK_RIGHT 39
+#define ACCESSIBLE_VK_UP 38
+
+ // a key binding associates with a component
+ typedef struct AccessibleKeyBindingInfoTag {
+ jchar character; // the key character
+ jint modifiers; // the key modifiers
+ } AccessibleKeyBindingInfo;
+
+ // all of the key bindings associated with a component
+ typedef struct AccessibleKeyBindingsTag {
+ int keyBindingsCount; // number of key bindings
+ AccessibleKeyBindingInfo keyBindingInfo[MAX_KEY_BINDINGS];
+ } AccessibleKeyBindings;
+
+ // struct to get the key bindings associated with a component
+ typedef struct GetAccessibleKeyBindingsPackageTag {
+ long vmID; // the virtual machine id
+ JOBJECT64 accessibleContext; // the component
+ AccessibleKeyBindings rAccessibleKeyBindings; // the key bindings
+ } GetAccessibleKeyBindingsPackage;
+
+ /**
+******************************************************
+* AccessibleIcon packages
+******************************************************
+*/
+#define MAX_ICON_INFO 8
+
+ // an icon assocated with a component
+ typedef struct AccessibleIconInfoTag {
+ wchar_t description[SHORT_STRING_SIZE]; // icon description
+ jint height; // icon height
+ jint width; // icon width
+ } AccessibleIconInfo;
+
+ // all of the icons associated with a component
+ typedef struct AccessibleIconsTag {
+ jint iconsCount; // number of icons
+ AccessibleIconInfo iconInfo[MAX_ICON_INFO]; // the icons
+ } AccessibleIcons;
+
+ // struct to get the icons associated with a component
+ typedef struct GetAccessibleIconsPackageTag {
+ long vmID; // the virtual machine id
+ JOBJECT64 accessibleContext; // the component
+ AccessibleIcons rAccessibleIcons; // the icons
+ } GetAccessibleIconsPackage;
+
+
+ /**
+******************************************************
+* AccessibleAction packages
+******************************************************
+*/
+#define MAX_ACTION_INFO 256
+#define MAX_ACTIONS_TO_DO 32
+
+ // an action assocated with a component
+ typedef struct AccessibleActionInfoTag {
+ wchar_t name[SHORT_STRING_SIZE]; // action name
+ } AccessibleActionInfo;
+
+ // all of the actions associated with a component
+ typedef struct AccessibleActionsTag {
+ jint actionsCount; // number of actions
+ AccessibleActionInfo actionInfo[MAX_ACTION_INFO]; // the action information
+ } AccessibleActions;
+
+ // struct for requesting the actions associated with a component
+ typedef struct GetAccessibleActionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext; // the component
+ AccessibleActions rAccessibleActions; // the actions
+ } GetAccessibleActionsPackage;
+
+ // list of AccessibleActions to do
+ typedef struct AccessibleActionsToDoTag {
+ jint actionsCount; // number of actions to do
+ AccessibleActionInfo actions[MAX_ACTIONS_TO_DO];// the accessible actions to do
+ } AccessibleActionsToDo;
+
+ // struct for sending an message to do one or more actions
+ typedef struct DoAccessibleActionsPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // component to do the action
+ AccessibleActionsToDo actionsToDo; // the accessible actions to do
+ BOOL rResult; // action return value
+ jint failure; // index of action that failed if rResult is FALSE
+ } DoAccessibleActionsPackage;
+
+ /**
+******************************************************
+* AccessibleText packages
+******************************************************
+*/
+
+ typedef struct GetAccessibleTextInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint x;
+ jint y;
+ AccessibleTextInfo rTextInfo;
+ } GetAccessibleTextInfoPackage;
+
+ typedef struct GetAccessibleTextItemsPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextItemsInfo rTextItemsInfo;
+ } GetAccessibleTextItemsPackage;
+
+ typedef struct GetAccessibleTextSelectionInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ AccessibleTextSelectionInfo rTextSelectionItemsInfo;
+ } GetAccessibleTextSelectionInfoPackage;
+
+ typedef struct GetAccessibleTextAttributeInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextAttributesInfo rAttributeInfo;
+ } GetAccessibleTextAttributeInfoPackage;
+
+ typedef struct GetAccessibleTextRectInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextRectInfo rTextRectInfo;
+ } GetAccessibleTextRectInfoPackage;
+
+ typedef struct GetCaretLocationPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextRectInfo rTextRectInfo;
+ } GetCaretLocationPackage;
+
+ typedef struct GetAccessibleTextLineBoundsPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ jint rLineStart;
+ jint rLineEnd;
+ } GetAccessibleTextLineBoundsPackage;
+
+ typedef struct GetAccessibleTextRangePackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint start;
+ jint end;
+ wchar_t rText[MAX_BUFFER_SIZE];
+ } GetAccessibleTextRangePackage;
+
+ /**
+******************************************************
+*
+* Utility method packages
+******************************************************
+*/
+
+ typedef struct SetTextContentsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext; // the text field
+ wchar_t text[MAX_STRING_SIZE]; // the text
+ BOOL rResult;
+ } SetTextContentsPackage;
+
+ typedef struct GetParentWithRolePackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above
+ JOBJECT64 rAccessibleContext;
+ } GetParentWithRolePackage;
+
+ typedef struct GetTopLevelObjectPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetTopLevelObjectPackage;
+
+ typedef struct GetParentWithRoleElseRootPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above
+ JOBJECT64 rAccessibleContext;
+ } GetParentWithRoleElseRootPackage;
+
+ typedef struct GetObjectDepthPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint rResult;
+ } GetObjectDepthPackage;
+
+ typedef struct GetActiveDescendentPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetActiveDescendentPackage;
+
+ /**
+******************************************************
+* AccessibleValue packages
+******************************************************
+*/
+
+ typedef struct GetCurrentAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetCurrentAccessibleValueFromContextPackage;
+
+ typedef struct GetMaximumAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetMaximumAccessibleValueFromContextPackage;
+
+ typedef struct GetMinimumAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetMinimumAccessibleValueFromContextPackage;
+
+
+ /**
+******************************************************
+* AccessibleSelection packages
+******************************************************
+*/
+
+ typedef struct AddAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ } AddAccessibleSelectionFromContextPackage;
+
+ typedef struct ClearAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ } ClearAccessibleSelectionFromContextPackage;
+
+ typedef struct GetAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleSelectionFromContextPackage;
+
+ typedef struct GetAccessibleSelectionCountFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint rCount;
+ } GetAccessibleSelectionCountFromContextPackage;
+
+ typedef struct IsAccessibleChildSelectedFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ jboolean rResult;
+ } IsAccessibleChildSelectedFromContextPackage;
+
+ typedef struct RemoveAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ } RemoveAccessibleSelectionFromContextPackage;
+
+ typedef struct SelectAllAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ } SelectAllAccessibleSelectionFromContextPackage;
+
+
+ /**
+******************************************************
+* Java Event Notification Registration packages
+******************************************************
+*/
+
+ typedef struct AddJavaEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } AddJavaEventNotificationPackage;
+
+ typedef struct RemoveJavaEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } RemoveJavaEventNotificationPackage;
+
+
+ /**
+******************************************************
+* Accessibility Event Notification Registration packages
+******************************************************
+*/
+
+ typedef struct AddAccessibilityEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } AddAccessibilityEventNotificationPackage;
+
+ typedef struct RemoveAccessibilityEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } RemoveAccessibilityEventNotificationPackage;
+
+
+ /**
+******************************************************
+* Accessibility Property Change Event packages
+******************************************************
+*/
+
+ typedef struct PropertyCaretChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ jint oldPosition;
+ jint newPosition;
+ } PropertyCaretChangePackage;
+
+ typedef struct PropertyDescriptionChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldDescription[SHORT_STRING_SIZE];
+ wchar_t newDescription[SHORT_STRING_SIZE];
+ } PropertyDescriptionChangePackage;
+
+ typedef struct PropertyNameChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldName[SHORT_STRING_SIZE];
+ wchar_t newName[SHORT_STRING_SIZE];
+ } PropertyNameChangePackage;
+
+ typedef struct PropertySelectionChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertySelectionChangePackage;
+
+ typedef struct PropertyStateChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldState[SHORT_STRING_SIZE];
+ wchar_t newState[SHORT_STRING_SIZE];
+ } PropertyStateChangePackage;
+
+ typedef struct PropertyTextChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertyTextChangePackage;
+
+ typedef struct PropertyValueChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldValue[SHORT_STRING_SIZE];
+ wchar_t newValue[SHORT_STRING_SIZE];
+ } PropertyValueChangePackage;
+
+ typedef struct PropertyVisibleDataChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertyVisibleDataChangePackage;
+
+ typedef struct PropertyChildChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ JOBJECT64 oldChildAccessibleContext;
+ JOBJECT64 newChildAccessibleContext;
+ } PropertyChildChangePackage;
+
+ typedef struct PropertyActiveDescendentChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ JOBJECT64 oldActiveDescendentAccessibleContext;
+ JOBJECT64 newActiveDescendentAccessibleContext;
+ } PropertyActiveDescendentChangePackage;
+
+
+ // String format for newValue is:
+ // "type" one of "INSERT", "UPDATE" or "DELETE"
+ // "firstRow"
+ // "lastRow"
+ // "firstColumn"
+ // "lastColumn"
+ //
+ // oldValue is currently unused
+ //
+ typedef struct PropertyTableModelChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldValue[SHORT_STRING_SIZE];
+ wchar_t newValue[SHORT_STRING_SIZE];
+ } PropertyTableModelChangePackage;
+
+
+ /**
+******************************************************
+* Property Change Event packages
+******************************************************
+*/
+
+ /*
+ typedef struct PropertyChangePackageTag {
+ long vmID;
+ jobject Event;
+ jobject AccessibleContextSource;
+ char propertyName[SHORT_STRING_SIZE];
+ char oldValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getOldValue().toString()
+ char newValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getNewValue().toString()
+ } PropertyChangePackage;
+ */
+
+ /*
+ * Java shutdown event package
+ */
+ typedef struct JavaShutdownPackageTag {
+ long vmID;
+ } JavaShutdownPackage;
+
+
+ /**
+******************************************************
+* Focus Event packages
+******************************************************
+*/
+
+ typedef struct FocusGainedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } FocusGainedPackage;
+
+ typedef struct FocusLostPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } FocusLostPackage;
+
+
+ /**
+******************************************************
+* Caret Event packages
+******************************************************
+*/
+
+ typedef struct CaretUpdatePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } CaretUpdatePackage;
+
+
+ /**
+******************************************************
+* Mouse Event packages
+******************************************************
+*/
+
+ typedef struct MouseClickedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseClickedPackage;
+
+ typedef struct MouseEnteredPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseEnteredPackage;
+
+ typedef struct MouseExitedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseExitedPackage;
+
+ typedef struct MousePressedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MousePressedPackage;
+
+ typedef struct MouseReleasedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseReleasedPackage;
+
+
+ /**
+******************************************************
+* Menu/PopupMenu Event packages
+******************************************************
+*/
+
+ typedef struct MenuCanceledPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuCanceledPackage;
+
+ typedef struct MenuDeselectedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuDeselectedPackage;
+
+ typedef struct MenuSelectedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuSelectedPackage;
+
+
+ typedef struct PopupMenuCanceledPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuCanceledPackage;
+
+ typedef struct PopupMenuWillBecomeInvisiblePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuWillBecomeInvisiblePackage;
+
+ typedef struct PopupMenuWillBecomeVisiblePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuWillBecomeVisiblePackage;
+
+ /**
+******************************************************
+* Additional methods for Teton
+******************************************************
+*/
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ typedef struct GetVirtualAccessibleNamePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ wchar_t rName[MAX_STRING_SIZE];
+ int len;
+ } GetVirtualAccessibleNamePackage;
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ typedef struct RequestFocusPackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ } RequestFocusPackage;
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ typedef struct SelectTextRangePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint startIndex;
+ jint endIndex;
+ } SelectTextRangePackage;
+
+ /**
+ * Gets the number of contiguous characters with the same attributes.
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ typedef struct GetTextAttributesInRangePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint startIndex; // start index (inclusive)
+ jint endIndex; // end index (inclusive)
+ AccessibleTextAttributesInfo attributes; // character attributes to match
+ short rLength; // number of contiguous characters with matching attributes
+ } GetTextAttributesInRangePackage;
+
+#define MAX_VISIBLE_CHILDREN 256
+
+ // visible children information
+ typedef struct VisibleChildenInfoTag {
+ int returnedChildrenCount; // number of children returned
+ AccessibleContext children[MAX_VISIBLE_CHILDREN]; // the visible children
+ } VisibleChildrenInfo;
+
+ // struct for sending a message to get the number of visible children
+ typedef struct GetVisibleChildrenCountPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext of parent component
+ jint rChildrenCount; // visible children count return value
+ } GetVisibleChildrenCountPackage;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ // starting at a specified index in the document
+ typedef struct GetVisibleChildrenPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext of parent component
+ jint startIndex; // start index for retrieving children
+ VisibleChildrenInfo rVisibleChildrenInfo; // returned info
+ BOOL rSuccess; // whether call succeeded
+ } GetVisibleChildrenPackage;
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ typedef struct SetCaretPositionPackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint position;
+ } SetCaretPositionPackage;
+
+
+ /**
+ ******************************************************
+ * Wrapping up all of the packages
+ ******************************************************
+ */
+
+ /**
+ * What is the type of this package
+ */
+ typedef enum PackageType {
+
+ cMemoryMappedFileCreatedPackage = 0x11000,
+
+ // many of these will go away...
+ cJavaVMCreatedPackage = 0x10000,
+ cJavaVMDestroyedPackage,
+ cWindowsATCreatedPackage,
+ cWindowsATDestroyedPackage,
+ cJavaVMPresentNotificationPackage,
+ cWindowsATPresentNotificationPackage,
+
+ cReleaseJavaObjectPackage = 1,
+ cGetAccessBridgeVersionPackage = 2,
+
+ cGetAccessibleContextFromHWNDPackage = 0x10,
+ cIsJavaWindowPackage,
+ cGetHWNDFromAccessibleContextPackage,
+
+ cGetAccessibleContextAtPackage = 0x100,
+ cGetAccessibleContextWithFocusPackage,
+ cGetAccessibleContextInfoPackage,
+ cGetAccessibleChildFromContextPackage,
+ cGetAccessibleParentFromContextPackage,
+ cIsSameObjectPackage,
+
+ cGetAccessibleTextInfoPackage = 0x200,
+ cGetAccessibleTextItemsPackage,
+ cGetAccessibleTextSelectionInfoPackage,
+ cGetAccessibleTextAttributeInfoPackage,
+ cGetAccessibleTextRectInfoPackage,
+ cGetAccessibleTextLineBoundsPackage,
+ cGetAccessibleTextRangePackage,
+
+ cGetCurrentAccessibleValueFromContextPackage = 0x300,
+ cGetMaximumAccessibleValueFromContextPackage,
+ cGetMinimumAccessibleValueFromContextPackage,
+
+ cAddAccessibleSelectionFromContextPackage = 0x400,
+ cClearAccessibleSelectionFromContextPackage,
+ cGetAccessibleSelectionFromContextPackage,
+ cGetAccessibleSelectionCountFromContextPackage,
+ cIsAccessibleChildSelectedFromContextPackage,
+ cRemoveAccessibleSelectionFromContextPackage,
+ cSelectAllAccessibleSelectionFromContextPackage,
+
+ cAddJavaEventNotificationPackage = 0x900,
+ cRemoveJavaEventNotificationPackage,
+ cAddAccessibilityEventNotificationPackage,
+ cRemoveAccessibilityEventNotificationPackage,
+
+ cPropertyChangePackage = 0x1000,
+
+ cJavaShutdownPackage = 0x1010,
+ cFocusGainedPackage,
+ cFocusLostPackage,
+
+ cCaretUpdatePackage = 0x1020,
+
+ cMouseClickedPackage = 0x1030,
+ cMouseEnteredPackage,
+ cMouseExitedPackage,
+ cMousePressedPackage,
+ cMouseReleasedPackage,
+
+ cMenuCanceledPackage = 0x1040,
+ cMenuDeselectedPackage,
+ cMenuSelectedPackage,
+ cPopupMenuCanceledPackage,
+ cPopupMenuWillBecomeInvisiblePackage,
+ cPopupMenuWillBecomeVisiblePackage,
+
+ cPropertyCaretChangePackage = 0x1100,
+ cPropertyDescriptionChangePackage,
+ cPropertyNameChangePackage,
+ cPropertySelectionChangePackage,
+ cPropertyStateChangePackage,
+ cPropertyTextChangePackage,
+ cPropertyValueChangePackage,
+ cPropertyVisibleDataChangePackage,
+ cPropertyChildChangePackage,
+ cPropertyActiveDescendentChangePackage,
+
+
+ // AccessibleTable
+ cGetAccessibleTableInfoPackage = 0x1200,
+ cGetAccessibleTableCellInfoPackage,
+
+ cGetAccessibleTableRowHeaderPackage,
+ cGetAccessibleTableColumnHeaderPackage,
+
+ cGetAccessibleTableRowDescriptionPackage,
+ cGetAccessibleTableColumnDescriptionPackage,
+
+ cGetAccessibleTableRowSelectionCountPackage,
+ cIsAccessibleTableRowSelectedPackage,
+ cGetAccessibleTableRowSelectionsPackage,
+
+ cGetAccessibleTableColumnSelectionCountPackage,
+ cIsAccessibleTableColumnSelectedPackage,
+ cGetAccessibleTableColumnSelectionsPackage,
+
+ cGetAccessibleTableRowPackage,
+ cGetAccessibleTableColumnPackage,
+ cGetAccessibleTableIndexPackage,
+
+ cPropertyTableModelChangePackage,
+
+
+ // AccessibleRelationSet
+ cGetAccessibleRelationSetPackage = 0x1300,
+
+ // AccessibleHypertext
+ cGetAccessibleHypertextPackage = 0x1400,
+ cActivateAccessibleHyperlinkPackage,
+ cGetAccessibleHyperlinkCountPackage,
+ cGetAccessibleHypertextExtPackage,
+ cGetAccessibleHypertextLinkIndexPackage,
+ cGetAccessibleHyperlinkPackage,
+
+ // Accessible KeyBinding, Icon and Action
+ cGetAccessibleKeyBindingsPackage = 0x1500,
+ cGetAccessibleIconsPackage,
+ cGetAccessibleActionsPackage,
+ cDoAccessibleActionsPackage,
+
+ // Utility methods
+ cSetTextContentsPackage = 0x1600,
+ cGetParentWithRolePackage,
+ cGetTopLevelObjectPackage,
+ cGetParentWithRoleElseRootPackage,
+ cGetObjectDepthPackage,
+ cGetActiveDescendentPackage,
+
+ // Additional methods for Teton
+ cGetVirtualAccessibleNamePackage = 0x1700,
+ cRequestFocusPackage,
+ cSelectTextRangePackage,
+ cGetTextAttributesInRangePackage,
+ cGetSameTextAttributesInRangePackage,
+ cGetVisibleChildrenCountPackage,
+ cGetVisibleChildrenPackage,
+ cSetCaretPositionPackage,
+ cGetCaretLocationPackage
+
+
+ } PackageType;
+
+
+ /**
+ * Union of all package contents
+ */
+ typedef union AllPackagesTag {
+
+ // Initial Rendezvous packages
+ MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage;
+
+ JavaVMCreatedPackage javaVMCreatedPackage;
+ JavaVMDestroyedPackage javaVMDestroyedPackage;
+ WindowsATCreatedPackage windowsATCreatedPackage;
+ WindowsATDestroyedPackage windowsATDestroyedPackage;
+ JavaVMPresentNotificationPackage javaVMPresentNotificationPackage;
+ WindowsATPresentNotificationPackage windowsATPresentNotificationPackage;
+
+ // Core packages
+ ReleaseJavaObjectPackage releaseJavaObject;
+ GetAccessBridgeVersionPackage getAccessBridgeVersion;
+
+ // Window packages
+ GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND;
+ GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext;
+
+ // AccessibleContext packages
+ GetAccessibleContextAtPackage getAccessibleContextAt;
+ GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus;
+ GetAccessibleContextInfoPackage getAccessibleContextInfo;
+ GetAccessibleChildFromContextPackage getAccessibleChildFromContext;
+ GetAccessibleParentFromContextPackage getAccessibleParentFromContext;
+
+ // AccessibleText packages
+ GetAccessibleTextInfoPackage getAccessibleTextInfo;
+ GetAccessibleTextItemsPackage getAccessibleTextItems;
+ GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo;
+ GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo;
+ GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds;
+ GetAccessibleTextRangePackage getAccessibleTextRange;
+
+ // AccessibleValue packages
+ GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext;
+
+ // AccessibleSelection packages
+ AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext;
+
+ // Event Notification Registration packages
+ AddJavaEventNotificationPackage addJavaEventNotification;
+ RemoveJavaEventNotificationPackage removeJavaEventNotification;
+ AddAccessibilityEventNotificationPackage addAccessibilityEventNotification;
+ RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification;
+
+ // Event contents packages
+ // PropertyChangePackage propertyChange;
+ PropertyCaretChangePackage propertyCaretChangePackage;
+ PropertyDescriptionChangePackage propertyDescriptionChangePackage;
+ PropertyNameChangePackage propertyNameChangePackage;
+ PropertySelectionChangePackage propertySelectionChangePackage;
+ PropertyStateChangePackage propertyStateChangePackage;
+ PropertyTextChangePackage propertyTextChangePackage;
+ PropertyValueChangePackage propertyValueChangePackage;
+ PropertyVisibleDataChangePackage propertyVisibleDataChangePackage;
+ PropertyChildChangePackage propertyChildChangePackage;
+ PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage;
+
+ PropertyTableModelChangePackage propertyTableModelChangePackage;
+
+ JavaShutdownPackage JavaShutdown;
+ FocusGainedPackage focusGained;
+ FocusLostPackage focusLost;
+
+ CaretUpdatePackage caretUpdate;
+
+ MouseClickedPackage mouseClicked;
+ MouseEnteredPackage mouseEntered;
+ MouseExitedPackage mouseExited;
+ MousePressedPackage mousePressed;
+ MouseReleasedPackage mouseReleased;
+
+ MenuCanceledPackage menuCanceled;
+ MenuDeselectedPackage menuDeselected;
+ MenuSelectedPackage menuSelected;
+ PopupMenuCanceledPackage popupMenuCanceled;
+ PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible;
+ PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible;
+
+ // AccessibleRelationSet
+ GetAccessibleRelationSetPackage getAccessibleRelationSet;
+
+ // AccessibleHypertext
+ GetAccessibleHypertextPackage _getAccessibleHypertext;
+ ActivateAccessibleHyperlinkPackage _activateAccessibleHyperlink;
+ GetAccessibleHyperlinkCountPackage _getAccessibleHyperlinkCount;
+ GetAccessibleHypertextExtPackage _getAccessibleHypertextExt;
+ GetAccessibleHypertextLinkIndexPackage _getAccessibleHypertextLinkIndex;
+ GetAccessibleHyperlinkPackage _getAccessibleHyperlink;
+
+ // Accessible KeyBinding, Icon and Action
+ GetAccessibleKeyBindingsPackage getAccessibleKeyBindings;
+ GetAccessibleIconsPackage getAccessibleIcons;
+ GetAccessibleActionsPackage getAccessibleActions;
+ DoAccessibleActionsPackage doAccessibleActions;
+
+ // utility methods
+ SetTextContentsPackage _setTextContents;
+ GetParentWithRolePackage _getParentWithRole;
+ GetTopLevelObjectPackage _getTopLevelObject;
+ GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot;
+ GetObjectDepthPackage _getObjectDepth;
+ GetActiveDescendentPackage _getActiveDescendent;
+
+ // Additional methods for Teton
+ GetVirtualAccessibleNamePackage _getVirtualAccessibleName;
+ RequestFocusPackage _requestFocus;
+ SelectTextRangePackage _selectTextRange;
+ GetTextAttributesInRangePackage _getTextAttributesInRange;
+ GetVisibleChildrenCountPackage _getVisibleChildrenCount;
+ GetVisibleChildrenPackage _getVisibleChildren;
+ SetCaretPositionPackage _setCaretPosition;
+
+ } AllPackages;
+
+
+ /**
+ * Union of all Java-initiated package contents
+ */
+ typedef union JavaInitiatedPackagesTag {
+
+ // Initial Rendezvous packages
+ JavaVMCreatedPackage javaVMCreatedPackage;
+ JavaVMDestroyedPackage javaVMDestroyedPackage;
+ JavaVMPresentNotificationPackage javaVMPresentNotificationPackage;
+
+ // Event contents packages
+ PropertyCaretChangePackage propertyCaretChangePackage;
+ PropertyDescriptionChangePackage propertyDescriptionChangePackage;
+ PropertyNameChangePackage propertyNameChangePackage;
+ PropertySelectionChangePackage propertySelectionChangePackage;
+ PropertyStateChangePackage propertyStateChangePackage;
+ PropertyTextChangePackage propertyTextChangePackage;
+ PropertyValueChangePackage propertyValueChangePackage;
+ PropertyVisibleDataChangePackage propertyVisibleDataChangePackage;
+ PropertyChildChangePackage propertyChildChangePackage;
+ PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage;
+
+ PropertyTableModelChangePackage propertyTableModelChangePackage;
+
+ JavaShutdownPackage JavaShutdown;
+ FocusGainedPackage focusGained;
+ FocusLostPackage focusLost;
+
+ CaretUpdatePackage caretUpdate;
+
+ MouseClickedPackage mouseClicked;
+ MouseEnteredPackage mouseEntered;
+ MouseExitedPackage mouseExited;
+ MousePressedPackage mousePressed;
+ MouseReleasedPackage mouseReleased;
+
+ MenuCanceledPackage menuCanceled;
+ MenuDeselectedPackage menuDeselected;
+ MenuSelectedPackage menuSelected;
+ PopupMenuCanceledPackage popupMenuCanceled;
+ PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible;
+ PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible;
+
+ } JavaInitiatedPackages;
+
+
+ /**
+ * Union of all Windows-initiated package contents
+ */
+ typedef union WindowsInitiatedPackagesTag {
+
+ // Initial Rendezvous packages
+ MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage;
+
+ WindowsATCreatedPackage windowsATCreatedPackage;
+ WindowsATDestroyedPackage windowsATDestroyedPackage;
+ WindowsATPresentNotificationPackage windowsATPresentNotificationPackage;
+
+ // Core packages
+ ReleaseJavaObjectPackage releaseJavaObject;
+ GetAccessBridgeVersionPackage getAccessBridgeVersion;
+
+ // Window packages
+ GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND;
+ GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext;
+
+ // AccessibleContext packages
+ GetAccessibleContextAtPackage getAccessibleContextAt;
+ GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus;
+ GetAccessibleContextInfoPackage getAccessibleContextInfo;
+ GetAccessibleChildFromContextPackage getAccessibleChildFromContext;
+ GetAccessibleParentFromContextPackage getAccessibleParentFromContext;
+
+ // AccessibleText packages
+ GetAccessibleTextInfoPackage getAccessibleTextInfo;
+ GetAccessibleTextItemsPackage getAccessibleTextItems;
+ GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo;
+ GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo;
+ GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds;
+ GetAccessibleTextRangePackage getAccessibleTextRange;
+
+ // AccessibleValue packages
+ GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext;
+
+ // AccessibleSelection packages
+ AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext;
+
+ // Event Notification Registration packages
+ AddJavaEventNotificationPackage addJavaEventNotification;
+ RemoveJavaEventNotificationPackage removeJavaEventNotification;
+ AddAccessibilityEventNotificationPackage addAccessibilityEventNotification;
+ RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification;
+
+ // AccessibleTable
+ GetAccessibleTableInfoPackage _getAccessibleTableInfo;
+ GetAccessibleTableCellInfoPackage _getAccessibleTableCellInfo;
+
+ GetAccessibleTableRowHeaderPackage _getAccessibleTableRowHeader;
+ GetAccessibleTableColumnHeaderPackage _getAccessibleTableColumnHeader;
+
+ GetAccessibleTableRowDescriptionPackage _getAccessibleTableRowDescription;
+ GetAccessibleTableColumnDescriptionPackage _getAccessibleTableColumnDescription;
+
+ GetAccessibleTableRowSelectionCountPackage _getAccessibleTableRowSelectionCount;
+ IsAccessibleTableRowSelectedPackage _isAccessibleTableRowSelected;
+ GetAccessibleTableRowSelectionsPackage _getAccessibleTableRowSelections;
+
+ GetAccessibleTableColumnSelectionCountPackage _getAccessibleTableColumnSelectionCount;
+ IsAccessibleTableColumnSelectedPackage _isAccessibleTableColumnSelected;
+ GetAccessibleTableColumnSelectionsPackage _getAccessibleTableColumnSelections;
+
+ GetAccessibleTableRowPackage _getAccessibleTableRow;
+ GetAccessibleTableColumnPackage _getAccessibleTableColumn;
+ GetAccessibleTableIndexPackage _getAccessibleTableIndex;
+
+ // AccessibleRelationSet
+ GetAccessibleRelationSetPackage _getAccessibleRelationSet;
+
+ // Accessible KeyBindings, Icons and Actions
+ GetAccessibleKeyBindingsPackage _getAccessibleKeyBindings;
+ GetAccessibleIconsPackage _getAccessibleIcons;
+ GetAccessibleActionsPackage _getAccessibleActions;
+ DoAccessibleActionsPackage _doAccessibleActions;
+
+
+ IsSameObjectPackage _isSameObject;
+
+ // utility methods
+ SetTextContentsPackage _setTextContents;
+ GetParentWithRolePackage _getParentWithRole;
+ GetTopLevelObjectPackage _getTopLevelObject;
+ GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot;
+ GetObjectDepthPackage _getObjectDepth;
+ GetActiveDescendentPackage _getActiveDescendent;
+
+ // Additional methods for Teton
+ GetVirtualAccessibleNamePackage _getVirtualAccessibleName;
+ RequestFocusPackage _requestFocus;
+ SelectTextRangePackage _selectTextRange;
+ GetTextAttributesInRangePackage _getTextAttributesInRange;
+ GetVisibleChildrenCountPackage _getVisibleChildrenCount;
+ GetVisibleChildrenPackage _getVisibleChildren;
+ SetCaretPositionPackage _setCaretPosition;
+
+
+ } WindowsInitiatedPackages;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/client/jni/windows/win32/jawt_md.h b/source/client/jni/windows/win32/jawt_md.h
new file mode 100644
index 0000000000000000000000000000000000000000..1dab7cf2d2243cdaaa022299b213293b884652a6
--- /dev/null
+++ b/source/client/jni/windows/win32/jawt_md.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JAWT_MD_H_
+#define _JAVASOFT_JAWT_MD_H_
+
+#include
+#include "jawt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Win32-specific declarations for AWT native interface.
+ * See notes in jawt.h for an example of use.
+ */
+typedef struct jawt_Win32DrawingSurfaceInfo {
+ /* Native window, DDB, or DIB handle */
+ union {
+ HWND hwnd;
+ HBITMAP hbitmap;
+ void* pbits;
+ };
+ /*
+ * This HDC should always be used instead of the HDC returned from
+ * BeginPaint() or any calls to GetDC().
+ */
+ HDC hdc;
+ HPALETTE hpalette;
+} JAWT_Win32DrawingSurfaceInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_JAVASOFT_JAWT_MD_H_ */
diff --git a/source/client/jni/windows/win32/jni_md.h b/source/client/jni/windows/win32/jni_md.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d7dece990242ce7b5b6ad9215b6a3132a349300
--- /dev/null
+++ b/source/client/jni/windows/win32/jni_md.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT __declspec(dllexport)
+#define JNIIMPORT __declspec(dllimport)
+#define JNICALL __stdcall
+
+typedef long jint;
+typedef __int64 jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/source/client/src/TMQConnector.c b/source/client/src/TMQConnector.c
new file mode 100644
index 0000000000000000000000000000000000000000..1d84dcf7a2be09516b15a095a6013af53f68c60c
--- /dev/null
+++ b/source/client/src/TMQConnector.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "com_taosdata_jdbc_tmq_TMQConnector.h"
+#include "jniCommon.h"
+#include "taos.h"
+
+void commit_cb(tmq_t *tmq, int32_t code, void *param) {
+ JNIEnv *env = NULL;
+ int status = (*g_vm)->GetEnv(g_vm, (void **)&env, JNI_VERSION_1_6);
+ bool needDetach = false;
+ if (status < 0) {
+ if ((*g_vm)->AttachCurrentThread(g_vm, (void **)&env, NULL) != 0) {
+ return;
+ }
+ needDetach = true;
+ }
+
+ jobject obj = (jobject)param;
+ (*env)->CallVoidMethod(env, obj, g_commitCallback, code);
+
+ (*env)->DeleteGlobalRef(env, obj);
+ param = NULL;
+
+ if (needDetach) {
+ (*g_vm)->DetachCurrentThread(g_vm);
+ }
+ env = NULL;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfNewImp(JNIEnv *env, jobject jobj) {
+ tmq_conf_t *conf = tmq_conf_new();
+ return (jlong)conf;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfSetImp(JNIEnv *env, jobject jobj, jlong conf,
+ jstring jkey, jstring jvalue) {
+ if (jkey == NULL) {
+ jniError("jobj:%p, failed set tmq config. key is null", jobj);
+ return TMQ_CONF_KEY_NULL;
+ }
+ const char *key = (*env)->GetStringUTFChars(env, jkey, NULL);
+
+ if (jvalue == NULL) {
+ jniError("jobj:%p, failed set tmq config. key %s, value is null", jobj, key);
+ (*env)->ReleaseStringUTFChars(env, jkey, key);
+ return TMQ_CONF_VALUE_NULL;
+ }
+ const char *value = (*env)->GetStringUTFChars(env, jvalue, NULL);
+
+ tmq_conf_res_t res = tmq_conf_set((tmq_conf_t *)conf, key, value);
+ (*env)->ReleaseStringUTFChars(env, jkey, key);
+ (*env)->ReleaseStringUTFChars(env, jvalue, value);
+ return (jint)res;
+}
+
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfDestroyImp(JNIEnv *env, jobject jobj,
+ jlong jconf) {
+ tmq_conf_t *conf = (tmq_conf_t *)jconf;
+ if (conf == NULL) {
+ jniDebug("jobj:%p, tmq config is already destroyed", jobj);
+ } else {
+ tmq_conf_destroy(conf);
+ jniDebug("jobj:%p, config:%p, tmq successfully destroy config", jobj, conf);
+ }
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerNewImp(JNIEnv *env, jobject jobj,
+ jlong jconf, jobject jconsumer) {
+ tmq_conf_t *conf = (tmq_conf_t *)jconf;
+ if (conf == NULL) {
+ jniError("jobj:%p, tmq config is already destroyed", jobj);
+ return TMQ_CONF_NULL;
+ }
+ int len = 1024;
+ char *msg = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1));
+ if (msg == NULL) {
+ jniError("jobj:%p, config:%p, tmq alloc memory failed", jobj, conf);
+ return JNI_OUT_OF_MEMORY;
+ }
+ tmq_t *tmq = tmq_consumer_new((tmq_conf_t *)conf, msg, len);
+ if (strlen(msg) > 0) {
+ jniError("jobj:%p, config:%p, tmq create consumer error: %s", jobj, conf, msg);
+ (*env)->CallVoidMethod(env, jconsumer, g_createConsumerErrorCallback, (*env)->NewStringUTF(env, msg));
+ taosMemoryFreeClear(msg);
+ return TMQ_CONSUMER_CREATE_ERROR;
+ }
+ taosMemoryFreeClear(msg);
+ return (jlong)tmq;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicNewImp(JNIEnv *env, jobject jobj, jlong jtmq) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+
+ tmq_list_t *topics = tmq_list_new();
+ return (jlong)topics;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicAppendImp(JNIEnv *env, jobject jobj,
+ jlong jtopic, jstring jname) {
+ tmq_list_t *topic = (tmq_list_t *)jtopic;
+ if (topic == NULL) {
+ jniError("jobj:%p, tmq topic list is null", jobj);
+ return TMQ_TOPIC_NULL;
+ }
+ if (jname == NULL) {
+ jniDebug("jobj:%p, tmq topic append jname is null", jobj);
+ return TMQ_TOPIC_NAME_NULL;
+ }
+
+ const char *name = (*env)->GetStringUTFChars(env, jname, NULL);
+
+ int32_t res = tmq_list_append((tmq_list_t *)topic, name);
+ (*env)->ReleaseStringUTFChars(env, jname, name);
+ return (jint)res;
+}
+
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqTopicDestroyImp(JNIEnv *env, jobject jobj,
+ jlong jtopic) {
+ tmq_list_t *topic = (tmq_list_t *)jtopic;
+ if (topic == NULL) {
+ jniDebug("jobj:%p, tmq topic list is already destroyed", jobj);
+ } else {
+ tmq_list_destroy((tmq_list_t *)topic);
+ jniDebug("jobj:%p, tmq successfully destroy topic list", jobj);
+ }
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSubscribeImp(JNIEnv *env, jobject jobj, jlong jtmq,
+ jlong jtopic) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+
+ tmq_list_t *topic = (tmq_list_t *)jtopic;
+ if (topic == NULL) {
+ jniDebug("jobj:%p, tmq topic list is already destroyed", jobj);
+ return TMQ_TOPIC_NULL;
+ }
+
+ int32_t res = tmq_subscribe(tmq, topic);
+ return (jint)res;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSubscriptionImp(JNIEnv *env, jobject jobj, jlong jtmq,
+ jobject jconsumer) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+
+ tmq_list_t *topicList = NULL;
+ int32_t res = tmq_subscription((tmq_t *)tmq, &topicList);
+ if (res != JNI_SUCCESS) {
+ tmq_list_destroy(topicList);
+ jniError("jobj:%p, tmq:%p, tmq get subscription error: %s", jobj, tmq, tmq_err2str(res));
+ return (jint)res;
+ }
+
+ char **topics = tmq_list_to_c_array(topicList);
+ int32_t sz = tmq_list_get_size(topicList);
+
+ jobjectArray arr = (jobjectArray)(*env)->NewObjectArray(env, sz, (*env)->FindClass(env, "java/lang/String"),
+ (*env)->NewStringUTF(env, ""));
+ for (int32_t i = 0; i < sz; i++) {
+ (*env)->SetObjectArrayElement(env, arr, i, (*env)->NewStringUTF(env, topics[i]));
+ }
+ (*env)->CallVoidMethod(env, jconsumer, g_topicListCallback, arr);
+ tmq_list_destroy(topicList);
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitSync(JNIEnv *env, jobject jobj, jlong jtmq,
+ jlong jres) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+ TAOS_RES *res = (TAOS_RES *)jres;
+ return tmq_commit_sync(tmq, res);
+}
+
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JNIEnv *env, jobject jobj, jlong jtmq,
+ jlong jres, jobject consumer) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ }
+ TAOS_RES *res = (TAOS_RES *)jres;
+ consumer = (*env)->NewGlobalRef(env, consumer);
+ tmq_commit_async(tmq, res, commit_cb, consumer);
+}
+
+JNIEXPORT int JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqUnsubscribeImp(JNIEnv *env, jobject jobj, jlong jtmq) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniError("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+ jniDebug("jobj:%p, tmq:%p, successfully unsubscribe", jobj, tmq);
+ return tmq_unsubscribe((tmq_t *)tmq);
+}
+
+JNIEXPORT int JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerCloseImp(JNIEnv *env, jobject jobj,
+ jlong jtmq) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniDebug("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+ return tmq_consumer_close((tmq_t *)tmq);
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jint code) {
+ return (*env)->NewStringUTF(env, tmq_err2str(code));
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConsumerPoll(JNIEnv *env, jobject jobj, jlong jtmq,
+ jlong time) {
+ tmq_t *tmq = (tmq_t *)jtmq;
+ if (tmq == NULL) {
+ jniDebug("jobj:%p, tmq is closed", jobj);
+ return TMQ_CONSUMER_NULL;
+ }
+ return (jlong)tmq_consumer_poll((tmq_t *)tmq, time);
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTopicName(JNIEnv *env, jobject jobj,
+ jlong jres) {
+ TAOS_RES *res = (TAOS_RES *)jres;
+ if (res == NULL) {
+ jniDebug("jobj:%p, invalid res handle", jobj);
+ }
+ return (*env)->NewStringUTF(env, tmq_get_topic_name(res));
+}
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetDbName(JNIEnv *env, jobject jobj, jlong jres) {
+ TAOS_RES *res = (TAOS_RES *)jres;
+ if (res == NULL) {
+ jniDebug("jobj:%p, invalid res handle", jobj);
+ }
+ return (*env)->NewStringUTF(env, tmq_get_db_name(res));
+}
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetVgroupId(JNIEnv *env, jobject jobj, jlong jres) {
+ TAOS_RES *res = (TAOS_RES *)jres;
+ if (res == NULL) {
+ jniDebug("jobj:%p, invalid res handle", jobj);
+ }
+ return tmq_get_vgroup_id(res);
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTableName(JNIEnv *env, jobject jobj,
+ jlong jres) {
+ TAOS_RES *res = (TAOS_RES *)jres;
+ if (res == NULL) {
+ jniDebug("jobj:%p, invalid res handle", jobj);
+ }
+ return (*env)->NewStringUTF(env, tmq_get_table_name(res));
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res, jobject rowobj, jint flag,
+ jobject arrayListObj) {
+ TAOS *tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ TAOS_RES *tres = (TAOS_RES *)res;
+
+ void *data;
+ int32_t numOfRows;
+ int error_code = taos_fetch_raw_block(tres, &numOfRows, &data);
+ if (numOfRows == 0) {
+ if (error_code == JNI_SUCCESS) {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, no data to retrieve", jobj, tscon, (void *)res);
+ return JNI_FETCH_END;
+ } else {
+ jniError("jobj:%p, conn:%p, query interrupted", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+ }
+
+ int32_t numOfFields = taos_num_fields(tres);
+ if (numOfFields == 0) {
+ jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, numOfFields);
+ return JNI_NUM_OF_FIELDS_0;
+ }
+
+ TAOS_FIELD *fields = taos_fetch_fields(tres);
+ jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, numOfFields);
+ if (flag) {
+ for (int i = 0; i < numOfFields; ++i) {
+ jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp);
+ (*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type);
+ (*env)->SetIntField(env, metadataObj, g_metadataColsizeField, fields[i].bytes);
+ (*env)->SetIntField(env, metadataObj, g_metadataColindexField, i);
+ jstring metadataObjColname = (*env)->NewStringUTF(env, fields[i].name);
+ (*env)->SetObjectField(env, metadataObj, g_metadataColnameField, metadataObjColname);
+ (*env)->CallBooleanMethod(env, arrayListObj, g_arrayListAddFp, metadataObj);
+ }
+ }
+
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfRowsFp, (jint)numOfRows);
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields);
+
+ int32_t len = *(int32_t *)data;
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, jniFromNCharToByteArray(env, (char *)data, len));
+ return JNI_SUCCESS;
+}
diff --git a/source/client/src/TSDBJNIConnector.c b/source/client/src/TSDBJNIConnector.c
new file mode 100644
index 0000000000000000000000000000000000000000..227c2fff1860170f47074f7f3a7a73d1de569510
--- /dev/null
+++ b/source/client/src/TSDBJNIConnector.c
@@ -0,0 +1,1090 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "taos.h"
+
+#include "com_taosdata_jdbc_TSDBJNIConnector.h"
+#include "jniCommon.h"
+
+int __init = 0;
+
+JavaVM *g_vm = NULL;
+
+jclass g_arrayListClass;
+jmethodID g_arrayListConstructFp;
+jmethodID g_arrayListAddFp;
+
+jclass g_metadataClass;
+jmethodID g_metadataConstructFp;
+jfieldID g_metadataColtypeField;
+jfieldID g_metadataColnameField;
+jfieldID g_metadataColsizeField;
+jfieldID g_metadataColindexField;
+
+jclass g_rowdataClass;
+jmethodID g_rowdataConstructor;
+jmethodID g_rowdataClearFp;
+jmethodID g_rowdataSetBooleanFp;
+jmethodID g_rowdataSetByteFp;
+jmethodID g_rowdataSetShortFp;
+jmethodID g_rowdataSetIntFp;
+jmethodID g_rowdataSetLongFp;
+jmethodID g_rowdataSetFloatFp;
+jmethodID g_rowdataSetDoubleFp;
+jmethodID g_rowdataSetStringFp;
+jmethodID g_rowdataSetTimestampFp;
+jmethodID g_rowdataSetByteArrayFp;
+
+jmethodID g_blockdataSetByteArrayFp;
+jmethodID g_blockdataSetNumOfRowsFp;
+jmethodID g_blockdataSetNumOfColsFp;
+
+jclass g_tmqClass;
+jmethodID g_createConsumerErrorCallback;
+jmethodID g_topicListCallback;
+
+jclass g_consumerClass;
+jmethodID g_commitCallback;
+
+void jniGetGlobalMethod(JNIEnv *env) {
+ // make sure init function executed once
+ switch (atomic_val_compare_exchange_32(&__init, 0, 1)) {
+ case 0:
+ break;
+ case 1:
+ do {
+ taosMsleep(0);
+ } while (atomic_load_32(&__init) == 1);
+ case 2:
+ return;
+ }
+
+ if (g_vm == NULL) {
+ (*env)->GetJavaVM(env, &g_vm);
+ }
+
+ jclass arrayListClass = (*env)->FindClass(env, "java/util/ArrayList");
+ g_arrayListClass = (*env)->NewGlobalRef(env, arrayListClass);
+ g_arrayListConstructFp = (*env)->GetMethodID(env, g_arrayListClass, "", "()V");
+ g_arrayListAddFp = (*env)->GetMethodID(env, g_arrayListClass, "add", "(Ljava/lang/Object;)Z");
+ (*env)->DeleteLocalRef(env, arrayListClass);
+
+ jclass metadataClass = (*env)->FindClass(env, "com/taosdata/jdbc/ColumnMetaData");
+ g_metadataClass = (*env)->NewGlobalRef(env, metadataClass);
+ g_metadataConstructFp = (*env)->GetMethodID(env, g_metadataClass, "", "()V");
+ g_metadataColtypeField = (*env)->GetFieldID(env, g_metadataClass, "colType", "I");
+ g_metadataColnameField = (*env)->GetFieldID(env, g_metadataClass, "colName", "Ljava/lang/String;");
+ g_metadataColsizeField = (*env)->GetFieldID(env, g_metadataClass, "colSize", "I");
+ g_metadataColindexField = (*env)->GetFieldID(env, g_metadataClass, "colIndex", "I");
+ (*env)->DeleteLocalRef(env, metadataClass);
+
+ jclass rowdataClass = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBResultSetRowData");
+ g_rowdataClass = (*env)->NewGlobalRef(env, rowdataClass);
+ g_rowdataConstructor = (*env)->GetMethodID(env, g_rowdataClass, "", "(I)V");
+ g_rowdataClearFp = (*env)->GetMethodID(env, g_rowdataClass, "clear", "()V");
+ g_rowdataSetBooleanFp = (*env)->GetMethodID(env, g_rowdataClass, "setBoolean", "(IZ)V");
+ g_rowdataSetByteFp = (*env)->GetMethodID(env, g_rowdataClass, "setByte", "(IB)V");
+ g_rowdataSetShortFp = (*env)->GetMethodID(env, g_rowdataClass, "setShort", "(IS)V");
+ g_rowdataSetIntFp = (*env)->GetMethodID(env, g_rowdataClass, "setInt", "(II)V");
+ g_rowdataSetLongFp = (*env)->GetMethodID(env, g_rowdataClass, "setLong", "(IJ)V");
+ g_rowdataSetFloatFp = (*env)->GetMethodID(env, g_rowdataClass, "setFloat", "(IF)V");
+ g_rowdataSetDoubleFp = (*env)->GetMethodID(env, g_rowdataClass, "setDouble", "(ID)V");
+ g_rowdataSetStringFp = (*env)->GetMethodID(env, g_rowdataClass, "setString", "(ILjava/lang/String;)V");
+ g_rowdataSetTimestampFp = (*env)->GetMethodID(env, g_rowdataClass, "setTimestamp", "(IJI)V");
+ g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V");
+ (*env)->DeleteLocalRef(env, rowdataClass);
+
+ jclass blockdataClass = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBResultSetBlockData");
+ jclass g_blockdataClass = (*env)->NewGlobalRef(env, blockdataClass);
+ g_blockdataSetByteArrayFp = (*env)->GetMethodID(env, g_blockdataClass, "setByteArray", "([B)V");
+ g_blockdataSetNumOfRowsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfRows", "(I)V");
+ g_blockdataSetNumOfColsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfCols", "(I)V");
+ (*env)->DeleteLocalRef(env, blockdataClass);
+
+ jclass tmqClass = (*env)->FindClass(env, "com/taosdata/jdbc/tmq/TMQConnector");
+ jclass g_tmqClass = (*env)->NewGlobalRef(env, tmqClass);
+ g_createConsumerErrorCallback =
+ (*env)->GetMethodID(env, g_tmqClass, "setCreateConsumerErrorMsg", "(Ljava/lang/String;)V");
+ g_topicListCallback = (*env)->GetMethodID(env, g_tmqClass, "setTopicList", "([Ljava/lang/String;)V");
+ (*env)->DeleteLocalRef(env, tmqClass);
+
+ jclass consumerClass = (*env)->FindClass(env, "com/taosdata/jdbc/tmq/TaosConsumer");
+ jclass g_consumerClass = (*env)->NewGlobalRef(env, consumerClass);
+ g_commitCallback = (*env)->GetMethodID(env, g_consumerClass, "commitCallbackHandler", "(I)V");
+ (*env)->DeleteLocalRef(env, consumerClass);
+
+ atomic_store_32(&__init, 2);
+ jniDebug("native method register finished");
+}
+
+int32_t check_for_params(jobject jobj, jlong conn, jlong res) {
+ if ((TAOS *)conn == NULL) {
+ jniError("jobj:%p, connection is closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ if ((TAOS_RES *)res == NULL) {
+ jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS *)conn);
+ return JNI_RESULT_SET_NULL;
+ }
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) {
+ if (jconfigDir != NULL) {
+ const char *confDir = (*env)->GetStringUTFChars(env, jconfigDir, NULL);
+ if (confDir && strlen(confDir) != 0) {
+ tstrncpy(configDir, confDir, TSDB_FILENAME_LEN);
+ }
+ (*env)->ReleaseStringUTFChars(env, jconfigDir, confDir);
+ }
+
+ jniGetGlobalMethod(env);
+ jniDebug("jni initialized successfully, config directory: %s", configDir);
+}
+
+JNIEXPORT jobject createTSDBException(JNIEnv *env, int code, char *msg) {
+ // find class
+ jclass exception_clazz = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBException");
+ // find methods
+ jmethodID init_method = (*env)->GetMethodID(env, exception_clazz, "", "()V");
+ jmethodID setCode_method = (*env)->GetMethodID(env, exception_clazz, "setCode", "(I)V");
+ jmethodID setMessage_method = (*env)->GetMethodID(env, exception_clazz, "setMessage", "(Ljava/lang/String;)V");
+ // new exception
+ jobject exception_obj = (*env)->NewObject(env, exception_clazz, init_method);
+ // set code
+ (*env)->CallVoidMethod(env, exception_obj, setCode_method, code);
+ // set message
+ jstring message = (*env)->NewStringUTF(env, msg);
+ (*env)->CallVoidMethod(env, exception_obj, setMessage_method, message);
+
+ return exception_obj;
+}
+
+JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp(JNIEnv *env, jclass jobj,
+ jstring config) {
+ if (config == NULL) {
+ char *msg = "config value is null";
+ jniDebug("config value is null");
+ return createTSDBException(env, -1, msg);
+ }
+
+ const char *cfg = (*env)->GetStringUTFChars(env, config, NULL);
+ if (!cfg) {
+ char *msg = "config value is null";
+ jniDebug("config value is null");
+ return createTSDBException(env, -1, msg);
+ }
+
+ setConfRet result = taos_set_config(cfg);
+ int code = result.retCode;
+ char *msg = result.retMsg;
+
+ return createTSDBException(env, code, msg);
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *env, jobject jobj, jint optionIndex,
+ jstring optionValue) {
+ if (optionValue == NULL) {
+ jniDebug("option index:%d value is null", (int32_t)optionIndex);
+ return 0;
+ }
+
+ int res = 0;
+
+ if (optionIndex == TSDB_OPTION_LOCALE) {
+ const char *locale = (*env)->GetStringUTFChars(env, optionValue, NULL);
+ if (locale && strlen(locale) != 0) {
+ res = taos_options(TSDB_OPTION_LOCALE, locale);
+ jniDebug("set locale to %s, result:%d", locale, res);
+ } else {
+ jniDebug("input locale is empty");
+ }
+ (*env)->ReleaseStringUTFChars(env, optionValue, locale);
+ } else if (optionIndex == TSDB_OPTION_CHARSET) {
+ const char *charset = (*env)->GetStringUTFChars(env, optionValue, NULL);
+ if (charset && strlen(charset) != 0) {
+ res = taos_options(TSDB_OPTION_CHARSET, charset);
+ jniDebug("set character encoding to %s, result:%d", charset, res);
+ } else {
+ jniDebug("input character encoding is empty");
+ }
+ (*env)->ReleaseStringUTFChars(env, optionValue, charset);
+ } else if (optionIndex == TSDB_OPTION_TIMEZONE) {
+ const char *tz1 = (*env)->GetStringUTFChars(env, optionValue, NULL);
+ if (tz1 && strlen(tz1) != 0) {
+ res = taos_options(TSDB_OPTION_TIMEZONE, tz1);
+ jniDebug("set timezone to %s, result:%d", tz1, res);
+ } else {
+ jniDebug("input timezone is empty");
+ }
+ (*env)->ReleaseStringUTFChars(env, optionValue, tz1);
+ } else {
+ jniError("option index:%d is not found", (int32_t)optionIndex);
+ }
+
+ return res;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *env, jobject jobj, jstring jhost,
+ jint jport, jstring jdbName, jstring juser,
+ jstring jpass) {
+ jlong ret = 0;
+ const char *host = NULL;
+ const char *user = NULL;
+ const char *pass = NULL;
+ const char *dbname = NULL;
+
+ if (jhost != NULL) {
+ host = (*env)->GetStringUTFChars(env, jhost, NULL);
+ }
+
+ if (jdbName != NULL) {
+ dbname = (*env)->GetStringUTFChars(env, jdbName, NULL);
+ }
+
+ if (juser != NULL) {
+ user = (*env)->GetStringUTFChars(env, juser, NULL);
+ }
+
+ if (jpass != NULL) {
+ pass = (*env)->GetStringUTFChars(env, jpass, NULL);
+ }
+
+ if (user == NULL) {
+ jniDebug("jobj:%p, user not specified, use default user %s", jobj, TSDB_DEFAULT_USER);
+ }
+
+ if (pass == NULL) {
+ jniDebug("jobj:%p, pass not specified, use default password", jobj);
+ }
+
+ ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport);
+ if (ret == 0) {
+ jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
+ (char *)host, (char *)user, (char *)dbname, (int32_t)jport);
+ } else {
+ jniDebug("jobj:%p, conn:%p, connect to database succeed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
+ (char *)host, (char *)user, (char *)dbname, (int32_t)jport);
+ }
+
+ if (host != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jhost, host);
+ }
+
+ if (dbname != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jdbName, dbname);
+ }
+
+ if (user != NULL) {
+ (*env)->ReleaseStringUTFChars(env, juser, user);
+ }
+
+ if (pass != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jpass, pass);
+ }
+
+ return ret;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(JNIEnv *env, jobject jobj,
+ jbyteArray jsql, jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ if (jsql == NULL) {
+ jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ jsize len = (*env)->GetArrayLength(env, jsql);
+
+ char *str = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1));
+ if (str == NULL) {
+ jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon);
+ return JNI_OUT_OF_MEMORY;
+ }
+
+ (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str);
+ if ((*env)->ExceptionCheck(env)) {
+ // todo handle error
+ }
+
+ TAOS_RES *tres = taos_query(tscon, str);
+ int32_t code = taos_errno(tres);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(tres));
+ } else {
+ if (taos_is_update_query(tres)) {
+ int32_t affectRows = taos_affected_rows(tres);
+ jniDebug("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows);
+ } else {
+ jniDebug("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ }
+ }
+
+ taosMemoryFreeClear(str);
+ return (jlong)tres;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres) {
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ return (jint)taos_errno((TAOS_RES *)tres);
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jlong tres) {
+ TAOS_RES *pSql = (TAOS_RES *)tres;
+ return (*env)->NewStringUTF(env, (const char *)taos_errstr(pSql));
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres) {
+ TAOS *tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ if (taos_is_update_query((TAOS_RES *)tres)) {
+ jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, tscon, (void *)tres);
+ } else {
+ jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, tscon, (void *)tres);
+ }
+
+ return tres;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres) {
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ return (taos_is_update_query((TAOS_RES *)tres) ? 1 : 0);
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res) {
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ taos_free_result((void *)res);
+ jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS *)con, (void *)res);
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res) {
+ TAOS *tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ jint ret = taos_affected_rows((TAOS_RES *)res);
+ jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res,
+ (int32_t)ret);
+
+ return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp(JNIEnv *env, jobject jobj,
+ jlong con, jlong res,
+ jobject arrayListObj) {
+ TAOS *tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ TAOS_RES *tres = (TAOS_RES *)res;
+ TAOS_FIELD *fields = taos_fetch_fields(tres);
+
+ int32_t num_fields = taos_num_fields(tres);
+ if (num_fields == 0) {
+ jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields);
+ return JNI_NUM_OF_FIELDS_0;
+ } else {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields);
+ for (int i = 0; i < num_fields; ++i) {
+ jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp);
+ (*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type);
+ (*env)->SetIntField(env, metadataObj, g_metadataColsizeField, fields[i].bytes);
+ (*env)->SetIntField(env, metadataObj, g_metadataColindexField, i);
+ jstring metadataObjColname = (*env)->NewStringUTF(env, fields[i].name);
+ (*env)->SetObjectField(env, metadataObj, g_metadataColnameField, metadataObjColname);
+ (*env)->CallBooleanMethod(env, arrayListObj, g_arrayListAddFp, metadataObj);
+ }
+ }
+
+ return JNI_SUCCESS;
+}
+
+/**
+ *
+ * @param env vm
+ * @param nchar true multibytes data
+ * @param maxBytes the maximum allowable field length
+ * @return
+ */
+jstring jniFromNCharToByteArray(JNIEnv *env, char *nchar, int32_t maxBytes) {
+ jbyteArray bytes = (*env)->NewByteArray(env, maxBytes);
+ (*env)->SetByteArrayRegion(env, bytes, 0, maxBytes, (jbyte *)nchar);
+ return bytes;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res, jobject rowobj) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection is closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_RES *result = (TAOS_RES *)res;
+ if (result == NULL) {
+ jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+
+ TAOS_FIELD *fields = taos_fetch_fields(result);
+
+ int32_t numOfFields = taos_num_fields(result);
+ if (numOfFields == 0) {
+ jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void *)res, numOfFields);
+ return JNI_NUM_OF_FIELDS_0;
+ }
+
+ TAOS_ROW row = taos_fetch_row(result);
+ if (row == NULL) {
+ int code = taos_errno(result);
+ if (code == TSDB_CODE_SUCCESS) {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void *)res,
+ numOfFields);
+ return JNI_FETCH_END;
+ } else {
+ jniDebug("jobj:%p, conn:%p, interrupted query", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+ }
+
+ int32_t *length = taos_fetch_lengths(result);
+
+ char tmp[TSDB_MAX_BYTES_PER_ROW] = {0};
+
+ for (int i = 0; i < numOfFields; i++) {
+ if (row[i] == NULL) {
+ continue;
+ }
+
+ switch (fields[i].type) {
+ case TSDB_DATA_TYPE_BOOL:
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetBooleanFp, i, (jboolean)(*((char *)row[i]) == 1));
+ break;
+ case TSDB_DATA_TYPE_UTINYINT:
+ case TSDB_DATA_TYPE_TINYINT:
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteFp, i, (jbyte) * ((int8_t *)row[i]));
+ break;
+ case TSDB_DATA_TYPE_USMALLINT:
+ case TSDB_DATA_TYPE_SMALLINT:
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetShortFp, i, (jshort) * ((int16_t *)row[i]));
+ break;
+ case TSDB_DATA_TYPE_UINT:
+ case TSDB_DATA_TYPE_INT:
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetIntFp, i, (jint) * (int32_t *)row[i]);
+ break;
+ case TSDB_DATA_TYPE_UBIGINT:
+ case TSDB_DATA_TYPE_BIGINT:
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetLongFp, i, (jlong) * ((int64_t *)row[i]));
+ break;
+ case TSDB_DATA_TYPE_FLOAT: {
+ float fv = 0;
+ fv = GET_FLOAT_VAL(row[i]);
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetFloatFp, i, (jfloat)fv);
+ } break;
+ case TSDB_DATA_TYPE_DOUBLE: {
+ double dv = 0;
+ dv = GET_DOUBLE_VAL(row[i]);
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetDoubleFp, i, (jdouble)dv);
+ } break;
+ case TSDB_DATA_TYPE_BINARY: {
+ memcpy(tmp, row[i], length[i]); // handle the case that terminated does not exist
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetStringFp, i, (*env)->NewStringUTF(env, tmp));
+
+ memset(tmp, 0, length[i]);
+ break;
+ }
+ case TSDB_DATA_TYPE_NCHAR: {
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteArrayFp, i,
+ jniFromNCharToByteArray(env, (char *)row[i], length[i]));
+ break;
+ }
+ case TSDB_DATA_TYPE_JSON: {
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteArrayFp, i,
+ jniFromNCharToByteArray(env, (char *)row[i], length[i]));
+ break;
+ }
+ case TSDB_DATA_TYPE_TIMESTAMP: {
+ int precision = taos_result_precision(result);
+ (*env)->CallVoidMethod(env, rowobj, g_rowdataSetTimestampFp, i, (jlong) * ((int64_t *)row[i]), precision);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res, jobject rowobj) {
+ TAOS *tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ TAOS_RES *tres = (TAOS_RES *)res;
+
+ int32_t numOfFields = taos_num_fields(tres);
+ assert(numOfFields > 0);
+
+ void *data;
+ int32_t numOfRows;
+ int error_code = taos_fetch_raw_block(tres, &numOfRows, &data);
+ if (numOfRows == 0) {
+ if (error_code == JNI_SUCCESS) {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, no data to retrieve", jobj, tscon, (void *)res);
+ return JNI_FETCH_END;
+ } else {
+ jniError("jobj:%p, conn:%p, query interrupted", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+ }
+
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfRowsFp, (jint)numOfRows);
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields);
+
+ int32_t len = *(int32_t *)data;
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, jniFromNCharToByteArray(env, (char *)data, len));
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *env, jobject jobj,
+ jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection is already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ } else {
+ jniDebug("jobj:%p, conn:%p, close connection success", jobj, tscon);
+ taos_close(tscon);
+ return JNI_SUCCESS;
+ }
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNIEnv *env, jobject jobj, jlong con,
+ jboolean restart, jstring jtopic,
+ jstring jsql, jint jinterval) {
+ jlong sub = 0;
+ TAOS *taos = (TAOS *)con;
+ char *topic = NULL;
+ char *sql = NULL;
+
+ jniGetGlobalMethod(env);
+ jniDebug("jobj:%p, in TSDBJNIConnector_subscribeImp", jobj);
+
+ if (jtopic != NULL) {
+ topic = (char *)(*env)->GetStringUTFChars(env, jtopic, NULL);
+ }
+ if (jsql != NULL) {
+ sql = (char *)(*env)->GetStringUTFChars(env, jsql, NULL);
+ }
+
+ if (topic == NULL || sql == NULL) {
+ jniDebug("jobj:%p, invalid argument: topic or sql is NULL", jobj);
+ return sub;
+ }
+
+ TAOS_SUB *tsub = taos_subscribe(taos, (int)restart, topic, sql, NULL, NULL, jinterval);
+ sub = (jlong)tsub;
+
+ if (sub == 0) {
+ jniDebug("jobj:%p, failed to subscribe: topic:%s", jobj, topic);
+ } else {
+ jniDebug("jobj:%p, successfully subscribe: topic: %s", jobj, topic);
+ }
+
+ (*env)->ReleaseStringUTFChars(env, jtopic, topic);
+ (*env)->ReleaseStringUTFChars(env, jsql, sql);
+
+ return sub;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEnv *env, jobject jobj, jlong sub) {
+ jniDebug("jobj:%p, in TSDBJNIConnector_consumeImp, sub:%lld", jobj, sub);
+ jniGetGlobalMethod(env);
+
+ TAOS_SUB *tsub = (TAOS_SUB *)sub;
+ TAOS_RES *res = taos_consume(tsub);
+
+ if (res == NULL) {
+ jniError("jobj:%p, tsub:%p, taos_consume returns NULL", jobj, tsub);
+ return 0l;
+ }
+
+ return (jlong)res;
+}
+
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_unsubscribeImp(JNIEnv *env, jobject jobj, jlong sub,
+ jboolean keepProgress) {
+ TAOS_SUB *tsub = (TAOS_SUB *)sub;
+ taos_unsubscribe(tsub, keepProgress);
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTableSqlImp(JNIEnv *env, jobject jobj,
+ jlong con, jbyteArray jsql) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection is closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ if (jsql == NULL) {
+ jniError("jobj:%p, conn:%p, sql is null", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ jsize len = (*env)->GetArrayLength(env, jsql);
+
+ char *str = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1));
+ (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str);
+ if ((*env)->ExceptionCheck(env)) {
+ // todo handle error
+ }
+
+ int code = taos_validate_sql(tscon, str);
+ jniDebug("jobj:%p, conn:%p, code is %d", jobj, tscon, code);
+
+ taosMemoryFreeClear(str);
+ return code;
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(JNIEnv *env, jobject jobj) {
+ return (*env)->NewStringUTF(env, (const char *)tsCharset);
+}
+
+/**
+ * Get Result Time Precision
+ * @param env vm
+ * @param jobj the TSDBJNIConnector java object
+ * @param con the c connection pointer
+ * @param res the TAOS_RES object, i.e. the SSqlObject
+ * @return precision 0:ms 1:us 2:ns
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultTimePrecisionImp(JNIEnv *env, jobject jobj,
+ jlong con, jlong res) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection is closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_RES *result = (TAOS_RES *)res;
+ if (result == NULL) {
+ jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+
+ return taos_result_precision(result);
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *env, jobject jobj,
+ jbyteArray jsql, jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ if (jsql == NULL) {
+ jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ jsize len = (*env)->GetArrayLength(env, jsql);
+
+ char *str = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1));
+ if (str == NULL) {
+ jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon);
+ return JNI_OUT_OF_MEMORY;
+ }
+
+ (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str);
+ if ((*env)->ExceptionCheck(env)) {
+ // todo handle error
+ }
+
+ TAOS_STMT *pStmt = taos_stmt_init(tscon);
+ int32_t code = taos_stmt_prepare(pStmt, str, len);
+ taosMemoryFreeClear(str);
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ return (jlong)pStmt;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp(JNIEnv *env, jobject jobj,
+ jlong stmt, jstring jname,
+ jlong conn) {
+ TAOS *tsconn = (TAOS *)conn;
+ if (tsconn == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn);
+ return JNI_SQL_NULL;
+ }
+
+ const char *name = (*env)->GetStringUTFChars(env, jname, NULL);
+
+ int32_t code = taos_stmt_set_tbname((void *)stmt, name);
+ if (code != TSDB_CODE_SUCCESS) {
+ (*env)->ReleaseStringUTFChars(env, jname, name);
+
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ jniDebug("jobj:%p, conn:%p, set stmt bind table name:%s", jobj, tsconn, name);
+ (*env)->ReleaseStringUTFChars(env, jname, name);
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp(
+ JNIEnv *env, jobject jobj, jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList,
+ jbyteArray lengthList, jbyteArray nullList, jlong conn) {
+ TAOS *tsconn = (TAOS *)conn;
+ if (tsconn == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn);
+ return JNI_SQL_NULL;
+ }
+
+ jsize len = (*env)->GetArrayLength(env, tags);
+ char *tagsData = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, tags, 0, len, (jbyte *)tagsData);
+ if ((*env)->ExceptionCheck(env)) {
+ // todo handle error
+ }
+
+ len = (*env)->GetArrayLength(env, lengthList);
+ int32_t *lengthArray = (int32_t *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray);
+ if ((*env)->ExceptionCheck(env)) {
+ }
+
+ len = (*env)->GetArrayLength(env, typeList);
+ char *typeArray = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte *)typeArray);
+ if ((*env)->ExceptionCheck(env)) {
+ }
+
+ len = (*env)->GetArrayLength(env, nullList);
+ char *nullArray = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray);
+ if ((*env)->ExceptionCheck(env)) {
+ }
+
+ const char *name = (*env)->GetStringUTFChars(env, tableName, NULL);
+ char *curTags = tagsData;
+
+ TAOS_MULTI_BIND *tagsBind = taosMemoryCalloc(numOfTags, sizeof(TAOS_MULTI_BIND));
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ tagsBind[i].buffer_type = typeArray[i];
+ tagsBind[i].buffer = curTags;
+ tagsBind[i].is_null = &nullArray[i];
+ tagsBind[i].length = &lengthArray[i];
+
+ curTags += lengthArray[i];
+ }
+
+ int32_t code = taos_stmt_set_tbname_tags((void *)stmt, name, tagsBind);
+
+ int32_t nTags = (int32_t)numOfTags;
+ jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, nTags);
+
+ taosMemoryFreeClear(tagsData);
+ taosMemoryFreeClear(lengthArray);
+ taosMemoryFreeClear(typeArray);
+ taosMemoryFreeClear(nullArray);
+ taosMemoryFreeClear(tagsBind);
+ (*env)->ReleaseStringUTFChars(env, tableName, name);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(
+ JNIEnv *env, jobject jobj, jlong stmt, jbyteArray colDataList, jbyteArray lengthList, jbyteArray nullList,
+ jint dataType, jint dataBytes, jint numOfRows, jint colIndex, jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ // todo refactor
+ jsize len = (*env)->GetArrayLength(env, colDataList);
+ char *colBuf = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, colDataList, 0, len, (jbyte *)colBuf);
+ if ((*env)->ExceptionCheck(env)) {
+ // todo handle error
+ }
+
+ len = (*env)->GetArrayLength(env, lengthList);
+ char *lengthArray = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray);
+ if ((*env)->ExceptionCheck(env)) {
+ }
+
+ len = (*env)->GetArrayLength(env, nullList);
+ char *nullArray = (char *)taosMemoryCalloc(1, len);
+ (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray);
+ if ((*env)->ExceptionCheck(env)) {
+ }
+
+ // bind multi-rows with only one invoke.
+ TAOS_MULTI_BIND *b = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND));
+
+ b->num = numOfRows;
+ b->buffer_type = dataType; // todo check data type
+ b->buffer_length = IS_VAR_DATA_TYPE(dataType) ? dataBytes : tDataTypes[dataType].bytes;
+ b->is_null = nullArray;
+ b->buffer = colBuf;
+ b->length = (int32_t *)lengthArray;
+
+ // set the length and is_null array
+ if (!IS_VAR_DATA_TYPE(dataType)) {
+ int32_t bytes = tDataTypes[dataType].bytes;
+ for (int32_t i = 0; i < numOfRows; ++i) {
+ b->length[i] = bytes;
+ }
+ }
+
+ int32_t code = taos_stmt_bind_single_param_batch(pStmt, b, colIndex);
+ taosMemoryFreeClear(b->length);
+ taosMemoryFreeClear(b->buffer);
+ taosMemoryFreeClear(b->is_null);
+ taosMemoryFreeClear(b);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ int32_t code = taos_stmt_add_batch(pStmt);
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon);
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ int32_t code = taos_stmt_execute(pStmt);
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ jniDebug("jobj:%p, conn:%p, batch execute", jobj, tscon);
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con) {
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ return JNI_SQL_NULL;
+ }
+
+ int32_t code = taos_stmt_close(pStmt);
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
+ return JNI_TDENGINE_ERROR;
+ }
+
+ jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon);
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con) {
+ char errMsg[128];
+ TAOS *tscon = (TAOS *)con;
+ if (tscon == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ sprintf(errMsg, "jobj:%p, connection already closed", jobj);
+ return (*env)->NewStringUTF(env, errMsg);
+ }
+
+ TAOS_STMT *pStmt = (TAOS_STMT *)stmt;
+ if (pStmt == NULL) {
+ jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ sprintf(errMsg, "jobj:%p, conn:%p, invalid stmt", jobj, tscon);
+ return (*env)->NewStringUTF(env, errMsg);
+ }
+
+ return (*env)->NewStringUTF(env, taos_stmt_errstr((TAOS_STMT *)stmt));
+}
+
+TAOS_RES *schemalessInsert(JNIEnv *env, jobject jobj, jobjectArray lines, TAOS *taos, jint protocol, jint precision) {
+ int numLines = (*env)->GetArrayLength(env, lines);
+ char **c_lines = taosMemoryCalloc(numLines, sizeof(char *));
+ if (c_lines == NULL) {
+ jniError("c_lines:%p, alloc memory failed", c_lines);
+ return NULL;
+ }
+ for (int i = 0; i < numLines; ++i) {
+ jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i));
+ c_lines[i] = (char *)(*env)->GetStringUTFChars(env, line, 0);
+ }
+
+ TAOS_RES *tres = taos_schemaless_insert(taos, c_lines, numLines, protocol, precision);
+
+ for (int i = 0; i < numLines; ++i) {
+ jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i));
+ (*env)->ReleaseStringUTFChars(env, line, c_lines[i]);
+ }
+
+ taosMemoryFreeClear(c_lines);
+ return tres;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj,
+ jobjectArray lines, jlong conn,
+ jint protocol, jint precision) {
+ TAOS *taos = (TAOS *)conn;
+ if (taos == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_RES *tres = schemalessInsert(env, jobj, lines, taos, protocol, precision);
+
+ if (tres == NULL) {
+ return JNI_OUT_OF_MEMORY;
+ }
+ int code = taos_errno(tres);
+ if (code != TSDB_CODE_SUCCESS) {
+ jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, taos, tstrerror(code), taos_errstr(tres));
+ taos_free_result(tres);
+ return JNI_TDENGINE_ERROR;
+ }
+ taos_free_result(tres);
+
+ return JNI_SUCCESS;
+}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp(JNIEnv *env, jobject jobj,
+ jobjectArray lines, jlong conn,
+ jint protocol, jint precision) {
+ TAOS *taos = (TAOS *)conn;
+ if (taos == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ TAOS_RES *tres = schemalessInsert(env, jobj, lines, taos, protocol, precision);
+ if (tres == NULL) {
+ return JNI_OUT_OF_MEMORY;
+ }
+ return (jlong)tres;
+}
\ No newline at end of file
diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c
index 9f04e89694f77153b747892872d0cdb0c173ca6f..207ac01a2c46eb50123ce6e108c617d74560de74 100644
--- a/source/client/src/clientEnv.c
+++ b/source/client/src/clientEnv.c
@@ -13,11 +13,11 @@
* along with this program. If not, see .
*/
-#include "os.h"
#include "catalog.h"
-#include "functionMgt.h"
#include "clientInt.h"
#include "clientLog.h"
+#include "functionMgt.h"
+#include "os.h"
#include "query.h"
#include "scheduler.h"
#include "tcache.h"
@@ -25,6 +25,7 @@
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
+#include "tsched.h"
#include "ttime.h"
#define TSC_VAR_NOT_RELEASE 1
@@ -37,11 +38,7 @@ int32_t clientConnRefPool = -1;
static TdThreadOnce tscinit = PTHREAD_ONCE_INIT;
volatile int32_t tscInitRes = 0;
-static void registerRequest(SRequestObj *pRequest) {
- STscObj *pTscObj = acquireTscObj(*(int64_t*)pRequest->pTscObj->id);
-
- assert(pTscObj != NULL);
-
+static int32_t registerRequest(SRequestObj *pRequest, STscObj *pTscObj) {
// connection has been released already, abort creating request.
pRequest->self = taosAddRef(clientReqRefPool, pRequest);
@@ -54,14 +51,16 @@ static void registerRequest(SRequestObj *pRequest) {
int32_t currentInst = atomic_add_fetch_64((int64_t *)&pSummary->currentRequests, 1);
tscDebug("0x%" PRIx64 " new Request from connObj:0x%" PRIx64
", current:%d, app current:%d, total:%d, reqId:0x%" PRIx64,
- pRequest->self, *(int64_t*)pRequest->pTscObj->id, num, currentInst, total, pRequest->requestId);
+ pRequest->self, pRequest->pTscObj->id, num, currentInst, total, pRequest->requestId);
}
+
+ return TSDB_CODE_SUCCESS;
}
static void deregisterRequest(SRequestObj *pRequest) {
assert(pRequest != NULL);
- STscObj *pTscObj = pRequest->pTscObj;
+ STscObj *pTscObj = pRequest->pTscObj;
SAppClusterSummary *pActivity = &pTscObj->pAppInfo->summary;
int32_t currentInst = atomic_sub_fetch_64((int64_t *)&pActivity->currentRequests, 1);
@@ -70,22 +69,26 @@ static void deregisterRequest(SRequestObj *pRequest) {
int64_t duration = taosGetTimestampUs() - pRequest->metric.start;
tscDebug("0x%" PRIx64 " free Request from connObj: 0x%" PRIx64 ", reqId:0x%" PRIx64 " elapsed:%" PRIu64
" ms, current:%d, app current:%d",
- pRequest->self, *(int64_t*)pTscObj->id, pRequest->requestId, duration / 1000, num, currentInst);
- releaseTscObj(*(int64_t*)pTscObj->id);
+ pRequest->self, pTscObj->id, pRequest->requestId, duration / 1000, num, currentInst);
+ releaseTscObj(pTscObj->id);
}
// todo close the transporter properly
-void closeTransporter(STscObj *pTscObj) {
- if (pTscObj == NULL || pTscObj->pAppInfo->pTransporter == NULL) {
+void closeTransporter(SAppInstInfo *pAppInfo) {
+ if (pAppInfo == NULL || pAppInfo->pTransporter == NULL) {
return;
}
- tscDebug("free transporter:%p in connObj: 0x%" PRIx64, pTscObj->pAppInfo->pTransporter, *(int64_t*)pTscObj->id);
- rpcClose(pTscObj->pAppInfo->pTransporter);
+ tscDebug("free transporter:%p in app inst %p", pAppInfo->pTransporter, pAppInfo);
+ rpcClose(pAppInfo->pTransporter);
}
-static bool clientRpcRfp(int32_t code) {
- if (code == TSDB_CODE_RPC_REDIRECT) {
+static bool clientRpcRfp(int32_t code, tmsg_t msgType) {
+ if (NEED_REDIRECT_ERROR(code)) {
+ if (msgType == TDMT_SCH_QUERY || msgType == TDMT_SCH_MERGE_QUERY || msgType == TDMT_SCH_FETCH ||
+ msgType == TDMT_SCH_MERGE_FETCH) {
+ return false;
+ }
return true;
} else {
return false;
@@ -114,32 +117,83 @@ void *openTransporter(const char *user, const char *auth, int32_t numOfThread) {
return pDnodeConn;
}
-void closeAllRequests(SHashObj *pRequests) {
+void destroyAllRequests(SHashObj *pRequests) {
void *pIter = taosHashIterate(pRequests, NULL);
while (pIter != NULL) {
int64_t *rid = pIter;
- releaseRequest(*rid);
+ SRequestObj *pRequest = acquireRequest(*rid);
+ if (pRequest) {
+ destroyRequest(pRequest);
+ releaseRequest(*rid);
+ }
pIter = taosHashIterate(pRequests, pIter);
}
}
+void stopAllRequests(SHashObj *pRequests) {
+ void *pIter = taosHashIterate(pRequests, NULL);
+ while (pIter != NULL) {
+ int64_t *rid = pIter;
+
+ SRequestObj *pRequest = acquireRequest(*rid);
+ if (pRequest) {
+ taos_stop_query(pRequest);
+ releaseRequest(*rid);
+ }
+
+ pIter = taosHashIterate(pRequests, pIter);
+ }
+}
+
+void destroyAppInst(SAppInstInfo *pAppInfo) {
+ tscDebug("destroy app inst mgr %p", pAppInfo);
+
+ taosThreadMutexLock(&appInfo.mutex);
+
+ hbRemoveAppHbMrg(&pAppInfo->pAppHbMgr);
+ taosHashRemove(appInfo.pInstMap, pAppInfo->instKey, strlen(pAppInfo->instKey));
+
+ taosThreadMutexUnlock(&appInfo.mutex);
+
+ taosMemoryFreeClear(pAppInfo->instKey);
+ closeTransporter(pAppInfo);
+
+ taosThreadMutexLock(&pAppInfo->qnodeMutex);
+ taosArrayDestroy(pAppInfo->pQnodeList);
+ taosThreadMutexUnlock(&pAppInfo->qnodeMutex);
+
+ taosMemoryFree(pAppInfo);
+}
+
void destroyTscObj(void *pObj) {
+ if (NULL == pObj) {
+ return;
+ }
+
STscObj *pTscObj = pObj;
+ int64_t tscId = pTscObj->id;
+ tscTrace("begin to destroy tscObj %" PRIx64 " p:%p", tscId, pTscObj);
- SClientHbKey connKey = {.tscRid = *(int64_t*)pTscObj->id, .connType = pTscObj->connType};
+ SClientHbKey connKey = {.tscRid = pTscObj->id, .connType = pTscObj->connType};
hbDeregisterConn(pTscObj->pAppInfo->pAppHbMgr, connKey);
- int64_t connNum = atomic_sub_fetch_64(&pTscObj->pAppInfo->numOfConns, 1);
- closeAllRequests(pTscObj->pRequests);
+
+ destroyAllRequests(pTscObj->pRequests);
+ taosHashCleanup(pTscObj->pRequests);
+
schedulerStopQueryHb(pTscObj->pAppInfo->pTransporter);
+ tscDebug("connObj 0x%" PRIx64 " p:%p destroyed, remain inst totalConn:%" PRId64, pTscObj->id, pTscObj,
+ pTscObj->pAppInfo->numOfConns);
+
+ int64_t connNum = atomic_sub_fetch_64(&pTscObj->pAppInfo->numOfConns, 1);
if (0 == connNum) {
- // TODO
- //closeTransporter(pTscObj);
+ destroyAppInst(pTscObj->pAppInfo);
}
- tscDebug("connObj 0x%" PRIx64 " destroyed, totalConn:%" PRId64, *(int64_t*)pTscObj->id, pTscObj->pAppInfo->numOfConns);
taosThreadMutexDestroy(&pTscObj->mutex);
- taosMemoryFreeClear(pTscObj);
+ taosMemoryFree(pTscObj);
+
+ tscTrace("end to destroy tscObj %" PRIx64 " p:%p", tscId, pTscObj);
}
void *createTscObj(const char *user, const char *auth, const char *db, int32_t connType, SAppInstInfo *pAppInfo) {
@@ -166,11 +220,12 @@ void *createTscObj(const char *user, const char *auth, const char *db, int32_t c
}
taosThreadMutexInit(&pObj->mutex, NULL);
- pObj->id = taosMemoryMalloc(sizeof(int64_t));
- *(int64_t*)pObj->id = taosAddRef(clientConnRefPool, pObj);
+ pObj->id = taosAddRef(clientConnRefPool, pObj);
pObj->schemalessType = 1;
- tscDebug("connObj created, 0x%" PRIx64, *(int64_t*)pObj->id);
+ atomic_add_fetch_64(&pObj->pAppInfo->numOfConns, 1);
+
+ tscDebug("connObj created, 0x%" PRIx64 ",p:%p", pObj->id, pObj);
return pObj;
}
@@ -178,29 +233,37 @@ STscObj *acquireTscObj(int64_t rid) { return (STscObj *)taosAcquireRef(clientCon
int32_t releaseTscObj(int64_t rid) { return taosReleaseRef(clientConnRefPool, rid); }
-void *createRequest(STscObj *pObj, int32_t type) {
- assert(pObj != NULL);
-
+void *createRequest(uint64_t connId, int32_t type) {
SRequestObj *pRequest = (SRequestObj *)taosMemoryCalloc(1, sizeof(SRequestObj));
if (NULL == pRequest) {
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
return NULL;
}
+ STscObj *pTscObj = acquireTscObj(connId);
+ if (pTscObj == NULL) {
+ terrno = TSDB_CODE_TSC_DISCONNECTED;
+ return NULL;
+ }
+
pRequest->resType = RES_TYPE__QUERY;
- pRequest->pDb = getDbOfConnection(pObj);
pRequest->requestId = generateRequestId();
pRequest->metric.start = taosGetTimestampUs();
pRequest->body.resInfo.convertUcs4 = true; // convert ucs4 by default
-
pRequest->type = type;
- pRequest->pTscObj = pObj;
+
+ pRequest->pDb = getDbOfConnection(pTscObj);
+ pRequest->pTscObj = pTscObj;
+
pRequest->msgBuf = taosMemoryCalloc(1, ERROR_MSG_BUF_DEFAULT_SIZE);
pRequest->msgBufLen = ERROR_MSG_BUF_DEFAULT_SIZE;
tsem_init(&pRequest->body.rspSem, 0, 0);
- registerRequest(pRequest);
+ if (registerRequest(pRequest, pTscObj)) {
+ doDestroyRequest(pRequest);
+ return NULL;
+ }
return pRequest;
}
@@ -222,32 +285,43 @@ void doFreeReqResultInfo(SReqResultInfo *pResInfo) {
}
}
-static void doDestroyRequest(void *p) {
- assert(p != NULL);
+SRequestObj *acquireRequest(int64_t rid) { return (SRequestObj *)taosAcquireRef(clientReqRefPool, rid); }
+
+int32_t releaseRequest(int64_t rid) { return taosReleaseRef(clientReqRefPool, rid); }
+
+int32_t removeRequest(int64_t rid) { return taosRemoveRef(clientReqRefPool, rid); }
+
+void doDestroyRequest(void *p) {
+ if (NULL == p) {
+ return;
+ }
+
SRequestObj *pRequest = (SRequestObj *)p;
- assert(RID_VALID(pRequest->self));
+ int64_t reqId = pRequest->self;
+ tscTrace("begin to destroy request %" PRIx64 " p:%p", reqId, pRequest);
taosHashRemove(pRequest->pTscObj->pRequests, &pRequest->self, sizeof(pRequest->self));
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- }
+ schedulerFreeJob(&pRequest->body.queryJob, 0);
taosMemoryFreeClear(pRequest->msgBuf);
taosMemoryFreeClear(pRequest->sqlstr);
taosMemoryFreeClear(pRequest->pDb);
doFreeReqResultInfo(&pRequest->body.resInfo);
- qDestroyQueryPlan(pRequest->body.pDag);
taosArrayDestroy(pRequest->tableList);
taosArrayDestroy(pRequest->dbList);
destroyQueryExecRes(&pRequest->body.resInfo.execRes);
- deregisterRequest(pRequest);
- taosMemoryFreeClear(pRequest);
+ if (pRequest->self) {
+ deregisterRequest(pRequest);
+ }
+
+ taosMemoryFree(pRequest);
+ tscTrace("end to destroy request %" PRIx64 " p:%p", reqId, pRequest);
}
void destroyRequest(SRequestObj *pRequest) {
@@ -255,18 +329,14 @@ void destroyRequest(SRequestObj *pRequest) {
return;
}
- taosRemoveRef(clientReqRefPool, pRequest->self);
+ taos_stop_query(pRequest);
+ removeRequest(pRequest->self);
}
-SRequestObj *acquireRequest(int64_t rid) { return (SRequestObj *)taosAcquireRef(clientReqRefPool, rid); }
-
-int32_t releaseRequest(int64_t rid) { return taosReleaseRef(clientReqRefPool, rid); }
-
void taos_init_imp(void) {
// In the APIs of other program language, taos_cleanup is not available yet.
// So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning.
atexit(taos_cleanup);
-
errno = TSDB_CODE_SUCCESS;
taosSeedRand(taosGetTimestampSec());
diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c
index c6d0d6a860e747a7240b4bab4f9153a07f5ae8c6..2a9d113108a565694091de4c3ea0c78431c50b57 100644
--- a/source/client/src/clientHb.c
+++ b/source/client/src/clientHb.c
@@ -66,25 +66,31 @@ static int32_t hbProcessDBInfoRsp(void *value, int32_t valueLen, struct SCatalog
if (rsp->vgVersion < 0) {
code = catalogRemoveDB(pCatalog, rsp->db, rsp->uid);
} else {
- SDBVgInfo vgInfo = {0};
- vgInfo.vgVersion = rsp->vgVersion;
- vgInfo.hashMethod = rsp->hashMethod;
- vgInfo.vgHash = taosHashInit(rsp->vgNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
- if (NULL == vgInfo.vgHash) {
+ SDBVgInfo *vgInfo = taosMemoryCalloc(1, sizeof(SDBVgInfo));
+ if (NULL == vgInfo) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+
+ vgInfo->vgVersion = rsp->vgVersion;
+ vgInfo->hashMethod = rsp->hashMethod;
+ vgInfo->vgHash = taosHashInit(rsp->vgNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
+ if (NULL == vgInfo->vgHash) {
+ taosMemoryFree(vgInfo);
tscError("hash init[%d] failed", rsp->vgNum);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
for (int32_t j = 0; j < rsp->vgNum; ++j) {
SVgroupInfo *pInfo = taosArrayGet(rsp->pVgroupInfos, j);
- if (taosHashPut(vgInfo.vgHash, &pInfo->vgId, sizeof(int32_t), pInfo, sizeof(SVgroupInfo)) != 0) {
+ if (taosHashPut(vgInfo->vgHash, &pInfo->vgId, sizeof(int32_t), pInfo, sizeof(SVgroupInfo)) != 0) {
tscError("hash push failed, errno:%d", errno);
- taosHashCleanup(vgInfo.vgHash);
+ taosHashCleanup(vgInfo->vgHash);
+ taosMemoryFree(vgInfo);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
}
- catalogUpdateDBVgInfo(pCatalog, rsp->db, rsp->uid, &vgInfo);
+ catalogUpdateDBVgInfo(pCatalog, rsp->db, rsp->uid, vgInfo);
}
if (code) {
@@ -161,6 +167,9 @@ static int32_t hbQueryHbRspHandle(SAppHbMgr *pAppHbMgr, SClientHbRsp *pRsp) {
updateEpSet_s(&pTscObj->pAppInfo->mgmtEp, &pRsp->query->epSet);
}
+
+ pTscObj->pAppInfo->totalDnodes = pRsp->query->totalDnodes;
+ pTscObj->pAppInfo->onlineDnodes = pRsp->query->onlineDnodes;
pTscObj->connId = pRsp->query->connId;
if (pRsp->query->killRid) {
@@ -253,21 +262,21 @@ static int32_t hbQueryHbRspHandle(SAppHbMgr *pAppHbMgr, SClientHbRsp *pRsp) {
return TSDB_CODE_SUCCESS;
}
-static int32_t hbAsyncCallBack(void *param, const SDataBuf *pMsg, int32_t code) {
+static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) {
static int32_t emptyRspNum = 0;
- if (code != 0) {
- taosMemoryFreeClear(param);
- return -1;
- }
-
char *key = (char *)param;
SClientHbBatchRsp pRsp = {0};
- tDeserializeSClientHbBatchRsp(pMsg->pData, pMsg->len, &pRsp);
-
+ if (TSDB_CODE_SUCCESS == code) {
+ tDeserializeSClientHbBatchRsp(pMsg->pData, pMsg->len, &pRsp);
+ }
+
int32_t rspNum = taosArrayGetSize(pRsp.rsps);
+ taosThreadMutexLock(&appInfo.mutex);
+
SAppInstInfo **pInst = taosHashGet(appInfo.pInstMap, key, strlen(key));
if (pInst == NULL || NULL == *pInst) {
+ taosThreadMutexUnlock(&appInfo.mutex);
tscError("cluster not exist, key:%s", key);
taosMemoryFreeClear(param);
tFreeClientHbBatchRsp(&pRsp);
@@ -276,6 +285,10 @@ static int32_t hbAsyncCallBack(void *param, const SDataBuf *pMsg, int32_t code)
taosMemoryFreeClear(param);
+ if (code != 0) {
+ (*pInst)->onlineDnodes = 0;
+ }
+
if (rspNum) {
tscDebug("hb got %d rsp, %d empty rsp received before", rspNum,
atomic_val_compare_exchange_32(&emptyRspNum, emptyRspNum, 0));
@@ -291,6 +304,8 @@ static int32_t hbAsyncCallBack(void *param, const SDataBuf *pMsg, int32_t code)
}
}
+ taosThreadMutexUnlock(&appInfo.mutex);
+
tFreeClientHbBatchRsp(&pRsp);
return code;
@@ -317,7 +332,7 @@ int32_t hbBuildQueryDesc(SQueryHbReqBasic *hbBasic, STscObj *pObj) {
desc.reqRid = pRequest->self;
desc.stableQuery = pRequest->stableQuery;
taosGetFqdn(desc.fqdn);
- desc.subPlanNum = pRequest->body.pDag ? pRequest->body.pDag->numOfSubplans : 0;
+ desc.subPlanNum = pRequest->body.subplanNum;
if (desc.subPlanNum) {
desc.subDesc = taosArrayInit(desc.subPlanNum, sizeof(SQuerySubDesc));
@@ -656,8 +671,7 @@ static void *hbThreadFunc(void *param) {
}
#endif
while (1) {
- int8_t threadStop = atomic_val_compare_exchange_8(&clientHbMgr.threadStop, 1, 2);
- if (1 == threadStop) {
+ if (1 == clientHbMgr.threadStop) {
break;
}
@@ -745,9 +759,7 @@ static void hbStopThread() {
return;
}
- while (2 != atomic_load_8(&clientHbMgr.threadStop)) {
- taosUsleep(10);
- }
+ taosThreadJoin(clientHbMgr.thread, NULL);
tscDebug("hb thread stopped");
}
@@ -787,22 +799,40 @@ SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) {
return pAppHbMgr;
}
+void hbFreeAppHbMgr(SAppHbMgr *pTarget) {
+ void *pIter = taosHashIterate(pTarget->activeInfo, NULL);
+ while (pIter != NULL) {
+ SClientHbReq *pOneReq = pIter;
+ tFreeClientHbReq(pOneReq);
+ pIter = taosHashIterate(pTarget->activeInfo, pIter);
+ }
+ taosHashCleanup(pTarget->activeInfo);
+ pTarget->activeInfo = NULL;
+
+ taosMemoryFree(pTarget->key);
+ taosMemoryFree(pTarget);
+}
+
+void hbRemoveAppHbMrg(SAppHbMgr **pAppHbMgr) {
+ taosThreadMutexLock(&clientHbMgr.lock);
+ int32_t mgrSize = taosArrayGetSize(clientHbMgr.appHbMgrs);
+ for (int32_t i = 0; i < mgrSize; ++i) {
+ SAppHbMgr *pItem = taosArrayGetP(clientHbMgr.appHbMgrs, i);
+ if (pItem == *pAppHbMgr) {
+ hbFreeAppHbMgr(*pAppHbMgr);
+ *pAppHbMgr = NULL;
+ taosArrayRemove(clientHbMgr.appHbMgrs, i);
+ break;
+ }
+ }
+ taosThreadMutexUnlock(&clientHbMgr.lock);
+}
+
void appHbMgrCleanup(void) {
int sz = taosArrayGetSize(clientHbMgr.appHbMgrs);
for (int i = 0; i < sz; i++) {
SAppHbMgr *pTarget = taosArrayGetP(clientHbMgr.appHbMgrs, i);
-
- void *pIter = taosHashIterate(pTarget->activeInfo, NULL);
- while (pIter != NULL) {
- SClientHbReq *pOneReq = pIter;
- tFreeClientHbReq(pOneReq);
- pIter = taosHashIterate(pTarget->activeInfo, pIter);
- }
- taosHashCleanup(pTarget->activeInfo);
- pTarget->activeInfo = NULL;
-
- taosMemoryFree(pTarget->key);
- taosMemoryFree(pTarget);
+ hbFreeAppHbMgr(pTarget);
}
}
diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c
index 8920922006d517df10e536ad407e8f83909350c4..d846cb93af6a2c16fd21d2f954b8393e426aa27a 100644
--- a/source/client/src/clientImpl.c
+++ b/source/client/src/clientImpl.c
@@ -25,6 +25,7 @@
#include "tmsgtype.h"
#include "tpagedbuf.h"
#include "tref.h"
+#include "tsched.h"
static int32_t initEpSetFromCfg(const char* firstEp, const char* secondEp, SCorEpSet* pEpSet);
static SMsgSendInfo* buildConnectMsg(SRequestObj* pRequest);
@@ -55,11 +56,23 @@ static char* getClusterKey(const char* user, const char* auth, const char* ip, i
return strdup(key);
}
+bool chkRequestKilled(void* param) {
+ bool killed = false;
+ SRequestObj* pRequest = acquireRequest((int64_t)param);
+ if (NULL == pRequest || pRequest->killed) {
+ killed = true;
+ }
+
+ releaseRequest((int64_t)param);
+
+ return killed;
+}
+
static STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __taos_async_fn_t fp, void* param,
SAppInstInfo* pAppInfo, int connType);
STscObj* taos_connect_internal(const char* ip, const char* user, const char* pass, const char* auth, const char* db,
- uint16_t port, int connType) {
+ uint16_t port, int connType) {
if (taos_init() != TSDB_CODE_SUCCESS) {
return NULL;
}
@@ -122,6 +135,9 @@ STscObj* taos_connect_internal(const char* ip, const char* user, const char* pas
p->pTransporter = openTransporter(user, secretEncrypt, tsNumOfCores);
p->pAppHbMgr = appHbMgrInit(p, key);
taosHashPut(appInfo.pInstMap, key, strlen(key), &p, POINTER_BYTES);
+ p->instKey = key;
+ key = NULL;
+ tscDebug("new app inst mgr %p, user:%s, ip:%s, port:%d", p, user, ip, port);
pInst = &p;
}
@@ -132,29 +148,50 @@ STscObj* taos_connect_internal(const char* ip, const char* user, const char* pas
return taosConnectImpl(user, &secretEncrypt[0], localDb, NULL, NULL, *pInst, connType);
}
-int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj** pRequest) {
- *pRequest = createRequest(pTscObj, TSDB_SQL_SELECT);
+int32_t buildRequest(uint64_t connId, const char* sql, int sqlLen, void* param, bool validateSql,
+ SRequestObj** pRequest) {
+ *pRequest = createRequest(connId, TSDB_SQL_SELECT);
if (*pRequest == NULL) {
- tscError("failed to malloc sqlObj");
- return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ tscError("failed to malloc sqlObj, %s", sql);
+ return terrno;
}
(*pRequest)->sqlstr = taosMemoryMalloc(sqlLen + 1);
if ((*pRequest)->sqlstr == NULL) {
- tscError("0x%" PRIx64 " failed to prepare sql string buffer", (*pRequest)->self);
- (*pRequest)->msgBuf = strdup("failed to prepare sql string buffer");
+ tscError("0x%" PRIx64 " failed to prepare sql string buffer, %s", (*pRequest)->self, sql);
+ destroyRequest(*pRequest);
+ *pRequest = NULL;
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
strntolower((*pRequest)->sqlstr, sql, (int32_t)sqlLen);
(*pRequest)->sqlstr[sqlLen] = 0;
(*pRequest)->sqlLen = sqlLen;
+ (*pRequest)->validateOnly = validateSql;
+
+ if (param == NULL) {
+ SSyncQueryParam* pParam = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
+ if (pParam == NULL) {
+ destroyRequest(*pRequest);
+ *pRequest = NULL;
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+
+ tsem_init(&pParam->sem, 0, 0);
+ pParam->pRequest = (*pRequest);
+ param = pParam;
+ }
+
+ (*pRequest)->body.param = param;
+ STscObj* pTscObj = (*pRequest)->pTscObj;
if (taosHashPut(pTscObj->pRequests, &(*pRequest)->self, sizeof((*pRequest)->self), &(*pRequest)->self,
sizeof((*pRequest)->self))) {
+ tscError("%d failed to add to request container, reqId:0x%" PRIx64 ", conn:%d, %s", (*pRequest)->self,
+ (*pRequest)->requestId, pTscObj->id, sql);
+
destroyRequest(*pRequest);
*pRequest = NULL;
- tscError("put request to request hash failed");
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
@@ -178,7 +215,9 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC
.pStmtCb = pStmtCb,
.pUser = pTscObj->user,
.schemalessType = pTscObj->schemalessType,
- .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER))};
+ .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
+ .svrVer = pTscObj->sVer,
+ .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes)};
cxt.mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
int32_t code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &cxt.pCatalog);
@@ -237,6 +276,10 @@ static SAppInstInfo* getAppInfo(SRequestObj* pRequest) { return pRequest->pTscOb
void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) {
SRetrieveTableRsp* pRsp = NULL;
+ if (pRequest->validateOnly) {
+ pRequest->body.queryFp(pRequest->body.param, pRequest, 0);
+ return;
+ }
int32_t code = qExecCommand(pQuery->pRoot, &pRsp);
if (TSDB_CODE_SUCCESS == code && NULL != pRsp) {
@@ -244,10 +287,10 @@ void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) {
}
SReqResultInfo* pResultInfo = &pRequest->body.resInfo;
+ pRequest->code = code;
if (pRequest->code != TSDB_CODE_SUCCESS) {
pResultInfo->numOfRows = 0;
- pRequest->code = code;
tscError("0x%" PRIx64 " fetch results failed, code:%s, reqId:0x%" PRIx64, pRequest->self, tstrerror(code),
pRequest->requestId);
} else {
@@ -256,11 +299,15 @@ void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) {
pRequest->requestId);
}
- pRequest->body.queryFp(pRequest->body.param, pRequest, 0);
- // pRequest->body.fetchFp(pRequest->body.param, pRequest, pResultInfo->numOfRows);
+ pRequest->body.queryFp(pRequest->body.param, pRequest, code);
}
int32_t asyncExecDdlQuery(SRequestObj* pRequest, SQuery* pQuery) {
+ if (pRequest->validateOnly) {
+ pRequest->body.queryFp(pRequest->body.param, pRequest, 0);
+ return TSDB_CODE_SUCCESS;
+ }
+
// drop table if exists not_exists_table
if (NULL == pQuery->pCmdMsg) {
pRequest->body.queryFp(pRequest->body.param, pRequest, 0);
@@ -276,8 +323,11 @@ int32_t asyncExecDdlQuery(SRequestObj* pRequest, SQuery* pQuery) {
SMsgSendInfo* pSendMsg = buildMsgInfoImpl(pRequest);
int64_t transporterId = 0;
- asyncSendMsgToServer(pAppInfo->pTransporter, &pMsgInfo->epSet, &transporterId, pSendMsg);
- return TSDB_CODE_SUCCESS;
+ int32_t code = asyncSendMsgToServer(pAppInfo->pTransporter, &pMsgInfo->epSet, &transporterId, pSendMsg);
+ if (code) {
+ pRequest->body.queryFp(pRequest->body.param, pRequest, code);
+ }
+ return code;
}
int compareQueryNodeLoad(const void* elem1, const void* elem2) {
@@ -296,11 +346,14 @@ int32_t updateQnodeList(SAppInstInfo* pInfo, SArray* pNodeList) {
if (pInfo->pQnodeList) {
taosArrayDestroy(pInfo->pQnodeList);
pInfo->pQnodeList = NULL;
+ tscDebug("QnodeList cleared in cluster 0x%" PRIx64, pInfo->clusterId);
}
if (pNodeList) {
pInfo->pQnodeList = taosArrayDup(pNodeList);
taosArraySort(pInfo->pQnodeList, compareQueryNodeLoad);
+ tscDebug("QnodeList updated in cluster 0x%" PRIx64 ", num:%d", pInfo->clusterId,
+ taosArrayGetSize(pInfo->pQnodeList));
}
taosThreadMutexUnlock(&pInfo->qnodeMutex);
@@ -313,8 +366,8 @@ bool qnodeRequired(SRequestObj* pRequest) {
}
SAppInstInfo* pInfo = pRequest->pTscObj->pAppInfo;
- bool required = false;
-
+ bool required = false;
+
taosThreadMutexLock(&pInfo->qnodeMutex);
required = (NULL == pInfo->pQnodeList);
taosThreadMutexUnlock(&pInfo->qnodeMutex);
@@ -362,7 +415,8 @@ int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArra
.pAstRoot = pQuery->pRoot,
.showRewrite = pQuery->showRewrite,
.pMsg = pRequest->msgBuf,
- .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE};
+ .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
+ .pUser = pRequest->pTscObj->user};
return qCreateQueryPlan(&cxt, pPlan, pNodeList);
}
@@ -419,11 +473,11 @@ int32_t buildVnodePolicyNodeList(SRequestObj* pRequest, SArray** pNodeList, SArr
}
for (int32_t j = 0; j < vgNum; ++j) {
- SVgroupInfo* pInfo = taosArrayGet(pVg, j);
+ SVgroupInfo* pInfo = taosArrayGet(pVg, j);
SQueryNodeLoad load = {0};
load.addr.nodeId = pInfo->vgId;
load.addr.epSet = pInfo->epSet;
-
+
taosArrayPush(nodeList, &load);
}
}
@@ -481,17 +535,16 @@ _return:
return TSDB_CODE_SUCCESS;
}
-
-int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList, SMetaData *pResultMeta) {
+int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList, SMetaData* pResultMeta) {
SArray* pDbVgList = NULL;
SArray* pQnodeList = NULL;
int32_t code = 0;
-
+
switch (tsQueryPolicy) {
case QUERY_POLICY_VNODE: {
if (pResultMeta) {
pDbVgList = taosArrayInit(4, POINTER_BYTES);
-
+
int32_t dbNum = taosArrayGetSize(pResultMeta->pDbVgroup);
for (int32_t i = 0; i < dbNum; ++i) {
SMetaRes* pRes = taosArrayGet(pResultMeta->pDbVgroup, i);
@@ -500,9 +553,9 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
}
taosArrayPush(pDbVgList, &pRes->pRes);
- }
+ }
}
-
+
code = buildVnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pDbVgList);
break;
}
@@ -523,7 +576,7 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
}
taosThreadMutexUnlock(&pInst->qnodeMutex);
}
-
+
code = buildQnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pQnodeList);
break;
}
@@ -534,7 +587,7 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
taosArrayDestroy(pDbVgList);
taosArrayDestroy(pQnodeList);
-
+
return code;
}
@@ -542,43 +595,43 @@ int32_t buildSyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray*
SArray* pDbVgList = NULL;
SArray* pQnodeList = NULL;
int32_t code = 0;
-
+
switch (tsQueryPolicy) {
case QUERY_POLICY_VNODE: {
int32_t dbNum = taosArrayGetSize(pRequest->dbList);
if (dbNum > 0) {
- SCatalog* pCtg = NULL;
+ SCatalog* pCtg = NULL;
SAppInstInfo* pInst = pRequest->pTscObj->pAppInfo;
code = catalogGetHandle(pInst->clusterId, &pCtg);
if (code != TSDB_CODE_SUCCESS) {
goto _return;
}
- pDbVgList = taosArrayInit(dbNum, POINTER_BYTES);
+ pDbVgList = taosArrayInit(dbNum, POINTER_BYTES);
SArray* pVgList = NULL;
for (int32_t i = 0; i < dbNum; ++i) {
- char* dbFName = taosArrayGet(pRequest->dbList, i);
+ char* dbFName = taosArrayGet(pRequest->dbList, i);
SRequestConnInfo conn = {.pTrans = pInst->pTransporter,
.requestId = pRequest->requestId,
.requestObjRefId = pRequest->self,
- .mgmtEps = getEpSet_s(&pInst->mgmtEp)};
-
+ .mgmtEps = getEpSet_s(&pInst->mgmtEp)};
+
code = catalogGetDBVgInfo(pCtg, &conn, dbFName, &pVgList);
if (code) {
goto _return;
}
-
+
taosArrayPush(pDbVgList, &pVgList);
- }
+ }
}
-
+
code = buildVnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pDbVgList);
break;
}
case QUERY_POLICY_HYBRID:
case QUERY_POLICY_QNODE: {
getQnodeList(pRequest, &pQnodeList);
-
+
code = buildQnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pQnodeList);
break;
}
@@ -591,86 +644,36 @@ _return:
taosArrayDestroy(pDbVgList);
taosArrayDestroy(pQnodeList);
-
- return code;
-}
-
-
-int32_t scheduleAsyncQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) {
- tsem_init(&schdRspSem, 0, 0);
-
- SQueryResult res = {.code = 0, .numOfRows = 0};
- SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter,
- .requestId = pRequest->requestId,
- .requestObjRefId = pRequest->self};
- SSchedulerReq req = {.pConn = &conn,
- .pNodeList = pNodeList,
- .pDag = pDag,
- .sql = pRequest->sqlstr,
- .startTs = pRequest->metric.start,
- .fp = schdExecCallback,
- .cbParam = &res};
-
- int32_t code = schedulerAsyncExecJob(&req, &pRequest->body.queryJob);
-
- pRequest->body.resInfo.execRes = res.res;
-
- while (true) {
- if (code != TSDB_CODE_SUCCESS) {
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- }
-
- pRequest->code = code;
- terrno = code;
- return pRequest->code;
- } else {
- tsem_wait(&schdRspSem);
-
- if (res.code) {
- code = res.code;
- } else {
- break;
- }
- }
- }
-
- if (TDMT_VND_SUBMIT == pRequest->type || TDMT_VND_CREATE_TABLE == pRequest->type) {
- pRequest->body.resInfo.numOfRows = res.numOfRows;
-
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- }
- }
- pRequest->code = res.code;
- terrno = res.code;
- return pRequest->code;
+ return code;
}
int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) {
void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter;
- SQueryResult res = {0};
+ SExecResult res = {0};
SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter,
.requestId = pRequest->requestId,
.requestObjRefId = pRequest->self};
- SSchedulerReq req = {.pConn = &conn,
- .pNodeList = pNodeList,
- .pDag = pDag,
- .sql = pRequest->sqlstr,
- .startTs = pRequest->metric.start,
- .fp = NULL,
- .cbParam = NULL,
- .reqKilled = &pRequest->killed};
-
- int32_t code = schedulerExecJob(&req, &pRequest->body.queryJob, &res);
- pRequest->body.resInfo.execRes = res.res;
+ SSchedulerReq req = {
+ .syncReq = true,
+ .pConn = &conn,
+ .pNodeList = pNodeList,
+ .pDag = pDag,
+ .sql = pRequest->sqlstr,
+ .startTs = pRequest->metric.start,
+ .execFp = NULL,
+ .cbParam = NULL,
+ .chkKillFp = chkRequestKilled,
+ .chkKillParam = (void*)pRequest->self,
+ .pExecRes = &res,
+ };
+
+ int32_t code = schedulerExecJob(&req, &pRequest->body.queryJob);
+ memcpy(&pRequest->body.resInfo.execRes, &res, sizeof(res));
if (code != TSDB_CODE_SUCCESS) {
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- }
+ schedulerFreeJob(&pRequest->body.queryJob, 0);
pRequest->code = code;
terrno = code;
@@ -681,9 +684,7 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList
TDMT_VND_CREATE_TABLE == pRequest->type) {
pRequest->body.resInfo.numOfRows = res.numOfRows;
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- }
+ schedulerFreeJob(&pRequest->body.queryJob, 0);
}
pRequest->code = res.code;
@@ -779,8 +780,8 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) {
return code;
}
- SEpSet epset = getEpSet_s(&pAppInfo->mgmtEp);
- SQueryExecRes* pRes = &pRequest->body.resInfo.execRes;
+ SEpSet epset = getEpSet_s(&pAppInfo->mgmtEp);
+ SExecResult* pRes = &pRequest->body.resInfo.execRes;
switch (pRes->msgType) {
case TDMT_VND_ALTER_TABLE:
@@ -792,7 +793,8 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) {
code = handleSubmitExecRes(pRequest, pRes->res, pCatalog, &epset);
break;
}
- case TDMT_VND_QUERY: {
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY: {
code = handleQueryExecRes(pRequest, pRes->res, pCatalog, &epset);
break;
}
@@ -805,22 +807,27 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) {
return code;
}
-void schedulerExecCb(SQueryResult* pResult, void* param, int32_t code) {
+void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) {
SRequestObj* pRequest = (SRequestObj*)param;
pRequest->code = code;
+ if (pResult) {
+ memcpy(&pRequest->body.resInfo.execRes, pResult, sizeof(*pResult));
+ }
+
if (TDMT_VND_SUBMIT == pRequest->type || TDMT_VND_DELETE == pRequest->type ||
TDMT_VND_CREATE_TABLE == pRequest->type) {
- pRequest->body.resInfo.numOfRows = pResult->numOfRows;
-
- if (pRequest->body.queryJob != 0) {
- schedulerFreeJob(pRequest->body.queryJob, 0);
- pRequest->body.queryJob = 0;
+ if (pResult) {
+ pRequest->body.resInfo.numOfRows = pResult->numOfRows;
}
+
+ schedulerFreeJob(&pRequest->body.queryJob, 0);
}
- tscDebug("0x%" PRIx64 " enter scheduler exec cb, code:%d - %s, reqId:0x%" PRIx64,
- pRequest->self, code, tstrerror(code), pRequest->requestId);
+ taosMemoryFree(pResult);
+
+ tscDebug("0x%" PRIx64 " enter scheduler exec cb, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code,
+ tstrerror(code), pRequest->requestId);
STscObj* pTscObj = pRequest->pTscObj;
if (code != TSDB_CODE_SUCCESS && NEED_CLIENT_HANDLE_ERROR(code)) {
@@ -851,20 +858,28 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQue
switch (pQuery->execMode) {
case QUERY_EXEC_MODE_LOCAL:
- code = execLocalCmd(pRequest, pQuery);
+ if (!pRequest->validateOnly) {
+ code = execLocalCmd(pRequest, pQuery);
+ }
break;
case QUERY_EXEC_MODE_RPC:
- code = execDdlQuery(pRequest, pQuery);
+ if (!pRequest->validateOnly) {
+ code = execDdlQuery(pRequest, pQuery);
+ }
break;
case QUERY_EXEC_MODE_SCHEDULE: {
- SArray* pMnodeList = taosArrayInit(4, sizeof(SQueryNodeLoad));
- code = getPlan(pRequest, pQuery, &pRequest->body.pDag, pMnodeList);
+ SArray* pMnodeList = taosArrayInit(4, sizeof(SQueryNodeLoad));
+ SQueryPlan* pDag = NULL;
+ code = getPlan(pRequest, pQuery, &pDag, pMnodeList);
if (TSDB_CODE_SUCCESS == code) {
- SArray* pNodeList = NULL;
- buildSyncExecNodeList(pRequest, &pNodeList, pMnodeList);
-
- code = scheduleQuery(pRequest, pRequest->body.pDag, pNodeList);
- taosArrayDestroy(pNodeList);
+ pRequest->body.subplanNum = pDag->numOfSubplans;
+ if (!pRequest->validateOnly) {
+ SArray* pNodeList = NULL;
+ buildSyncExecNodeList(pRequest, &pNodeList, pMnodeList);
+
+ code = scheduleQuery(pRequest, pDag, pNodeList);
+ taosArrayDestroy(pNodeList);
+ }
}
taosArrayDestroy(pMnodeList);
break;
@@ -894,11 +909,11 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQue
return pRequest;
}
-SRequestObj* launchQuery(STscObj* pTscObj, const char* sql, int sqlLen) {
+SRequestObj* launchQuery(uint64_t connId, const char* sql, int sqlLen, bool validateOnly) {
SRequestObj* pRequest = NULL;
SQuery* pQuery = NULL;
- int32_t code = buildRequest(pTscObj, sql, sqlLen, &pRequest);
+ int32_t code = buildRequest(connId, sql, sqlLen, NULL, validateOnly, &pRequest);
if (code != TSDB_CODE_SUCCESS) {
terrno = code;
return NULL;
@@ -915,9 +930,11 @@ SRequestObj* launchQuery(STscObj* pTscObj, const char* sql, int sqlLen) {
return launchQueryImpl(pRequest, pQuery, false, NULL);
}
-void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData *pResultMeta) {
+void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta) {
int32_t code = 0;
+ pRequest->body.execMode = pQuery->execMode;
+
switch (pQuery->execMode) {
case QUERY_EXEC_MODE_LOCAL:
asyncExecLocalCmd(pRequest, pQuery);
@@ -936,33 +953,42 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData *pResultM
.pAstRoot = pQuery->pRoot,
.showRewrite = pQuery->showRewrite,
.pMsg = pRequest->msgBuf,
- .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE};
+ .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
+ .pUser = pRequest->pTscObj->user};
SAppInstInfo* pAppInfo = getAppInfo(pRequest);
- code = qCreateQueryPlan(&cxt, &pRequest->body.pDag, pMnodeList);
+ SQueryPlan* pDag = NULL;
+ code = qCreateQueryPlan(&cxt, &pDag, pMnodeList);
if (code) {
tscError("0x%" PRIx64 " failed to create query plan, code:%s 0x%" PRIx64, pRequest->self, tstrerror(code),
pRequest->requestId);
+ } else {
+ pRequest->body.subplanNum = pDag->numOfSubplans;
}
- if (TSDB_CODE_SUCCESS == code) {
+ if (TSDB_CODE_SUCCESS == code && !pRequest->validateOnly) {
SArray* pNodeList = NULL;
buildAsyncExecNodeList(pRequest, &pNodeList, pMnodeList, pResultMeta);
-
+
SRequestConnInfo conn = {
.pTrans = pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
- SSchedulerReq req = {.pConn = &conn,
- .pNodeList = pNodeList,
- .pDag = pRequest->body.pDag,
- .sql = pRequest->sqlstr,
- .startTs = pRequest->metric.start,
- .fp = schedulerExecCb,
- .cbParam = pRequest,
- .reqKilled = &pRequest->killed};
- code = schedulerAsyncExecJob(&req, &pRequest->body.queryJob);
+ SSchedulerReq req = {
+ .syncReq = false,
+ .pConn = &conn,
+ .pNodeList = pNodeList,
+ .pDag = pDag,
+ .sql = pRequest->sqlstr,
+ .startTs = pRequest->metric.start,
+ .execFp = schedulerExecCb,
+ .cbParam = pRequest,
+ .chkKillFp = chkRequestKilled,
+ .chkKillParam = (void*)pRequest->self,
+ .pExecRes = NULL,
+ };
+ code = schedulerExecJob(&req, &pRequest->body.queryJob);
taosArrayDestroy(pNodeList);
} else {
- tscError("0x%" PRIx64 " failed to create query plan, code:%s 0x%" PRIx64, pRequest->self, tstrerror(code),
+ tscDebug("0x%" PRIx64 " plan not executed, code:%s 0x%" PRIx64, pRequest->self, tstrerror(code),
pRequest->requestId);
pRequest->body.queryFp(pRequest->body.param, pRequest, code);
}
@@ -976,6 +1002,7 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData *pResultM
pRequest->body.queryFp(pRequest->body.param, pRequest, 0);
break;
default:
+ pRequest->body.queryFp(pRequest->body.param, pRequest, -1);
break;
}
@@ -1045,19 +1072,20 @@ int32_t removeMeta(STscObj* pTscObj, SArray* tbList) {
return TSDB_CODE_SUCCESS;
}
-SRequestObj* execQuery(STscObj* pTscObj, const char* sql, int sqlLen) {
+// todo remove it soon
+SRequestObj* execQuery(uint64_t connId, const char* sql, int sqlLen, bool validateOnly) {
SRequestObj* pRequest = NULL;
int32_t retryNum = 0;
int32_t code = 0;
do {
destroyRequest(pRequest);
- pRequest = launchQuery(pTscObj, sql, sqlLen);
+ pRequest = launchQuery(connId, sql, sqlLen, validateOnly);
if (pRequest == NULL || TSDB_CODE_SUCCESS == pRequest->code || !NEED_CLIENT_HANDLE_ERROR(pRequest->code)) {
break;
}
- code = refreshMeta(pTscObj, pRequest);
+ code = refreshMeta(pRequest->pTscObj, pRequest);
if (code) {
pRequest->code = code;
break;
@@ -1065,7 +1093,7 @@ SRequestObj* execQuery(STscObj* pTscObj, const char* sql, int sqlLen) {
} while (retryNum++ < REQUEST_TOTAL_EXEC_TIMES);
if (NEED_CLIENT_RM_TBLMETA_REQ(pRequest->type)) {
- removeMeta(pTscObj, pRequest->tableList);
+ removeMeta(pRequest->pTscObj, pRequest->tableList);
}
return pRequest;
@@ -1120,10 +1148,9 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
return pTscObj;
}
- SRequestObj* pRequest = createRequest(pTscObj, TDMT_MND_CONNECT);
+ SRequestObj* pRequest = createRequest(pTscObj->id, TDMT_MND_CONNECT);
if (pRequest == NULL) {
destroyTscObj(pTscObj);
- terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
return NULL;
}
@@ -1143,7 +1170,7 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
taos_close_internal(pTscObj);
pTscObj = NULL;
} else {
- tscDebug("0x%" PRIx64 " connection is opening, connId:%u, dnodeConn:%p, reqId:0x%" PRIx64, *(int64_t*)pTscObj->id,
+ tscDebug("0x%" PRIx64 " connection is opening, connId:%u, dnodeConn:%p, reqId:0x%" PRIx64, pTscObj->id,
pTscObj->connId, pTscObj->pAppInfo->pTransporter, pRequest->requestId);
destroyRequest(pRequest);
}
@@ -1243,7 +1270,16 @@ void updateTargetEpSet(SMsgSendInfo* pSendInfo, STscObj* pTscObj, SRpcMsg* pMsg,
}
}
-void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
+typedef struct SchedArg {
+ SRpcMsg msg;
+ SEpSet* pEpset;
+} SchedArg;
+
+int32_t doProcessMsgFromServer(void* param) {
+ SchedArg* arg = (SchedArg*)param;
+ SRpcMsg* pMsg = &arg->msg;
+ SEpSet* pEpSet = arg->pEpset;
+
SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->info.ahandle;
assert(pMsg->info.ahandle != NULL);
STscObj* pTscObj = NULL;
@@ -1263,10 +1299,10 @@ void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
*/
int32_t elapsed = pRequest->metric.rsp - pRequest->metric.start;
if (pMsg->code == TSDB_CODE_SUCCESS) {
- tscDebug("0x%" PRIx64 " message:%s, code:%s rspLen:%d, elapsed:%d ms, reqId:0x%" PRIx64, pRequest->self,
+ tscDebug("0x%" PRIx64 " rsp msg:%s, code:%s rspLen:%d, elapsed:%d ms, reqId:0x%" PRIx64, pRequest->self,
TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), pMsg->contLen, elapsed / 1000, pRequest->requestId);
} else {
- tscError("0x%" PRIx64 " SQL cmd:%s, code:%s rspLen:%d, elapsed time:%d ms, reqId:0x%" PRIx64, pRequest->self,
+ tscError("0x%" PRIx64 " rsp msg:%s, code:%s rspLen:%d, elapsed time:%d ms, reqId:0x%" PRIx64, pRequest->self,
TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), pMsg->contLen, elapsed / 1000, pRequest->requestId);
}
@@ -1276,7 +1312,8 @@ void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
updateTargetEpSet(pSendInfo, pTscObj, pMsg, pEpSet);
- SDataBuf buf = {.len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle};
+ SDataBuf buf = {
+ .msgType = pMsg->msgType, .len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle, .pEpSet = pEpSet};
if (pMsg->contLen > 0) {
buf.pData = taosMemoryCalloc(1, pMsg->contLen);
@@ -1291,6 +1328,22 @@ void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
pSendInfo->fp(pSendInfo->param, &buf, pMsg->code);
rpcFreeCont(pMsg->pCont);
destroySendMsgInfo(pSendInfo);
+ taosMemoryFree(arg);
+ return TSDB_CODE_SUCCESS;
+}
+
+void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
+ SEpSet* tEpSet = NULL;
+ if (pEpSet != NULL) {
+ tEpSet = taosMemoryCalloc(1, sizeof(SEpSet));
+ memcpy((void*)tEpSet, (void*)pEpSet, sizeof(SEpSet));
+ }
+
+ SchedArg* arg = taosMemoryCalloc(1, sizeof(SchedArg));
+ arg->msg = *pMsg;
+ arg->pEpset = tEpSet;
+
+ taosAsyncExec(doProcessMsgFromServer, arg, NULL);
}
TAOS* taos_connect_auth(const char* ip, const char* user, const char* auth, const char* db, uint16_t port) {
@@ -1306,9 +1359,11 @@ TAOS* taos_connect_auth(const char* ip, const char* user, const char* auth, cons
STscObj* pObj = taos_connect_internal(ip, user, NULL, auth, db, port, CONN_TYPE__QUERY);
if (pObj) {
- return pObj->id;
+ int64_t* rid = taosMemoryCalloc(1, sizeof(int64_t));
+ *rid = pObj->id;
+ return (TAOS*)rid;
}
-
+
return NULL;
}
@@ -1367,7 +1422,11 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4)
}
SReqResultInfo* pResInfo = &pRequest->body.resInfo;
- pRequest->code = schedulerFetchRows(pRequest->body.queryJob, (void**)&pResInfo->pData);
+ SSchedulerReq req = {
+ .syncReq = true,
+ .pFetchRes = (void**)&pResInfo->pData,
+ };
+ pRequest->code = schedulerFetchRows(pRequest->body.queryJob, &req);
if (pRequest->code != TSDB_CODE_SUCCESS) {
pResultInfo->numOfRows = 0;
return NULL;
@@ -1412,21 +1471,24 @@ void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertU
return NULL;
}
- SSyncQueryParam* pParam = pRequest->body.param;
-
// convert ucs4 to native multi-bytes string
pResultInfo->convertUcs4 = convertUcs4;
+ SSyncQueryParam* pParam = pRequest->body.param;
taos_fetch_rows_a(pRequest, syncFetchFn, pParam);
tsem_wait(&pParam->sem);
}
- if (pRequest->code == TSDB_CODE_SUCCESS && pResultInfo->numOfRows > 0 && setupOneRowPtr) {
- doSetOneRowPtr(pResultInfo);
- pResultInfo->current += 1;
- }
+ if (pResultInfo->numOfRows == 0 || pRequest->code != TSDB_CODE_SUCCESS) {
+ return NULL;
+ } else {
+ if (setupOneRowPtr) {
+ doSetOneRowPtr(pResultInfo);
+ pResultInfo->current += 1;
+ }
- return pResultInfo->row;
+ return pResultInfo->row;
+ }
}
static int32_t doPrepareResPtr(SReqResultInfo* pResInfo) {
@@ -1444,80 +1506,6 @@ static int32_t doPrepareResPtr(SReqResultInfo* pResInfo) {
return TSDB_CODE_SUCCESS;
}
-static char* parseTagDatatoJson(void* p) {
- char* string = NULL;
- cJSON* json = cJSON_CreateObject();
- if (json == NULL) {
- goto end;
- }
-
- SArray* pTagVals = NULL;
- if (tTagToValArray((const STag*)p, &pTagVals) != 0) {
- goto end;
- }
-
- int16_t nCols = taosArrayGetSize(pTagVals);
- char tagJsonKey[256] = {0};
- for (int j = 0; j < nCols; ++j) {
- STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, j);
- // json key encode by binary
- memset(tagJsonKey, 0, sizeof(tagJsonKey));
- memcpy(tagJsonKey, pTagVal->pKey, strlen(pTagVal->pKey));
- // json value
- char type = pTagVal->type;
- if (type == TSDB_DATA_TYPE_NULL) {
- cJSON* value = cJSON_CreateNull();
- if (value == NULL) {
- goto end;
- }
- cJSON_AddItemToObject(json, tagJsonKey, value);
- } else if (type == TSDB_DATA_TYPE_NCHAR) {
- cJSON* value = NULL;
- if (pTagVal->nData > 0) {
- char* tagJsonValue = taosMemoryCalloc(pTagVal->nData, 1);
- int32_t length = taosUcs4ToMbs((TdUcs4*)pTagVal->pData, pTagVal->nData, tagJsonValue);
- if (length < 0) {
- tscError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset,
- pTagVal->pData);
- taosMemoryFree(tagJsonValue);
- goto end;
- }
- value = cJSON_CreateString(tagJsonValue);
- taosMemoryFree(tagJsonValue);
- if (value == NULL) {
- goto end;
- }
- } else if (pTagVal->nData == 0) {
- value = cJSON_CreateString("");
- } else {
- ASSERT(0);
- }
-
- cJSON_AddItemToObject(json, tagJsonKey, value);
- } else if (type == TSDB_DATA_TYPE_DOUBLE) {
- double jsonVd = *(double*)(&pTagVal->i64);
- cJSON* value = cJSON_CreateNumber(jsonVd);
- if (value == NULL) {
- goto end;
- }
- cJSON_AddItemToObject(json, tagJsonKey, value);
- } else if (type == TSDB_DATA_TYPE_BOOL) {
- char jsonVd = *(char*)(&pTagVal->i64);
- cJSON* value = cJSON_CreateBool(jsonVd);
- if (value == NULL) {
- goto end;
- }
- cJSON_AddItemToObject(json, tagJsonKey, value);
- } else {
- ASSERT(0);
- }
- }
- string = cJSON_PrintUnformatted(json);
-end:
- cJSON_Delete(json);
- return string;
-}
-
static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t numOfRows, int32_t numOfCols, int32_t* colLength) {
for (int32_t i = 0; i < numOfCols; ++i) {
int32_t type = pResultInfo->fields[i].type;
@@ -1554,10 +1542,10 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t numOfRows, int
return TSDB_CODE_SUCCESS;
}
-static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, int32_t numOfRows){
+static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, int32_t numOfRows) {
char* p = (char*)pResultInfo->pData;
- int32_t len = sizeof(int32_t) + sizeof(uint64_t) + numOfCols * (sizeof(int16_t) + sizeof(int32_t));
+ int32_t len = sizeof(int32_t) + sizeof(uint64_t) + numOfCols * (sizeof(int16_t) + sizeof(int32_t));
int32_t* colLength = (int32_t*)(p + len);
len += sizeof(int32_t) * numOfCols;
@@ -1567,7 +1555,7 @@ static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, i
if (pResultInfo->fields[i].type == TSDB_DATA_TYPE_JSON) {
int32_t* offset = (int32_t*)pStart;
- int32_t lenTmp = numOfRows * sizeof(int32_t);
+ int32_t lenTmp = numOfRows * sizeof(int32_t);
len += lenTmp;
pStart += lenTmp;
@@ -1581,7 +1569,7 @@ static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, i
char* jsonInnerData = data + CHAR_BYTES;
if (jsonInnerType == TSDB_DATA_TYPE_NULL) {
len += (VARSTR_HEADER_SIZE + strlen(TSDB_DATA_NULL_STR_L));
- } else if (jsonInnerType & TD_TAG_JSON) {
+ } else if (tTagIsJson(data)) {
len += (VARSTR_HEADER_SIZE + ((const STag*)(data))->len);
} else if (jsonInnerType == TSDB_DATA_TYPE_NCHAR) { // value -> "value"
len += varDataTLen(jsonInnerData) + CHAR_BYTES * 2;
@@ -1592,7 +1580,6 @@ static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, i
} else {
ASSERT(0);
}
-
}
} else if (IS_VAR_DATA_TYPE(pResultInfo->fields[i].type)) {
int32_t lenTmp = numOfRows * sizeof(int32_t);
@@ -1616,13 +1603,13 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int
break;
}
}
- if(!needConvert) return TSDB_CODE_SUCCESS;
+ if (!needConvert) return TSDB_CODE_SUCCESS;
- char* p = (char*)pResultInfo->pData;
+ char* p = (char*)pResultInfo->pData;
int32_t dataLen = estimateJsonLen(pResultInfo, numOfCols, numOfRows);
pResultInfo->convertJson = taosMemoryCalloc(1, dataLen);
- if(pResultInfo->convertJson == NULL) return TSDB_CODE_OUT_OF_MEMORY;
+ if (pResultInfo->convertJson == NULL) return TSDB_CODE_OUT_OF_MEMORY;
char* p1 = pResultInfo->convertJson;
int32_t len = sizeof(int32_t) + sizeof(uint64_t) + numOfCols * (sizeof(int16_t) + sizeof(int32_t));
@@ -1666,7 +1653,7 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int
if (jsonInnerType == TSDB_DATA_TYPE_NULL) {
sprintf(varDataVal(dst), "%s", TSDB_DATA_NULL_STR_L);
varDataSetLen(dst, strlen(varDataVal(dst)));
- } else if (jsonInnerType & TD_TAG_JSON) {
+ } else if (tTagIsJson(data)) {
char* jsonString = parseTagDatatoJson(data);
STR_TO_VARSTR(dst, jsonString);
taosMemoryFree(jsonString);
@@ -1691,7 +1678,7 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int
ASSERT(0);
}
- offset1[j]= len;
+ offset1[j] = len;
memcpy(pStart1 + len, dst, varDataTLen(dst));
len += varDataTLen(dst);
}
@@ -1709,7 +1696,6 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int
pStart += len;
pStart1 += len;
memcpy(pStart1, pStart, colLen);
-
}
pStart += colLen;
pStart1 += colLen1;
@@ -1777,7 +1763,7 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32
pStart += colLength[i];
}
- if(convertUcs4){
+ if (convertUcs4) {
code = doConvertUCS4(pResultInfo, numOfRows, numOfCols, colLength);
}
@@ -1893,3 +1879,230 @@ _OVER:
}
return code;
}
+
+int32_t appendTbToReq(SArray* pList, int32_t pos1, int32_t len1, int32_t pos2, int32_t len2, const char* str,
+ int32_t acctId, char* db) {
+ SName name;
+
+ if (len1 <= 0) {
+ return -1;
+ }
+
+ const char* dbName = db;
+ const char* tbName = NULL;
+ int32_t dbLen = 0;
+ int32_t tbLen = 0;
+ if (len2 > 0) {
+ dbName = str + pos1;
+ dbLen = len1;
+ tbName = str + pos2;
+ tbLen = len2;
+ } else {
+ dbLen = strlen(db);
+ tbName = str + pos1;
+ tbLen = len1;
+ }
+
+ if (dbLen <= 0 || tbLen <= 0) {
+ return -1;
+ }
+
+ if (tNameSetDbName(&name, acctId, dbName, dbLen)) {
+ return -1;
+ }
+
+ if (tNameAddTbName(&name, tbName, tbLen)) {
+ return -1;
+ }
+
+ taosArrayPush(pList, &name);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName, SArray** pReq) {
+ *pReq = taosArrayInit(10, sizeof(SName));
+ if (NULL == *pReq) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
+ }
+
+ bool inEscape = false;
+ int32_t code = 0;
+
+ int32_t vIdx = 0;
+ int32_t vPos[2];
+ int32_t vLen[2];
+
+ memset(vPos, -1, sizeof(vPos));
+ memset(vLen, 0, sizeof(vLen));
+
+ for (int32_t i = 0;; ++i) {
+ if (0 == *(tbList + i)) {
+ if (vPos[vIdx] >= 0 && vLen[vIdx] <= 0) {
+ vLen[vIdx] = i - vPos[vIdx];
+ }
+
+ code = appendTbToReq(*pReq, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
+ if (code) {
+ goto _return;
+ }
+
+ break;
+ }
+
+ if ('`' == *(tbList + i)) {
+ inEscape = !inEscape;
+ if (!inEscape) {
+ if (vPos[vIdx] >= 0) {
+ vLen[vIdx] = i - vPos[vIdx];
+ } else {
+ goto _return;
+ }
+ }
+
+ continue;
+ }
+
+ if (inEscape) {
+ if (vPos[vIdx] < 0) {
+ vPos[vIdx] = i;
+ }
+ continue;
+ }
+
+ if ('.' == *(tbList + i)) {
+ if (vPos[vIdx] < 0) {
+ goto _return;
+ }
+ if (vLen[vIdx] <= 0) {
+ vLen[vIdx] = i - vPos[vIdx];
+ }
+ vIdx++;
+ if (vIdx >= 2) {
+ goto _return;
+ }
+ continue;
+ }
+
+ if (',' == *(tbList + i)) {
+ if (vPos[vIdx] < 0) {
+ goto _return;
+ }
+ if (vLen[vIdx] <= 0) {
+ vLen[vIdx] = i - vPos[vIdx];
+ }
+
+ code = appendTbToReq(*pReq, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
+ if (code) {
+ goto _return;
+ }
+
+ memset(vPos, -1, sizeof(vPos));
+ memset(vLen, 0, sizeof(vLen));
+ vIdx = 0;
+ continue;
+ }
+
+ if (' ' == *(tbList + i) || '\r' == *(tbList + i) || '\t' == *(tbList + i) || '\n' == *(tbList + i)) {
+ if (vPos[vIdx] >= 0 && vLen[vIdx] <= 0) {
+ vLen[vIdx] = i - vPos[vIdx];
+ }
+ continue;
+ }
+
+ if (('a' <= *(tbList + i) && 'z' >= *(tbList + i)) || ('A' <= *(tbList + i) && 'Z' >= *(tbList + i)) ||
+ ('0' <= *(tbList + i) && '9' >= *(tbList + i))) {
+ if (vLen[vIdx] > 0) {
+ goto _return;
+ }
+ if (vPos[vIdx] < 0) {
+ vPos[vIdx] = i;
+ }
+ continue;
+ }
+
+ goto _return;
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ terrno = TSDB_CODE_TSC_INVALID_OPERATION;
+
+ taosArrayDestroy(*pReq);
+ *pReq = NULL;
+
+ return terrno;
+}
+
+void syncCatalogFn(SMetaData* pResult, void* param, int32_t code) {
+ SSyncQueryParam* pParam = param;
+ pParam->pRequest->code = code;
+
+ tsem_post(&pParam->sem);
+}
+
+void syncQueryFn(void* param, void* res, int32_t code) {
+ SSyncQueryParam* pParam = param;
+ pParam->pRequest = res;
+ if (pParam->pRequest) {
+ pParam->pRequest->code = code;
+ }
+
+ tsem_post(&pParam->sem);
+}
+
+void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly) {
+ if (sql == NULL || NULL == fp) {
+ terrno = TSDB_CODE_INVALID_PARA;
+ fp(param, NULL, terrno);
+ return;
+ }
+
+ size_t sqlLen = strlen(sql);
+ if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
+ tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
+ terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
+ fp(param, NULL, terrno);
+ return;
+ }
+
+ SRequestObj* pRequest = NULL;
+ int32_t code = buildRequest(connId, sql, sqlLen, param, validateOnly, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ fp(param, NULL, terrno);
+ return;
+ }
+
+ pRequest->body.queryFp = fp;
+ doAsyncQuery(pRequest, false);
+}
+
+TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly) {
+ if (NULL == taos) {
+ terrno = TSDB_CODE_TSC_DISCONNECTED;
+ return NULL;
+ }
+
+#if SYNC_ON_TOP_OF_ASYNC
+ SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
+ tsem_init(¶m->sem, 0, 0);
+
+ taosAsyncQueryImpl(*(int64_t*)taos, sql, syncQueryFn, param, validateOnly);
+ tsem_wait(¶m->sem);
+ return param->pRequest;
+#else
+ size_t sqlLen = strlen(sql);
+ if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
+ tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
+ terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
+ return NULL;
+ }
+
+ TAOS_RES* pRes = execQuery(connId, sql, sqlLen, validateOnly);
+ return pRes;
+#endif
+}
diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c
index ba7de659311bc9056a32d2f1bdec1b0e72b1d2fa..14a431feabab2934aed0a7eee46f85dbdae2009c 100644
--- a/source/client/src/clientMain.c
+++ b/source/client/src/clientMain.c
@@ -17,6 +17,7 @@
#include "clientInt.h"
#include "clientLog.h"
#include "clientStmt.h"
+#include "functionMgt.h"
#include "os.h"
#include "query.h"
#include "scheduler.h"
@@ -25,7 +26,6 @@
#include "tref.h"
#include "trpc.h"
#include "version.h"
-#include "functionMgt.h"
#define TSC_VAR_NOT_RELEASE 1
#define TSC_VAR_RELEASED 0
@@ -47,11 +47,9 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
atomic_store_32(&lock, 0);
return ret;
}
-
// this function may be called by user or system, or by both simultaneously.
void taos_cleanup(void) {
- tscInfo("start to cleanup client environment");
-
+ tscDebug("start to cleanup client environment");
if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
return;
}
@@ -60,7 +58,10 @@ void taos_cleanup(void) {
clientReqRefPool = -1;
taosCloseRef(id);
- cleanupTaskQueue();
+ hbMgrCleanUp();
+
+ catalogDestroy();
+ schedulerDestroy();
fmFuncMgtDestroy();
qCleanupKeywordsTable();
@@ -69,21 +70,26 @@ void taos_cleanup(void) {
clientConnRefPool = -1;
taosCloseRef(id);
- hbMgrCleanUp();
-
- catalogDestroy();
- schedulerDestroy();
-
rpcCleanup();
+ tscDebug("rpc cleanup");
+
+ cleanupTaskQueue();
tscInfo("all local resources released");
taosCleanupCfg();
taosCloseLog();
}
-setConfRet taos_set_config(const char *config) {
- // TODO
+static setConfRet taos_set_config_imp(const char *config) {
setConfRet ret = {SET_CONF_RET_SUCC, {0}};
+ // TODO: need re-implementation
+ return ret;
+}
+
+setConfRet taos_set_config(const char *config) {
+ // TODO pthread_mutex_lock(&setConfMutex);
+ setConfRet ret = taos_set_config_imp(config);
+ // pthread_mutex_unlock(&setConfMutex);
return ret;
}
@@ -97,11 +103,13 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha
pass = TSDB_DEFAULT_PASS;
}
- STscObj* pObj = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY);
+ STscObj *pObj = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY);
if (pObj) {
- return pObj->id;
+ int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
+ *rid = pObj->id;
+ return (TAOS *)rid;
}
-
+
return NULL;
}
@@ -111,41 +119,40 @@ void taos_close_internal(void *taos) {
}
STscObj *pTscObj = (STscObj *)taos;
- tscDebug("0x%" PRIx64 " try to close connection, numOfReq:%d", *(int64_t*)pTscObj->id, pTscObj->numOfReqs);
+ tscDebug("0x%" PRIx64 " try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
- taosRemoveRef(clientConnRefPool, *(int64_t*)pTscObj->id);
+ taosRemoveRef(clientConnRefPool, pTscObj->id);
}
void taos_close(TAOS *taos) {
if (taos == NULL) {
return;
}
-
- STscObj* pObj = acquireTscObj(*(int64_t*)taos);
+
+ STscObj *pObj = acquireTscObj(*(int64_t *)taos);
if (NULL == pObj) {
return;
}
-
+
taos_close_internal(pObj);
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
taosMemoryFree(taos);
}
-
-int taos_errno(TAOS_RES *tres) {
- if (tres == NULL) {
+int taos_errno(TAOS_RES *res) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return terrno;
}
- if (TD_RES_TMQ(tres)) {
+ if (TD_RES_TMQ(res)) {
return 0;
}
- return ((SRequestObj *)tres)->code;
+ return ((SRequestObj *)res)->code;
}
const char *taos_errstr(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return (const char *)tstrerror(terrno);
}
@@ -173,17 +180,30 @@ void taos_free_result(TAOS_RES *res) {
SMqRspObj *pRsp = (SMqRspObj *)res;
if (pRsp->rsp.blockData) taosArrayDestroyP(pRsp->rsp.blockData, taosMemoryFree);
if (pRsp->rsp.blockDataLen) taosArrayDestroy(pRsp->rsp.blockDataLen);
- if (pRsp->rsp.blockTags) taosArrayDestroy(pRsp->rsp.blockTags);
- if (pRsp->rsp.blockTagSchema) taosArrayDestroy(pRsp->rsp.blockTagSchema);
if (pRsp->rsp.withTbName) taosArrayDestroyP(pRsp->rsp.blockTbName, taosMemoryFree);
if (pRsp->rsp.withSchema) taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper);
pRsp->resInfo.pRspMsg = NULL;
doFreeReqResultInfo(&pRsp->resInfo);
+ } else if (TD_RES_TMQ_META(res)) {
+ SMqMetaRspObj *pRspObj = (SMqMetaRspObj *)res;
+ taosMemoryFree(pRspObj->metaRsp.metaRsp);
+ taosMemoryFree(pRspObj);
+ }
+}
+
+void taos_kill_query(TAOS *taos) {
+ if (NULL == taos) {
+ return;
}
+
+ int64_t rid = *(int64_t *)taos;
+ STscObj *pTscObj = acquireTscObj(rid);
+ stopAllRequests(pTscObj->pRequests);
+ releaseTscObj(rid);
}
int taos_field_count(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return 0;
}
@@ -194,7 +214,7 @@ int taos_field_count(TAOS_RES *res) {
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
- if (taos_num_fields(res) == 0) {
+ if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res)) {
return NULL;
}
@@ -202,52 +222,7 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
return pResInfo->userFields;
}
-static void syncQueryFn(void *param, void *res, int32_t code) {
- SSyncQueryParam *pParam = param;
- pParam->pRequest = res;
- pParam->pRequest->code = code;
-
- tsem_post(&pParam->sem);
-}
-
-TAOS_RES *taos_query(TAOS *taos, const char *sql) {
- if (NULL == taos) {
- terrno = TSDB_CODE_TSC_DISCONNECTED;
- return NULL;
- }
-
- STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
- if (pTscObj == NULL || sql == NULL) {
- terrno = TSDB_CODE_TSC_DISCONNECTED;
- return NULL;
- }
-
-#if SYNC_ON_TOP_OF_ASYNC
- SSyncQueryParam *param = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
- tsem_init(¶m->sem, 0, 0);
-
- taos_query_a(taos, sql, syncQueryFn, param);
- tsem_wait(¶m->sem);
-
- releaseTscObj(*(int64_t*)taos);
-
- return param->pRequest;
-#else
- size_t sqlLen = strlen(sql);
- if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
- releaseTscObj(*(int64_t*)taos);
- tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
- terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
- return NULL;
- }
-
- TAOS_RES* pRes = execQuery(pTscObj, sql, sqlLen);
-
- releaseTscObj(*(int64_t*)taos);
-
- return pRes;
-#endif
-}
+TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false); }
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
if (res == NULL) {
@@ -287,6 +262,8 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
pResultInfo->current += 1;
return pResultInfo->row;
}
+ } else if (TD_RES_TMQ_META(res)) {
+ return NULL;
} else {
// assert to avoid un-initialization error
ASSERT(0);
@@ -380,7 +357,7 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
}
int *taos_fetch_lengths(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return NULL;
}
@@ -389,7 +366,7 @@ int *taos_fetch_lengths(TAOS_RES *res) {
}
TAOS_ROW *taos_result_block(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
terrno = TSDB_CODE_INVALID_PARA;
return NULL;
}
@@ -438,7 +415,7 @@ const char *taos_data_type(int type) {
const char *taos_get_client_info() { return version; }
int taos_affected_rows(TAOS_RES *res) {
- if (res == NULL || TD_RES_TMQ(res)) {
+ if (res == NULL || TD_RES_TMQ(res) || TD_RES_TMQ_META(res)) {
return 0;
}
@@ -448,7 +425,7 @@ int taos_affected_rows(TAOS_RES *res) {
}
int taos_result_precision(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return TSDB_TIME_PRECISION_MILLI;
}
@@ -463,15 +440,15 @@ int taos_result_precision(TAOS_RES *res) {
}
int taos_select_db(TAOS *taos, const char *db) {
- STscObj* pObj = acquireTscObj(*(int64_t*)taos);
+ STscObj *pObj = acquireTscObj(*(int64_t *)taos);
if (pObj == NULL) {
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
terrno = TSDB_CODE_TSC_DISCONNECTED;
return TSDB_CODE_TSC_DISCONNECTED;
}
if (db == NULL || strlen(db) == 0) {
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
terrno = TSDB_CODE_TSC_INVALID_INPUT;
return terrno;
}
@@ -483,33 +460,33 @@ int taos_select_db(TAOS *taos, const char *db) {
int32_t code = taos_errno(pRequest);
taos_free_result(pRequest);
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
return code;
}
void taos_stop_query(TAOS_RES *res) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ(res) || TD_RES_TMQ_META(res)) {
return;
}
SRequestObj *pRequest = (SRequestObj *)res;
pRequest->killed = true;
-
- int32_t numOfFields = taos_num_fields(pRequest);
+
+ int32_t numOfFields = taos_num_fields(pRequest);
// It is not a query, no need to stop.
if (numOfFields == 0) {
tscDebug("request %" PRIx64 " no need to be killed since not query", pRequest->requestId);
return;
}
- if (pRequest->body.queryJob) {
- schedulerFreeJob(pRequest->body.queryJob, TSDB_CODE_TSC_QUERY_KILLED);
- }
-
+ schedulerFreeJob(&pRequest->body.queryJob, TSDB_CODE_TSC_QUERY_KILLED);
tscDebug("request %" PRIx64 " killed", pRequest->requestId);
}
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
+ return true;
+ }
SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
return true;
@@ -532,7 +509,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
}
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return 0;
}
@@ -575,7 +552,7 @@ int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
}
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return 0;
}
@@ -615,7 +592,7 @@ int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
}
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
- if (res == NULL) {
+ if (res == NULL || TD_RES_TMQ_META(res)) {
return 0;
}
@@ -633,10 +610,17 @@ int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
return pResInfo->pCol[columnIndex].offset;
}
-int taos_validate_sql(TAOS *taos, const char *sql) { return true; }
+int taos_validate_sql(TAOS *taos, const char *sql) {
+ TAOS_RES *pObj = taosQueryImpl(taos, sql, true);
+
+ int code = taos_errno(pObj);
+
+ taos_free_result(pObj);
+ return code;
+}
void taos_reset_current_db(TAOS *taos) {
- STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
+ STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
if (pTscObj == NULL) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
return;
@@ -644,19 +628,19 @@ void taos_reset_current_db(TAOS *taos) {
resetConnectDB(pTscObj);
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
}
const char *taos_get_server_info(TAOS *taos) {
- STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
+ STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
if (pTscObj == NULL) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
return NULL;
}
- releaseTscObj(*(int64_t*)taos);
+ releaseTscObj(*(int64_t *)taos);
- return pTscObj->ver;
+ return pTscObj->sDetailVer;
}
typedef struct SqlParseWrapper {
@@ -681,8 +665,6 @@ static void destorySqlParseWrapper(SqlParseWrapper *pWrapper) {
}
void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) {
- tscDebug("enter meta callback, code %s", tstrerror(code));
-
SqlParseWrapper *pWrapper = (SqlParseWrapper *)param;
SQuery *pQuery = pWrapper->pQuery;
SRequestObj *pRequest = pWrapper->pRequest;
@@ -702,10 +684,12 @@ void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) {
TSWAP(pRequest->tableList, (pQuery)->pTableList);
destorySqlParseWrapper(pWrapper);
+
+ tscDebug("0x%" PRIx64 " analysis semantics completed, start async query, reqId:0x%" PRIx64, pRequest->self,
+ pRequest->requestId);
launchAsyncQuery(pRequest, pQuery, pResultMeta);
} else {
destorySqlParseWrapper(pWrapper);
- tscDebug("error happens, code:%d", code);
if (NEED_CLIENT_HANDLE_ERROR(code)) {
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%d - %s, tryCount:%d, reqId:0x%" PRIx64,
pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
@@ -723,38 +707,8 @@ void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) {
}
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
- STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
- if (pTscObj == NULL || sql == NULL || NULL == fp) {
- terrno = TSDB_CODE_INVALID_PARA;
- if (pTscObj) {
- releaseTscObj(*(int64_t*)taos);
- } else {
- terrno = TSDB_CODE_TSC_DISCONNECTED;
- }
- fp(param, NULL, terrno);
- return;
- }
-
- size_t sqlLen = strlen(sql);
- if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
- tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
- terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
-
- fp(param, NULL, terrno);
- return;
- }
-
- SRequestObj *pRequest = NULL;
- int32_t code = buildRequest(pTscObj, sql, sqlLen, &pRequest);
- if (code != TSDB_CODE_SUCCESS) {
- terrno = code;
- fp(param, NULL, terrno);
- return;
- }
-
- pRequest->body.queryFp = fp;
- pRequest->body.param = param;
- doAsyncQuery(pRequest, false);
+ int64_t connId = *(int64_t *)taos;
+ taosAsyncQueryImpl(connId, sql, fp, param, false);
}
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt) {
@@ -765,23 +719,23 @@ int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- **pCxt = (SParseContext){
- .requestId = pRequest->requestId,
- .requestRid = pRequest->self,
- .acctId = pTscObj->acctId,
- .db = pRequest->pDb,
- .topicQuery = false,
- .pSql = pRequest->sqlstr,
- .sqlLen = pRequest->sqlLen,
- .pMsg = pRequest->msgBuf,
- .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
- .pTransporter = pTscObj->pAppInfo->pTransporter,
- .pStmtCb = NULL,
- .pUser = pTscObj->user,
- .schemalessType = pTscObj->schemalessType,
- .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
- .async = true,
- };
+ **pCxt = (SParseContext){.requestId = pRequest->requestId,
+ .requestRid = pRequest->self,
+ .acctId = pTscObj->acctId,
+ .db = pRequest->pDb,
+ .topicQuery = false,
+ .pSql = pRequest->sqlstr,
+ .sqlLen = pRequest->sqlLen,
+ .pMsg = pRequest->msgBuf,
+ .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
+ .pTransporter = pTscObj->pAppInfo->pTransporter,
+ .pStmtCb = NULL,
+ .pUser = pTscObj->user,
+ .schemalessType = pTscObj->schemalessType,
+ .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
+ .async = true,
+ .svrVer = pTscObj->sVer,
+ .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes)};
return TSDB_CODE_SUCCESS;
}
@@ -830,7 +784,7 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
.requestObjRefId = pCxt->requestRid,
.mgmtEps = pCxt->mgmtEpSet};
- code = catalogAsyncGetAllMeta(pCxt->pCatalog, &conn, pRequest->requestId, &catalogReq, retrieveMetaCallback, pWrapper,
+ code = catalogAsyncGetAllMeta(pCxt->pCatalog, &conn, &catalogReq, retrieveMetaCallback, pWrapper,
&pRequest->body.queryJob);
if (code == TSDB_CODE_SUCCESS) {
return;
@@ -849,8 +803,8 @@ static void fetchCallback(void *pResult, void *param, int32_t code) {
SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
- tscDebug("0x%" PRIx64 " enter scheduler fetch cb, code:%d - %s, reqId:0x%" PRIx64,
- pRequest->self, code, tstrerror(code), pRequest->requestId);
+ tscDebug("0x%" PRIx64 " enter scheduler fetch cb, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code,
+ tstrerror(code), pRequest->requestId);
pResultInfo->pData = pResult;
pResultInfo->numOfRows = 0;
@@ -884,45 +838,66 @@ static void fetchCallback(void *pResult, void *param, int32_t code) {
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
ASSERT(res != NULL && fp != NULL);
+ ASSERT(TD_RES_QUERY(res));
SRequestObj *pRequest = res;
pRequest->body.fetchFp = fp;
pRequest->body.param = param;
SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
- if (taos_num_fields(pRequest) == 0) {
+
+ // this query has no results or error exists, return directly
+ if (taos_num_fields(pRequest) == 0 || pRequest->code != TSDB_CODE_SUCCESS) {
pResultInfo->numOfRows = 0;
pRequest->body.fetchFp(param, pRequest, pResultInfo->numOfRows);
return;
}
- if (pResultInfo->pData == NULL || pResultInfo->current >= pResultInfo->numOfRows) {
- // All data has returned to App already, no need to try again
- if (pResultInfo->completed) {
+ // all data has returned to App already, no need to try again
+ if (pResultInfo->completed) {
+ // it is a local executed query, no need to do async fetch
+ if (QUERY_EXEC_MODE_LOCAL == pRequest->body.execMode) {
+ ASSERT(pResultInfo->numOfRows >= 0);
+ if (pResultInfo->localResultFetched) {
+ pResultInfo->numOfRows = 0;
+ pResultInfo->current = 0;
+ } else {
+ pResultInfo->localResultFetched = true;
+ }
+ } else {
pResultInfo->numOfRows = 0;
- pRequest->body.fetchFp(param, pRequest, pResultInfo->numOfRows);
- return;
}
+
+ pRequest->body.fetchFp(param, pRequest, pResultInfo->numOfRows);
+ return;
}
- schedulerAsyncFetchRows(pRequest->body.queryJob, fetchCallback, pRequest);
+ SSchedulerReq req = {
+ .syncReq = false,
+ .fetchFp = fetchCallback,
+ .cbParam = pRequest,
+ };
+
+ schedulerFetchRows(pRequest->body.queryJob, &req);
}
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
ASSERT(res != NULL && fp != NULL);
- SRequestObj *pRequest = res;
-
- pRequest->body.resInfo.convertUcs4 = false;
+ ASSERT(TD_RES_QUERY(res));
+ SRequestObj *pRequest = res;
SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
// set the current block is all consumed
- pResultInfo->current = pResultInfo->numOfRows;
- taos_fetch_rows_a(res, fp, param);
+ pResultInfo->convertUcs4 = false;
+
+ // it is a local executed query, no need to do async fetch
+ taos_fetch_rows_a(pRequest, fp, param);
}
const void *taos_get_raw_block(TAOS_RES *res) {
ASSERT(res != NULL);
+ ASSERT(TD_RES_QUERY(res));
SRequestObj *pRequest = res;
return pRequest->body.resInfo.pData;
@@ -944,21 +919,78 @@ void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
}
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
- // TODO
- return -1;
+ if (NULL == taos) {
+ terrno = TSDB_CODE_TSC_DISCONNECTED;
+ return terrno;
+ }
+
+ int64_t connId = *(int64_t *)taos;
+ const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024; // 12MB list
+ int32_t code = 0;
+ SRequestObj *pRequest = NULL;
+ SCatalogReq catalogReq = {0};
+
+ if (NULL == tableNameList) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t length = (int32_t)strlen(tableNameList);
+ if (0 == length) {
+ return TSDB_CODE_SUCCESS;
+ } else if (length > MAX_TABLE_NAME_LENGTH) {
+ tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+
+ char *sql = "taos_load_table_info";
+ code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ goto _return;
+ }
+
+ STscObj *pTscObj = pRequest->pTscObj;
+ code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
+ if (code) {
+ goto _return;
+ }
+
+ SCatalog *pCtg = NULL;
+ code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _return;
+ }
+
+ SRequestConnInfo conn = {
+ .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
+
+ conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
+
+ code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, NULL, NULL);
+ if (code) {
+ goto _return;
+ }
+
+ SSyncQueryParam *pParam = pRequest->body.param;
+ tsem_wait(&pParam->sem);
+
+_return:
+ taosArrayDestroy(catalogReq.pTableMeta);
+ destroyRequest(pRequest);
+ return code;
}
TAOS_STMT *taos_stmt_init(TAOS *taos) {
- STscObj* pObj = acquireTscObj(*(int64_t*)taos);
+ STscObj *pObj = acquireTscObj(*(int64_t *)taos);
if (NULL == pObj) {
tscError("invalid parameter for %s", __FUNCTION__);
terrno = TSDB_CODE_TSC_DISCONNECTED;
return NULL;
}
- TAOS_STMT* pStmt = stmtInit(pObj);
-
- releaseTscObj(*(int64_t*)taos);
+ TAOS_STMT *pStmt = stmtInit(pObj);
+
+ releaseTscObj(*(int64_t *)taos);
return pStmt;
}
diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c
index db8aebb32293de4e20c95b96062283d4187e867e..94bd5dd7871fa7fa636bfd9c8aa6ff90097ff3e1 100644
--- a/source/client/src/clientMsgHandler.c
+++ b/source/client/src/clientMsgHandler.c
@@ -26,7 +26,7 @@ static void setErrno(SRequestObj* pRequest, int32_t code) {
terrno = code;
}
-int32_t genericRspCallback(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t genericRspCallback(void* param, SDataBuf* pMsg, int32_t code) {
SRequestObj* pRequest = param;
setErrno(pRequest, code);
@@ -39,7 +39,7 @@ int32_t genericRspCallback(void* param, const SDataBuf* pMsg, int32_t code) {
return code;
}
-int32_t processConnectRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) {
SRequestObj* pRequest = param;
if (code != TSDB_CODE_SUCCESS) {
taosMemoryFree(pMsg->pData);
@@ -67,30 +67,30 @@ int32_t processConnectRsp(void* param, const SDataBuf* pMsg, int32_t code) {
dstEpSet.eps[dstEpSet.inUse].fqdn);
} else if (connectRsp.dnodeNum > 1 && !isEpsetEqual(&pTscObj->pAppInfo->mgmtEp.epSet, &connectRsp.epSet)) {
SEpSet* pOrig = &pTscObj->pAppInfo->mgmtEp.epSet;
- SEp* pOrigEp = &pOrig->eps[pOrig->inUse];
- SEp* pNewEp = &connectRsp.epSet.eps[connectRsp.epSet.inUse];
- tscDebug("mnode epset updated from %d/%d=>%s:%d to %d/%d=>%s:%d in connRsp",
- pOrig->inUse, pOrig->numOfEps, pOrigEp->fqdn, pOrigEp->port,
- connectRsp.epSet.inUse, connectRsp.epSet.numOfEps, pNewEp->fqdn, pNewEp->port);
+ SEp* pOrigEp = &pOrig->eps[pOrig->inUse];
+ SEp* pNewEp = &connectRsp.epSet.eps[connectRsp.epSet.inUse];
+ tscDebug("mnode epset updated from %d/%d=>%s:%d to %d/%d=>%s:%d in connRsp", pOrig->inUse, pOrig->numOfEps,
+ pOrigEp->fqdn, pOrigEp->port, connectRsp.epSet.inUse, connectRsp.epSet.numOfEps, pNewEp->fqdn,
+ pNewEp->port);
updateEpSet_s(&pTscObj->pAppInfo->mgmtEp, &connectRsp.epSet);
}
for (int32_t i = 0; i < connectRsp.epSet.numOfEps; ++i) {
tscDebug("0x%" PRIx64 " epSet.fqdn[%d]:%s port:%d, connObj:0x%" PRIx64, pRequest->requestId, i,
- connectRsp.epSet.eps[i].fqdn, connectRsp.epSet.eps[i].port, *(int64_t*)pTscObj->id);
+ connectRsp.epSet.eps[i].fqdn, connectRsp.epSet.eps[i].port, pTscObj->id);
}
pTscObj->connId = connectRsp.connId;
pTscObj->acctId = connectRsp.acctId;
- tstrncpy(pTscObj->ver, connectRsp.sVersion, tListLen(pTscObj->ver));
+ tstrncpy(pTscObj->sVer, connectRsp.sVer, tListLen(pTscObj->sVer));
+ tstrncpy(pTscObj->sDetailVer, connectRsp.sDetailVer, tListLen(pTscObj->sDetailVer));
// update the appInstInfo
pTscObj->pAppInfo->clusterId = connectRsp.clusterId;
- atomic_add_fetch_64(&pTscObj->pAppInfo->numOfConns, 1);
pTscObj->connType = connectRsp.connType;
- hbRegisterConn(pTscObj->pAppInfo->pAppHbMgr, *(int64_t*)pTscObj->id, connectRsp.clusterId, connectRsp.connType);
+ hbRegisterConn(pTscObj->pAppInfo->pAppHbMgr, pTscObj->id, connectRsp.clusterId, connectRsp.connType);
// pRequest->body.resInfo.pRspMsg = pMsg->pData;
tscDebug("0x%" PRIx64 " clusterId:%" PRId64 ", totalConn:%" PRId64, pRequest->requestId, connectRsp.clusterId,
@@ -116,7 +116,7 @@ SMsgSendInfo* buildMsgInfoImpl(SRequestObj* pRequest) {
return pMsgSendInfo;
}
-int32_t processCreateDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processCreateDbRsp(void* param, SDataBuf* pMsg, int32_t code) {
// todo rsp with the vnode id list
SRequestObj* pRequest = param;
taosMemoryFree(pMsg->pData);
@@ -132,7 +132,7 @@ int32_t processCreateDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
return code;
}
-int32_t processUseDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processUseDbRsp(void* param, SDataBuf* pMsg, int32_t code) {
SRequestObj* pRequest = param;
if (TSDB_CODE_MND_DB_NOT_EXIST == code) {
@@ -179,7 +179,6 @@ int32_t processUseDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
if (code != 0) {
terrno = code;
if (output.dbVgroup) taosHashCleanup(output.dbVgroup->vgHash);
- taosMemoryFreeClear(output.dbVgroup);
tscError("0x%" PRIx64 " failed to build use db output since %s", pRequest->requestId, terrstr());
} else if (output.dbVgroup && output.dbVgroup->vgHash) {
@@ -189,12 +188,14 @@ int32_t processUseDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
if (code1 != TSDB_CODE_SUCCESS) {
tscWarn("catalogGetHandle failed, clusterId:%" PRIx64 ", error:%s", pRequest->pTscObj->pAppInfo->clusterId,
tstrerror(code1));
- taosMemoryFreeClear(output.dbVgroup);
} else {
catalogUpdateDBVgInfo(pCatalog, output.db, output.dbId, output.dbVgroup);
+ output.dbVgroup = NULL;
}
}
+ taosMemoryFreeClear(output.dbVgroup);
+
tFreeSUsedbRsp(&usedbRsp);
char db[TSDB_DB_NAME_LEN] = {0};
@@ -211,7 +212,7 @@ int32_t processUseDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
return 0;
}
-int32_t processCreateSTableRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processCreateSTableRsp(void* param, SDataBuf* pMsg, int32_t code) {
assert(pMsg != NULL && param != NULL);
SRequestObj* pRequest = param;
@@ -229,7 +230,7 @@ int32_t processCreateSTableRsp(void* param, const SDataBuf* pMsg, int32_t code)
return code;
}
-int32_t processDropDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processDropDbRsp(void* param, SDataBuf* pMsg, int32_t code) {
SRequestObj* pRequest = param;
if (code != TSDB_CODE_SUCCESS) {
setErrno(pRequest, code);
@@ -250,7 +251,7 @@ int32_t processDropDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
return code;
}
-int32_t processAlterStbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t processAlterStbRsp(void* param, SDataBuf* pMsg, int32_t code) {
SRequestObj* pRequest = param;
if (code != TSDB_CODE_SUCCESS) {
setErrno(pRequest, code);
@@ -266,7 +267,7 @@ int32_t processAlterStbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
}
if (pRequest->body.queryFp != NULL) {
- SQueryExecRes* pRes = &pRequest->body.resInfo.execRes;
+ SExecResult* pRes = &pRequest->body.resInfo.execRes;
if (code == TSDB_CODE_SUCCESS) {
SCatalog* pCatalog = NULL;
@@ -287,6 +288,101 @@ int32_t processAlterStbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
return code;
}
+static int32_t buildShowVariablesBlock(SArray* pVars, SSDataBlock** block) {
+ SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ pBlock->info.hasVarCol = true;
+
+ pBlock->pDataBlock = taosArrayInit(SHOW_VARIABLES_RESULT_COLS, sizeof(SColumnInfoData));
+
+ SColumnInfoData infoData = {0};
+ infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
+ infoData.info.bytes = SHOW_VARIABLES_RESULT_FIELD1_LEN;
+
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
+ infoData.info.bytes = SHOW_VARIABLES_RESULT_FIELD2_LEN;
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ int32_t numOfCfg = taosArrayGetSize(pVars);
+ blockDataEnsureCapacity(pBlock, numOfCfg);
+
+ for (int32_t i = 0, c = 0; i < numOfCfg; ++i, c = 0) {
+ SVariablesInfo* pInfo = taosArrayGet(pVars, i);
+
+ char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_WITH_MAXSIZE_TO_VARSTR(name, pInfo->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE);
+ SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, name, false);
+
+ char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_WITH_MAXSIZE_TO_VARSTR(value, pInfo->value, TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, value, false);
+ }
+
+ pBlock->info.rows = numOfCfg;
+
+ *block = pBlock;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t buildShowVariablesRsp(SArray* pVars, SRetrieveTableRsp** pRsp) {
+ SSDataBlock* pBlock = NULL;
+ int32_t code = buildShowVariablesBlock(pVars, &pBlock);
+ if (code) {
+ return code;
+ }
+
+ size_t rspSize = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
+ *pRsp = taosMemoryCalloc(1, rspSize);
+ if (NULL == *pRsp) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ (*pRsp)->useconds = 0;
+ (*pRsp)->completed = 1;
+ (*pRsp)->precision = 0;
+ (*pRsp)->compressed = 0;
+ (*pRsp)->compLen = 0;
+ (*pRsp)->numOfRows = htonl(pBlock->info.rows);
+ (*pRsp)->numOfCols = htonl(SHOW_VARIABLES_RESULT_COLS);
+
+ int32_t len = 0;
+ blockEncode(pBlock, (*pRsp)->data, &len, SHOW_VARIABLES_RESULT_COLS, false);
+ ASSERT(len == rspSize - sizeof(SRetrieveTableRsp));
+
+ blockDataDestroy(pBlock);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t processShowVariablesRsp(void* param, SDataBuf* pMsg, int32_t code) {
+ SRequestObj* pRequest = param;
+ if (code != TSDB_CODE_SUCCESS) {
+ setErrno(pRequest, code);
+ } else {
+ SShowVariablesRsp rsp = {0};
+ SRetrieveTableRsp* pRes = NULL;
+ code = tDeserializeSShowVariablesRsp(pMsg->pData, pMsg->len, &rsp);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = buildShowVariablesRsp(rsp.variables, &pRes);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false, false);
+ }
+
+ tFreeSShowVariablesRsp(&rsp);
+ }
+
+ if (pRequest->body.queryFp != NULL) {
+ pRequest->body.queryFp(pRequest->body.param, pRequest, code);
+ } else {
+ tsem_post(&pRequest->body.rspSem);
+ }
+ return code;
+}
+
__async_send_cb_fn_t getMsgRspHandle(int32_t msgType) {
switch (msgType) {
case TDMT_MND_CONNECT:
@@ -301,6 +397,8 @@ __async_send_cb_fn_t getMsgRspHandle(int32_t msgType) {
return processDropDbRsp;
case TDMT_MND_ALTER_STB:
return processAlterStbRsp;
+ case TDMT_MND_SHOW_VARIABLES:
+ return processShowVariablesRsp;
default:
return genericRspCallback;
}
diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c
index e724637620f0feabc089314edf33e603d92f5156..5f26db67fc7df53873f155e46ccdbf772da1ca6e 100644
--- a/source/client/src/clientSml.c
+++ b/source/client/src/clientSml.c
@@ -274,11 +274,16 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
return 0;
}
-static int32_t smlFindNearestPowerOf2(int32_t length) {
+static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
int32_t result = 1;
while (result <= length) {
result *= 2;
}
+ if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE){
+ result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE;
+ } 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;
+ }
return result;
}
@@ -287,7 +292,7 @@ static int32_t smlBuildColumnDescription(SSmlKv *field, char *buf, int32_t bufSi
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);
+ int32_t bytes = smlFindNearestPowerOf2(field->length, type);
int out = snprintf(buf, bufSize, "`%s` %s(%d)", tname, tDataTypes[field->type].name, bytes);
*outBytes = out;
} else {
@@ -309,7 +314,7 @@ static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *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(info->taos->id, result); // TODO async doAsyncQuery
+ 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) {
@@ -323,7 +328,7 @@ static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *action) {
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(info->taos->id, result); // TODO async doAsyncQuery
+ 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) {
@@ -337,7 +342,7 @@ static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *action) {
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(info->taos->id, result); // TODO async doAsyncQuery
+ 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));
@@ -350,7 +355,7 @@ static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *action) {
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(info->taos->id, result); // TODO async doAsyncQuery
+ 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));
@@ -405,7 +410,7 @@ static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *action) {
pos--;
++freeBytes;
outBytes = snprintf(pos, freeBytes, ")");
- TAOS_RES *res = taos_query(info->taos->id, result);
+ 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));
@@ -834,7 +839,7 @@ static int32_t smlParseTS(SSmlHandle *info, const char *data, int32_t len, SArra
ASSERT(0);
}
- if (ts == -1) return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ if (ts == -1) return TSDB_CODE_INVALID_TIMESTAMP;
// add ts to
SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1);
@@ -851,35 +856,41 @@ static int32_t smlParseTS(SSmlHandle *info, const char *data, int32_t len, SArra
return TSDB_CODE_SUCCESS;
}
-static bool smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) {
+static int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) {
// binary
if (smlIsBinary(pVal->value, pVal->length)) {
pVal->type = TSDB_DATA_TYPE_BINARY;
pVal->length -= BINARY_ADD_LEN;
+ if (pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE){
+ return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
+ }
pVal->value += (BINARY_ADD_LEN - 1);
- return true;
+ return TSDB_CODE_SUCCESS;
}
// nchar
if (smlIsNchar(pVal->value, pVal->length)) {
pVal->type = TSDB_DATA_TYPE_NCHAR;
pVal->length -= NCHAR_ADD_LEN;
+ if(pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE){
+ return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
+ }
pVal->value += (NCHAR_ADD_LEN - 1);
- return true;
+ return TSDB_CODE_SUCCESS;
}
// bool
if (smlParseBool(pVal)) {
pVal->type = TSDB_DATA_TYPE_BOOL;
pVal->length = (int16_t)tDataTypes[pVal->type].bytes;
- return true;
+ return TSDB_CODE_SUCCESS;
}
// number
if (smlParseNumber(pVal, msg)) {
pVal->length = (int16_t)tDataTypes[pVal->type].bytes;
- return true;
+ return TSDB_CODE_SUCCESS;
}
- return false;
+ return TSDB_CODE_TSC_INVALID_VALUE;
}
static int32_t smlParseInfluxString(const char *sql, SSmlLineInfo *elements, SSmlMsgBuf *msg) {
@@ -906,7 +917,7 @@ static int32_t smlParseInfluxString(const char *sql, SSmlLineInfo *elements, SSm
elements->measureLen = sql - elements->measure;
if (IS_INVALID_TABLE_LEN(elements->measureLen)) {
smlBuildInvalidDataMsg(msg, "measure is empty or too large than 192", NULL);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
}
// parse tag
@@ -1001,11 +1012,11 @@ static int32_t smlParseTelnetTags(const char *data, SArray *cols, char *childTab
if (IS_INVALID_COL_LEN(keyLen)) {
smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
}
if (smlCheckDuplicateKey(key, keyLen, dumplicateKey)) {
smlBuildInvalidDataMsg(msg, "dumplicate key", key);
- return TSDB_CODE_TSC_DUP_TAG_NAMES;
+ return TSDB_CODE_TSC_DUP_NAMES;
}
// parse value
@@ -1026,7 +1037,7 @@ static int32_t smlParseTelnetTags(const char *data, SArray *cols, char *childTab
if (valueLen == 0) {
smlBuildInvalidDataMsg(msg, "invalid value", value);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_VALUE;
}
// handle child table name
@@ -1059,7 +1070,7 @@ static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, SSmlTable
smlParseTelnetElement(&sql, &tinfo->sTableName, &tinfo->sTableNameLen);
if (!(tinfo->sTableName) || IS_INVALID_TABLE_LEN(tinfo->sTableNameLen)) {
smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", sql);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
}
// parse timestamp
@@ -1074,7 +1085,7 @@ static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, SSmlTable
int32_t ret = smlParseTS(info, timestamp, tLen, cols);
if (ret != TSDB_CODE_SUCCESS) {
smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", sql);
- return TSDB_CODE_SML_INVALID_DATA;
+ return ret;
}
// parse value
@@ -1083,7 +1094,7 @@ static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, SSmlTable
smlParseTelnetElement(&sql, &value, &valueLen);
if (!value || valueLen == 0) {
smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", sql);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_VALUE;
}
SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1);
@@ -1093,15 +1104,15 @@ static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, SSmlTable
kv->keyLen = VALUE_LEN;
kv->value = value;
kv->length = valueLen;
- if (!smlParseValue(kv, &info->msgBuf)) {
- return TSDB_CODE_SML_INVALID_DATA;
+ if ((ret = smlParseValue(kv, &info->msgBuf)) != TSDB_CODE_SUCCESS) {
+ return ret;
}
// parse tags
ret = smlParseTelnetTags(sql, tinfo->tags, tinfo->childTableName, info->dumplicateKey, &info->msgBuf);
if (ret != TSDB_CODE_SUCCESS) {
smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", sql);
- return TSDB_CODE_SML_INVALID_DATA;
+ return ret;
}
return TSDB_CODE_SUCCESS;
@@ -1135,11 +1146,11 @@ static int32_t smlParseCols(const char *data, int32_t len, SArray *cols, char *c
if (IS_INVALID_COL_LEN(keyLen)) {
smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
}
if (smlCheckDuplicateKey(key, keyLen, dumplicateKey)) {
smlBuildInvalidDataMsg(msg, "dumplicate key", key);
- return TSDB_CODE_TSC_DUP_TAG_NAMES;
+ return TSDB_CODE_TSC_DUP_NAMES;
}
// parse value
@@ -1195,8 +1206,9 @@ static int32_t smlParseCols(const char *data, int32_t len, SArray *cols, char *c
if (isTag) {
kv->type = TSDB_DATA_TYPE_NCHAR;
} else {
- if (!smlParseValue(kv, msg)) {
- return TSDB_CODE_SML_INVALID_DATA;
+ int32_t ret = smlParseValue(kv, msg);
+ if (ret != TSDB_CODE_SUCCESS) {
+ return ret;
}
}
}
@@ -1204,8 +1216,8 @@ static int32_t smlParseCols(const char *data, int32_t len, SArray *cols, char *c
return TSDB_CODE_SUCCESS;
}
-static bool smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, SSmlMsgBuf *msg) {
- for (int i = 0; i < taosArrayGetSize(cols); ++i) { // jump timestamp
+static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, SSmlMsgBuf *msg) {
+ for (int i = 0; i < taosArrayGetSize(cols); ++i) {
SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i);
int16_t *index = (int16_t *)taosHashGet(metaHash, kv->key, kv->keyLen);
@@ -1213,7 +1225,7 @@ static bool smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, S
SSmlKv **value = (SSmlKv **)taosArrayGet(metaArray, *index);
if (kv->type != (*value)->type) {
smlBuildInvalidDataMsg(msg, "the type is not the same like before", kv->key);
- return false;
+ return TSDB_CODE_SML_NOT_SAME_TYPE;
} else {
if (IS_VAR_DATA_TYPE(kv->type)) { // update string len, if bigger
if (kv->length > (*value)->length) {
@@ -1230,7 +1242,7 @@ static bool smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, S
}
}
- return true;
+ return TSDB_CODE_SUCCESS;
}
static void smlInsertMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols) {
@@ -1564,47 +1576,52 @@ static int32_t smlParseTSFromJSONObj(SSmlHandle *info, cJSON *root, int64_t *tsV
double timeDouble = value->valuedouble;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- if (timeDouble <= 0) {
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+
+ if (timeDouble == 0) {
+ *tsVal = taosGetTimestampNs();
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (timeDouble < 0) {
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
+ *tsVal = timeDouble;
size_t typeLen = strlen(type->valuestring);
if (typeLen == 1 && (type->valuestring[0] == 's' || type->valuestring[0] == 'S')) {
// seconds
- timeDouble = timeDouble * 1e9;
+ *tsVal = *tsVal * NANOSECOND_PER_SEC;
+ timeDouble = timeDouble * NANOSECOND_PER_SEC;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- *tsVal = timeDouble;
} else if (typeLen == 2 && (type->valuestring[1] == 's' || type->valuestring[1] == 'S')) {
switch (type->valuestring[0]) {
case 'm':
case 'M':
// milliseconds
- timeDouble = timeDouble * 1e6;
+ *tsVal = *tsVal * NANOSECOND_PER_MSEC;
+ timeDouble = timeDouble * NANOSECOND_PER_MSEC;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- *tsVal = timeDouble;
break;
case 'u':
case 'U':
// microseconds
- timeDouble = timeDouble * 1e3;
+ *tsVal = *tsVal * NANOSECOND_PER_USEC;
+ timeDouble = timeDouble * NANOSECOND_PER_USEC;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- *tsVal = timeDouble;
break;
case 'n':
case 'N':
- // nanoseconds
- *tsVal = timeDouble;
break;
default:
return TSDB_CODE_TSC_INVALID_JSON;
@@ -1635,31 +1652,33 @@ static int32_t smlParseTSFromJSON(SSmlHandle *info, cJSON *root, SArray *cols) {
double timeDouble = timestamp->valuedouble;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
if (timeDouble < 0) {
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
+
uint8_t tsLen = smlGetTimestampLen((int64_t)timeDouble);
+ tsVal = (int64_t)timeDouble;
if (tsLen == TSDB_TIME_PRECISION_SEC_DIGITS) {
- timeDouble = timeDouble * 1e9;
+ tsVal = tsVal * NANOSECOND_PER_SEC;
+ timeDouble = timeDouble * NANOSECOND_PER_SEC;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- tsVal = timeDouble;
} else if (tsLen == TSDB_TIME_PRECISION_MILLI_DIGITS) {
- timeDouble = timeDouble * 1e6;
+ tsVal = tsVal * NANOSECOND_PER_MSEC;
+ timeDouble = timeDouble * NANOSECOND_PER_MSEC;
if (smlDoubleToInt64OverFlow(timeDouble)) {
smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL);
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
- tsVal = timeDouble;
} else if (timeDouble == 0) {
tsVal = taosGetTimestampNs();
} else {
- return TSDB_CODE_TSC_INVALID_TIME_STAMP;
+ return TSDB_CODE_INVALID_TIMESTAMP;
}
} else if (cJSON_IsObject(timestamp)) {
int32_t ret = smlParseTSFromJSONObj(info, timestamp, &tsVal);
@@ -1778,6 +1797,14 @@ static int32_t smlConvertJSONString(SSmlKv *pVal, char *typeStr, cJSON *value) {
return TSDB_CODE_TSC_INVALID_JSON_TYPE;
}
pVal->length = (int16_t)strlen(value->valuestring);
+
+ if (pVal->type == TSDB_DATA_TYPE_BINARY && pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE){
+ return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
+ }
+ if (pVal->type == TSDB_DATA_TYPE_NCHAR && pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE){
+ return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
+ }
+
return smlJsonCreateSring(&pVal->value, value->valuestring, pVal->length);
}
@@ -1912,7 +1939,7 @@ static int32_t smlParseTagsFromJSON(cJSON *root, SArray *pKVs, char *childTableN
}
// check duplicate keys
if (smlCheckDuplicateKey(tag->string, keyLen, dumplicateKey)) {
- return TSDB_CODE_TSC_DUP_TAG_NAMES;
+ return TSDB_CODE_TSC_DUP_NAMES;
}
// handle child table name
@@ -2032,7 +2059,7 @@ static int32_t smlParseInfluxLine(SSmlHandle *info, const char *sql) {
}
if (taosArrayGetSize(cols) > TSDB_MAX_COLUMNS) {
smlBuildInvalidDataMsg(&info->msgBuf, "too many columns than 4096", NULL);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_PAR_TOO_MANY_COLUMNS;
}
bool hasTable = true;
@@ -2064,7 +2091,7 @@ static int32_t smlParseInfluxLine(SSmlHandle *info, const char *sql) {
if (taosArrayGetSize((*oneTable)->tags) > TSDB_MAX_TAGS) {
smlBuildInvalidDataMsg(&info->msgBuf, "too many tags than 128", NULL);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_PAR_INVALID_TAGS_NUM;
}
(*oneTable)->sTableName = elements.measure;
@@ -2083,12 +2110,12 @@ static int32_t smlParseInfluxLine(SSmlHandle *info, const char *sql) {
SSmlSTableMeta **tableMeta = (SSmlSTableMeta **)taosHashGet(info->superTables, elements.measure, elements.measureLen);
if (tableMeta) { // update meta
ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, cols, &info->msgBuf);
- if (!hasTable && ret) {
+ if (!hasTable && ret == TSDB_CODE_SUCCESS) {
ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, (*oneTable)->tags, &info->msgBuf);
}
- if (!ret) {
+ if (ret != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id);
- return TSDB_CODE_SML_INVALID_DATA;
+ return ret;
}
} else {
SSmlSTableMeta *meta = smlBuildSTableMeta();
@@ -2137,7 +2164,7 @@ static int32_t smlParseTelnetLine(SSmlHandle *info, void *data) {
smlDestroyTableInfo(info, tinfo);
smlDestroyCols(cols);
taosArrayDestroy(cols);
- return TSDB_CODE_SML_INVALID_DATA;
+ return TSDB_CODE_PAR_INVALID_TAGS_NUM;
}
taosHashClear(info->dumplicateKey);
@@ -2168,9 +2195,9 @@ static int32_t smlParseTelnetLine(SSmlHandle *info, void *data) {
if (!hasTable && ret) {
ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, (*oneTable)->tags, &info->msgBuf);
}
- if (!ret) {
+ if (ret != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id);
- return TSDB_CODE_SML_INVALID_DATA;
+ return ret;
}
} else {
SSmlSTableMeta *meta = smlBuildSTableMeta();
@@ -2255,7 +2282,7 @@ static int32_t smlInsertData(SSmlHandle *info) {
(*pMeta)->tableMeta->uid = tableData->uid; // one table merge data block together according uid
code = smlBindData(info->exec, tableData->tags, (*pMeta)->cols, tableData->cols, info->dataFormat,
- (*pMeta)->tableMeta, tableData->childTableName, info->msgBuf.buf, info->msgBuf.len);
+ (*pMeta)->tableMeta, tableData->childTableName, tableData->sTableName, tableData->sTableNameLen, info->msgBuf.buf, info->msgBuf.len);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlBindData failed", info->id);
return code;
@@ -2436,21 +2463,20 @@ static void smlInsertCallback(void *param, void *res, int32_t code) {
*/
TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int protocol, int precision) {
- STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
- if (NULL == pTscObj) {
+ if (NULL == taos) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
- uError("SML:taos_schemaless_insert invalid taos");
return NULL;
}
-
- SRequestObj* request = (SRequestObj*)createRequest(pTscObj, TSDB_SQL_INSERT);
+
+ SRequestObj* request = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT);
if(!request){
- releaseTscObj(*(int64_t*)taos);
uError("SML:taos_schemaless_insert error request is null");
return NULL;
}
int batchs = 0;
+ STscObj* pTscObj = request->pTscObj;
+
pTscObj->schemalessType = 1;
SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf};
@@ -2500,7 +2526,7 @@ TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int pr
batchs = ceil(((double)numLines) / LINE_BATCH);
for (int i = 0; i < batchs; ++i) {
- SRequestObj* req = (SRequestObj*)createRequest(pTscObj, TSDB_SQL_INSERT);
+ SRequestObj* req = (SRequestObj*)createRequest(pTscObj->id, TSDB_SQL_INSERT);
if(!req){
request->code = TSDB_CODE_OUT_OF_MEMORY;
uError("SML:taos_schemaless_insert error request is null");
@@ -2542,6 +2568,5 @@ end:
// ((STscObj *)taos)->schemalessType = 0;
pTscObj->schemalessType = 1;
uDebug("resultend:%s", request->msgBuf);
- releaseTscObj(*(int64_t*)taos);
return (TAOS_RES*)request;
}
diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c
index 1c0caec8102b5b0311c4cfd7240ea78270163628..bf00965c7ad6f267d2d942d2a8e5d00e677026e9 100644
--- a/source/client/src/clientStmt.c
+++ b/source/client/src/clientStmt.c
@@ -5,6 +5,14 @@
#include "clientStmt.h"
+static int32_t stmtCreateRequest(STscStmt* pStmt) {
+ if (pStmt->exec.pRequest == NULL) {
+ return buildRequest(pStmt->taos->id, pStmt->sql.sqlStr, pStmt->sql.sqlLen, NULL, false, &pStmt->exec.pRequest);
+ } else {
+ return TSDB_CODE_SUCCESS;
+ }
+}
+
int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) {
int32_t code = 0;
@@ -128,7 +136,7 @@ int32_t stmtRestoreQueryFields(STscStmt* pStmt) {
return TSDB_CODE_SUCCESS;
}
-int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, char* tbFName) {
+int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, char* tbFName, const char* sTableName) {
STscStmt* pStmt = (STscStmt*)stmt;
strncpy(pStmt->bInfo.tbFName, tbFName, sizeof(pStmt->bInfo.tbFName) - 1);
@@ -139,6 +147,7 @@ int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags,
pStmt->bInfo.tbType = pTableMeta->tableType;
pStmt->bInfo.boundTags = tags;
pStmt->bInfo.tagsCached = false;
+ strcpy(pStmt->bInfo.stbFName, sTableName);
return TSDB_CODE_SUCCESS;
}
@@ -154,10 +163,10 @@ int32_t stmtUpdateExecInfo(TAOS_STMT* stmt, SHashObj* pVgHash, SHashObj* pBlockH
}
int32_t stmtUpdateInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, char* tbFName, bool autoCreateTbl,
- SHashObj* pVgHash, SHashObj* pBlockHash) {
+ SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName) {
STscStmt* pStmt = (STscStmt*)stmt;
- STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbFName));
+ STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbFName, sTableName));
STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash, autoCreateTbl));
pStmt->sql.autoCreateTbl = autoCreateTbl;
@@ -217,9 +226,7 @@ int32_t stmtParseSql(STscStmt* pStmt) {
.getExecInfoFn = stmtGetExecInfo,
};
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
STMT_ERR_RET(parseSql(pStmt->exec.pRequest, false, &pStmt->sql.pQuery, &stmtCb));
@@ -247,7 +254,7 @@ int32_t stmtCleanBindInfo(STscStmt* pStmt) {
destroyBoundColumnInfo(pStmt->bInfo.boundTags);
taosMemoryFreeClear(pStmt->bInfo.boundTags);
}
-
+ memset(pStmt->bInfo.stbFName, 0, TSDB_TABLE_FNAME_LEN);
return TSDB_CODE_SUCCESS;
}
@@ -324,9 +331,9 @@ int32_t stmtCleanSQLInfo(STscStmt* pStmt) {
}
int32_t stmtRebuildDataBlock(STscStmt* pStmt, STableDataBlocks* pDataBlock, STableDataBlocks** newBlock, uint64_t uid) {
- SEpSet ep = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp);
- SVgroupInfo vgInfo = {0};
- SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
+ SEpSet ep = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp);
+ SVgroupInfo vgInfo = {0};
+ SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
.requestId = pStmt->exec.pRequest->requestId,
.requestObjRefId = pStmt->exec.pRequest->self,
.mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)};
@@ -351,6 +358,7 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
pStmt->bInfo.inExecCache = true;
if (pStmt->sql.autoCreateTbl) {
+ tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName);
return TSDB_CODE_SUCCESS;
}
}
@@ -359,9 +367,11 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
if (pStmt->bInfo.inExecCache) {
ASSERT(taosHashGetSize(pStmt->exec.pBlockHash) == 1);
pStmt->bInfo.needParse = false;
+ tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName);
return TSDB_CODE_SUCCESS;
}
+ tscDebug("no stmt block cache for tb %s", pStmt->bInfo.tbFName);
return TSDB_CODE_SUCCESS;
}
@@ -385,22 +395,25 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
+ tscDebug("reuse stmt block for tb %s in sqlBlock, suid:0x%" PRIx64 , pStmt->bInfo.tbFName, pStmt->bInfo.tbSuid);
+
return TSDB_CODE_SUCCESS;
}
STMT_RET(stmtCleanBindInfo(pStmt));
}
- STableMeta* pTableMeta = NULL;
- SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
+ STableMeta* pTableMeta = NULL;
+ SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
.requestId = pStmt->exec.pRequest->requestId,
.requestObjRefId = pStmt->exec.pRequest->self,
.mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)};
- int32_t code =
- catalogGetTableMeta(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &pTableMeta);
+ int32_t code = catalogGetTableMeta(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &pTableMeta);
if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code) {
STMT_ERR_RET(stmtCleanBindInfo(pStmt));
+ tscDebug("tb %s not exist", pStmt->bInfo.tbFName);
+
return TSDB_CODE_SUCCESS;
}
@@ -415,6 +428,8 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
if (uid == pStmt->bInfo.tbUid) {
pStmt->bInfo.needParse = false;
+ tscDebug("tb %s is current table", pStmt->bInfo.tbFName);
+
return TSDB_CODE_SUCCESS;
}
@@ -435,6 +450,8 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
pStmt->bInfo.boundTags = pCache->boundTags;
pStmt->bInfo.tagsCached = true;
+ tscDebug("tb %s in execBlock list, set to current", pStmt->bInfo.tbFName);
+
return TSDB_CODE_SUCCESS;
}
@@ -456,6 +473,8 @@ int32_t stmtGetFromCache(STscStmt* pStmt) {
STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
+ tscDebug("tb %s in sqlBlock list, set to current", pStmt->bInfo.tbFName);
+
return TSDB_CODE_SUCCESS;
}
@@ -505,6 +524,8 @@ TAOS_STMT* stmtInit(STscObj* taos) {
int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
STscStmt* pStmt = (STscStmt*)stmt;
+ tscDebug("stmt start to prepare");
+
if (pStmt->sql.status >= STMT_PREPARE) {
STMT_ERR_RET(stmtResetStmt(pStmt));
}
@@ -524,6 +545,8 @@ int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) {
STscStmt* pStmt = (STscStmt*)stmt;
+ tscDebug("stmt start to set tbName: %s", tbName);
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTBNAME));
int32_t insert = 0;
@@ -533,9 +556,7 @@ int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) {
STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
STMT_ERR_RET(qCreateSName(&pStmt->bInfo.sname, tbName, pStmt->taos->acctId, pStmt->exec.pRequest->pDb,
pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen));
@@ -556,6 +577,8 @@ int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) {
int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) {
STscStmt* pStmt = (STscStmt*)stmt;
+ tscDebug("stmt start to set tbTags");
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS));
if (pStmt->bInfo.inExecCache) {
@@ -569,7 +592,8 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) {
STMT_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
}
- STMT_ERR_RET(qBindStmtTagsValue(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbSuid, pStmt->bInfo.sname.tname,
+ tscDebug("start to bind stmt tag values");
+ STMT_ERR_RET(qBindStmtTagsValue(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbSuid, pStmt->bInfo.stbFName, pStmt->bInfo.sname.tname,
tags, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen));
return TSDB_CODE_SUCCESS;
@@ -614,6 +638,8 @@ int stmtFetchColFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields
int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
STscStmt* pStmt = (STscStmt*)stmt;
+ tscDebug("start to bind stmt data, colIdx: %d", colIdx);
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_BIND));
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
@@ -626,9 +652,7 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
pStmt->exec.pRequest = NULL;
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
if (pStmt->bInfo.needParse) {
STMT_ERR_RET(stmtParseSql(pStmt));
@@ -706,6 +730,8 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
int stmtAddBatch(TAOS_STMT* stmt) {
STscStmt* pStmt = (STscStmt*)stmt;
+ tscDebug("stmt start to add batch");
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_ADD_BATCH));
STMT_ERR_RET(stmtCacheBlock(pStmt));
@@ -714,6 +740,8 @@ int stmtAddBatch(TAOS_STMT* stmt) {
}
int stmtUpdateTableUid(STscStmt* pStmt, SSubmitRsp* pRsp) {
+ tscDebug("stmt start to update tbUid, blockNum: %d", pRsp->nBlocks);
+
if (pRsp->nBlocks <= 0) {
tscError("invalid submit resp block number %d", pRsp->nBlocks);
STMT_ERR_RET(TSDB_CODE_TSC_APP_ERROR);
@@ -726,11 +754,6 @@ int stmtUpdateTableUid(STscStmt* pStmt, SSubmitRsp* pRsp) {
char* key = taosHashGetKey(pIter, &keyLen);
STableMeta* pMeta = qGetTableMetaInDataBlock(pBlock);
- if (pMeta->uid != pStmt->bInfo.tbUid) {
- tscError("table uid %" PRIx64 " mis-match with current table uid %" PRIx64, pMeta->uid, pStmt->bInfo.tbUid);
- STMT_ERR_RET(TSDB_CODE_TSC_APP_ERROR);
- }
-
if (pMeta->uid) {
pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
continue;
@@ -774,6 +797,8 @@ int stmtExec(TAOS_STMT* stmt) {
SSubmitRsp* pRsp = NULL;
bool autoCreateTbl = pStmt->exec.autoCreateTbl;
+ tscDebug("stmt start to exec");
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE));
if (STMT_TYPE_QUERY == pStmt->sql.type) {
@@ -849,7 +874,7 @@ int stmtIsInsert(TAOS_STMT* stmt, int* insert) {
if (pStmt->sql.type) {
*insert = (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type);
} else {
- *insert = qIsInsertSql(pStmt->sql.sqlStr, 0);
+ *insert = qIsInsertValuesSql(pStmt->sql.sqlStr, pStmt->sql.sqlLen);
}
return TSDB_CODE_SUCCESS;
@@ -861,7 +886,7 @@ int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
if (STMT_TYPE_QUERY == pStmt->sql.type) {
STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR);
}
-
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
@@ -874,9 +899,7 @@ int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
pStmt->exec.pRequest = NULL;
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
if (pStmt->bInfo.needParse) {
STMT_ERR_RET(stmtParseSql(pStmt));
@@ -893,7 +916,7 @@ int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
if (STMT_TYPE_QUERY == pStmt->sql.type) {
STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR);
}
-
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
@@ -906,9 +929,7 @@ int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
pStmt->exec.pRequest = NULL;
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
if (pStmt->bInfo.needParse) {
STMT_ERR_RET(stmtParseSql(pStmt));
@@ -919,7 +940,6 @@ int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
return TSDB_CODE_SUCCESS;
}
-
int stmtGetParamNum(TAOS_STMT* stmt, int* nums) {
STscStmt* pStmt = (STscStmt*)stmt;
@@ -935,10 +955,7 @@ int stmtGetParamNum(TAOS_STMT* stmt, int* nums) {
pStmt->exec.pRequest = NULL;
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
-
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
if (pStmt->bInfo.needParse) {
STMT_ERR_RET(stmtParseSql(pStmt));
}
@@ -952,13 +969,13 @@ int stmtGetParamNum(TAOS_STMT* stmt, int* nums) {
return TSDB_CODE_SUCCESS;
}
-int stmtGetParam(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
+int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
STscStmt* pStmt = (STscStmt*)stmt;
if (STMT_TYPE_QUERY == pStmt->sql.type) {
STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR);
}
-
+
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
@@ -971,16 +988,14 @@ int stmtGetParam(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
pStmt->exec.pRequest = NULL;
}
- if (NULL == pStmt->exec.pRequest) {
- STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest));
- }
+ STMT_ERR_RET(stmtCreateRequest(pStmt));
if (pStmt->bInfo.needParse) {
STMT_ERR_RET(stmtParseSql(pStmt));
}
- int32_t nums = 0;
- TAOS_FIELD_E *pField = NULL;
+ int32_t nums = 0;
+ TAOS_FIELD_E* pField = NULL;
STMT_ERR_RET(stmtFetchColFields(stmt, &nums, &pField));
if (idx >= nums) {
tscError("idx %d is too big", idx);
diff --git a/source/client/src/tmq.c b/source/client/src/tmq.c
index 638b4f1ea559fed1d76009f1f1141aa1c9e36e07..ad47348c2291ecd4a0edabd1f1500b7d0031e34b 100644
--- a/source/client/src/tmq.c
+++ b/source/client/src/tmq.c
@@ -13,6 +13,7 @@
* along with this program. If not, see .
*/
+#include "cJSON.h"
#include "clientInt.h"
#include "clientLog.h"
#include "parser.h"
@@ -49,17 +50,18 @@ struct tmq_list_t {
};
struct tmq_conf_t {
- char clientId[256];
- char groupId[TSDB_CGROUP_LEN];
- int8_t autoCommit;
- int8_t resetOffset;
- int8_t withTbName;
- uint16_t port;
- int32_t autoCommitInterval;
- char* ip;
- char* user;
- char* pass;
- /*char* db;*/
+ char clientId[256];
+ char groupId[TSDB_CGROUP_LEN];
+ int8_t autoCommit;
+ int8_t resetOffset;
+ int8_t withTbName;
+ int8_t spEnable;
+ int32_t spBatchSize;
+ uint16_t port;
+ int32_t autoCommitInterval;
+ char* ip;
+ char* user;
+ char* pass;
tmq_commit_cb* commitCb;
void* commitCbUserParam;
};
@@ -69,6 +71,7 @@ struct tmq_t {
char groupId[TSDB_CGROUP_LEN];
char clientId[256];
int8_t withTbName;
+ int8_t useSnapshot;
int8_t autoCommit;
int32_t autoCommitInterval;
int32_t resetOffsetCfg;
@@ -103,6 +106,12 @@ struct tmq_t {
tsem_t rspSem;
};
+struct tmq_raw_data {
+ void* raw_meta;
+ int32_t raw_meta_len;
+ int16_t raw_meta_type;
+};
+
enum {
TMQ_VG_STATUS__IDLE = 0,
TMQ_VG_STATUS__WAIT,
@@ -124,8 +133,10 @@ typedef struct {
// statistics
int64_t pollCnt;
// offset
- int64_t committedOffset;
- int64_t currentOffset;
+ /*int64_t committedOffset;*/
+ /*int64_t currentOffset;*/
+ STqOffsetVal committedOffsetNew;
+ STqOffsetVal currentOffsetNew;
// connection info
int32_t vgId;
int32_t vgStatus;
@@ -149,7 +160,10 @@ typedef struct {
int32_t epoch;
SMqClientVg* vgHandle;
SMqClientTopic* topicHandle;
- SMqDataBlkRsp msg;
+ union {
+ SMqDataRsp dataRsp;
+ SMqMetaRsp metaRsp;
+ };
} SMqPollRspWrapper;
typedef struct {
@@ -174,6 +188,7 @@ typedef struct {
tsem_t rspSem;
} SMqPollCbParam;
+#if 0
typedef struct {
tmq_t* tmq;
int8_t async;
@@ -185,12 +200,13 @@ typedef struct {
SArray* offsets;
void* userParam;
} SMqCommitCbParam;
+#endif
typedef struct {
- tmq_t* tmq;
- int8_t automatic;
- int8_t async;
- int8_t freeOffsets;
+ tmq_t* tmq;
+ int8_t automatic;
+ int8_t async;
+ /*int8_t freeOffsets;*/
int32_t waitingRspNum;
int32_t totalRspNum;
int32_t rspErr;
@@ -279,6 +295,23 @@ tmq_conf_res_t tmq_conf_set(tmq_conf_t* conf, const char* key, const char* value
}
}
+ if (strcmp(key, "experimental.snapshot.enable") == 0) {
+ if (strcmp(value, "true") == 0) {
+ conf->spEnable = true;
+ return TMQ_CONF_OK;
+ } else if (strcmp(value, "false") == 0) {
+ conf->spEnable = false;
+ return TMQ_CONF_OK;
+ } else {
+ return TMQ_CONF_INVALID;
+ }
+ }
+
+ if (strcmp(key, "experimental.snapshot.batch.size") == 0) {
+ conf->spBatchSize = atoi(value);
+ return TMQ_CONF_OK;
+ }
+
if (strcmp(key, "td.connect.ip") == 0) {
conf->ip = strdup(value);
return TMQ_CONF_OK;
@@ -310,7 +343,7 @@ tmq_list_t* tmq_list_new() {
int32_t tmq_list_append(tmq_list_t* list, const char* src) {
SArray* container = &list->container;
- char* topic = strdup(src);
+ char* topic = strDupUnquo(src);
if (taosArrayPush(container, &topic) == NULL) return -1;
return 0;
}
@@ -334,6 +367,7 @@ static int32_t tmqMakeTopicVgKey(char* dst, const char* topicName, int32_t vg) {
return sprintf(dst, "%s:%d", topicName, vg);
}
+#if 0
int32_t tmqCommitCb(void* param, const SDataBuf* pMsg, int32_t code) {
SMqCommitCbParam* pParam = (SMqCommitCbParam*)param;
pParam->rspErr = code;
@@ -354,8 +388,9 @@ int32_t tmqCommitCb(void* param, const SDataBuf* pMsg, int32_t code) {
}
return 0;
}
+#endif
-int32_t tmqCommitCb2(void* param, const SDataBuf* pBuf, int32_t code) {
+int32_t tmqCommitCb2(void* param, SDataBuf* pBuf, int32_t code) {
SMqCommitCbParam2* pParam = (SMqCommitCbParam2*)param;
SMqCommitCbParamSet* pParamSet = (SMqCommitCbParamSet*)pParam->params;
// push into array
@@ -367,7 +402,7 @@ int32_t tmqCommitCb2(void* param, const SDataBuf* pBuf, int32_t code) {
}
#endif
- /*tscDebug("receive offset commit cb of %s on vg %d, offset is %ld", pParam->pOffset->subKey, pParam->->vgId,
+ /*tscDebug("receive offset commit cb of %s on vgId:%d, offset is %" PRId64, pParam->pOffset->subKey, pParam->->vgId,
* pOffset->version);*/
// count down waiting rsp
@@ -396,130 +431,86 @@ int32_t tmqCommitCb2(void* param, const SDataBuf* pBuf, int32_t code) {
return 0;
}
-int32_t tmqCommitInner2(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_t async, tmq_commit_cb* userCb,
- void* userParam) {
- int32_t code = -1;
+static int32_t tmqSendCommitReq(tmq_t* tmq, SMqClientVg* pVg, SMqClientTopic* pTopic, SMqCommitCbParamSet* pParamSet) {
+ STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset));
+ if (pOffset == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ pOffset->val = pVg->currentOffsetNew;
- if (msg != NULL) {
- SMqRspObj* pRspObj = (SMqRspObj*)msg;
- if (!TD_RES_TMQ(pRspObj)) {
- return TSDB_CODE_TMQ_INVALID_MSG;
- }
+ int32_t groupLen = strlen(tmq->groupId);
+ memcpy(pOffset->subKey, tmq->groupId, groupLen);
+ pOffset->subKey[groupLen] = TMQ_SEPARATOR;
+ strcpy(pOffset->subKey + groupLen + 1, pTopic->topicName);
- SMqCommitCbParamSet* pParamSet = taosMemoryCalloc(1, sizeof(SMqCommitCbParamSet));
- if (pParamSet == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
- pParamSet->tmq = tmq;
- pParamSet->automatic = automatic;
- pParamSet->async = async;
- pParamSet->freeOffsets = 1;
- pParamSet->userCb = userCb;
- pParamSet->userParam = userParam;
- tsem_init(&pParamSet->rspSem, 0, 0);
+ int32_t len;
+ int32_t code;
+ tEncodeSize(tEncodeSTqOffset, pOffset, len, code);
+ if (code < 0) {
+ ASSERT(0);
+ return -1;
+ }
+ void* buf = taosMemoryCalloc(1, sizeof(SMsgHead) + len);
+ if (buf == NULL) return -1;
+ ((SMsgHead*)buf)->vgId = htonl(pVg->vgId);
- for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) {
- SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
- if (strcmp(pTopic->topicName, pRspObj->topic) == 0) {
- for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) {
- SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
- if (pVg->vgId == pRspObj->vgId) {
- if (pVg->currentOffset < 0 || pVg->committedOffset == pVg->currentOffset) {
- tscDebug("consumer %ld skip commit for topic %s vg %d, current offset is %ld, committed offset is %ld",
- tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->currentOffset, pVg->committedOffset);
-
- return 0;
- }
-
- STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset));
- if (pOffset == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
- pOffset->type = TMQ_OFFSET__LOG;
- pOffset->version = pVg->currentOffset;
-
- int32_t groupLen = strlen(tmq->groupId);
- memcpy(pOffset->subKey, tmq->groupId, groupLen);
- pOffset->subKey[groupLen] = TMQ_SEPARATOR;
- strcpy(pOffset->subKey + groupLen + 1, pTopic->topicName);
-
- int32_t len;
- int32_t code;
- tEncodeSize(tEncodeSTqOffset, pOffset, len, code);
- if (code < 0) {
- ASSERT(0);
- }
- void* buf = taosMemoryCalloc(1, sizeof(SMsgHead) + len);
- ((SMsgHead*)buf)->vgId = htonl(pVg->vgId);
-
- void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
-
- SEncoder encoder;
- tEncoderInit(&encoder, abuf, len);
- tEncodeSTqOffset(&encoder, pOffset);
-
- // build param
- SMqCommitCbParam2* pParam = taosMemoryCalloc(1, sizeof(SMqCommitCbParam2));
- pParam->params = pParamSet;
- pParam->pOffset = pOffset;
-
- // build send info
- SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
- if (pMsgSendInfo == NULL) {
- // TODO
- continue;
- }
- pMsgSendInfo->msgInfo = (SDataBuf){
- .pData = buf,
- .len = sizeof(SMsgHead) + len,
- .handle = NULL,
- };
-
- tscDebug("consumer %ld commit offset of %s on vg %d, offset is %ld", tmq->consumerId, pOffset->subKey,
- pVg->vgId, pOffset->version);
-
- // TODO: put into cb
- pVg->committedOffset = pVg->currentOffset;
-
- pMsgSendInfo->requestId = generateRequestId();
- pMsgSendInfo->requestObjRefId = 0;
- pMsgSendInfo->param = pParam;
- pMsgSendInfo->fp = tmqCommitCb2;
- pMsgSendInfo->msgType = TDMT_VND_MQ_COMMIT_OFFSET;
- // send msg
-
- int64_t transporterId = 0;
- asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, pMsgSendInfo);
- pParamSet->waitingRspNum++;
- pParamSet->totalRspNum++;
- }
- }
- }
- }
- if (pParamSet->totalRspNum == 0) {
- tsem_destroy(&pParamSet->rspSem);
- taosMemoryFree(pParamSet);
- return 0;
- }
+ void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
- if (!async) {
- tsem_wait(&pParamSet->rspSem);
- code = pParamSet->rspErr;
- tsem_destroy(&pParamSet->rspSem);
- } else {
- code = 0;
- }
+ SEncoder encoder;
+ tEncoderInit(&encoder, abuf, len);
+ tEncodeSTqOffset(&encoder, pOffset);
- if (code != 0 && async) {
- if (automatic) {
- tmq->commitCb(tmq, code, tmq->commitCbUserParam);
- } else {
- userCb(tmq, code, userParam);
- }
- }
- return 0;
+ // build param
+ SMqCommitCbParam2* pParam = taosMemoryCalloc(1, sizeof(SMqCommitCbParam2));
+ pParam->params = pParamSet;
+ pParam->pOffset = pOffset;
+
+ // build send info
+ SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
+ if (pMsgSendInfo == NULL) {
+ return -1;
+ }
+ pMsgSendInfo->msgInfo = (SDataBuf){
+ .pData = buf,
+ .len = sizeof(SMsgHead) + len,
+ .handle = NULL,
+ };
+
+ tscDebug("consumer:%" PRId64 ", commit offset of %s on vgId:%d, offset is %" PRId64, tmq->consumerId, pOffset->subKey,
+ pVg->vgId, pOffset->val.version);
+
+ // TODO: put into cb
+ pVg->committedOffsetNew = pVg->currentOffsetNew;
+
+ pMsgSendInfo->requestId = generateRequestId();
+ pMsgSendInfo->requestObjRefId = 0;
+ pMsgSendInfo->param = pParam;
+ pMsgSendInfo->fp = tmqCommitCb2;
+ pMsgSendInfo->msgType = TDMT_VND_MQ_COMMIT_OFFSET;
+ // send msg
+
+ int64_t transporterId = 0;
+ asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, pMsgSendInfo);
+ pParamSet->waitingRspNum++;
+ pParamSet->totalRspNum++;
+ return 0;
+}
+
+int32_t tmqCommitMsgImpl(tmq_t* tmq, const TAOS_RES* msg, int8_t async, tmq_commit_cb* userCb, void* userParam) {
+ char* topic;
+ int32_t vgId;
+ ASSERT(msg != NULL);
+ if (TD_RES_TMQ(msg)) {
+ SMqRspObj* pRspObj = (SMqRspObj*)msg;
+ topic = pRspObj->topic;
+ vgId = pRspObj->vgId;
+ } else if (TD_RES_TMQ_META(msg)) {
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)msg;
+ topic = pMetaRspObj->topic;
+ vgId = pMetaRspObj->vgId;
+ } else {
+ return TSDB_CODE_TMQ_INVALID_MSG;
}
SMqCommitCbParamSet* pParamSet = taosMemoryCalloc(1, sizeof(SMqCommitCbParamSet));
@@ -528,93 +519,92 @@ int32_t tmqCommitInner2(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_
return -1;
}
pParamSet->tmq = tmq;
- pParamSet->automatic = automatic;
+ pParamSet->automatic = 0;
pParamSet->async = async;
- pParamSet->freeOffsets = 1;
+ /*pParamSet->freeOffsets = 1;*/
pParamSet->userCb = userCb;
pParamSet->userParam = userParam;
tsem_init(&pParamSet->rspSem, 0, 0);
+ int32_t code = -1;
+
for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) {
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
-
- tscDebug("consumer %ld begin commit for topic %s, vgNum %d", tmq->consumerId, pTopic->topicName,
- (int32_t)taosArrayGetSize(pTopic->vgs));
-
+ if (strcmp(pTopic->topicName, topic) != 0) continue;
for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) {
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
+ if (pVg->vgId != vgId) continue;
- tscDebug("consumer %ld begin commit for topic %s, vgId %d", tmq->consumerId, pTopic->topicName, pVg->vgId);
+ if (pVg->currentOffsetNew.type > 0 && !tOffsetEqual(&pVg->currentOffsetNew, &pVg->committedOffsetNew)) {
+ if (tmqSendCommitReq(tmq, pVg, pTopic, pParamSet) < 0) {
+ goto FAIL;
+ }
+ goto HANDLE_RSP;
+ }
+ }
+ }
- /*if (pVg->currentOffset < 0) {*/
- if (pVg->currentOffset < 0 || pVg->committedOffset == pVg->currentOffset) {
- tscDebug("consumer %ld skip commit for topic %s vg %d, current offset is %ld, committed offset is %ld",
- tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->currentOffset, pVg->committedOffset);
+HANDLE_RSP:
+ if (pParamSet->totalRspNum == 0) {
+ tsem_destroy(&pParamSet->rspSem);
+ taosMemoryFree(pParamSet);
+ return 0;
+ }
- continue;
- }
- STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset));
- if (pOffset == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
- pOffset->type = TMQ_OFFSET__LOG;
- pOffset->version = pVg->currentOffset;
-
- int32_t groupLen = strlen(tmq->groupId);
- memcpy(pOffset->subKey, tmq->groupId, groupLen);
- pOffset->subKey[groupLen] = TMQ_SEPARATOR;
- strcpy(pOffset->subKey + groupLen + 1, pTopic->topicName);
-
- int32_t len;
- int32_t code;
- tEncodeSize(tEncodeSTqOffset, pOffset, len, code);
- if (code < 0) {
- ASSERT(0);
- }
- void* buf = taosMemoryCalloc(1, sizeof(SMsgHead) + len);
- ((SMsgHead*)buf)->vgId = htonl(pVg->vgId);
+ if (!async) {
+ tsem_wait(&pParamSet->rspSem);
+ code = pParamSet->rspErr;
+ tsem_destroy(&pParamSet->rspSem);
+ return code;
+ } else {
+ code = 0;
+ }
- void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
+FAIL:
+ if (code != 0 && async) {
+ userCb(tmq, code, userParam);
+ }
+ return 0;
+}
- SEncoder encoder;
- tEncoderInit(&encoder, abuf, len);
- tEncodeSTqOffset(&encoder, pOffset);
+int32_t tmqCommitInner2(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_t async, tmq_commit_cb* userCb,
+ void* userParam) {
+ int32_t code = -1;
- // build param
- SMqCommitCbParam2* pParam = taosMemoryCalloc(1, sizeof(SMqCommitCbParam2));
- pParam->params = pParamSet;
- pParam->pOffset = pOffset;
+ if (msg != NULL) {
+ return tmqCommitMsgImpl(tmq, msg, async, userCb, userParam);
+ }
- // build send info
- SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
- if (pMsgSendInfo == NULL) {
- // TODO
- continue;
- }
- pMsgSendInfo->msgInfo = (SDataBuf){
- .pData = buf,
- .len = sizeof(SMsgHead) + len,
- .handle = NULL,
- };
+ SMqCommitCbParamSet* pParamSet = taosMemoryCalloc(1, sizeof(SMqCommitCbParamSet));
+ if (pParamSet == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ pParamSet->tmq = tmq;
+ pParamSet->automatic = automatic;
+ pParamSet->async = async;
+ /*pParamSet->freeOffsets = 1;*/
+ pParamSet->userCb = userCb;
+ pParamSet->userParam = userParam;
+ tsem_init(&pParamSet->rspSem, 0, 0);
- tscDebug("consumer %ld commit offset of %s on vg %d, offset is %ld", tmq->consumerId, pOffset->subKey, pVg->vgId,
- pOffset->version);
+ for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) {
+ SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
- // TODO: put into cb
- pVg->committedOffset = pVg->currentOffset;
+ tscDebug("consumer:%" PRId64 ", begin commit for topic %s, vgNum %d", tmq->consumerId, pTopic->topicName,
+ (int32_t)taosArrayGetSize(pTopic->vgs));
- pMsgSendInfo->requestId = generateRequestId();
- pMsgSendInfo->requestObjRefId = 0;
- pMsgSendInfo->param = pParam;
- pMsgSendInfo->fp = tmqCommitCb2;
- pMsgSendInfo->msgType = TDMT_VND_MQ_COMMIT_OFFSET;
- // send msg
+ for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) {
+ SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
- int64_t transporterId = 0;
- asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, pMsgSendInfo);
- pParamSet->waitingRspNum++;
- pParamSet->totalRspNum++;
+ tscDebug("consumer:%" PRId64 ", begin commit for topic %s, vgId:%d", tmq->consumerId, pTopic->topicName,
+ pVg->vgId);
+
+ if (pVg->currentOffsetNew.type > 0 && !tOffsetEqual(&pVg->currentOffsetNew, &pVg->committedOffsetNew)) {
+ if (tmqSendCommitReq(tmq, pVg, pTopic, pParamSet) < 0) {
+ continue;
+ }
+ }
}
}
@@ -836,7 +826,7 @@ void tmqClearUnhandleMsg(tmq_t* tmq) {
}
}
-int32_t tmqSubscribeCb(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t tmqSubscribeCb(void* param, SDataBuf* pMsg, int32_t code) {
SMqSubscribeCbParam* pParam = (SMqSubscribeCbParam*)param;
pParam->rspErr = code;
/*tmq_t* tmq = pParam->tmq;*/
@@ -911,6 +901,8 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
tmq_t* pTmq = taosMemoryCalloc(1, sizeof(tmq_t));
if (pTmq == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ tscError("consumer %ld setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), pTmq->groupId);
return NULL;
}
@@ -927,6 +919,8 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
pTmq->delayedTask = taosOpenQueue();
if (pTmq->clientTopics == NULL || pTmq->mqueue == NULL || pTmq->qall == NULL || pTmq->delayedTask == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ tscError("consumer %ld setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), pTmq->groupId);
goto FAIL;
}
@@ -941,6 +935,7 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
strcpy(pTmq->clientId, conf->clientId);
strcpy(pTmq->groupId, conf->groupId);
pTmq->withTbName = conf->withTbName;
+ pTmq->useSnapshot = conf->spEnable;
pTmq->autoCommit = conf->autoCommit;
pTmq->autoCommitInterval = conf->autoCommitInterval;
pTmq->commitCb = conf->commitCb;
@@ -952,16 +947,20 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
// init semaphore
if (tsem_init(&pTmq->rspSem, 0, 0) != 0) {
+ tscError("consumer %ld setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), pTmq->groupId);
goto FAIL;
}
// init connection
pTmq->pTscObj = taos_connect_internal(conf->ip, user, pass, NULL, NULL, conf->port, CONN_TYPE__TMQ);
if (pTmq->pTscObj == NULL) {
+ tscError("consumer %ld setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), pTmq->groupId);
tsem_destroy(&pTmq->rspSem);
goto FAIL;
}
+ tscInfo("consumer %ld is setup, consumer group %s", pTmq->consumerId, pTmq->groupId);
+
return pTmq;
FAIL:
@@ -1089,7 +1088,7 @@ int32_t tmqGetSkipLogNum(tmq_message_t* tmq_message) {
}
#endif
-int32_t tmqPollCb(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
SMqPollCbParam* pParam = (SMqPollCbParam*)param;
SMqClientVg* pVg = pParam->pVg;
SMqClientTopic* pTopic = pParam->pTopic;
@@ -1098,13 +1097,13 @@ int32_t tmqPollCb(void* param, const SDataBuf* pMsg, int32_t code) {
int32_t epoch = pParam->epoch;
taosMemoryFree(pParam);
if (code != 0) {
- tscWarn("msg discard from vg %d, epoch %d, code:%x", vgId, epoch, code);
+ tscWarn("msg discard from vgId:%d, epoch %d, code:%x", vgId, epoch, code);
if (pMsg->pData) taosMemoryFree(pMsg->pData);
if (code == TSDB_CODE_TQ_NO_COMMITTED_OFFSET) {
SMqPollRspWrapper* pRspWrapper = taosAllocateQitem(sizeof(SMqPollRspWrapper), DEF_QITEM);
if (pRspWrapper == NULL) {
taosMemoryFree(pMsg->pData);
- tscWarn("msg discard from vg %d, epoch %d since out of memory", vgId, epoch);
+ tscWarn("msg discard from vgId:%d, epoch %d since out of memory", vgId, epoch);
goto CREATE_MSG_FAIL;
}
pRspWrapper->tmqRspType = TMQ_MSG_TYPE__END_RSP;
@@ -1120,7 +1119,7 @@ int32_t tmqPollCb(void* param, const SDataBuf* pMsg, int32_t code) {
int32_t tmqEpoch = atomic_load_32(&tmq->epoch);
if (msgEpoch < tmqEpoch) {
// do not write into queue since updating epoch reset
- tscWarn("msg discard from vg %d since from earlier epoch, rsp epoch %d, current epoch %d", vgId, msgEpoch,
+ tscWarn("msg discard from vgId:%d since from earlier epoch, rsp epoch %d, current epoch %d", vgId, msgEpoch,
tmqEpoch);
tsem_post(&tmq->rspSem);
taosMemoryFree(pMsg->pData);
@@ -1128,27 +1127,39 @@ int32_t tmqPollCb(void* param, const SDataBuf* pMsg, int32_t code) {
}
if (msgEpoch != tmqEpoch) {
- tscWarn("mismatch rsp from vg %d, epoch %d, current epoch %d", vgId, msgEpoch, tmqEpoch);
+ tscWarn("mismatch rsp from vgId:%d, epoch %d, current epoch %d", vgId, msgEpoch, tmqEpoch);
}
+ // handle meta rsp
+ int8_t rspType = ((SMqRspHead*)pMsg->pData)->mqMsgType;
+
SMqPollRspWrapper* pRspWrapper = taosAllocateQitem(sizeof(SMqPollRspWrapper), DEF_QITEM);
if (pRspWrapper == NULL) {
taosMemoryFree(pMsg->pData);
- tscWarn("msg discard from vg %d, epoch %d since out of memory", vgId, epoch);
+ tscWarn("msg discard from vgId:%d, epoch %d since out of memory", vgId, epoch);
goto CREATE_MSG_FAIL;
}
- pRspWrapper->tmqRspType = TMQ_MSG_TYPE__POLL_RSP;
+ pRspWrapper->tmqRspType = rspType;
pRspWrapper->vgHandle = pVg;
pRspWrapper->topicHandle = pTopic;
- memcpy(&pRspWrapper->msg, pMsg->pData, sizeof(SMqRspHead));
+ if (rspType == TMQ_MSG_TYPE__POLL_RSP) {
+ SDecoder decoder;
+ tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
+ tDecodeSMqDataRsp(&decoder, &pRspWrapper->dataRsp);
+ memcpy(&pRspWrapper->dataRsp, pMsg->pData, sizeof(SMqRspHead));
+ } else {
+ ASSERT(rspType == TMQ_MSG_TYPE__POLL_META_RSP);
+ tDecodeSMqMetaRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &pRspWrapper->metaRsp);
+ memcpy(&pRspWrapper->metaRsp, pMsg->pData, sizeof(SMqRspHead));
+ }
- tDecodeSMqDataBlkRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &pRspWrapper->msg);
taosMemoryFree(pMsg->pData);
- tscDebug("consumer %ld recv poll: vg %d, req offset %ld, rsp offset %ld", tmq->consumerId, pVg->vgId,
- pRspWrapper->msg.reqOffset, pRspWrapper->msg.rspOffset);
+ tscDebug("consumer:%" PRId64 ", recv poll: vgId:%d, req offset %" PRId64 ", rsp offset %" PRId64 " type %d",
+ tmq->consumerId, pVg->vgId, pRspWrapper->dataRsp.reqOffset.version, pRspWrapper->dataRsp.rspOffset.version,
+ rspType);
taosWriteQitem(tmq->mqueue, pRspWrapper);
tsem_post(&tmq->rspSem);
@@ -1167,7 +1178,7 @@ bool tmqUpdateEp2(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
int32_t topicNumGet = taosArrayGetSize(pRsp->topics);
char vgKey[TSDB_TOPIC_FNAME_LEN + 22];
- tscDebug("consumer %ld update ep epoch %d to epoch %d, topic num: %d", tmq->consumerId, tmq->epoch, epoch,
+ tscDebug("consumer:%" PRId64 ", update ep epoch %d to epoch %d, topic num:%d", tmq->consumerId, tmq->epoch, epoch,
topicNumGet);
SArray* newTopics = taosArrayInit(topicNumGet, sizeof(SMqClientTopic));
@@ -1186,13 +1197,15 @@ bool tmqUpdateEp2(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
SMqClientTopic* pTopicCur = taosArrayGet(tmq->clientTopics, i);
if (pTopicCur->vgs) {
int32_t vgNumCur = taosArrayGetSize(pTopicCur->vgs);
- tscDebug("consumer %ld new vg num: %d", tmq->consumerId, vgNumCur);
+ tscDebug("consumer:%" PRId64 ", new vg num: %d", tmq->consumerId, vgNumCur);
for (int32_t j = 0; j < vgNumCur; j++) {
SMqClientVg* pVgCur = taosArrayGet(pTopicCur->vgs, j);
sprintf(vgKey, "%s:%d", pTopicCur->topicName, pVgCur->vgId);
- tscDebug("consumer %ld epoch %d vg %d vgKey is %s, offset is %ld", tmq->consumerId, epoch, pVgCur->vgId, vgKey,
- pVgCur->currentOffset);
- taosHashPut(pHash, vgKey, strlen(vgKey), &pVgCur->currentOffset, sizeof(int64_t));
+ char buf[80];
+ tFormatOffset(buf, 80, &pVgCur->currentOffsetNew);
+ tscDebug("consumer:%" PRId64 ", epoch %d vgId:%d vgKey is %s, offset is %s", tmq->consumerId, epoch,
+ pVgCur->vgId, vgKey, buf);
+ taosHashPut(pHash, vgKey, strlen(vgKey), &pVgCur->currentOffsetNew, sizeof(STqOffsetVal));
}
}
}
@@ -1204,24 +1217,25 @@ bool tmqUpdateEp2(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
topic.topicName = strdup(pTopicEp->topic);
tstrncpy(topic.db, pTopicEp->db, TSDB_DB_FNAME_LEN);
- tscDebug("consumer %ld update topic: %s", tmq->consumerId, topic.topicName);
+ tscDebug("consumer:%" PRId64 ", update topic: %s", tmq->consumerId, topic.topicName);
int32_t vgNumGet = taosArrayGetSize(pTopicEp->vgs);
topic.vgs = taosArrayInit(vgNumGet, sizeof(SMqClientVg));
for (int32_t j = 0; j < vgNumGet; j++) {
SMqSubVgEp* pVgEp = taosArrayGet(pTopicEp->vgs, j);
sprintf(vgKey, "%s:%d", topic.topicName, pVgEp->vgId);
- int64_t* pOffset = taosHashGet(pHash, vgKey, strlen(vgKey));
- int64_t offset = tmq->resetOffsetCfg;
+ STqOffsetVal* pOffset = taosHashGet(pHash, vgKey, strlen(vgKey));
+ STqOffsetVal offsetNew = {.type = tmq->resetOffsetCfg};
if (pOffset != NULL) {
- offset = *pOffset;
+ offsetNew = *pOffset;
}
- tscDebug("consumer %ld(epoch %d) offset of vg %d updated to %ld, vgKey is %s", tmq->consumerId, epoch,
- pVgEp->vgId, offset, vgKey);
+ /*tscDebug("consumer:%" PRId64 ", (epoch %d) offset of vgId:%d updated to %" PRId64 ", vgKey is %s",
+ * tmq->consumerId, epoch,*/
+ /*pVgEp->vgId, offset, vgKey);*/
SMqClientVg clientVg = {
.pollCnt = 0,
- .currentOffset = offset,
+ .currentOffsetNew = offsetNew,
.vgId = pVgEp->vgId,
.epSet = pVgEp->epSet,
.vgStatus = TMQ_VG_STATUS__IDLE,
@@ -1245,13 +1259,13 @@ bool tmqUpdateEp2(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
return set;
}
-#if 1
+#if 0
bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
/*printf("call update ep %d\n", epoch);*/
bool set = false;
int32_t topicNumGet = taosArrayGetSize(pRsp->topics);
char vgKey[TSDB_TOPIC_FNAME_LEN + 22];
- tscDebug("consumer %ld update ep epoch %d to epoch %d, topic num: %d", tmq->consumerId, tmq->epoch, epoch,
+ tscDebug("consumer:%" PRId64 ", update ep epoch %d to epoch %d, topic num: %d", tmq->consumerId, tmq->epoch, epoch,
topicNumGet);
SArray* newTopics = taosArrayInit(topicNumGet, sizeof(SMqClientTopic));
if (newTopics == NULL) {
@@ -1272,19 +1286,19 @@ bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
topic.topicName = strdup(pTopicEp->topic);
tstrncpy(topic.db, pTopicEp->db, TSDB_DB_FNAME_LEN);
- tscDebug("consumer %ld update topic: %s", tmq->consumerId, topic.topicName);
+ tscDebug("consumer:%" PRId64 ", update topic: %s", tmq->consumerId, topic.topicName);
int32_t topicNumCur = taosArrayGetSize(tmq->clientTopics);
for (int32_t j = 0; j < topicNumCur; j++) {
// find old topic
SMqClientTopic* pTopicCur = taosArrayGet(tmq->clientTopics, j);
if (pTopicCur->vgs && strcmp(pTopicCur->topicName, pTopicEp->topic) == 0) {
int32_t vgNumCur = taosArrayGetSize(pTopicCur->vgs);
- tscDebug("consumer %ld new vg num: %d", tmq->consumerId, vgNumCur);
+ tscDebug("consumer:%" PRId64 ", new vg num: %d", tmq->consumerId, vgNumCur);
if (vgNumCur == 0) break;
for (int32_t k = 0; k < vgNumCur; k++) {
SMqClientVg* pVgCur = taosArrayGet(pTopicCur->vgs, k);
sprintf(vgKey, "%s:%d", topic.topicName, pVgCur->vgId);
- tscDebug("consumer %ld epoch %d vg %d build %s", tmq->consumerId, epoch, pVgCur->vgId, vgKey);
+ tscDebug("consumer:%" PRId64 ", epoch %d vgId:%d build %s", tmq->consumerId, epoch, pVgCur->vgId, vgKey);
taosHashPut(pHash, vgKey, strlen(vgKey), &pVgCur->currentOffset, sizeof(int64_t));
}
break;
@@ -1298,13 +1312,13 @@ bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
sprintf(vgKey, "%s:%d", topic.topicName, pVgEp->vgId);
int64_t* pOffset = taosHashGet(pHash, vgKey, strlen(vgKey));
int64_t offset = pVgEp->offset;
- tscDebug("consumer %ld(epoch %d) original offset of vg %d is %ld", tmq->consumerId, epoch, pVgEp->vgId, offset);
+ tscDebug("consumer:%" PRId64 ", (epoch %d) original offset of vgId:%d is %" PRId64, tmq->consumerId, epoch, pVgEp->vgId, offset);
if (pOffset != NULL) {
offset = *pOffset;
- tscDebug("consumer %ld(epoch %d) receive offset of vg %d, full key is %s", tmq->consumerId, epoch, pVgEp->vgId,
+ tscDebug("consumer:%" PRId64 ", (epoch %d) receive offset of vgId:%d, full key is %s", tmq->consumerId, epoch, pVgEp->vgId,
vgKey);
}
- tscDebug("consumer %ld(epoch %d) offset of vg %d updated to %ld", tmq->consumerId, epoch, pVgEp->vgId, offset);
+ tscDebug("consumer:%" PRId64 ", (epoch %d) offset of vgId:%d updated to %" PRId64, tmq->consumerId, epoch, pVgEp->vgId, offset);
SMqClientVg clientVg = {
.pollCnt = 0,
.currentOffset = offset,
@@ -1332,13 +1346,13 @@ bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
}
#endif
-int32_t tmqAskEpCb(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t tmqAskEpCb(void* param, SDataBuf* pMsg, int32_t code) {
SMqAskEpCbParam* pParam = (SMqAskEpCbParam*)param;
tmq_t* tmq = pParam->tmq;
int8_t async = pParam->async;
pParam->code = code;
if (code != 0) {
- tscError("consumer %ld get topic endpoint error, not ready, wait:%d", tmq->consumerId, pParam->async);
+ tscError("consumer:%" PRId64 ", get topic endpoint error, not ready, wait:%d", tmq->consumerId, pParam->async);
goto END;
}
@@ -1347,7 +1361,7 @@ int32_t tmqAskEpCb(void* param, const SDataBuf* pMsg, int32_t code) {
// Epoch will only increase when received newer epoch ep msg
SMqRspHead* head = pMsg->pData;
int32_t epoch = atomic_load_32(&tmq->epoch);
- tscDebug("consumer %ld recv ep, msg epoch %d, current epoch %d", tmq->consumerId, head->epoch, epoch);
+ tscDebug("consumer:%" PRId64 ", recv ep, msg epoch %d, current epoch %d", tmq->consumerId, head->epoch, epoch);
if (head->epoch <= epoch) {
goto END;
}
@@ -1355,8 +1369,8 @@ int32_t tmqAskEpCb(void* param, const SDataBuf* pMsg, int32_t code) {
if (!async) {
SMqAskEpRsp rsp;
tDecodeSMqAskEpRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &rsp);
- /*printf("rsp epoch %ld sz %ld\n", rsp.epoch, rsp.topics->size);*/
- /*printf("tmq epoch %ld sz %ld\n", tmq->epoch, tmq->clientTopics->size);*/
+ /*printf("rsp epoch %" PRId64 " sz %" PRId64 "\n", rsp.epoch, rsp.topics->size);*/
+ /*printf("tmq epoch %" PRId64 " sz %" PRId64 "\n", tmq->epoch, tmq->clientTopics->size);*/
tmqUpdateEp2(tmq, head->epoch, &rsp);
tDeleteSMqAskEpRsp(&rsp);
} else {
@@ -1391,7 +1405,7 @@ int32_t tmqAskEp(tmq_t* tmq, bool async) {
int8_t epStatus = atomic_val_compare_exchange_8(&tmq->epStatus, 0, 1);
if (epStatus == 1) {
int32_t epSkipCnt = atomic_add_fetch_32(&tmq->epSkipCnt, 1);
- tscTrace("consumer %ld skip ask ep cnt %d", tmq->consumerId, epSkipCnt);
+ tscTrace("consumer:%" PRId64 ", skip ask ep cnt %d", tmq->consumerId, epSkipCnt);
if (epSkipCnt < 5000) return 0;
}
atomic_store_32(&tmq->epSkipCnt, 0);
@@ -1441,7 +1455,7 @@ int32_t tmqAskEp(tmq_t* tmq, bool async) {
SEpSet epSet = getEpSet_s(&tmq->pTscObj->pAppInfo->mgmtEp);
- tscDebug("consumer %ld ask ep", tmq->consumerId);
+ tscDebug("consumer:%" PRId64 ", ask ep", tmq->consumerId);
int64_t transporterId = 0;
asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo);
@@ -1480,16 +1494,16 @@ int32_t tmq_seek(tmq_t* tmq, const tmq_topic_vgroup_t* offset) {
#endif
SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t timeout, SMqClientTopic* pTopic, SMqClientVg* pVg) {
- int64_t reqOffset;
- if (pVg->currentOffset >= 0) {
- reqOffset = pVg->currentOffset;
- } else {
- /*if (tmq->resetOffsetCfg == TMQ_CONF__RESET_OFFSET__NONE) {*/
- /*tscError("unable to poll since no committed offset but reset offset is set to none");*/
- /*return NULL;*/
- /*}*/
- reqOffset = tmq->resetOffsetCfg;
- }
+ /*int64_t reqOffset;*/
+ /*if (pVg->currentOffset >= 0) {*/
+ /*reqOffset = pVg->currentOffset;*/
+ /*} else {*/
+ /*if (tmq->resetOffsetCfg == TMQ_CONF__RESET_OFFSET__NONE) {*/
+ /*tscError("unable to poll since no committed offset but reset offset is set to none");*/
+ /*return NULL;*/
+ /*}*/
+ /*reqOffset = tmq->resetOffsetCfg;*/
+ /*}*/
SMqPollReq* pReq = taosMemoryCalloc(1, sizeof(SMqPollReq));
if (pReq == NULL) {
@@ -1508,14 +1522,28 @@ SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t timeout, SMqClientTopic*
pReq->timeout = timeout;
pReq->consumerId = tmq->consumerId;
pReq->epoch = tmq->epoch;
- pReq->currentOffset = reqOffset;
+ /*pReq->currentOffset = reqOffset;*/
+ pReq->reqOffset = pVg->currentOffsetNew;
pReq->reqId = generateRequestId();
+ pReq->useSnapshot = tmq->useSnapshot;
+
pReq->head.vgId = htonl(pVg->vgId);
pReq->head.contLen = htonl(sizeof(SMqPollReq));
return pReq;
}
+SMqMetaRspObj* tmqBuildMetaRspFromWrapper(SMqPollRspWrapper* pWrapper) {
+ SMqMetaRspObj* pRspObj = taosMemoryCalloc(1, sizeof(SMqMetaRspObj));
+ pRspObj->resType = RES_TYPE__TMQ_META;
+ tstrncpy(pRspObj->topic, pWrapper->topicHandle->topicName, TSDB_TOPIC_FNAME_LEN);
+ tstrncpy(pRspObj->db, pWrapper->topicHandle->db, TSDB_DB_FNAME_LEN);
+ pRspObj->vgId = pWrapper->vgHandle->vgId;
+
+ memcpy(&pRspObj->metaRsp, &pWrapper->metaRsp, sizeof(SMqMetaRsp));
+ return pRspObj;
+}
+
SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) {
SMqRspObj* pRspObj = taosMemoryCalloc(1, sizeof(SMqRspObj));
pRspObj->resType = RES_TYPE__TMQ;
@@ -1523,11 +1551,11 @@ SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) {
tstrncpy(pRspObj->db, pWrapper->topicHandle->db, TSDB_DB_FNAME_LEN);
pRspObj->vgId = pWrapper->vgHandle->vgId;
pRspObj->resIter = -1;
- memcpy(&pRspObj->rsp, &pWrapper->msg, sizeof(SMqDataBlkRsp));
+ memcpy(&pRspObj->rsp, &pWrapper->dataRsp, sizeof(SMqDataRsp));
pRspObj->resInfo.totalRows = 0;
pRspObj->resInfo.precision = TSDB_TIME_PRECISION_MILLI;
- if (!pWrapper->msg.withSchema) {
+ if (!pWrapper->dataRsp.withSchema) {
setResSchemaInfo(&pRspObj->resInfo, pWrapper->topicHandle->schema.pSchema, pWrapper->topicHandle->schema.nCols);
}
@@ -1535,7 +1563,7 @@ SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) {
}
int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) {
- /*printf("call poll\n");*/
+ /*tscDebug("call poll");*/
for (int i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) {
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
for (int j = 0; j < taosArrayGetSize(pTopic->vgs); j++) {
@@ -1543,14 +1571,15 @@ int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) {
int32_t vgStatus = atomic_val_compare_exchange_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE, TMQ_VG_STATUS__WAIT);
if (vgStatus != TMQ_VG_STATUS__IDLE) {
int32_t vgSkipCnt = atomic_add_fetch_32(&pVg->vgSkipCnt, 1);
- tscTrace("consumer %ld epoch %d skip vg %d skip cnt %d", tmq->consumerId, tmq->epoch, pVg->vgId, vgSkipCnt);
+ tscTrace("consumer:%" PRId64 ", epoch %d skip vgId:%d skip cnt %d", tmq->consumerId, tmq->epoch, pVg->vgId,
+ vgSkipCnt);
continue;
/*if (vgSkipCnt < 10000) continue;*/
#if 0
if (skipCnt < 30000) {
continue;
} else {
- tscDebug("consumer %ld skip vg %d skip too much reset", tmq->consumerId, pVg->vgId);
+ tscDebug("consumer:%" PRId64 ",skip vgId:%d skip too much reset", tmq->consumerId, pVg->vgId);
}
#endif
}
@@ -1596,9 +1625,12 @@ int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) {
int64_t transporterId = 0;
/*printf("send poll\n");*/
- tscDebug("consumer %ld send poll to %s : vg %d, epoch %d, req offset %ld, reqId %lu", tmq->consumerId,
- pTopic->topicName, pVg->vgId, tmq->epoch, pVg->currentOffset, pReq->reqId);
- /*printf("send vg %d %ld\n", pVg->vgId, pVg->currentOffset);*/
+
+ char offsetFormatBuf[80];
+ tFormatOffset(offsetFormatBuf, 80, &pVg->currentOffsetNew);
+ tscDebug("consumer:%" PRId64 ", send poll to %s vgId:%d, epoch %d, req offset:%s, reqId:%" PRIu64,
+ tmq->consumerId, pTopic->topicName, pVg->vgId, tmq->epoch, offsetFormatBuf, pReq->reqId);
+ /*printf("send vgId:%d %" PRId64 "\n", pVg->vgId, pVg->currentOffset);*/
asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, sendInfo);
pVg->pollCnt++;
tmq->pollCnt++;
@@ -1625,7 +1657,7 @@ int32_t tmqHandleNoPollRsp(tmq_t* tmq, SMqRspWrapper* rspWrapper, bool* pReset)
return 0;
}
-SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
+void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
while (1) {
SMqRspWrapper* rspWrapper = NULL;
taosGetQitem(tmq->qall, (void**)&rspWrapper);
@@ -1643,12 +1675,13 @@ SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)rspWrapper;
/*atomic_sub_fetch_32(&tmq->readyRequest, 1);*/
int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
- if (pollRspWrapper->msg.head.epoch == consumerEpoch) {
+ if (pollRspWrapper->dataRsp.head.epoch == consumerEpoch) {
SMqClientVg* pVg = pollRspWrapper->vgHandle;
- /*printf("vg %d offset %ld up to %ld\n", pVg->vgId, pVg->currentOffset, rspMsg->msg.rspOffset);*/
- pVg->currentOffset = pollRspWrapper->msg.rspOffset;
+ /*printf("vgId:%d offset %" PRId64 " up to %" PRId64 "\n", pVg->vgId, pVg->currentOffset,
+ * rspMsg->msg.rspOffset);*/
+ pVg->currentOffsetNew = pollRspWrapper->dataRsp.rspOffset;
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
- if (pollRspWrapper->msg.blockNum == 0) {
+ if (pollRspWrapper->dataRsp.blockNum == 0) {
taosFreeQitem(pollRspWrapper);
rspWrapper = NULL;
continue;
@@ -1658,8 +1691,27 @@ SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
taosFreeQitem(pollRspWrapper);
return pRsp;
} else {
- tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d\n", pollRspWrapper->msg.head.epoch,
- consumerEpoch);
+ tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d\n",
+ pollRspWrapper->dataRsp.head.epoch, consumerEpoch);
+ taosFreeQitem(pollRspWrapper);
+ }
+ } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) {
+ SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)rspWrapper;
+ int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
+ if (pollRspWrapper->metaRsp.head.epoch == consumerEpoch) {
+ SMqClientVg* pVg = pollRspWrapper->vgHandle;
+ /*printf("vgId:%d offset %" PRId64 " up to %" PRId64 "\n", pVg->vgId, pVg->currentOffset,
+ * rspMsg->msg.rspOffset);*/
+ pVg->currentOffsetNew.version = pollRspWrapper->metaRsp.rspOffset;
+ pVg->currentOffsetNew.type = TMQ_OFFSET__LOG;
+ atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
+ // build rsp
+ SMqMetaRspObj* pRsp = tmqBuildMetaRspFromWrapper(pollRspWrapper);
+ taosFreeQitem(pollRspWrapper);
+ return pRsp;
+ } else {
+ tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d\n",
+ pollRspWrapper->metaRsp.head.epoch, consumerEpoch);
taosFreeQitem(pollRspWrapper);
}
} else {
@@ -1668,7 +1720,7 @@ SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
tmqHandleNoPollRsp(tmq, rspWrapper, &reset);
taosFreeQitem(rspWrapper);
if (pollIfReset && reset) {
- tscDebug("consumer %ld reset and repoll", tmq->consumerId);
+ tscDebug("consumer:%" PRId64 ", reset and repoll", tmq->consumerId);
tmqPollImpl(tmq, timeout);
}
}
@@ -1676,8 +1728,9 @@ SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
}
TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
- SMqRspObj* rspObj;
- int64_t startTime = taosGetTimestampMs();
+ /*tscDebug("call poll1");*/
+ void* rspObj;
+ int64_t startTime = taosGetTimestampMs();
#if 0
tmqHandleAllDelayedTask(tmq);
@@ -1707,7 +1760,7 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
int64_t endTime = taosGetTimestampMs();
int64_t leftTime = endTime - startTime;
if (leftTime > timeout) {
- tscDebug("consumer %ld (epoch %d) timeout, no rsp", tmq->consumerId, tmq->epoch);
+ tscDebug("consumer:%" PRId64 ", (epoch %d) timeout, no rsp", tmq->consumerId, tmq->epoch);
return NULL;
}
tsem_timewait(&tmq->rspSem, leftTime * 1000);
@@ -1747,10 +1800,23 @@ const char* tmq_err2str(int32_t err) {
}
}
+tmq_res_t tmq_get_res_type(TAOS_RES* res) {
+ if (TD_RES_TMQ(res)) {
+ return TMQ_RES_DATA;
+ } else if (TD_RES_TMQ_META(res)) {
+ return TMQ_RES_TABLE_META;
+ } else {
+ return TMQ_RES_INVALID;
+ }
+}
+
const char* tmq_get_topic_name(TAOS_RES* res) {
if (TD_RES_TMQ(res)) {
SMqRspObj* pRspObj = (SMqRspObj*)res;
return strchr(pRspObj->topic, '.') + 1;
+ } else if (TD_RES_TMQ_META(res)) {
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)res;
+ return strchr(pMetaRspObj->topic, '.') + 1;
} else {
return NULL;
}
@@ -1760,6 +1826,9 @@ const char* tmq_get_db_name(TAOS_RES* res) {
if (TD_RES_TMQ(res)) {
SMqRspObj* pRspObj = (SMqRspObj*)res;
return strchr(pRspObj->db, '.') + 1;
+ } else if (TD_RES_TMQ_META(res)) {
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)res;
+ return strchr(pMetaRspObj->db, '.') + 1;
} else {
return NULL;
}
@@ -1769,6 +1838,9 @@ int32_t tmq_get_vgroup_id(TAOS_RES* res) {
if (TD_RES_TMQ(res)) {
SMqRspObj* pRspObj = (SMqRspObj*)res;
return pRspObj->vgId;
+ } else if (TD_RES_TMQ_META(res)) {
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)res;
+ return pMetaRspObj->vgId;
} else {
return -1;
}
@@ -1786,8 +1858,1050 @@ const char* tmq_get_table_name(TAOS_RES* res) {
return NULL;
}
+tmq_raw_data *tmq_get_raw_meta(TAOS_RES* res) {
+ if (TD_RES_TMQ_META(res)) {
+ tmq_raw_data *raw = taosMemoryCalloc(1, sizeof(tmq_raw_data));
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)res;
+ raw->raw_meta = pMetaRspObj->metaRsp.metaRsp;
+ raw->raw_meta_len = pMetaRspObj->metaRsp.metaRspLen;
+ raw->raw_meta_type = pMetaRspObj->metaRsp.resMsgType;
+ return raw;
+ }
+ return NULL;
+}
+
+static char *buildCreateTableJson(SSchemaWrapper *schemaRow, SSchemaWrapper* schemaTag, char* name, int64_t id, int8_t t){
+ char* string = NULL;
+ cJSON* json = cJSON_CreateObject();
+ if (json == NULL) {
+ return string;
+ }
+ cJSON* type = cJSON_CreateString("create");
+ cJSON_AddItemToObject(json, "type", type);
+
+// char uid[32] = {0};
+// sprintf(uid, "%"PRIi64, id);
+// cJSON* id_ = cJSON_CreateString(uid);
+// cJSON_AddItemToObject(json, "id", id_);
+ cJSON* tableName = cJSON_CreateString(name);
+ cJSON_AddItemToObject(json, "tableName", tableName);
+ cJSON* tableType = cJSON_CreateString(t == TSDB_NORMAL_TABLE ? "normal" : "super");
+ cJSON_AddItemToObject(json, "tableType", tableType);
+// cJSON* version = cJSON_CreateNumber(1);
+// cJSON_AddItemToObject(json, "version", version);
+
+ cJSON* columns = cJSON_CreateArray();
+ for(int i = 0; i < schemaRow->nCols; i++){
+ cJSON* column = cJSON_CreateObject();
+ SSchema *s = schemaRow->pSchema + i;
+ cJSON* cname = cJSON_CreateString(s->name);
+ cJSON_AddItemToObject(column, "name", cname);
+ cJSON* ctype = cJSON_CreateNumber(s->type);
+ cJSON_AddItemToObject(column, "type", ctype);
+ if(s->type == TSDB_DATA_TYPE_BINARY){
+ int32_t length = s->bytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(column, "length", cbytes);
+ }else if (s->type == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (s->bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(column, "length", cbytes);
+ }
+ cJSON_AddItemToArray(columns, column);
+ }
+ cJSON_AddItemToObject(json, "columns", columns);
+
+ cJSON* tags = cJSON_CreateArray();
+ for(int i = 0; schemaTag && i < schemaTag->nCols; i++){
+ cJSON* tag = cJSON_CreateObject();
+ SSchema *s = schemaTag->pSchema + i;
+ cJSON* tname = cJSON_CreateString(s->name);
+ cJSON_AddItemToObject(tag, "name", tname);
+ cJSON* ttype = cJSON_CreateNumber(s->type);
+ cJSON_AddItemToObject(tag, "type", ttype);
+ if(s->type == TSDB_DATA_TYPE_BINARY){
+ int32_t length = s->bytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(tag, "length", cbytes);
+ }else if (s->type == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (s->bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(tag, "length", cbytes);
+ }
+ cJSON_AddItemToArray(tags, tag);
+ }
+ cJSON_AddItemToObject(json, "tags", tags);
+
+ string = cJSON_PrintUnformatted(json);
+ cJSON_Delete(json);
+ return string;
+}
+
+static char *buildAlterSTableJson(void* alterData, int32_t alterDataLen){
+ SMAlterStbReq req = {0};
+ cJSON* json = NULL;
+ char* string = NULL;
+
+ if (tDeserializeSMAlterStbReq(alterData, alterDataLen, &req) != 0) {
+ goto end;
+ }
+
+ json = cJSON_CreateObject();
+ if (json == NULL) {
+ goto end;
+ }
+ cJSON* type = cJSON_CreateString("alter");
+ cJSON_AddItemToObject(json, "type", type);
+// cJSON* uid = cJSON_CreateNumber(id);
+// cJSON_AddItemToObject(json, "uid", uid);
+ SName name = {0};
+ tNameFromString(&name, req.name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+ cJSON* tableName = cJSON_CreateString(name.tname);
+ cJSON_AddItemToObject(json, "tableName", tableName);
+ cJSON* tableType = cJSON_CreateString("super");
+ cJSON_AddItemToObject(json, "tableType", tableType);
+
+ cJSON* alterType = cJSON_CreateNumber(req.alterType);
+ cJSON_AddItemToObject(json, "alterType", alterType);
+ switch (req.alterType) {
+ case TSDB_ALTER_TABLE_ADD_TAG:
+ case TSDB_ALTER_TABLE_ADD_COLUMN: {
+ TAOS_FIELD *field = taosArrayGet(req.pFields, 0);
+ cJSON* colName = cJSON_CreateString(field->name);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colType = cJSON_CreateNumber(field->type);
+ cJSON_AddItemToObject(json, "colType", colType);
+
+ if(field->type == TSDB_DATA_TYPE_BINARY){
+ int32_t length = field->bytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }else if (field->type == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (field->bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }
+ break;
+ }
+ case TSDB_ALTER_TABLE_DROP_TAG:
+ case TSDB_ALTER_TABLE_DROP_COLUMN:{
+ TAOS_FIELD *field = taosArrayGet(req.pFields, 0);
+ cJSON* colName = cJSON_CreateString(field->name);
+ cJSON_AddItemToObject(json, "colName", colName);
+ break;
+ }
+ case TSDB_ALTER_TABLE_UPDATE_TAG_BYTES:
+ case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:{
+ TAOS_FIELD *field = taosArrayGet(req.pFields, 0);
+ cJSON* colName = cJSON_CreateString(field->name);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colType = cJSON_CreateNumber(field->type);
+ cJSON_AddItemToObject(json, "colType", colType);
+ if(field->type == TSDB_DATA_TYPE_BINARY){
+ int32_t length = field->bytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }else if (field->type == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (field->bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }
+ break;
+ }
+ case TSDB_ALTER_TABLE_UPDATE_TAG_NAME:
+ case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:{
+ TAOS_FIELD *oldField = taosArrayGet(req.pFields, 0);
+ TAOS_FIELD *newField = taosArrayGet(req.pFields, 1);
+ cJSON* colName = cJSON_CreateString(oldField->name);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colNewName = cJSON_CreateString(newField->name);
+ cJSON_AddItemToObject(json, "colNewName", colNewName);
+ break;
+ }
+ default:
+ break;
+ }
+ string = cJSON_PrintUnformatted(json);
+
+ end:
+ cJSON_Delete(json);
+ tFreeSMAltertbReq(&req);
+ return string;
+}
+
+static char *processCreateStb(SMqMetaRsp *metaRsp){
+ SVCreateStbReq req = {0};
+ SDecoder coder;
+ char* string = NULL;
+
+ // decode and process req
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+
+ if (tDecodeSVCreateStbReq(&coder, &req) < 0) {
+ goto _err;
+ }
+ string = buildCreateTableJson(&req.schemaRow, &req.schemaTag, req.name, req.suid, TSDB_SUPER_TABLE);
+ tDecoderClear(&coder);
+ return string;
+
+ _err:
+ tDecoderClear(&coder);
+ return string;
+}
+
+static char *processAlterStb(SMqMetaRsp *metaRsp){
+ SVCreateStbReq req = {0};
+ SDecoder coder;
+ char* string = NULL;
+
+ // decode and process req
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+
+ if (tDecodeSVCreateStbReq(&coder, &req) < 0) {
+ goto _err;
+ }
+ string = buildAlterSTableJson(req.alterOriData, req.alterOriDataLen);
+ tDecoderClear(&coder);
+ return string;
+
+ _err:
+ tDecoderClear(&coder);
+ return string;
+}
+
+static char *buildCreateCTableJson(STag* pTag, char* sname, char* name, SArray* tagName, int64_t id){
+ char* string = NULL;
+ SArray* pTagVals = NULL;
+ cJSON* json = cJSON_CreateObject();
+ if (json == NULL) {
+ return string;
+ }
+ cJSON* type = cJSON_CreateString("create");
+ cJSON_AddItemToObject(json, "type", type);
+// char cid[32] = {0};
+// sprintf(cid, "%"PRIi64, id);
+// cJSON* cid_ = cJSON_CreateString(cid);
+// cJSON_AddItemToObject(json, "id", cid_);
+
+ cJSON* tableName = cJSON_CreateString(name);
+ cJSON_AddItemToObject(json, "tableName", tableName);
+ cJSON* tableType = cJSON_CreateString("child");
+ cJSON_AddItemToObject(json, "tableType", tableType);
+ cJSON* using = cJSON_CreateString(sname);
+ cJSON_AddItemToObject(json, "using", using);
+// cJSON* version = cJSON_CreateNumber(1);
+// cJSON_AddItemToObject(json, "version", version);
+
+ cJSON* tags = cJSON_CreateArray();
+ int32_t code = tTagToValArray(pTag, &pTagVals);
+ if (code) {
+ goto end;
+ }
+
+ if (tTagIsJson(pTag)) {
+ STag* p = (STag*)pTag;
+ if(p->nTag == 0){
+ goto end;
+ }
+ char* pJson = parseTagDatatoJson(pTag);
+ cJSON* tag = cJSON_CreateObject();
+ STagVal* pTagVal = taosArrayGet(pTagVals, 0);
+
+ char* ptname = taosArrayGet(tagName, 0);
+ cJSON* tname = cJSON_CreateString(ptname);
+ cJSON_AddItemToObject(tag, "name", tname);
+// cJSON* cid_ = cJSON_CreateString("");
+// cJSON_AddItemToObject(tag, "cid", cid_);
+ cJSON* ttype = cJSON_CreateNumber(TSDB_DATA_TYPE_JSON);
+ cJSON_AddItemToObject(tag, "type", ttype);
+ cJSON* tvalue = cJSON_CreateString(pJson);
+ cJSON_AddItemToObject(tag, "value", tvalue);
+ cJSON_AddItemToArray(tags, tag);
+ taosMemoryFree(pJson);
+ goto end;
+ }
+
+ for(int i = 0; i < taosArrayGetSize(pTagVals); i++){
+ STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, i);
+
+ cJSON* tag = cJSON_CreateObject();
+
+ char* ptname = taosArrayGet(tagName, i);
+ cJSON* tname = cJSON_CreateString(ptname);
+ cJSON_AddItemToObject(tag, "name", tname);
+// cJSON* cid = cJSON_CreateNumber(pTagVal->cid);
+// cJSON_AddItemToObject(tag, "cid", cid);
+ cJSON* ttype = cJSON_CreateNumber(pTagVal->type);
+ cJSON_AddItemToObject(tag, "type", ttype);
+
+ char* buf = NULL;
+ if (IS_VAR_DATA_TYPE(pTagVal->type)) {
+ buf = taosMemoryCalloc(pTagVal->nData + 1, 1);
+ dataConverToStr(buf, pTagVal->type, pTagVal->pData, pTagVal->nData, NULL);
+ } else {
+ buf = taosMemoryCalloc(32, 1);
+ dataConverToStr(buf, pTagVal->type, &pTagVal->i64, tDataTypes[pTagVal->type].bytes, NULL);
+ }
+
+ cJSON* tvalue = cJSON_CreateString(buf);
+ taosMemoryFree(buf);
+ cJSON_AddItemToObject(tag, "value", tvalue);
+ cJSON_AddItemToArray(tags, tag);
+ }
+
+ end:
+ cJSON_AddItemToObject(json, "tags", tags);
+ string = cJSON_PrintUnformatted(json);
+ cJSON_Delete(json);
+ taosArrayDestroy(pTagVals);
+ return string;
+}
+
+static char *processCreateTable(SMqMetaRsp *metaRsp){
+ SDecoder decoder = {0};
+ SVCreateTbBatchReq req = {0};
+ SVCreateTbReq *pCreateReq;
+ char *string = NULL;
+ // decode
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&decoder, data, len);
+ if (tDecodeSVCreateTbBatchReq(&decoder, &req) < 0) {
+ goto _exit;
+ }
+
+ // loop to create table
+ for (int32_t iReq = 0; iReq < req.nReqs; iReq++) {
+ pCreateReq = req.pReqs + iReq;
+ if(pCreateReq->type == TSDB_CHILD_TABLE){
+ string = buildCreateCTableJson((STag*)pCreateReq->ctb.pTag, pCreateReq->ctb.name, pCreateReq->name, pCreateReq->ctb.tagName, pCreateReq->uid);
+ }else if(pCreateReq->type == TSDB_NORMAL_TABLE){
+ string = buildCreateTableJson(&pCreateReq->ntb.schemaRow, NULL, pCreateReq->name, pCreateReq->uid, TSDB_NORMAL_TABLE);
+ }
+ }
+
+ tDecoderClear(&decoder);
+
+ _exit:
+ tDecoderClear(&decoder);
+ return string;
+}
+
+static char *processAlterTable(SMqMetaRsp *metaRsp){
+ SDecoder decoder = {0};
+ SVAlterTbReq vAlterTbReq = {0};
+ char *string = NULL;
+
+ // decode
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&decoder, data, len);
+ if (tDecodeSVAlterTbReq(&decoder, &vAlterTbReq) < 0) {
+ goto _exit;
+ }
+
+ cJSON* json = cJSON_CreateObject();
+ if (json == NULL) {
+ goto _exit;
+ }
+ cJSON* type = cJSON_CreateString("alter");
+ cJSON_AddItemToObject(json, "type", type);
+// cJSON* uid = cJSON_CreateNumber(id);
+// cJSON_AddItemToObject(json, "uid", uid);
+ cJSON* tableName = cJSON_CreateString(vAlterTbReq.tbName);
+ cJSON_AddItemToObject(json, "tableName", tableName);
+ cJSON* tableType = cJSON_CreateString(vAlterTbReq.action == TSDB_ALTER_TABLE_UPDATE_TAG_VAL ? "child" : "normal");
+ cJSON_AddItemToObject(json, "tableType", tableType);
+ cJSON* alterType = cJSON_CreateNumber(vAlterTbReq.action);
+ cJSON_AddItemToObject(json, "alterType", alterType);
+
+ switch (vAlterTbReq.action) {
+ case TSDB_ALTER_TABLE_ADD_COLUMN: {
+ cJSON* colName = cJSON_CreateString(vAlterTbReq.colName);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colType = cJSON_CreateNumber(vAlterTbReq.type);
+ cJSON_AddItemToObject(json, "colType", colType);
+
+ if(vAlterTbReq.type == TSDB_DATA_TYPE_BINARY){
+ int32_t length = vAlterTbReq.bytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }else if (vAlterTbReq.type == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (vAlterTbReq.bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }
+ break;
+ }
+ case TSDB_ALTER_TABLE_DROP_COLUMN:{
+ cJSON* colName = cJSON_CreateString(vAlterTbReq.colName);
+ cJSON_AddItemToObject(json, "colName", colName);
+ break;
+ }
+ case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:{
+ cJSON* colName = cJSON_CreateString(vAlterTbReq.colName);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colType = cJSON_CreateNumber(vAlterTbReq.colModType);
+ cJSON_AddItemToObject(json, "colType", colType);
+ if(vAlterTbReq.colModType == TSDB_DATA_TYPE_BINARY){
+ int32_t length = vAlterTbReq.colModBytes - VARSTR_HEADER_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }else if (vAlterTbReq.colModType == TSDB_DATA_TYPE_NCHAR){
+ int32_t length = (vAlterTbReq.colModBytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ cJSON* cbytes = cJSON_CreateNumber(length);
+ cJSON_AddItemToObject(json, "colLength", cbytes);
+ }
+ break;
+ }
+ case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:{
+ cJSON* colName = cJSON_CreateString(vAlterTbReq.colName);
+ cJSON_AddItemToObject(json, "colName", colName);
+ cJSON* colNewName = cJSON_CreateString(vAlterTbReq.colNewName);
+ cJSON_AddItemToObject(json, "colNewName", colNewName);
+ break;
+ }
+ case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:{
+ cJSON* tagName = cJSON_CreateString(vAlterTbReq.tagName);
+ cJSON_AddItemToObject(json, "colName", tagName);
+
+ bool isNull = vAlterTbReq.isNull;
+ if(vAlterTbReq.tagType == TSDB_DATA_TYPE_JSON){
+ STag *jsonTag = (STag *)vAlterTbReq.pTagVal;
+ if(jsonTag->nTag == 0) isNull = true;
+ }
+ if (!isNull){
+ char* buf = NULL;
+
+ if (vAlterTbReq.tagType == TSDB_DATA_TYPE_JSON) {
+ ASSERT(tTagIsJson(vAlterTbReq.pTagVal) == true);
+ buf = parseTagDatatoJson(vAlterTbReq.pTagVal);
+ } else {
+ buf = taosMemoryCalloc(vAlterTbReq.nTagVal + 1, 1);
+ dataConverToStr(buf, vAlterTbReq.tagType, vAlterTbReq.pTagVal, vAlterTbReq.nTagVal, NULL);
+ }
+
+ cJSON* colValue = cJSON_CreateString(buf);
+ cJSON_AddItemToObject(json, "colValue", colValue);
+ taosMemoryFree(buf);
+ }
+
+ cJSON* isNullCJson = cJSON_CreateBool(isNull);
+ cJSON_AddItemToObject(json, "colValueNull", isNullCJson);
+ break;
+ }
+ default:
+ break;
+ }
+ string = cJSON_PrintUnformatted(json);
+
+ _exit:
+ tDecoderClear(&decoder);
+ return string;
+}
+
+static char *processDropSTable(SMqMetaRsp *metaRsp){
+ SDecoder decoder = {0};
+ SVDropStbReq req = {0};
+ char *string = NULL;
+
+ // decode
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&decoder, data, len);
+ if (tDecodeSVDropStbReq(&decoder, &req) < 0) {
+ goto _exit;
+ }
+
+ cJSON* json = cJSON_CreateObject();
+ if (json == NULL) {
+ goto _exit;
+ }
+ cJSON* type = cJSON_CreateString("drop");
+ cJSON_AddItemToObject(json, "type", type);
+ cJSON* tableName = cJSON_CreateString(req.name);
+ cJSON_AddItemToObject(json, "tableName", tableName);
+ cJSON* tableType = cJSON_CreateString("super");
+ cJSON_AddItemToObject(json, "tableType", tableType);
+
+ string = cJSON_PrintUnformatted(json);
+
+ _exit:
+ tDecoderClear(&decoder);
+ return string;
+}
+
+static char *processDropTable(SMqMetaRsp *metaRsp){
+ SDecoder decoder = {0};
+ SVDropTbBatchReq req = {0};
+ char *string = NULL;
+
+ // decode
+ void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead));
+ int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead);
+ tDecoderInit(&decoder, data, len);
+ if (tDecodeSVDropTbBatchReq(&decoder, &req) < 0) {
+ goto _exit;
+ }
+
+ cJSON* json = cJSON_CreateObject();
+ if (json == NULL) {
+ goto _exit;
+ }
+ cJSON* type = cJSON_CreateString("drop");
+ cJSON_AddItemToObject(json, "type", type);
+// cJSON* uid = cJSON_CreateNumber(id);
+// cJSON_AddItemToObject(json, "uid", uid);
+// cJSON* tableType = cJSON_CreateString("normal");
+// cJSON_AddItemToObject(json, "tableType", tableType);
+
+ cJSON* tableNameList = cJSON_CreateArray();
+ for (int32_t iReq = 0; iReq < req.nReqs; iReq++) {
+ SVDropTbReq* pDropTbReq = req.pReqs + iReq;
+
+ cJSON* tableName = cJSON_CreateString(pDropTbReq->name);
+ cJSON_AddItemToArray(tableNameList, tableName);
+ }
+ cJSON_AddItemToObject(json, "tableNameList", tableNameList);
+
+ string = cJSON_PrintUnformatted(json);
+
+ _exit:
+ tDecoderClear(&decoder);
+ return string;
+}
+
+char *tmq_get_json_meta(TAOS_RES *res){
+ if (!TD_RES_TMQ_META(res)) {
+ return NULL;
+ }
+
+ SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)res;
+ if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_CREATE_STB){
+ return processCreateStb(&pMetaRspObj->metaRsp);
+ }else if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_ALTER_STB){
+ return processAlterStb(&pMetaRspObj->metaRsp);
+ }else if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_DROP_STB){
+ return processDropSTable(&pMetaRspObj->metaRsp);
+ }else if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_CREATE_TABLE){
+ return processCreateTable(&pMetaRspObj->metaRsp);
+ }else if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_ALTER_TABLE){
+ return processAlterTable(&pMetaRspObj->metaRsp);
+ }else if(pMetaRspObj->metaRsp.resMsgType == TDMT_VND_DROP_TABLE){
+ return processDropTable(&pMetaRspObj->metaRsp);
+ }
+ return NULL;
+}
+
+void tmq_free_json_meta(char* jsonMeta){
+ taosMemoryFreeClear(jsonMeta);
+}
+
+static int32_t taosCreateStb(TAOS *taos, void *meta, int32_t metaLen){
+ SVCreateStbReq req = {0};
+ SDecoder coder;
+ SMCreateStbReq pReq = {0};
+ int32_t code = TSDB_CODE_SUCCESS;
+ SRequestObj* pRequest = NULL;
+
+ code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ if(!pRequest->pDb){
+ code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ goto end;
+ }
+ // decode and process req
+ void* data = POINTER_SHIFT(meta, sizeof(SMsgHead));
+ int32_t len = metaLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+ if (tDecodeSVCreateStbReq(&coder, &req) < 0) {
+ code = TSDB_CODE_INVALID_PARA;
+ goto end;
+ }
+ // build create stable
+ pReq.pColumns = taosArrayInit(req.schemaRow.nCols, sizeof(SField));
+ for(int32_t i = 0; i < req.schemaRow.nCols; i++){
+ SSchema* pSchema = req.schemaRow.pSchema + i;
+ SField field = {.type = pSchema->type, .bytes = pSchema->bytes};
+ strcpy(field.name, pSchema->name);
+ taosArrayPush(pReq.pColumns, &field);
+ }
+ pReq.pTags = taosArrayInit(req.schemaTag.nCols, sizeof(SField));
+ for(int32_t i = 0; i < req.schemaTag.nCols; i++){
+ SSchema* pSchema = req.schemaTag.pSchema + i;
+ SField field = {.type = pSchema->type, .bytes = pSchema->bytes};
+ strcpy(field.name, pSchema->name);
+ taosArrayPush(pReq.pTags, &field);
+ }
+
+ pReq.colVer = req.schemaRow.version;
+ pReq.tagVer = req.schemaTag.version;
+ pReq.numOfColumns = req.schemaRow.nCols;
+ pReq.numOfTags = req.schemaTag.nCols;
+ pReq.commentLen = -1;
+ pReq.suid = req.suid;
+ pReq.source = TD_REQ_FROM_TAOX;
+ pReq.igExists = true;
+
+ STscObj* pTscObj = pRequest->pTscObj;
+ SName tableName;
+ tNameExtractFullName(toName(pTscObj->acctId, pRequest->pDb, req.name, &tableName), pReq.name);
+
+ SCmdMsgInfo pCmdMsg = {0};
+ pCmdMsg.epSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
+ pCmdMsg.msgType = TDMT_MND_CREATE_STB;
+ pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq);
+ pCmdMsg.pMsg = taosMemoryMalloc(pCmdMsg.msgLen);
+ if (NULL == pCmdMsg.pMsg) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq);
+
+ SQuery pQuery = {0};
+ pQuery.execMode = QUERY_EXEC_MODE_RPC;
+ pQuery.pCmdMsg = &pCmdMsg;
+ pQuery.msgType = pQuery.pCmdMsg->msgType;
+ pQuery.stableQuery = true;
+
+ launchQueryImpl(pRequest, &pQuery, true, NULL);
+ code = pRequest->code;
+ taosMemoryFree(pCmdMsg.pMsg);
+
+ end:
+ destroyRequest(pRequest);
+ tFreeSMCreateStbReq(&pReq);
+ tDecoderClear(&coder);
+ return code;
+}
+
+static int32_t taosDropStb(TAOS *taos, void *meta, int32_t metaLen){
+ SVDropStbReq req = {0};
+ SDecoder coder;
+ SMDropStbReq pReq = {0};
+ int32_t code = TSDB_CODE_SUCCESS;
+ SRequestObj* pRequest = NULL;
+
+ code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ if(!pRequest->pDb){
+ code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ goto end;
+ }
+ // decode and process req
+ void* data = POINTER_SHIFT(meta, sizeof(SMsgHead));
+ int32_t len = metaLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+ if (tDecodeSVDropStbReq(&coder, &req) < 0) {
+ code = TSDB_CODE_INVALID_PARA;
+ goto end;
+ }
+
+ // build drop stable
+ pReq.igNotExists = true;
+ pReq.source = TD_REQ_FROM_TAOX;
+ pReq.suid = req.suid;
+
+ STscObj* pTscObj = pRequest->pTscObj;
+ SName tableName;
+ tNameExtractFullName(toName(pTscObj->acctId, pRequest->pDb, req.name, &tableName), pReq.name);
+
+ SCmdMsgInfo pCmdMsg = {0};
+ pCmdMsg.epSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
+ pCmdMsg.msgType = TDMT_MND_DROP_STB;
+ pCmdMsg.msgLen = tSerializeSMDropStbReq(NULL, 0, &pReq);
+ pCmdMsg.pMsg = taosMemoryMalloc(pCmdMsg.msgLen);
+ if (NULL == pCmdMsg.pMsg) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ tSerializeSMDropStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq);
+
+ SQuery pQuery = {0};
+ pQuery.execMode = QUERY_EXEC_MODE_RPC;
+ pQuery.pCmdMsg = &pCmdMsg;
+ pQuery.msgType = pQuery.pCmdMsg->msgType;
+ pQuery.stableQuery = true;
+
+ launchQueryImpl(pRequest, &pQuery, true, NULL);
+ code = pRequest->code;
+ taosMemoryFree(pCmdMsg.pMsg);
+
+ end:
+ destroyRequest(pRequest);
+ tDecoderClear(&coder);
+ return code;
+}
+
+typedef struct SVgroupCreateTableBatch {
+ SVCreateTbBatchReq req;
+ SVgroupInfo info;
+ char dbName[TSDB_DB_NAME_LEN];
+} SVgroupCreateTableBatch;
+
+static void destroyCreateTbReqBatch(void* data) {
+ SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*) data;
+ taosArrayDestroy(pTbBatch->req.pArray);
+}
+
+static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) {
+ SVCreateTbBatchReq req = {0};
+ SDecoder coder = {0};
+ int32_t code = TSDB_CODE_SUCCESS;
+ SRequestObj* pRequest = NULL;
+ SQuery* pQuery = NULL;
+ SHashObj* pVgroupHashmap = NULL;
+
+ code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+
+ if(!pRequest->pDb){
+ code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ goto end;
+ }
+ // decode and process req
+ void* data = POINTER_SHIFT(meta, sizeof(SMsgHead));
+ int32_t len = metaLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+ if (tDecodeSVCreateTbBatchReq(&coder, &req) < 0) {
+ code = TSDB_CODE_INVALID_PARA;
+ goto end;
+ }
+
+ STscObj* pTscObj = pRequest->pTscObj;
+
+ SVCreateTbReq* pCreateReq = NULL;
+ SCatalog* pCatalog = NULL;
+ code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCatalog);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
+ if (NULL == pVgroupHashmap) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ taosHashSetFreeFp(pVgroupHashmap, destroyCreateTbReqBatch);
+
+ SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter,
+ .requestId = pRequest->requestId,
+ .requestObjRefId = pRequest->self,
+ .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)};
+ // loop to create table
+ for (int32_t iReq = 0; iReq < req.nReqs; iReq++) {
+ pCreateReq = req.pReqs + iReq;
+
+ SVgroupInfo pInfo = {0};
+ SName pName;
+ toName(pTscObj->acctId, pRequest->pDb, pCreateReq->name, &pName);
+ code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &pInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ SVgroupCreateTableBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pInfo.vgId, sizeof(pInfo.vgId));
+ if (pTableBatch == NULL) {
+ SVgroupCreateTableBatch tBatch = {0};
+ tBatch.info = pInfo;
+ strcpy(tBatch.dbName, pRequest->pDb);
+
+ tBatch.req.pArray = taosArrayInit(4, sizeof(struct SVCreateTbReq));
+ taosArrayPush(tBatch.req.pArray, pCreateReq);
+
+ taosHashPut(pVgroupHashmap, &pInfo.vgId, sizeof(pInfo.vgId), &tBatch, sizeof(tBatch));
+ } else { // add to the correct vgroup
+ taosArrayPush(pTableBatch->req.pArray, pCreateReq);
+ }
+ }
+
+ SArray* pBufArray = serializeVgroupsCreateTableBatch(pVgroupHashmap);
+ if (NULL == pBufArray) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY);
+ pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
+ pQuery->msgType = TDMT_VND_CREATE_TABLE;
+ pQuery->stableQuery = false;
+ pQuery->pRoot = nodesMakeNode(QUERY_NODE_CREATE_TABLE_STMT);
+
+ code = rewriteToVnodeModifyOpStmt(pQuery, pBufArray);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ launchQueryImpl(pRequest, pQuery, false, NULL);
+ pQuery = NULL; // no need to free in the end
+ code = pRequest->code;
+
+ end:
+ taosHashCleanup(pVgroupHashmap);
+ destroyRequest(pRequest);
+ tDecoderClear(&coder);
+ qDestroyQuery(pQuery);
+ return code;
+}
+
+typedef struct SVgroupDropTableBatch {
+ SVDropTbBatchReq req;
+ SVgroupInfo info;
+ char dbName[TSDB_DB_NAME_LEN];
+} SVgroupDropTableBatch;
+
+static void destroyDropTbReqBatch(void* data) {
+ SVgroupDropTableBatch* pTbBatch = (SVgroupDropTableBatch*)data;
+ taosArrayDestroy(pTbBatch->req.pArray);
+}
+
+static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) {
+ SVDropTbBatchReq req = {0};
+ SDecoder coder = {0};
+ int32_t code = TSDB_CODE_SUCCESS;
+ SRequestObj* pRequest = NULL;
+ SQuery* pQuery = NULL;
+ SHashObj* pVgroupHashmap = NULL;
+
+ code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ if(!pRequest->pDb){
+ code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ goto end;
+ }
+ // decode and process req
+ void* data = POINTER_SHIFT(meta, sizeof(SMsgHead));
+ int32_t len = metaLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+ if (tDecodeSVDropTbBatchReq(&coder, &req) < 0) {
+ code = TSDB_CODE_INVALID_PARA;
+ goto end;
+ }
+
+ STscObj* pTscObj = pRequest->pTscObj;
+
+ SVDropTbReq* pDropReq = NULL;
+ SCatalog* pCatalog = NULL;
+ code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCatalog);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
+ if (NULL == pVgroupHashmap) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ taosHashSetFreeFp(pVgroupHashmap, destroyDropTbReqBatch);
+
+ SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter,
+ .requestId = pRequest->requestId,
+ .requestObjRefId = pRequest->self,
+ .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)};
+ // loop to create table
+ for (int32_t iReq = 0; iReq < req.nReqs; iReq++) {
+ pDropReq = req.pReqs + iReq;
+ pDropReq->igNotExists = true;
+
+ SVgroupInfo pInfo = {0};
+ SName pName;
+ toName(pTscObj->acctId, pRequest->pDb, pDropReq->name, &pName);
+ code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &pInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ SVgroupDropTableBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pInfo.vgId, sizeof(pInfo.vgId));
+ if (pTableBatch == NULL) {
+ SVgroupDropTableBatch tBatch = {0};
+ tBatch.info = pInfo;
+ tBatch.req.pArray = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SVDropTbReq));
+ taosArrayPush(tBatch.req.pArray, pDropReq);
+
+ taosHashPut(pVgroupHashmap, &pInfo.vgId, sizeof(pInfo.vgId), &tBatch, sizeof(tBatch));
+ } else { // add to the correct vgroup
+ taosArrayPush(pTableBatch->req.pArray, pDropReq);
+ }
+ }
+
+ SArray* pBufArray = serializeVgroupsDropTableBatch(pVgroupHashmap);
+ if (NULL == pBufArray) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY);
+ pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
+ pQuery->msgType = TDMT_VND_DROP_TABLE;
+ pQuery->stableQuery = false;
+ pQuery->pRoot = nodesMakeNode(QUERY_NODE_DROP_TABLE_STMT);
+
+ code = rewriteToVnodeModifyOpStmt(pQuery, pBufArray);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ launchQueryImpl(pRequest, pQuery, false, NULL);
+ pQuery = NULL; // no need to free in the end
+ code = pRequest->code;
+
+ end:
+ taosHashCleanup(pVgroupHashmap);
+ destroyRequest(pRequest);
+ tDecoderClear(&coder);
+ qDestroyQuery(pQuery);
+ return code;
+}
+
+static int32_t taosAlterTable(TAOS *taos, void *meta, int32_t metaLen){
+ SVAlterTbReq req = {0};
+ SDecoder coder = {0};
+ int32_t code = TSDB_CODE_SUCCESS;
+ SRequestObj *pRequest = NULL;
+ SQuery *pQuery = NULL;
+ SArray *pArray = NULL;
+ SVgDataBlocks *pVgData = NULL;
+
+ code = buildRequest(*(int64_t*) taos, "", 0, NULL, false, &pRequest);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ if(!pRequest->pDb){
+ code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ goto end;
+ }
+ // decode and process req
+ void* data = POINTER_SHIFT(meta, sizeof(SMsgHead));
+ int32_t len = metaLen - sizeof(SMsgHead);
+ tDecoderInit(&coder, data, len);
+ if (tDecodeSVAlterTbReq(&coder, &req) < 0) {
+ code = TSDB_CODE_INVALID_PARA;
+ goto end;
+ }
+
+ // do not deal TSDB_ALTER_TABLE_UPDATE_OPTIONS
+ if(req.action == TSDB_ALTER_TABLE_UPDATE_OPTIONS){
+ goto end;
+ }
+
+ STscObj* pTscObj = pRequest->pTscObj;
+ SCatalog *pCatalog = NULL;
+ code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCatalog);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter,
+ .requestId = pRequest->requestId,
+ .requestObjRefId = pRequest->self,
+ .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)};
+
+ SVgroupInfo pInfo = {0};
+ SName pName = {0};
+ toName(pTscObj->acctId, pRequest->pDb, req.tbName, &pName);
+ code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &pInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ pArray = taosArrayInit(1, sizeof(void*));
+ if (NULL == pArray) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ pVgData = taosMemoryCalloc(1, sizeof(SVgDataBlocks));
+ if (NULL == pVgData) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ pVgData->vg = pInfo;
+ pVgData->pData = taosMemoryMalloc(metaLen);
+ if (NULL == pVgData->pData) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto end;
+ }
+ memcpy(pVgData->pData, meta, metaLen);
+ ((SMsgHead*)pVgData->pData)->vgId = htonl(pInfo.vgId);
+ pVgData->size = metaLen;
+ pVgData->numOfTables = 1;
+ taosArrayPush(pArray, &pVgData);
+
+ pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY);
+ pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
+ pQuery->msgType = TDMT_VND_ALTER_TABLE;
+ pQuery->stableQuery = false;
+ pQuery->pRoot = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT);
+
+ code = rewriteToVnodeModifyOpStmt(pQuery, pArray);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto end;
+ }
+
+ launchQueryImpl(pRequest, pQuery, false, NULL);
+ pQuery = NULL; // no need to free in the end
+ pVgData = NULL;
+ pArray = NULL;
+ code = pRequest->code;
+ if (code == TSDB_CODE_VND_TABLE_NOT_EXIST){
+ code = 0;
+ }
+
+ end:
+ taosArrayDestroy(pArray);
+ if(pVgData) taosMemoryFreeClear(pVgData->pData);
+ taosMemoryFreeClear(pVgData);
+ destroyRequest(pRequest);
+ tDecoderClear(&coder);
+ qDestroyQuery(pQuery);
+ return code;
+}
+
+int32_t taos_write_raw_meta(TAOS *taos, tmq_raw_data *raw_meta){
+ if (!taos || !raw_meta) {
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ if(raw_meta->raw_meta_type == TDMT_VND_CREATE_STB) {
+ return taosCreateStb(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }else if(raw_meta->raw_meta_type == TDMT_VND_ALTER_STB){
+ return taosCreateStb(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }else if(raw_meta->raw_meta_type == TDMT_VND_DROP_STB){
+ return taosDropStb(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }else if(raw_meta->raw_meta_type == TDMT_VND_CREATE_TABLE){
+ return taosCreateTable(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }else if(raw_meta->raw_meta_type == TDMT_VND_ALTER_TABLE){
+ return taosAlterTable(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }else if(raw_meta->raw_meta_type == TDMT_VND_DROP_TABLE){
+ return taosDropTable(taos, raw_meta->raw_meta, raw_meta->raw_meta_len);
+ }
+ return TSDB_CODE_INVALID_PARA;
+}
+
+void tmq_free_raw_meta(tmq_raw_data *rawMeta){
+ taosMemoryFreeClear(rawMeta);
+}
+
void tmq_commit_async(tmq_t* tmq, const TAOS_RES* msg, tmq_commit_cb* cb, void* param) {
tmqCommitInner2(tmq, msg, 0, 1, cb, param);
}
-int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* msg) { return tmqCommitInner2(tmq, msg, 0, 0, NULL, NULL); }
+int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* msg) { return tmqCommitInner2(tmq, msg, 0, 0, NULL, NULL); }
\ No newline at end of file
diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp
index 36dcab5c192ea42a6ac4a98da16b5a48fd642b1d..7927c1e008c66c4fc54156be1d3509574555d01b 100644
--- a/source/client/test/clientTests.cpp
+++ b/source/client/test/clientTests.cpp
@@ -669,13 +669,13 @@ TEST(testCase, projection_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
-// TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 2");
-// if (taos_errno(pRes) != 0) {
-// printf("error in create db, reason:%s\n", taos_errstr(pRes));
-// }
-// taos_free_result(pRes);
+ TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 1");
+ if (taos_errno(pRes) != 0) {
+ printf("error in create db, reason:%s\n", taos_errstr(pRes));
+ }
+ taos_free_result(pRes);
- TAOS_RES* pRes = taos_query(pConn, "use abc1");
+ pRes = taos_query(pConn, "use abc1");
taos_free_result(pRes);
pRes = taos_query(pConn, "create stable st1 (ts timestamp, k int) tags(a int)");
@@ -700,55 +700,55 @@ TEST(testCase, projection_query_tables) {
printf("create table :%d\n", i);
createNewTable(pConn, i);
}
-// pRes = taos_query(pConn, "select * from tu");
-// if (taos_errno(pRes) != 0) {
-// printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
-// taos_free_result(pRes);
-// ASSERT_TRUE(false);
-// }
-// TAOS_ROW pRow = NULL;
-// TAOS_FIELD* pFields = taos_fetch_fields(pRes);
-// int32_t numOfFields = taos_num_fields(pRes);
-//
-// char str[512] = {0};
-// while ((pRow = taos_fetch_row(pRes)) != NULL) {
-// int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
-// printf("%s\n", str);
-// }
+ pRes = taos_query(pConn, "select * from tu");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
+ taos_free_result(pRes);
+ ASSERT_TRUE(false);
+ }
-// taos_free_result(pRes);
+ TAOS_ROW pRow = NULL;
+ TAOS_FIELD* pFields = taos_fetch_fields(pRes);
+ int32_t numOfFields = taos_num_fields(pRes);
+
+ char str[512] = {0};
+ while ((pRow = taos_fetch_row(pRes)) != NULL) {
+ int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
+ printf("%s\n", str);
+ }
+
+ taos_free_result(pRes);
taos_close(pConn);
}
-//TEST(testCase, projection_query_stables) {
-// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
-// ASSERT_NE(pConn, nullptr);
-//
-// TAOS_RES* pRes = taos_query(pConn, "use abc1");
-// taos_free_result(pRes);
-//
-// pRes = taos_query(pConn, "select ts from st1");
-// if (taos_errno(pRes) != 0) {
-// printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
-// taos_free_result(pRes);
-// ASSERT_TRUE(false);
-// }
-//
-// TAOS_ROW pRow = NULL;
-// TAOS_FIELD* pFields = taos_fetch_fields(pRes);
-// int32_t numOfFields = taos_num_fields(pRes);
-//
-// char str[512] = {0};
-// while ((pRow = taos_fetch_row(pRes)) != NULL) {
-// int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
-// printf("%s\n", str);
-// }
-//
-// taos_free_result(pRes);
-// taos_close(pConn);
-//}
+TEST(testCase, projection_query_stables) {
+ TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
+ ASSERT_NE(pConn, nullptr);
+ TAOS_RES* pRes = taos_query(pConn, "use abc1");
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "select ts from st1");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
+ taos_free_result(pRes);
+ ASSERT_TRUE(false);
+ }
+
+ TAOS_ROW pRow = NULL;
+ TAOS_FIELD* pFields = taos_fetch_fields(pRes);
+ int32_t numOfFields = taos_num_fields(pRes);
+
+ char str[512] = {0};
+ while ((pRow = taos_fetch_row(pRes)) != NULL) {
+ int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
+ printf("%s\n", str);
+ }
+
+ taos_free_result(pRes);
+ taos_close(pConn);
+}
TEST(testCase, agg_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
@@ -762,7 +762,7 @@ TEST(testCase, agg_query_tables) {
}
taos_free_result(pRes);
- pRes = taos_query(pConn, "show table distributed st1");
+ pRes = taos_query(pConn, "show table distributed tup");
if (taos_errno(pRes) != 0) {
printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
taos_free_result(pRes);
@@ -773,7 +773,7 @@ TEST(testCase, agg_query_tables) {
taos_free_result(pRes);
taos_close(pConn);
}
-#endif
+
/*
--- copy the following script in the shell to setup the environment ---
@@ -819,5 +819,42 @@ TEST(testCase, async_api_test) {
getchar();
taos_close(pConn);
}
+#endif
+
+
+TEST(testCase, update_test) {
+ TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
+ ASSERT_NE(pConn, nullptr);
+
+ TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1");
+ if (taos_errno(pRes) != TSDB_CODE_SUCCESS) {
+ printf("failed to create database, code:%s", taos_errstr(pRes));
+ taos_free_result(pRes);
+ return;
+ }
+
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "use abc1");
+ if (taos_errno(pRes) != TSDB_CODE_SUCCESS) {
+ printf("failed to use db, code:%s", taos_errstr(pRes));
+ taos_free_result(pRes);
+ return;
+ }
+ taos_free_result(pRes);
+
+ pRes = taos_query(pConn, "create table tup (ts timestamp, k int);");
+ if (taos_errno(pRes) != 0) {
+ printf("failed to create table, reason:%s", taos_errstr(pRes));
+ }
+
+ taos_free_result(pRes);
+ char s[256] = {0};
+ for(int32_t i = 0; i < 17000; ++i) {
+ sprintf(s, "insert into tup values(now+%da, %d)", i, i);
+ pRes = taos_query(pConn, s);
+ taos_free_result(pRes);
+ }
+}
#pragma GCC diagnostic pop
diff --git a/source/client/test/smlTest.cpp b/source/client/test/smlTest.cpp
index 25cbb42ee978f4edc5c966890ed9195242ad2b68..17025db730eeefe4c445e7810f7266e71dafdac9 100644
--- a/source/client/test/smlTest.cpp
+++ b/source/client/test/smlTest.cpp
@@ -623,8 +623,12 @@ TEST(testCase, smlParseLine_error_Test) {
taos_free_result(pRes);
const char *sql[] = {
- "measure,t1=3 c1=8",
- "measure,t2=3 c1=8u8"
+ "st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
+ "st123456,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000",
+ "test_stb,t2=5f64,t3=L\"ste\" c1=true,c2=4i64,c3=\"iam\" 1626056811823316532"
+// "mqjqbesqqq,t0=t c0=f,c1=\"grigbrpnjctnyhamnwfqsjrywdforgpwpabdisdnymlboguwxuoscfyyajiyusxrocjndexxcvcqrzgxceqolvtdrpeabrcokpmcnhduylzxxljospclwuebutrdbpklpdbtkrdppamenzlmkkzttacrfxaozvwodpxzralhmdhvgaurtacnyhlsaojjglfnrylswactjumeldmuuafnmwsuuyiwhpdzqludgpluvllfowkwhfbtgsjsnxdbfbcrqnrxllmokbzrkiuxkhumfcjogeugbbjowmckoeyrilsoenowqwjpuufprqnxxzjlwfxnoljtodghyfdtyyptxafertndevhewboikewxwtwvbusnjpxwpnhhcrqqyicuuxmadxqjhbodsbexgpuaicbxduewqnogdhyjhcyjyftfbvbctgbjrwrkqtmqhzwxnilkmorotbiuwsimuvloeykzxqdepdkvvdcjtzmsvdseygtprbvhuikvomoafwnfojzaojxbkbpwbjqasazgokjjpktofqhjqhxxplkdvttwflbekawvozxiuhoahajwpimnjsbzjfhqgbbcgjgrjszmuqmwupxqlosfdsqnpkertnamcipfanxxewygtkeiaqopvykygkfbihdqqvhwapyctmxbjvzdndobrooemwtotrjzuknaupwxrjbrjzmnmupbwcdwkoghsilyfrjeefwrmgordzlafyjweavrapqqsicqnmkjulambrjxcmmsnvcjbbbwrloifqnmcmqlndubcynhumpikddliddyduafrpfgcltiymwlpbhtukmyawxdaaqiscvpfvsacjdljlfaeqhearjyczdpjsyjygfwaegqtylpibtdqinncmttbtiifbsesqbhpieectocontqhoyggjgbgjiyegoypfxorfqgbewhfqhkqftjdwtcnaiconxwjwryxqyexmlauoiysodziwfyyzyfewnfjyvfnvvxkkxeajmwbypoodsfrfygadcwpcjhzvemaplczgqxpsxkgxuqbxqhchpybojemqgxlhcyxmddjvwnbkvykkhwebfdpoovtvzgpkuwneodbochwxwauggxulmkynhoohchnkkcybhtwelotxpzoqzuczhwbjxsuqckuzsapdfkeiwxkcutimncyfpuaovhzwaebebkxgbognzpcxldjptnnldzqwtzzsiyjambnbrbyuyptxdkyxhlvigovllmkylbyzecxhdxczlkvsconlfvnafqvrwhcughqbtlmwgumeponoonhqqbklqaxvslkxowcuztjikgbutrnkmizschzrjxbmzvkkdlcuchpnrbxhgvxjqxawftlbirksyqbnltbaxtpyivrrqgxcjjgbhhvlltfqogehhddmgzivwlznkfuqgfbxrtixuonnywsxsdunhsmziyitecmrmxjkzmqhivinqkqywggffljpoxnofmzxkrmnxbdkokaleaqwbqizzhvywrweklybntszygkvuvypmukyxawhgbtnltemjchaytpqjplavcbypkwjwdmfogdxiddrtwrvvoqlmhsqlrdmmibawotbouzosrmbzocqvqdhoamuzvrfeyxkrnzpzyuacffbuvlcqupmbmqughegvjrobyzcyhynnpvvjntdcyplahaajwcbbleblkhjyauehbuoudyzrsgrtqnufijaawllbiexvhveipkaxffuiyczbkpcpzdnajwkkbbfrfchpedgabsraaalfbddgypeayprqwjzfvifjmgwaexrezitgaqgjmgizaohcfizhocckuzysshxzwqolddumeomghgsoaaerfxsapupejhywucurrhgctmmlgbyfjigveayriyvdmapvafzeydlxiwxcgnnajwjaqzkecczrdlbxgtdvehelzibmogdijpdiatcafnediqldwszonasgodqnnvajqxuwuftuvcqwtvayeiyysihhckitlimuimjllslrcnbobmumpbtoakqxallkqhszloxzpogfxxclnkmbfnqqomtzfpzdgxnfyvppeybjnekchjsafvhkrpvxpiumfvraeqcwqneatdrxdykoyscehvputknetluvfexdvtnnnaitrbdwyrzwnymuimydmadqbncdfixsgrcxkdnjzzyimcfbomioddimdxzxbmqwgnrezaquhiqytxmgsqpmywzxqksahlgwpxprtuzxtghkdbgxwpmdqxastvqggkhaqkxhjdsfcwyljwlleymorfgkezzroxaalrguityckdxsgqkcpaxxcsqvttvmmmmxezdztmkgcpnxbobuggzuqaetqfnmttjbshhfqqfsmfylavatksdchwvfvhyipfsepkwzqtprzogoxxohvibkwwiuwpsybbqqgbvziecnulnudzpudxvtcosvedrdxkhnkprghljzltucqljhdwpsfrsfryxpzybmybockeswpyihgossicvoxroiuzvgkbtduxzgsmgrohrxjbdvpnqwhgtvfkjrgpmirfdqddoyaztlooxlzllljsniwxfbihodjfywxallozikruusmzigztbzlyofrxtghhjwgptdbntmqkoxmrgzaznesgsgjnbmgarjqsqvswzygkbgquhbxsulabxzfpfnopzfnbiqeivuzayjbaikqrxrhyysttcafyxfdzgbbadcxiqltlwyhbcibkcxildnhmgwskeztcnmzdncqlyzpbzifjrhflsahlecmxwxlzmvpkqdexbfflmjhdqymxmjrktxaratynebetkfaltnrjgvsbdbvdcdyqujuypensmjnjskovbeweuwnqfjueeylefnqvmdmkwjqfvbjcuaibosymddysdymzhscroykljydnfvwosgplfphpznaqsddtbcjmyxhmcnxwdesycovtwrlmixqmpnzsbyfwpgnujxxqillwpbasdnbfxzokimfkujvlabycfwlplzpcgangjagrrhhjbrtddgitpoemixmobwyabyhsnkjtbeasdejawrueegmijbupygyciwbrhiwisguhlthnkpjqyzhiwvfrpgglqphhjtirtjxsjqxvqjpmokcgqbtjpsvravymmrrpyedruuncsjbjyrysjowqsnwtmvbakadxkxbyfunxnrkqhqvoeuzffmbpzfiiwrfdaekcrevffoxpsauhzziuyyjodsisaadbnyuugaxadvyxhfhbwhbmsgaklslihzwgvprpcawdtrniispfdnjoxkatlwebopgdqnaemwsflgfcuhkdnofblftofqzsphykpirzuckdnuxarzakvwurtrtbprdryikxmzytqhdmoyuizplphpvoliisgzhiganghwvqhzdmijccnfqqvboifovqxqvziktibyzpbffaguffgaqpbujvrvxecmaqygoyyptgzmwlnrwbeyuiiapgazdrgyrobtkcmsoheumgzjjpztatlpjkckxjqgfwvlhojdwztjgjdfdvalsglxjggmlfrbvtfeyhdbkggzukvdjnjtoytyrvxgrlvbqkkgrixhmjvwmojeiugbcyetihdtsizatgeukaczqllddwfqtwzsdquxmjmsypnftypppdsrqmkrfwxpwasrbtbeaaflqiatngmxylmhzwfoczsvcvwkgmxvhzyaoxrbblpqhbcozesrkjqncpyjukhppbubshyhwclceaefzhlbncxwdgglbtmzlksugrgnwjghgscqxfydztoraxrnthpqfojlgnablbxsovkcvpboujoczpihxrdblfirvlpxzgjhgiueyinhzasfelqnwmyhwwiaahrwoivetpfyyeeponmaqofwcbpvagruzshxaugnfzpaognklwcmfjmojrmjgmhroomwinouwdosuwtbrpkrzqtjfyspdnzgtbybsjyuohmchoukdyjfgovroyigpxqavcpmwnccdouskjxpqmpkjzkmcouwmauimkpatyfgkerqazsjuhctrbmqvqfdjfogajgrjnskzmrwnfjjfszebtbsioumdvhvqzgdkkhmsciutobqaefncvepnwqhvrfajmmrqnjryniwrckbaampnegmzoiqibwszbrqcpfgvtnlzemcmzaooywydmonegybzpdtukduxedpyquadxslnvirvewqihhnarvkpsbhmoggmoypwbimrnkuuiztvdqltnrytvvzlvhovoaekomlkqacgvlhdjaxhusehccgzjljjxjdpzpfnsrfnrxbzhoopziyrcmtpuvaqpvrevjjvmucezpecyckcmyvgnzgvitbkkdoptciamgkovowlhfcjmraynfyvlepowelkcjmjnibcsnabchcesnrwiplkavzgvdjyhulhthtbjgeckloshfcgobqovmxpryfbaaxfemkkpmtllovhqncrsbgbhjaozoycdnbcilhhlyfxbzvcmumpspgjszohxqhdocwnoxatmtnkqkpvupobukdudumdpsspzjxrcxstvajlarmicnsnjgdyyxcliqftvftmjmztbktbfmddbqtrfrygqzzzplqgemtvgijkydpshxiajzgcpmxsuamhtucpnejafrjqiwdxxflmaeyhntqfftvmsovtzunqszbvmvjhxcemtorseiariixtbnmxhkcwrghzposhvfnorlcwipsolpmkmvfpwdjswietamqfggxhpwfnsbkooocopbjzzxuhqxbtkklsxmmsgqvxldrfutlgntrewlyksrxdfexgkburyxbuqzhjmvqsqdzwppzyoqibdbhavyhexuybqhstktgtvtrckzqezauehcoxlnntilnkqekvdachlmvuxcowizzbqrldzaggpbvvlfwhsqfdyqvwqwrbkqvrqpzdihtnnafxbxqulzfswevlvxsjugrsaombysnngstmnlyayizrynmofiwbggehbfugsufhmyogsctxkfzlwwwshxnvoaqvstgpjtvyczlgoueutienayowbzwuhzearmhhbukmebpyewdrlmflwbvrzfhrkixvgewburjiqfovxrkiwvvbdrswvbcsznriinohlfeukcxmgmoyrlpqzjtgpjpvsnzbriifdyljkbqqiketrpvmvimmxhmpxlfzqluenskwrtshagizqrxigmmynfppfxfzxcvwbogamdxfipiqdasphwixefwvgrihkqjcflqvqqfvzxdtqyvvnnfzeucqhwlmxjconjuqkachpnysbnhrcfadculwgxcruihnuixxuvdmztugpvesdddargavwiudrtybxwmvywqleepplrchioqkyomusvamfawlxcwdkdjnydcmgfrlmkxpvqhcuioilsahnzrvlxnrfyxmjxvtlliyilcjtcwwcuucgurbbcshnlzrzilgkhdojcivhgltssezykltyzcubevrbapzmnhfhtntgnmjytjubvasdfiagwlzzwohzaibzqwqdlsikaodfljcgnhyckowudmfbqimtuszqgyxxzvipniipgsotrpkzamiwpkngnvwmjjivjtxhpzlmrwcjznavijhjjmvhxkjdahleprpynjnqltqhyamkfdfspbridpbuphtqxkncpognjgxwwyzxnkizrzvobpdxepncwvuhdspajmooiybeksqkhpncluiwwgsapihnkvgmwektybpzlnizkhtxtgeqqgaphditecptyoquueofaleodgsvfjxhokmzgjwflceebrbbjkxvqvkymjatpvdcvatnvkecfpxrpvwgnusmuetshyeyphgzjwktlwycqjqmsfjtiqkkbhndslyfxdegaejuzfylnbqlvacephpbuytqmxvwosukulbwdoofqomqlgdptocqlnjkikcvwcvyrpubzoeegonjhdtuibklelcgtacvovyntmucnzknumratvvwcphkfcxzjfmzwbqluzpexancupokekqnykxmwnyxvclvvxstnbbylaqknrgfegxfgkrnipkrstthxkkyborfgciqgksruwjzxwfuztgizrjrilmshcmnfzxwucrsscgotmniegribamhyzwjwyeuminjukrurpspcjmfllgceyuivmqfgegjjjpbswhjijrlajtbtevijdyanduyhbtedmihjaadtwbnjgrhlxgbvxxmtqzinsclkctlvhocntuppgfeaubksbwxouqsmdeaijulvlpawxuuvadmroswmaceodnqnxaxnwxwsoogqctfkadzabezoeufgskhtxgeefigmjcwrsoymyardzujtpejrsjslnorwixaawuqkhtgtqgrbjrzoxdpgetayqwsvptbwoljgypbkaxjcfujykdtikngwvnmwlpefdecpkywsbkoqjuyiaaizknmygqiqdjhfxfzpsdnlzqosmcdgacngjdrmhhnmltesihrwsfrfjvhctfjinwolonpeuibvxhhunarulabdrrwpipkczhxaxrqxvydmuerawuoshzupvvhfhlvbdahibhygftjmfqostlufujpwrfduppuhidftnjegdoqjyfekysuglomymoybrcypfkabcgiddimrpahbmtjwropodagfdfrpffqqgffriqcmvqsbnrjqwkqrpappefsabbjkotyspncbzjdlqjobgzkxzebhuliwikfvhfroqotbwsyywapztlwnnumngdwuinqefmgmndpvfsmmzrozkzplzmgjojgkzwkfwgljxrvvfuvozeihsiwqvksibqdkbsqslxwydowhsekwuslrppizukfcvvfxuffrnnceoriukxnqoujatnhqvgjaertcqcdfccsttyirwzxytgflyoedmkhzufythspclmyrwzxlvvhhqohxdppsvzoqgcvclykgadmtkwxfnzpcoziukoajwjjaiufyzormcokrwbdpnhcotdmvyihscatzmotgqoqthdcdegnxxsxdqgtbdirmvujyvssdvpztvhzaklkqvvhkpqmqyrwbfwcygnvbjjvrfmccrmjmspvqmxadbpipprbcurcjcjyjjbnzbjdnpgobvckrdcbjiphtgmavthjedrkulplgedfiavvdupwfugxvrowmuipujzqdkzebvfgzqxxznnbdfjmfrrgjwpqkudgscpotdhtguvgyymhhwkrctnvuphhjnrwcqzwargqxxpsdvsvfynlhxrzekjfgtdmcaspmtmzdaojduyhqieipeetptyfuhrynsszfnxcgtvnfahfgkjfbxmgnuhxtifzhgtlmjlgayybpshyzixkvocjlorxlpvsjqgssxlwmxwpmwouocgylxbmyfrezwpubyewxsnqalzgetnpdfwrgxsawaargjclnfxoucwljnuqaiokxgixwogrmfhegurpyzitefhejtqawnmglkhlhxoxblmgdhzkavxnqhoeagcrbbqlssotgphffqtcgkupzvlkmljmjomnqxgcmiyysmkvziridmuijdrzozgzxsuiudhjzuxxjoatipfcpjsqqckmvcgsjdaoecooposrptdwtrdwvfltbtczbnyqhvdrkphccwyyponubffazdikxuifbxnqmoubdtqbpxrpsfyoevuwgmwlnvgblxlvshhdavmdhbmurkmlhsiepzyiqoaiugfdzwkpmtjozzpqfrxpafkiebadrglatgpoiargnyofrhsdrpfgdipxnlsxopmbhxupantpxyasrvqziefcarckihgxkbfszzgtjpoazjuuuxxccegqhjtsjqdhgshczrznrbyjrraxeyzdgciyvaeapkwgvkejkrckdsbyekoukliqozslwgghnjrfbzpqkrfwjawoutztlnasoecujozksrefzdduhnvnskvziighbejokbqyrdespapyqbidgkzwlfvapyjcxcoybgwxweivmzblrdyumcxcnddqgvlthtfjwmefwzkzvnycnfduawgvsqmullejnpapzeujmmwkbmtalkrpunhjlargfhxpjphesgxdvldteileyzxpftdikjyyqgldfwrzglixzuegwslfyhrqjceeeggllgbvfeaefztngfpjncbjeyfmyvcmdashzponstxigskortcevevfpqcbwzmqrbvbniwjwajbdhdfqlyujnwiuveihahtbakokmzkpznqqrqdbbivaettleiciafubnklnowubzzhvzhyhkfhzvvcsajxkqnruuyoaxmrahzmqnuedlmjyiioucsaxvhspmrmglcmpoxvqzwssgxgptdcclstkjxwwaqekdwkixnowusxbnftnzjectfsckbeeevhytludfcdzwdiujywcsgwrvmbecqwibvusgqhhvmztiavlsmvlwztgburxaaotbcslvxnffaohthhwhaatkyvaptdxwoztfcqovimzbpsbxwuwbjwkbdvrkuytovzsvcmkporgabibniqiiobhljsbgeqsdbofcdpuxgdiqlmpwpadfuymdmauguvvewtnrkbkgfogitcidofpaduxeetslyqppgsquivqvvmfmdpyfvmqfliuhkasezljpmlagfgqcqahtfojamfwjmptsuvgbslskjmvqhmdlhouymghfngfysjiqkjfcwbjjtorzpjblzuabghntwyxrcqrrtviijbcknzjolpatwpssnzmobrpxwyaubjgakgdzydkkvsisnfscwklbmkdhrzbopcdmimqleofwvfugtbtogbdmazqjmlslpfeukuqcpmpwggseebnoqpadfpudcnriiwlhojpzpbbqdgqoweijlyjplkxxpxawanihmdkxmmdsdlknwcxrbsmrpsxawxxoepzckcilssqxntruzwmtqqjrxsupdaedboovfkecckmdxtymhagyoweznpgtwxkpbnoqfkrnzvsxpdlgynleqcpyrodfqngjgmkweiotmvpmbujluktefwwhhprfqtusjzebtnhyztjhbhlnmfzdrcsxktxbzqsoczgwoydpcssgksstfeslmesjkdbwhlorqtswfcfsxkysbedidqzsxorpgnhgieonzdzlpyqxjkkncypuhjtgwzxvrqmpleelcampexgswcdtezuqdghfzzxkzzyulqpfojwsdgcdniblomxrxflbnylwqxtifxxfkembyxhkvhfjnmpdinrpodvticucowipekvthfobnkdvgfhoobhhtwdtppcogtwqyynixndujqclzrvwfirjqsmvfjxbhisdaugeaswspcljkdigdqcekcftqcemsjlxhplmrxootbcsjylvkvwtvvnusaxtkxcjrxazsjeheguoxrebicpecuuorpwzsgpfgztgtfpilvauzikosbtzbhrwafktgltkteknizcioxefizyvwfgyfwhbgkssmvobxrzvqfkdhcvezdmyvqqedjvspyvsgwqwovdxrecdanapoydetgehibxaslvllrqkxdzhsebmrdflqxylvgfaaghcstzrlutizgxkgfjzatylehdqcctkhqahctbyazuibdkvvgyyoqlmiocgkripiofrbmjvkavkebaelrhrizmzbskptanrhwzcpzrtofjxzkrushctxejlaziteklpjakzskzklmdgukiabxxduslretgbomoexppmgimlfhfehoswtixefjffecudfmacfvlguvvbzcbtgywrxbwifkrxlhoqvtslpwhbcanoaynjonlyiobcwstxshesdowbviqdejatogcfbllmnctasbeininbnwmtpdhmuvurvtpnkqpscvwtlzhtlpvoztdqbncxxmqymjojjnllivocansiodawzlcygkejjgisvzvvdlmacnffffhxyodgtmmlevrjhnplezrfidsuygsariqdqbyvntpqnurmtrxtentgnopsipnayoxipkvysbunxqjisyjevmjvgxoqruhxvsqedcsimagxmsbjslwohsckiivuhbjnegobkpxjdoqfnicgunugidyfngasefvcbwltaljvxamhnuefkvhgbwyozaggdszyqghnnfmcyjfvhfcamcxjrggysglomdptedlthpfxmmbqbfzlzgodcsahagnuepupqbrfxjgqldwbuenabygoeduhwgtxnfmzlsojbvxmmavdbmxivmdozdratbytpyjysrzpejdggqguhyeshcobbfodtuqnwwundapkfkblfzdlnsbylsufiuycoejkljrcovadehyazpwqordifrsomfskmjzogqciiluldojkxfgtwrlbqjekbqotuhffowjptmjkitgolgsofzkvjasgzktoophkpnidqujvcdxofcfuwwwihpgitnsfsrgxxqzvzfjlabwqptlvsusszjajgxshshzncuhafxndwqcxujigvkymfztczglcuwbzhgomvqxkdmxilzewacpnffzlkxezzpxbfvlfosxkvmdopnuwoqkbjrogfecxpzcqvyzeuadikskcwpgyknryrgcumvspxtgzzdsoebizpsehtpqfmtgnwjhrcoqthrjxjugvzyhvoglnerbyffgastsyoizzzrmmeawztdizcebilasdsthmujjvmjsssvhwlyglddnljtigltporpjaiokkoeuqreawmpbvbnjiuvhdslieeanfazyxubwacizffpahfndinebzcqdrnqnbrwdddcorvatawhqeacjtfikkastvtluavsyixwldxuifyxpmgtxqpdcpyggdiztwihzsvhtotqgtscvmwtpsakuuyuastebtsivnoemlzhdllyvyifirqcvxfapegnfyaxepsvvqhdrztwzgbbtbslrtifugxhrsiidptyafyaxbtbrpxlsvwmxvcmrpgatnpnqoghnjqqxwtfpsicpwrtwtqrxgxrdzlkamgspznezzlezvaftrvbvjatefhsrtrqusxnrxrahdckrsdgyzbtflaaelpkwfddzgapzlktcrizyawqeazasrtkcsryowkcjvmsbkvhkmdxrudjjpczpzfxtjbmgpvwhchvtlctrhdqqjijrnkunalsucruwhhfrrdsjztcrkivvrlszopymvuxnnlqklatzgcjjuxmhrmydtcyxhisvxepljzwjuhinuxvsmkdtmrrojutimnivlxxcjvgbpclzuxcppfopckrvndccoelzzmzcdyqrkuxdwompgshazcuzxwytnjeejmpwpabiuaorkhctezqydizuuontnukrkvithhctnmwwivqbabuvqwvjyxpwsgpsoyszfsnjeeofmqoyxyakfcmwrwkisglzadmtcolpwhrnpasmxbkozdfgtuchqhvdnfahlxbzqqxgfisdjrwwqsjihtcgflpnskznnfdzeotcrzylojcuvsabyngjoetcptkdbihowprmxokppjfjvxsztypzkzgwuurqmlwdzapowwsaozebryypltamqzmduirxskstryqrdaagwerlbnwgteibjiktrladowyuhsuasqppzkqtsvpxzdcxyulrqgjzspppjqujffcwrtovaxaflttvrwdlojqdmmcvgeoiieifzkpzfusoozkunhnxaafpnrnhsfraglsbylzbigxjxqbjgxfbtevzeuqrewyjywvmedtwajobluxrsdlvaghovxhfcieuudwrhffehgfuwkqvgpofqijpklraclahqmewxggvrboqxveabgovkfylybrbrxqnvljafuooyscossddrmuosmcxbthyynfuhytjyhkkvwiaqpicrfjxvwftatdwhwuxxqessofyecjfzbzhpqblvqooasrwnlaqrlzindcvxzunpizmgpgsmnangmfargzqcvclgphenedrlpkfnhcccwzkhsgswrtqnqidkaleqitfqyikkjkcjokeelqfldfbzmtmvcyfzbpcgbsjfedviylpheoilpddgtohbywwuuqdcvihhcqtkrmntgfkeytjeytnfjzxongdmvahbyubjbsdkrejpiyezopkkvrfeiwycizgexqcnrpbqwrksztcjqlrhbyhenwqlxxjkicoajfphdxjpndnkfsjrfoqsmntuenabiufbjkyhemewernlberrrlivflnehtterrvdgnrlaosrljjggogsyxpguzinyohitcbcaqebmogtkamdzhgtiufxeshimfdrcmfqrqtcbapddsmerewofiqrwprfcgdmwzuddpavlnohnybgibsnxtsnzilexfehiphpbpqghnocawhmkzakmotjkeuuilvkagummlcclpuwxbyeoubwqtqsokrnxgotuajewgabdyzzyglufirtdfebmvafinbboecugtxacqdxwmbxyhcksiygftwubfrnxlivjiofvjctzygkjqsnjlhhmoshoxpbrkhbqkztkhjcmeqxgpzxymlfwozldnpllxboixvivoquplfrvtwxljpbmyjlbvbgujcczqhjwdvqtgatnvcuwmncazwmsykjsgjpvhkgusfzyctzmigqowhmdicguijmatupdjzxqbunxbeqardupokgfbtgnkwmajdacajwzsuvpiwjmtzyimluenlcrybwpvtuztfxfsvgrgndhljizthoceovimkxsxyneohxnbzbkmnxlidsczqkknlhrbqdlhxsfypqviucqiywljmiqlzlaofolpmtkvhzgvscoowmzlkehvfidefmcfeqssjquavrehjhugjoeeuqrrskpnsituzqjxoydxxssszyzgmczdtdahjisrjjgdwlnjglrqrzrnyudairljibcutnfcojuyjzuhazszfepncfyvoxgnbiyyixzspcnlhclxddafebdukcvdkblnqmzqkonheehbszjkhhyvecpizqjdnwraosmbfntitxhocadbbniuqzxfuyjqfrpvocwnrziazjitmtxxvkewhfdcewxqfovliuxzilicokdjmuncxipcixlipdcmuwukshsotjjcabvewtorjckmmqtknmdrsvvgqzilbwnxuzlogloepyrsaiqyoxwjwmxbnwckvbiesvybwdqvjnywbwthuadbgeieblmdboggqwxugtiporxgkbroidfuykuypwyavecwgfskshqogbvajbthoemgryusercuxztwgtbzofcsiduoavtafszohwwchuqjpjbbrbxsudotmxprrtavzddwxijonauwgscsvtrjwomoqchhwxtohwatxghcvsbaqxsntzsluhxsmrajjefralceyhhympznjuzmwqummdxuwwqzwdffrgkjggfnjnyebxegzzbujfyeivmlwwgwrglrooznuhlfvguwezrqwnekgnahtocwbjamdtrtowwyyohusnsmznehzpieuayritybnlrldihnbdsbsbdqtpdpqyjkdrcecfwlljsljpdgifxetsajmymzcdlefllhtcotecgnbtputyabsmeigdjxwxywoyvyimdleebaadxpsfeadudsvebxbjrnotvqldkxutesdeimkhwpdbbyvhxsgjalsoosgpikstmbapoffdkljthvhlagsjtnglpuomrvejsdvfcxlgwhitnekotzcmagrjnvqdumqohzpshypkcijkgwozgyxvdozkaasbuohhkzaabuhllmnvtxtwqooxzkkcfaveprjtvklmaoxtftwzkdbpvvuezwbgohnzcomtjsudbbdpowrrtvqixxfellzkloxbrxdroctzwywujgzzptupqmfpstlpiowfnmdgvgkciyzlvskiinwoxsxvbgyprttxjgasztpuvjvwztcnutyxplebjnsgipbarhlcnwjkaspbohchtiurjfykknkslygfkomhqnaiocohyccfguufzebncmchjsapecxdbkouugsmtnipfmdxdamfhfoxcdoqjnjnzfpqsgdirbcaszqchlqhxupypvepxgxecyrwpkaziqndjjkjrpqjowpspvbizerthixqznivlbaflzhtujtkmqgcjdkpnjdrxktphtwfbwpcwcavxaxdrojjteqsajvizogsvgcctyinjqzsjplfkjajuxaprouznlyepxtvfswdsglgbaclhnpoiwkfqrggbmlmpdavzubxdcifoxaokwfwonulygizsuvxqxnomczdjcrcgxfduosvazmwzbzlhcuvxywlzguxjjkkvyutqwwlvtgxljaiercxbzmlwgudfdhseusqifvoxksxpbxublditsfyiflzcvzfdfpdeibmoekyjpddexbfnudsusdxbthmtfxhrgwtiirccxhbizvqffcwghjuusqfcbynbfewdsskwexmpvtrilyqsgraromzsuhbqnjldrpchnclecocjykihgzlwynfcrnhigbfxkrwblbphkdjttqjihergujyickvhoaomtnkmsjpzkyvzljexphylviqyhnbuxrgqdirpcfbevfjtmmodmarupbgicdefifsprpfqszlgjpnhzowtorkanvprqqtjiausxyhtjmtiiwfidmasztdcpynqacphntdtmfpdvpjtaekaggbevqmyxymtiokdspbzgnxubwikzaapehiabcktjhwkgjzhzldgrxjsfyuwgmghenfrtzsdauuaodxqvvyerjuebapknrmhwjhbrojwzcodwhpdbgaeninbtyrhzqxsfpdwzrvfnbruccjfqfupcdsiqjlnrfjasrkhznssbintubxchjhhiqahjtkfawlfyonocudtjpgkgjlyrrkohgrzzvqcwfwgprofintyzpwiregtwyxjywrvrusvnsqyvciubsqaotawxlmromuszooghkkfxwjpsdmvxdkjukxjwjdksmrxpkkpxtpbwbfisfqneuohxhbinrbxmaklfdjzhhpzrfnzrkpegzqnjmdlngvthppmovnrbclgpmiqnzzcwxgstfbrtmealyfigyxfnogdxpoxonzlrzjrvoplzkaimklngxqvhkiijuecthgeqrtxfsajsimbwyknlohabegrkrrwfytemczxogrdrrgibzankeqfddiufslellsggwthsvwkentzyrfppyacqczprryimfnhzowoxtrlpvmtfkstlbcgicqsnkgpysifmykfdzreydxneuydzjhqpmbwrbxgefmsojgbhuxkdfhpfxzvdbpfgdhekmnmaokhssvbsdbgqisfcpwsfzsvojfjsrqhuuduwifaywnthkiuhsrgnkrvuknmilvrowfwsqohmrusibdhuhcjvzjlvrufbtypotgjqagipmmhlcmliieerwhuizsvjnxtubqwabqaifcvsrzlklwxbgwfmxrmimdgxjnlaxtctdrerfpxvifkwbxuskrybktiyeambeebcptsvvmsmhgdxollkhlomdzlyjvyvvnrbaddfrujpvzngaisvfluqjscncriugpimqlcinkebcrtczhiyyirdanhddlusnoezbziuwphjeejhfivvznkemfbtcoiyahtljlynrwzearpvekmzhlguwvmgmmbwzadorelfxidnoiwiehpzgzefmppajnmttvdyemgzwfodtlpirdsmnzkitryomcyfukylxoinaornrtmdisoiuddnzwqitqzwhjecrmyhoretzgxciqngpsxcfgfzyneoxresrogmeebiqrcnpyehfriprzueajqfnrczmullahnexfebqaqfnzzkysvbagwemvxttmwvrvflcfjenjoizhuubutzmsxogboepyyezibsqbmgkwkwrcjyqhikbfpiqsmrjmqriwppdbijldaqzxpuiawhxkaujicxchftemfyfmscxhbxweswtjgtlmtkhpyvpybrkmtgtqvtocnqvaxpkjwkedgvvgsjiftgdqdbukackiefopjqpnhzezgrgrzpyvttugsedhmjcmrvnkeofqqignddniiazspgwgfbxolzwwklvairwvqchjxybwfjugmyflkkuuulqzgqkgsuymvrlemwrblieexszuzkygujowopflsaadzidkrqgsnmntbipofuwrahnypixrpzp\" 1626006833639000000",
+// "measure,t1=3 c1=8",
+// "measure,t2=3 c1=8u8"
};
pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql)/sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
ASSERT_NE(taos_errno(pRes), 0);
@@ -692,7 +696,7 @@ TEST(testCase, smlProcess_json1_Test) {
"[\n"
" {\n"
" \"metric\": \"sys.cpu.nice\",\n"
- " \"timestamp\": 1346846400,\n"
+ " \"timestamp\": 0,\n"
" \"value\": 18,\n"
" \"tags\": {\n"
" \"host\": \"web01\",\n"
@@ -910,7 +914,7 @@ TEST(testCase, smlParseTelnetLine_error_Test) {
pRes = taos_query(taos, "use sml_db");
taos_free_result(pRes);
- SRequestObj *request = (SRequestObj *)createRequest((STscObj*)taos, TSDB_SQL_INSERT);
+ SRequestObj *request = (SRequestObj *)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT);
ASSERT_NE(request, nullptr);
STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
@@ -960,9 +964,35 @@ TEST(testCase, smlParseTelnetLine_diff_type_Test) {
pRes = taos_query(taos, "use sml_db");
taos_free_result(pRes);
- const char *sql[2] = {
+ const char *sql[] = {
"sys.procs.running 1479496104000 42 host=web01",
- "sys.procs.running 1479496104000 42u8 host=web01"
+ "sys.procs.running 1479496104000 42u8 host=web01",
+ "appywjnuct 1626006833641 True id=\"appywjnuct_40601_49808_1\" t0=t t1=127i8 id=\"appywjnuct_40601_49808_2\" t2=32767i16 t3=2147483647i32 t4=9223372036854775807i64 t5=11.12345f32 t6=22.123456789f64 t7=\"binaryTagValue\" t8=L\"ncharTagValue\""
+// "meters 1601481600000 -863431872.000000f32 t0=-418706150i64 t1=844637295i64 t2=482576837i64 t3=736261541i64 t4=L\"5S6jypOYDYkALfeXCf2gbUEio7iTM9vFOrMcGqYae0yNeDAEIrKHacOo0U7JTrev\"",
+// "meters 1601481600010 742480256.000000f32 t0=-418706150i64 t1=844637295i64 t2=482576837i64 t3=736261541i64 t4=L\"5S6jypOYDYkALfeXCf2gbUEio7iTM9vFOrMcGqYae0yNeDAEIrKHacOo0U7JTrev\"",
+// "meters 1601481600020 -163715920.000000f32 t0=-418706150i64 t1=844637295i64 t2=482576837i64 t3=736261541i64 t4=L\"5S6jypOYDYkALfeXCf2gbUEio7iTM9vFOrMcGqYae0yNeDAEIrKHacOo0U7JTrev\"",
+// "meters 1601481600030 63386372.000000f32 t0=-418706150i64 t1=844637295i64 t2=482576837i64 t3=736261541i64 t4=L\"5S6jypOYDYkALfeXCf2gbUEio7iTM9vFOrMcGqYae0yNeDAEIrKHacOo0U7JTrev\"",
+// "meters 1601481600040 -82687824.000000f32 t0=-418706150i64 t1=844637295i64 t2=482576837i64 t3=736261541i64 t4=L\"5S6jypOYDYkALfeXCf2gbUEio7iTM9vFOrMcGqYae0yNeDAEIrKHacOo0U7JTrev\"",
+// "meters 1601481600000 -683842112.000000f32 t0=354941102i64 t1=-228279853i64 t2=-78283134i64 t3=91718788i64 t4=L\"wQyjbkfama3csU7N9TPIVAzx3v5ZUoMg3bn3jq3tqSuHAqky8X8QnwbeQ64AjGEa\"",
+// "meters 1601481600010 362312416.000000f32 t0=354941102i64 t1=-228279853i64 t2=-78283134i64 t3=91718788i64 t4=L\"wQyjbkfama3csU7N9TPIVAzx3v5ZUoMg3bn3jq3tqSuHAqky8X8QnwbeQ64AjGEa\"",
+// "meters 1601481600020 178229296.000000f32 t0=354941102i64 t1=-228279853i64 t2=-78283134i64 t3=91718788i64 t4=L\"wQyjbkfama3csU7N9TPIVAzx3v5ZUoMg3bn3jq3tqSuHAqky8X8QnwbeQ64AjGEa\"",
+// "meters 1601481600030 977283136.000000f32 t0=354941102i64 t1=-228279853i64 t2=-78283134i64 t3=91718788i64 t4=L\"wQyjbkfama3csU7N9TPIVAzx3v5ZUoMg3bn3jq3tqSuHAqky8X8QnwbeQ64AjGEa\"",
+// "meters 1601481600040 -774479360.000000f32 t0=354941102i64 t1=-228279853i64 t2=-78283134i64 t3=91718788i64 t4=L\"wQyjbkfama3csU7N9TPIVAzx3v5ZUoMg3bn3jq3tqSuHAqky8X8QnwbeQ64AjGEa\"",
+// "meters 1601481600000 -863431872.000000f32 t0=-503950941i64 t1=-1008101453i64 t2=800907871i64 t3=688116272i64 t4=L\"5kb9hzKk1aOxqn5qnGCmryWaOYtkDPlx1ku8I5hy3UVi6OwikZvBlfzX4R7wwfUm\"",
+// "meters 1601481600010 742480256.000000f32 t0=-503950941i64 t1=-1008101453i64 t2=800907871i64 t3=688116272i64 t4=L\"5kb9hzKk1aOxqn5qnGCmryWaOYtkDPlx1ku8I5hy3UVi6OwikZvBlfzX4R7wwfUm\"",
+// "meters 1601481600020 -163715920.000000f32 t0=-503950941i64 t1=-1008101453i64 t2=800907871i64 t3=688116272i64 t4=L\"5kb9hzKk1aOxqn5qnGCmryWaOYtkDPlx1ku8I5hy3UVi6OwikZvBlfzX4R7wwfUm\"",
+// "meters 1601481600030 63386372.000000f32 t0=-503950941i64 t1=-1008101453i64 t2=800907871i64 t3=688116272i64 t4=L\"5kb9hzKk1aOxqn5qnGCmryWaOYtkDPlx1ku8I5hy3UVi6OwikZvBlfzX4R7wwfUm\"",
+// "meters 1601481600040 -82687824.000000f32 t0=-503950941i64 t1=-1008101453i64 t2=800907871i64 t3=688116272i64 t4=L\"5kb9hzKk1aOxqn5qnGCmryWaOYtkDPlx1ku8I5hy3UVi6OwikZvBlfzX4R7wwfUm\"",
+// "meters 1601481600000 -863431872.000000f32 t0=28805371i64 t1=-231884121i64 t2=940124207i64 t3=176395723i64 t4=L\"7pkY8763Ir0QeugozDbqk6NHbvRpx2drfndch74No3sqmyCJZCZaxAFwVmLgcMvh\"",
+// "meters 1601481600010 742480256.000000f32 t0=28805371i64 t1=-231884121i64 t2=940124207i64 t3=176395723i64 t4=L\"7pkY8763Ir0QeugozDbqk6NHbvRpx2drfndch74No3sqmyCJZCZaxAFwVmLgcMvh\"",
+// "meters 1601481600020 -163715920.000000f32 t0=28805371i64 t1=-231884121i64 t2=940124207i64 t3=176395723i64 t4=L\"7pkY8763Ir0QeugozDbqk6NHbvRpx2drfndch74No3sqmyCJZCZaxAFwVmLgcMvh\"",
+// "meters 1601481600030 63386372.000000f32 t0=28805371i64 t1=-231884121i64 t2=940124207i64 t3=176395723i64 t4=L\"7pkY8763Ir0QeugozDbqk6NHbvRpx2drfndch74No3sqmyCJZCZaxAFwVmLgcMvh\"",
+// "meters 1601481600040 -82687824.000000f32 t0=28805371i64 t1=-231884121i64 t2=940124207i64 t3=176395723i64 t4=L\"7pkY8763Ir0QeugozDbqk6NHbvRpx2drfndch74No3sqmyCJZCZaxAFwVmLgcMvh\"",
+// "meters 1601481600000 -863431872.000000f32 t0=-208520225i64 t1=-254703350i64 t2=-1059776552i64 t3=1056267931i64 t4=L\"1zWxWvHNZYailPvb4XxafeA6QvrUrKUf8ECU1axNWvV9ae851s34wqZcMeU2ME7J\"",
+// "meters 1601481600010 742480256.000000f32 t0=-208520225i64 t1=-254703350i64 t2=-1059776552i64 t3=1056267931i64 t4=L\"1zWxWvHNZYailPvb4XxafeA6QvrUrKUf8ECU1axNWvV9ae851s34wqZcMeU2ME7J\"",
+// "meters 1601481600020 -163715920.000000f32 t0=-208520225i64 t1=-254703350i64 t2=-1059776552i64 t3=1056267931i64 t4=L\"1zWxWvHNZYailPvb4XxafeA6QvrUrKUf8ECU1axNWvV9ae851s34wqZcMeU2ME7J\"",
+// "meters 1601481600030 63386372.000000f32 t0=-208520225i64 t1=-254703350i64 t2=-1059776552i64 t3=1056267931i64 t4=L\"1zWxWvHNZYailPvb4XxafeA6QvrUrKUf8ECU1axNWvV9ae851s34wqZcMeU2ME7J\"",
+// "meters 1601481600040 -82687824.000000f32 t0=-208520225i64 t1=-254703350i64 t2=-1059776552i64 t3=1056267931i64 t4=L\"1zWxWvHNZYailPvb4XxafeA6QvrUrKUf8ECU1axNWvV9ae851s34wqZcMeU2ME7J\""
};
pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql)/sizeof(sql[0]), TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
ASSERT_NE(taos_errno(pRes), 0);
@@ -980,7 +1010,7 @@ TEST(testCase, smlParseTelnetLine_json_error_Test) {
pRes = taos_query(taos, "use sml_db");
taos_free_result(pRes);
- SRequestObj *request = (SRequestObj *)createRequest((STscObj*)taos, TSDB_SQL_INSERT);
+ SRequestObj *request = (SRequestObj *)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT);
ASSERT_NE(request, nullptr);
STscObj* pTscObj = acquireTscObj(*(int64_t*)taos);
@@ -1285,5 +1315,211 @@ TEST(testCase, sml_dup_time_Test) {
pRes = taos_schemaless_insert(taos, (char**)sql, sizeof(sql)/sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, 0);
ASSERT_EQ(taos_errno(pRes), 0);
taos_free_result(pRes);
-}*/
+}
+
+TEST(testCase, sml_16960_Test) {
+TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
+ASSERT_NE(taos, nullptr);
+
+TAOS_RES* pRes = taos_query(taos, "create database if not exists d16368 schemaless 1");
+taos_free_result(pRes);
+
+pRes = taos_query(taos, "use d16368");
+taos_free_result(pRes);
+
+const char *sql[] = {
+ "[\n"
+ "{\n"
+ "\"timestamp\":\n"
+ "\n"
+ "{ \"value\": 1349020800000, \"type\": \"ms\" }\n"
+ ",\n"
+ "\"value\":\n"
+ "\n"
+ "{ \"value\": 830525384, \"type\": \"int\" }\n"
+ ",\n"
+ "\"tags\": {\n"
+ "\"id\": \"stb00_0\",\n"
+ "\"t0\":\n"
+ "\n"
+ "{ \"value\": 83972721, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t1\":\n"
+ "\n"
+ "{ \"value\": 539147525, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t2\":\n"
+ "\n"
+ "{ \"value\": 618258572, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t3\":\n"
+ "\n"
+ "{ \"value\": -10536201, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t4\":\n"
+ "\n"
+ "{ \"value\": 349227409, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t5\":\n"
+ "\n"
+ "{ \"value\": 249347042, \"type\": \"int\" }\n"
+ "},\n"
+ "\"metric\": \"stb0\"\n"
+ "},\n"
+ "{\n"
+ "\"timestamp\":\n"
+ "\n"
+ "{ \"value\": 1349020800001, \"type\": \"ms\" }\n"
+ ",\n"
+ "\"value\":\n"
+ "\n"
+ "{ \"value\": -588348364, \"type\": \"int\" }\n"
+ ",\n"
+ "\"tags\": {\n"
+ "\"id\": \"stb00_0\",\n"
+ "\"t0\":\n"
+ "\n"
+ "{ \"value\": 83972721, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t1\":\n"
+ "\n"
+ "{ \"value\": 539147525, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t2\":\n"
+ "\n"
+ "{ \"value\": 618258572, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t3\":\n"
+ "\n"
+ "{ \"value\": -10536201, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t4\":\n"
+ "\n"
+ "{ \"value\": 349227409, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t5\":\n"
+ "\n"
+ "{ \"value\": 249347042, \"type\": \"int\" }\n"
+ "},\n"
+ "\"metric\": \"stb0\"\n"
+ "},\n"
+ "{\n"
+ "\"timestamp\":\n"
+ "\n"
+ "{ \"value\": 1349020800002, \"type\": \"ms\" }\n"
+ ",\n"
+ "\"value\":\n"
+ "\n"
+ "{ \"value\": -370310823, \"type\": \"int\" }\n"
+ ",\n"
+ "\"tags\": {\n"
+ "\"id\": \"stb00_0\",\n"
+ "\"t0\":\n"
+ "\n"
+ "{ \"value\": 83972721, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t1\":\n"
+ "\n"
+ "{ \"value\": 539147525, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t2\":\n"
+ "\n"
+ "{ \"value\": 618258572, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t3\":\n"
+ "\n"
+ "{ \"value\": -10536201, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t4\":\n"
+ "\n"
+ "{ \"value\": 349227409, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t5\":\n"
+ "\n"
+ "{ \"value\": 249347042, \"type\": \"int\" }\n"
+ "},\n"
+ "\"metric\": \"stb0\"\n"
+ "},\n"
+ "{\n"
+ "\"timestamp\":\n"
+ "\n"
+ "{ \"value\": 1349020800003, \"type\": \"ms\" }\n"
+ ",\n"
+ "\"value\":\n"
+ "\n"
+ "{ \"value\": -811250191, \"type\": \"int\" }\n"
+ ",\n"
+ "\"tags\": {\n"
+ "\"id\": \"stb00_0\",\n"
+ "\"t0\":\n"
+ "\n"
+ "{ \"value\": 83972721, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t1\":\n"
+ "\n"
+ "{ \"value\": 539147525, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t2\":\n"
+ "\n"
+ "{ \"value\": 618258572, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t3\":\n"
+ "\n"
+ "{ \"value\": -10536201, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t4\":\n"
+ "\n"
+ "{ \"value\": 349227409, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t5\":\n"
+ "\n"
+ "{ \"value\": 249347042, \"type\": \"int\" }\n"
+ "},\n"
+ "\"metric\": \"stb0\"\n"
+ "},\n"
+ "{\n"
+ "\"timestamp\":\n"
+ "\n"
+ "{ \"value\": 1349020800004, \"type\": \"ms\" }\n"
+ ",\n"
+ "\"value\":\n"
+ "\n"
+ "{ \"value\": -330340558, \"type\": \"int\" }\n"
+ ",\n"
+ "\"tags\": {\n"
+ "\"id\": \"stb00_0\",\n"
+ "\"t0\":\n"
+ "\n"
+ "{ \"value\": 83972721, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t1\":\n"
+ "\n"
+ "{ \"value\": 539147525, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t2\":\n"
+ "\n"
+ "{ \"value\": 618258572, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t3\":\n"
+ "\n"
+ "{ \"value\": -10536201, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t4\":\n"
+ "\n"
+ "{ \"value\": 349227409, \"type\": \"int\" }\n"
+ ",\n"
+ "\"t5\":\n"
+ "\n"
+ "{ \"value\": 249347042, \"type\": \"int\" }\n"
+ "},\n"
+ "\"metric\": \"stb0\"\n"
+ "}\n"
+ "]"
+};
+
+pRes = taos_schemaless_insert(taos, (char**)sql, sizeof(sql)/sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
+ASSERT_EQ(taos_errno(pRes), 0);
+taos_free_result(pRes);
+}
+*/
diff --git a/source/common/src/systable.c b/source/common/src/systable.c
index e7b6342150a4b48242eac408c021ad9cc2bfa170..08997bcaf8ba4f745db9f7d13b131cad47db901b 100644
--- a/source/common/src/systable.c
+++ b/source/common/src/systable.c
@@ -108,13 +108,11 @@ static const SSysDbTableSchema userFuncSchema[] = {
};
static const SSysDbTableSchema userIdxSchema[] = {
+ {.name = "index_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "table_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "index_database", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "index_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "column_name", .bytes = SYSTABLE_SCH_COL_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "index_type", .bytes = 10, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "index_extensions", .bytes = 256, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "vgroup_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
+ {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
};
static const SSysDbTableSchema userStbsSchema[] = {
@@ -125,6 +123,9 @@ static const SSysDbTableSchema userStbsSchema[] = {
{.name = "tags", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
{.name = "last_update", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
{.name = "table_comment", .bytes = TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "watermark", .bytes = 64 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "max_delay", .bytes = 64 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "rollup", .bytes = 128 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
};
static const SSysDbTableSchema streamSchema[] = {
@@ -148,8 +149,8 @@ static const SSysDbTableSchema userTblsSchema[] = {
{.name = "uid", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT},
{.name = "vgroup_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
{.name = "ttl", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
- {.name = "table_comment", .bytes = TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "type", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "table_comment", .bytes = TSDB_TB_COMMENT_LEN - 1 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "type", .bytes = 21 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
};
static const SSysDbTableSchema userTblDistSchema[] = {
@@ -231,7 +232,13 @@ static const SSysDbTableSchema transSchema[] = {
static const SSysDbTableSchema configSchema[] = {
{.name = "name", .bytes = TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "value", .bytes = TSDB_CONIIG_VALUE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "value", .bytes = TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+};
+
+static const SSysDbTableSchema variablesSchema[] = {
+ {.name = "dnode_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
+ {.name = "name", .bytes = TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "value", .bytes = TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
};
static const SSysTableMeta infosMeta[] = {
@@ -248,11 +255,12 @@ static const SSysTableMeta infosMeta[] = {
{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_TABLE_DISTRIBUTED, userTblDistSchema, tListLen(userTblDistSchema)},
+ // {TSDB_INS_TABLE_USER_TABLE_DISTRIBUTED, userTblDistSchema, tListLen(userTblDistSchema)},
{TSDB_INS_TABLE_USER_USERS, userUsersSchema, tListLen(userUsersSchema)},
{TSDB_INS_TABLE_LICENCES, grantsSchema, tListLen(grantsSchema)},
{TSDB_INS_TABLE_VGROUPS, vgroupsSchema, tListLen(vgroupsSchema)},
{TSDB_INS_TABLE_CONFIGS, configSchema, tListLen(configSchema)},
+ {TSDB_INS_TABLE_DNODE_VARIABLES, variablesSchema, tListLen(variablesSchema)},
};
static const SSysDbTableSchema connectionsSchema[] = {
@@ -306,7 +314,7 @@ static const SSysDbTableSchema querySchema[] = {
{.name = "query_id", .bytes = TSDB_QUERY_ID_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "req_id", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
{.name = "connId", .bytes = 4, .type = TSDB_DATA_TYPE_UINT},
- {.name = "app", .bytes = TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "app", .bytes = TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "pid", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
{.name = "user", .bytes = TSDB_USER_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "end_point", .bytes = TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
@@ -322,17 +330,17 @@ static const SSysDbTableSchema appSchema[] = {
{.name = "app_id", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
{.name = "ip", .bytes = TSDB_IPv4ADDR_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "pid", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
- {.name = "name", .bytes = TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
- {.name = "start_time", .bytes = 8 , .type = TSDB_DATA_TYPE_TIMESTAMP},
- {.name = "insert_req", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "insert_row", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "insert_time", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "insert_bytes", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "fetch_bytes", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "query_time", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "show_query", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "total_req", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
- {.name = "current_req", .bytes = 8 , .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "name", .bytes = TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "start_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
+ {.name = "insert_req", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "insert_row", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "insert_time", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "insert_bytes", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "fetch_bytes", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "query_time", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "show_query", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "total_req", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
+ {.name = "current_req", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
{.name = "last_access", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
};
@@ -346,8 +354,7 @@ static const SSysTableMeta perfsMeta[] = {
{TSDB_PERFS_TABLE_TRANS, transSchema, tListLen(transSchema)},
{TSDB_PERFS_TABLE_SMAS, smaSchema, tListLen(smaSchema)},
{TSDB_PERFS_TABLE_STREAMS, streamSchema, tListLen(streamSchema)},
- {TSDB_PERFS_TABLE_APPS, appSchema, tListLen(appSchema)}
-};
+ {TSDB_PERFS_TABLE_APPS, appSchema, tListLen(appSchema)}};
void getInfosDbMeta(const SSysTableMeta** pInfosTableMeta, size_t* size) {
*pInfosTableMeta = infosMeta;
diff --git a/source/common/src/tdata.c b/source/common/src/tdata.c
deleted file mode 100644
index 6dea4a4e57392be988126c579648f39a8270b9bf..0000000000000000000000000000000000000000
--- a/source/common/src/tdata.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
\ No newline at end of file
diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c
index 3c3d3e953dc567f7f9edb83d56d6ff48dca9edf6..47cfa5d4106c5368105abe18d2970a05203e4d8d 100644
--- a/source/common/src/tdatablock.c
+++ b/source/common/src/tdatablock.c
@@ -110,7 +110,7 @@ int32_t getJsonValueLen(const char* data) {
dataLen = DOUBLE_BYTES + CHAR_BYTES;
} else if (*data == TSDB_DATA_TYPE_BOOL) {
dataLen = CHAR_BYTES + CHAR_BYTES;
- } else if (*data & TD_TAG_JSON) { // json string
+ } else if (tTagIsJson(data)) { // json string
dataLen = ((STag*)(data))->len;
} else {
ASSERT(0);
@@ -214,7 +214,7 @@ static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, c
}
}
-int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, int32_t* capacity,
+int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, uint32_t* capacity,
const SColumnInfoData* pSource, uint32_t numOfRow2) {
ASSERT(pColumnInfoData != NULL && pSource != NULL && pColumnInfoData->info.type == pSource->info.type);
if (numOfRow2 == 0) {
@@ -228,7 +228,7 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, in
uint32_t finalNumOfRows = numOfRow1 + numOfRow2;
if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
// Handle the bitmap
- if (finalNumOfRows > *capacity) {
+ if (finalNumOfRows > *capacity || numOfRow1 == 0) {
char* p = taosMemoryRealloc(pColumnInfoData->varmeta.offset, sizeof(int32_t) * (numOfRow1 + numOfRow2));
if (p == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -262,7 +262,8 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, in
memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len);
pColumnInfoData->varmeta.length = len + oldLen;
} else {
- if (finalNumOfRows > *capacity) {
+ if (finalNumOfRows > *capacity || numOfRow1 == 0) {
+ ASSERT(finalNumOfRows * pColumnInfoData->info.bytes);
char* tmp = taosMemoryRealloc(pColumnInfoData->pData, finalNumOfRows * pColumnInfoData->info.bytes);
if (tmp == NULL) {
return TSDB_CODE_VND_OUT_OF_MEMORY;
@@ -292,22 +293,19 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, in
return numOfRow1 + numOfRow2;
}
-int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows) {
+int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows,
+ const SDataBlockInfo* pBlockInfo) {
ASSERT(pColumnInfoData != NULL && pSource != NULL && pColumnInfoData->info.type == pSource->info.type);
if (numOfRows <= 0) {
return numOfRows;
}
- if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
- // Handle the bitmap
- char* p = taosMemoryRealloc(pColumnInfoData->varmeta.offset, sizeof(int32_t) * numOfRows);
- if (p == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
+ if (pBlockInfo != NULL) {
+ ASSERT(pBlockInfo->capacity >= numOfRows);
+ }
- pColumnInfoData->varmeta.offset = (int32_t*)p;
+ if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
memcpy(pColumnInfoData->varmeta.offset, pSource->varmeta.offset, sizeof(int32_t) * numOfRows);
-
if (pColumnInfoData->varmeta.allocLen < pSource->varmeta.length) {
char* tmp = taosMemoryRealloc(pColumnInfoData->pData, pSource->varmeta.length);
if (tmp == NULL) {
@@ -318,25 +316,11 @@ int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* p
pColumnInfoData->varmeta.allocLen = pSource->varmeta.length;
}
- memcpy(pColumnInfoData->pData, pSource->pData, pSource->varmeta.length);
pColumnInfoData->varmeta.length = pSource->varmeta.length;
+ memcpy(pColumnInfoData->pData, pSource->pData, pSource->varmeta.length);
} else {
- char* tmp = taosMemoryRealloc(pColumnInfoData->nullbitmap, BitmapLen(numOfRows));
- if (tmp == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- pColumnInfoData->nullbitmap = tmp;
memcpy(pColumnInfoData->nullbitmap, pSource->nullbitmap, BitmapLen(numOfRows));
-
if (pSource->pData) {
- int32_t newSize = numOfRows * pColumnInfoData->info.bytes;
- tmp = taosMemoryRealloc(pColumnInfoData->pData, newSize);
- if (tmp == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- pColumnInfoData->pData = tmp;
memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows);
}
}
@@ -346,10 +330,7 @@ int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* p
return 0;
}
-size_t blockDataGetNumOfCols(const SSDataBlock* pBlock) {
- ASSERT(pBlock && pBlock->info.numOfCols == taosArrayGetSize(pBlock->pDataBlock));
- return pBlock->info.numOfCols;
-}
+size_t blockDataGetNumOfCols(const SSDataBlock* pBlock) { return taosArrayGetSize(pBlock->pDataBlock); }
size_t blockDataGetNumOfRows(const SSDataBlock* pBlock) { return pBlock->info.rows; }
@@ -358,7 +339,8 @@ int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex)
return 0;
}
- if (pDataBlock->info.numOfCols <= 0) {
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
+ if (numOfCols <= 0) {
return -1;
}
@@ -382,7 +364,8 @@ int32_t blockDataMerge(SSDataBlock* pDest, const SSDataBlock* pSrc) {
assert(pSrc != NULL && pDest != NULL);
int32_t capacity = pDest->info.capacity;
- for (int32_t i = 0; i < pDest->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pDest->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
@@ -398,9 +381,8 @@ int32_t blockDataMerge(SSDataBlock* pDest, const SSDataBlock* pSrc) {
size_t blockDataGetSize(const SSDataBlock* pBlock) {
assert(pBlock != NULL);
- size_t total = 0;
- int32_t numOfCols = pBlock->info.numOfCols;
-
+ size_t total = 0;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
total += colDataGetFullLength(pColInfoData, pBlock->info.rows);
@@ -415,7 +397,7 @@ int32_t blockDataSplitRows(SSDataBlock* pBlock, bool hasVarCol, int32_t startInd
int32_t pageSize) {
ASSERT(pBlock != NULL && stopIndex != NULL);
- int32_t numOfCols = pBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
int32_t numOfRows = pBlock->info.rows;
int32_t bitmapChar = 1;
@@ -476,33 +458,25 @@ SSDataBlock* blockDataExtractBlock(SSDataBlock* pBlock, int32_t startIndex, int3
return NULL;
}
- SSDataBlock* pDst = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ SSDataBlock* pDst = createDataBlock();
if (pDst == NULL) {
return NULL;
}
pDst->info = pBlock->info;
-
pDst->info.rows = 0;
- pDst->pDataBlock = taosArrayInit(pBlock->info.numOfCols, sizeof(SColumnInfoData));
-
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ pDst->info.capacity = 0;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData colInfo = {0};
SColumnInfoData* pSrcCol = taosArrayGet(pBlock->pDataBlock, i);
colInfo.info = pSrcCol->info;
-
- if (IS_VAR_DATA_TYPE(pSrcCol->info.type)) {
- SVarColAttr* pAttr = &colInfo.varmeta;
- pAttr->offset = taosMemoryCalloc(rowCount, sizeof(int32_t));
- } else {
- colInfo.nullbitmap = taosMemoryCalloc(1, BitmapLen(rowCount));
- colInfo.pData = taosMemoryCalloc(rowCount, colInfo.info.bytes);
- }
-
- taosArrayPush(pDst->pDataBlock, &colInfo);
+ blockDataAppendColInfo(pDst, &colInfo);
}
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ blockDataEnsureCapacity(pDst, rowCount);
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
@@ -540,7 +514,7 @@ int32_t blockDataToBuf(char* buf, const SSDataBlock* pBlock) {
// write the number of rows
*(uint32_t*)buf = pBlock->info.rows;
- int32_t numOfCols = pBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
int32_t numOfRows = pBlock->info.rows;
char* pStart = buf + sizeof(uint32_t);
@@ -568,9 +542,11 @@ int32_t blockDataToBuf(char* buf, const SSDataBlock* pBlock) {
}
int32_t blockDataFromBuf(SSDataBlock* pBlock, const char* buf) {
- pBlock->info.rows = *(int32_t*)buf;
+ int32_t numOfRows = *(int32_t*) buf;
+ blockDataEnsureCapacity(pBlock, numOfRows);
- int32_t numOfCols = pBlock->info.numOfCols;
+ pBlock->info.rows = numOfRows;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
const char* pStart = buf + sizeof(uint32_t);
for (int32_t i = 0; i < numOfCols; ++i) {
@@ -615,11 +591,13 @@ int32_t blockDataFromBuf(SSDataBlock* pBlock, const char* buf) {
return TSDB_CODE_SUCCESS;
}
+// todo remove this
int32_t blockDataFromBuf1(SSDataBlock* pBlock, const char* buf, size_t capacity) {
pBlock->info.rows = *(int32_t*)buf;
pBlock->info.groupId = *(uint64_t*)(buf + sizeof(int32_t));
- int32_t numOfCols = pBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+
const char* pStart = buf + sizeof(uint32_t) + sizeof(uint64_t);
for (int32_t i = 0; i < numOfCols; ++i) {
@@ -665,7 +643,7 @@ size_t blockDataGetRowSize(SSDataBlock* pBlock) {
if (pBlock->info.rowSize == 0) {
size_t rowSize = 0;
- size_t numOfCols = pBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
rowSize += pColInfo->info.bytes;
@@ -692,7 +670,7 @@ double blockDataGetSerialRowSize(const SSDataBlock* pBlock) {
ASSERT(pBlock != NULL);
double rowSize = 0;
- size_t numOfCols = pBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
rowSize += pColInfo->info.bytes;
@@ -744,7 +722,12 @@ int32_t dataBlockCompar(const void* p1, const void* p2, const void* param) {
void* left1 = colDataGetData(pColInfoData, left);
void* right1 = colDataGetData(pColInfoData, right);
-
+ if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
+ if (tTagIsJson(left1) || tTagIsJson(right1)) {
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return 0;
+ }
+ }
__compar_fn_t fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
int ret = fn(left1, right1);
@@ -761,7 +744,7 @@ int32_t dataBlockCompar(const void* p1, const void* p2, const void* param) {
static int32_t doAssignOneTuple(SColumnInfoData* pDstCols, int32_t numOfRows, const SSDataBlock* pSrcBlock,
int32_t tupleIndex) {
int32_t code = 0;
- int32_t numOfCols = pSrcBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pSrcBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pDst = &pDstCols[i];
@@ -784,7 +767,7 @@ static int32_t doAssignOneTuple(SColumnInfoData* pDstCols, int32_t numOfRows, co
return TSDB_CODE_SUCCESS;
}
-static int32_t blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataBlock, int32_t* index) {
+static int32_t blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataBlock, const int32_t* index) {
#if 0
for (int32_t i = 0; i < pDataBlock->info.rows; ++i) {
int32_t code = doAssignOneTuple(pCols, i, pDataBlock, index[i]);
@@ -793,7 +776,8 @@ static int32_t blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataB
}
}
#else
- for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pDst = &pCols[i];
SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
@@ -820,7 +804,7 @@ static int32_t blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataB
static SColumnInfoData* createHelpColInfoData(const SSDataBlock* pDataBlock) {
int32_t rows = pDataBlock->info.rows;
- int32_t numOfCols = pDataBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
SColumnInfoData* pCols = taosMemoryCalloc(numOfCols, sizeof(SColumnInfoData));
if (pCols == NULL) {
@@ -847,7 +831,7 @@ static SColumnInfoData* createHelpColInfoData(const SSDataBlock* pDataBlock) {
}
static void copyBackToBlock(SSDataBlock* pDataBlock, SColumnInfoData* pCols) {
- int32_t numOfCols = pDataBlock->info.numOfCols;
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, i);
@@ -908,8 +892,10 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
}
}
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
+
if (taosArrayGetSize(pOrderInfo) == 1 && (!sortColumnHasNull)) {
- if (pDataBlock->info.numOfCols == 1) {
+ if (numOfCols == 1) {
if (!varTypeSort) {
SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, 0);
SBlockOrderInfo* pOrder = taosArrayGet(pOrderInfo, 0);
@@ -917,7 +903,7 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
int64_t p0 = taosGetTimestampUs();
__compar_fn_t fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
- qsort(pColInfoData->pData, pDataBlock->info.rows, pColInfoData->info.bytes, fn);
+ taosSort(pColInfoData->pData, pDataBlock->info.rows, pColInfoData->info.bytes, fn);
int64_t p1 = taosGetTimestampUs();
uDebug("blockDataSort easy cost:%" PRId64 ", rows:%d\n", p1 - p0, pDataBlock->info.rows);
@@ -925,7 +911,7 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
return TSDB_CODE_SUCCESS;
} else { // var data type
}
- } else if (pDataBlock->info.numOfCols == 2) {
+ } else if (numOfCols == 2) {
}
}
@@ -943,7 +929,9 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
pInfo->pColData = taosArrayGet(pDataBlock->pDataBlock, pInfo->slotId);
}
+ terrno = 0;
taosqsort(index, rows, sizeof(int32_t), &helper, dataBlockCompar);
+ if (terrno) return terrno;
int64_t p1 = taosGetTimestampUs();
@@ -1119,33 +1107,39 @@ int32_t blockDataSort_rv(SSDataBlock* pDataBlock, SArray* pOrderInfo, bool nullF
void blockDataCleanup(SSDataBlock* pDataBlock) {
pDataBlock->info.rows = 0;
- for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
colInfoDataCleanup(p, pDataBlock->info.capacity);
}
}
-int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, size_t existRows, uint32_t numOfRows) {
- if (0 == numOfRows || numOfRows <= existRows) {
+static int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* pBlockInfo, uint32_t numOfRows) {
+ ASSERT(numOfRows > 0 && pBlockInfo->capacity >= pBlockInfo->rows);
+ if (numOfRows < pBlockInfo->capacity) {
return TSDB_CODE_SUCCESS;
}
+ // todo temp disable it
+ // ASSERT(pColumn->info.bytes != 0);
+
+ int32_t existedRows = pBlockInfo->rows;
+
if (IS_VAR_DATA_TYPE(pColumn->info.type)) {
char* tmp = taosMemoryRealloc(pColumn->varmeta.offset, sizeof(int32_t) * numOfRows);
-
if (tmp == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
pColumn->varmeta.offset = (int32_t*)tmp;
- memset(&pColumn->varmeta.offset[existRows], 0, sizeof(int32_t) * (numOfRows - existRows));
+ memset(&pColumn->varmeta.offset[existedRows], 0, sizeof(int32_t) * (numOfRows - existedRows));
} else {
char* tmp = taosMemoryRealloc(pColumn->nullbitmap, BitmapLen(numOfRows));
if (tmp == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- int32_t oldLen = BitmapLen(existRows);
+ int32_t oldLen = BitmapLen(existedRows);
pColumn->nullbitmap = tmp;
memset(&pColumn->nullbitmap[oldLen], 0, BitmapLen(numOfRows) - oldLen);
@@ -1158,8 +1152,8 @@ int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, size_t existRows, ui
if (tmp == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- memset(tmp + pColumn->info.bytes * existRows, 0, pColumn->info.bytes * (numOfRows - existRows));
+ memset(tmp + pColumn->info.bytes * existedRows, 0, pColumn->info.bytes * (numOfRows - existedRows));
pColumn->pData = tmp;
}
@@ -1176,17 +1170,25 @@ void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) {
}
}
+int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, uint32_t numOfRows) {
+ SDataBlockInfo info = {0};
+ return doEnsureCapacity(pColumn, &info, numOfRows);
+}
+
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows) {
int32_t code = 0;
if (numOfRows == 0) {
return TSDB_CODE_SUCCESS;
}
- pDataBlock->info.capacity = numOfRows;
+ if (pDataBlock->info.capacity < numOfRows) {
+ pDataBlock->info.capacity = numOfRows;
+ }
- for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
- code = colInfoDataEnsureCapacity(p, pDataBlock->info.rows, numOfRows);
+ code = doEnsureCapacity(p, &pDataBlock->info, numOfRows);
if (code) {
return code;
}
@@ -1195,55 +1197,123 @@ int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows) {
return TSDB_CODE_SUCCESS;
}
+void blockDataFreeRes(SSDataBlock* pBlock) {
+ int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfOutput; ++i) {
+ SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
+ colDataDestroy(pColInfoData);
+ }
+
+ taosArrayDestroy(pBlock->pDataBlock);
+ taosMemoryFreeClear(pBlock->pBlockAgg);
+ memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
+}
+
void* blockDataDestroy(SSDataBlock* pBlock) {
if (pBlock == NULL) {
return NULL;
}
- blockDestroyInner(pBlock);
+ blockDataFreeRes(pBlock);
taosMemoryFreeClear(pBlock);
return NULL;
}
+int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
+ ASSERT(src != NULL);
+
+ dst->info = src->info;
+ dst->info.rows = 0;
+ dst->info.capacity = 0;
+
+ size_t numOfCols = taosArrayGetSize(src->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* p = taosArrayGet(src->pDataBlock, i);
+ SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
+ blockDataAppendColInfo(dst, &colInfo);
+ }
+
+ int32_t code = blockDataEnsureCapacity(dst, src->info.rows);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return -1;
+ }
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* pDst = taosArrayGet(dst->pDataBlock, i);
+ SColumnInfoData* pSrc = taosArrayGet(src->pDataBlock, i);
+ if (pSrc->pData == NULL && (!IS_VAR_DATA_TYPE(pSrc->info.type))) {
+ continue;
+ }
+
+ colDataAssign(pDst, pSrc, src->info.rows, &src->info);
+ }
+
+ dst->info.rows = src->info.rows;
+ dst->info.capacity = src->info.rows;
+ return 0;
+}
+
+int32_t copyDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
+ ASSERT(src != NULL && dst != NULL);
+
+ blockDataCleanup(dst);
+ int32_t code = blockDataEnsureCapacity(dst, src->info.rows);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return code;
+ }
+
+ size_t numOfCols = taosArrayGetSize(src->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* pDst = taosArrayGet(dst->pDataBlock, i);
+ SColumnInfoData* pSrc = taosArrayGet(src->pDataBlock, i);
+ if (pSrc->pData == NULL) {
+ continue;
+ }
+
+ 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;
+ return TSDB_CODE_SUCCESS;
+}
+
SSDataBlock* createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData) {
if (pDataBlock == NULL) {
return NULL;
}
- int32_t numOfCols = pDataBlock->info.numOfCols;
-
- SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
- pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
-
- pBlock->info.numOfCols = numOfCols;
- pBlock->info.hasVarCol = pDataBlock->info.hasVarCol;
- pBlock->info.rowSize = pDataBlock->info.rowSize;
- pBlock->info.groupId = pDataBlock->info.groupId;
- pBlock->info.childId = pDataBlock->info.childId;
- pBlock->info.type = pDataBlock->info.type;
+ SSDataBlock* pBlock = createDataBlock();
+ pBlock->info = pDataBlock->info;
+ pBlock->info.rows = 0;
+ pBlock->info.capacity = 0;
+ size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData colInfo = {0};
SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
- colInfo.info = p->info;
- colInfo.hasNull = true;
- taosArrayPush(pBlock->pDataBlock, &colInfo);
+ SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
+ blockDataAppendColInfo(pBlock, &colInfo);
}
if (copyData) {
+ int32_t code = blockDataEnsureCapacity(pBlock, pDataBlock->info.rows);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ blockDataDestroy(pBlock);
+ return NULL;
+ }
+
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
-
- int32_t code = colInfoDataEnsureCapacity(pDst, 0, pDataBlock->info.rows);
- if (code != TSDB_CODE_SUCCESS) {
- return NULL;
- }
-
if (pSrc->pData == NULL) {
continue;
}
- colDataAssign(pDst, pSrc, pDataBlock->info.rows);
+
+ colDataAssign(pDst, pSrc, pDataBlock->info.rows, &pDataBlock->info);
}
pBlock->info.rows = pDataBlock->info.rows;
@@ -1253,16 +1323,75 @@ SSDataBlock* createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData) {
return pBlock;
}
+SSDataBlock* createDataBlock() {
+ SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ if (pBlock == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
+ if (pBlock->pDataBlock == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ taosMemoryFree(pBlock);
+ }
+
+ return pBlock;
+}
+
+int32_t blockDataAppendColInfo(SSDataBlock* pBlock, SColumnInfoData* pColInfoData) {
+ ASSERT(pBlock != NULL && pColInfoData != NULL);
+ if (pBlock->pDataBlock == NULL) {
+ pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
+ if (pBlock->pDataBlock == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
+ }
+ }
+
+ void* p = taosArrayPush(pBlock->pDataBlock, pColInfoData);
+ if (p == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
+ }
+
+ // todo disable it temporarily
+ // ASSERT(pColInfoData->info.type != 0);
+ if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
+ pBlock->info.hasVarCol = true;
+ }
+
+ pBlock->info.rowSize += pColInfoData->info.bytes;
+ return TSDB_CODE_SUCCESS;
+}
+
+SColumnInfoData createColumnInfoData(int16_t type, int32_t bytes, int16_t colId) {
+ SColumnInfoData col = {.hasNull = true};
+ col.info.colId = colId;
+ col.info.type = type;
+ col.info.bytes = bytes;
+
+ return col;
+}
+
+SColumnInfoData* bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index) {
+ ASSERT(pBlock != NULL);
+ if (index >= taosArrayGetSize(pBlock->pDataBlock)) {
+ return NULL;
+ }
+
+ return taosArrayGet(pBlock->pDataBlock, index);
+}
+
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize) {
- int32_t payloadSize = pageSize - blockDataGetSerialMetaSize(pBlock->info.numOfCols);
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ int32_t payloadSize = pageSize - blockDataGetSerialMetaSize(numOfCols);
int32_t rowSize = pBlock->info.rowSize;
-
int32_t nRows = payloadSize / rowSize;
// the true value must be less than the value of nRows
int32_t additional = 0;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
if (IS_VAR_DATA_TYPE(pCol->info.type)) {
additional += nRows * sizeof(int32_t);
@@ -1327,9 +1456,39 @@ static void doShiftBitmap(char* nullBitmap, size_t n, size_t total) {
}
}
+static int32_t colDataMoveVarData(SColumnInfoData* pColInfoData, size_t start, size_t end) {
+ int32_t dataOffset = -1;
+ int32_t dataLen = 0;
+ int32_t beigin = start;
+ while (beigin < end) {
+ int32_t offset = pColInfoData->varmeta.offset[beigin];
+ if (offset == -1) {
+ beigin++;
+ continue;
+ }
+ if (start != 0) {
+ pColInfoData->varmeta.offset[beigin] = dataLen;
+ }
+ char* data = pColInfoData->pData + offset;
+ if (dataOffset == -1) dataOffset = offset; // mark the begin of data
+ int32_t type = pColInfoData->info.type;
+ if (type == TSDB_DATA_TYPE_JSON) {
+ dataLen += getJsonValueLen(data);
+ } else {
+ dataLen += varDataTLen(data);
+ }
+ beigin++;
+ }
+ if (dataOffset > 0) {
+ memmove(pColInfoData->pData, pColInfoData->pData + dataOffset, dataLen);
+ memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[start], (end - start) * sizeof(int32_t));
+ }
+ return dataLen;
+}
+
static void colDataTrimFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
- memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[n], (total - n) * sizeof(int32_t));
+ pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, n, total);
memset(&pColInfoData->varmeta.offset[total - n], 0, n);
} else {
int32_t bytes = pColInfoData->info.bytes;
@@ -1346,7 +1505,8 @@ int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n) {
if (pBlock->info.rows <= n) {
blockDataCleanup(pBlock);
} else {
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
colDataTrimFirstNRows(pColInfoData, n, pBlock->info.rows);
}
@@ -1356,9 +1516,36 @@ int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n) {
return TSDB_CODE_SUCCESS;
}
+static void colDataKeepFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
+ if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
+ pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, 0, n);
+ memset(&pColInfoData->varmeta.offset[n], 0, total - n);
+ }
+}
+
+int32_t blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n) {
+ if (n == 0) {
+ blockDataCleanup(pBlock);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (pBlock->info.rows <= n) {
+ return TSDB_CODE_SUCCESS;
+ } else {
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ colDataKeepFirstNRows(pColInfoData, n, pBlock->info.rows);
+ }
+
+ pBlock->info.rows = n;
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock) {
int64_t tbUid = pBlock->info.uid;
- int16_t numOfCols = pBlock->info.numOfCols;
+ int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
int16_t hasVarCol = pBlock->info.hasVarCol;
int32_t rows = pBlock->info.rows;
int32_t sz = taosArrayGetSize(pBlock->pDataBlock);
@@ -1393,8 +1580,10 @@ int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock) {
void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) {
int32_t sz;
- buf = taosDecodeFixedI64(buf, &pBlock->info.uid);
- buf = taosDecodeFixedI16(buf, &pBlock->info.numOfCols);
+ int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+
+ buf = taosDecodeFixedU64(buf, &pBlock->info.uid);
+ buf = taosDecodeFixedI16(buf, &numOfCols);
buf = taosDecodeFixedI16(buf, &pBlock->info.hasVarCol);
buf = taosDecodeFixedI32(buf, &pBlock->info.rows);
buf = taosDecodeFixedI32(buf, &sz);
@@ -1498,17 +1687,26 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
return buf;
}
-void blockDebugShowData(const SArray* dataBlocks, const char* flag) {
+void blockDebugShowDataBlock(SSDataBlock* pBlock, const char* flag) {
+ SArray* dataBlocks = taosArrayInit(1, sizeof(SSDataBlock));
+ taosArrayPush(dataBlocks, pBlock);
+ blockDebugShowDataBlocks(dataBlocks, flag);
+ taosArrayDestroy(dataBlocks);
+}
+
+void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) {
char pBuf[128] = {0};
int32_t sz = taosArrayGetSize(dataBlocks);
for (int32_t i = 0; i < sz; i++) {
SSDataBlock* pDataBlock = taosArrayGet(dataBlocks, i);
- int32_t colNum = pDataBlock->info.numOfCols;
- int32_t rows = pDataBlock->info.rows;
- printf("%s |block type %d |child id %d|\n", flag, (int32_t)pDataBlock->info.type, pDataBlock->info.childId);
+ 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);
for (int32_t j = 0; j < rows; j++) {
printf("%s |", flag);
- for (int32_t k = 0; k < colNum; k++) {
+ for (int32_t k = 0; k < numOfCols; k++) {
SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes);
if (colDataIsNull(pColInfoData, rows, j, NULL)) {
@@ -1545,6 +1743,71 @@ void blockDebugShowData(const SArray* dataBlocks, const char* flag) {
}
}
+// for debug
+char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) {
+ int32_t size = 2048;
+ *pDataBuf = taosMemoryCalloc(size, 1);
+ char* dumpBuf = *pDataBuf;
+ char pBuf[128] = {0};
+ int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
+ int32_t rows = pDataBlock->info.rows;
+ int32_t len = 0;
+ len += snprintf(dumpBuf + len, size - len, "\n%s |block type %d |child id %d|group id:%" PRIu64 "| uid:%ld\n", flag,
+ (int32_t)pDataBlock->info.type, pDataBlock->info.childId, pDataBlock->info.groupId,
+ pDataBlock->info.uid);
+ if (len >= size - 1) return dumpBuf;
+
+ for (int32_t j = 0; j < rows; j++) {
+ len += snprintf(dumpBuf + len, size - len, "%s |", flag);
+ if (len >= size - 1) return dumpBuf;
+
+ for (int32_t k = 0; k < colNum; k++) {
+ SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
+ void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes);
+ if (colDataIsNull(pColInfoData, rows, j, NULL) || !pColInfoData->pData) {
+ len += snprintf(dumpBuf + len, size - len, " %15s |", "NULL");
+ if (len >= size - 1) return dumpBuf;
+ continue;
+ }
+ switch (pColInfoData->info.type) {
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ formatTimestamp(pBuf, *(uint64_t*)var, TSDB_TIME_PRECISION_MILLI);
+ len += snprintf(dumpBuf + len, size - len, " %25s |", pBuf);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_INT:
+ len += snprintf(dumpBuf + len, size - len, " %15d |", *(int32_t*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_UINT:
+ len += snprintf(dumpBuf + len, size - len, " %15u |", *(uint32_t*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_BIGINT:
+ len += snprintf(dumpBuf + len, size - len, " %15ld |", *(int64_t*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_UBIGINT:
+ len += snprintf(dumpBuf + len, size - len, " %15lu |", *(uint64_t*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_FLOAT:
+ len += snprintf(dumpBuf + len, size - len, " %15f |", *(float*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ case TSDB_DATA_TYPE_DOUBLE:
+ len += snprintf(dumpBuf + len, size - len, " %15lf |", *(double*)var);
+ if (len >= size - 1) return dumpBuf;
+ break;
+ }
+ }
+ len += snprintf(dumpBuf + len, size - len, "\n");
+ if (len >= size - 1) return dumpBuf;
+ }
+ len += snprintf(dumpBuf + len, size - len, "%s |end\n", flag);
+ return dumpBuf;
+}
+
/**
* @brief TODO: Assume that the final generated result it less than 3M
*
@@ -1561,7 +1824,9 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks
int32_t bufSize = sizeof(SSubmitReq);
for (int32_t i = 0; i < sz; ++i) {
SDataBlockInfo* pBlkInfo = &((SSDataBlock*)taosArrayGet(pDataBlocks, i))->info;
- bufSize += pBlkInfo->rows * (TD_ROW_HEAD_LEN + pBlkInfo->rowSize + BitmapLen(pBlkInfo->numOfCols));
+
+ int32_t numOfCols = taosArrayGetSize(pDataBlocks);
+ bufSize += pBlkInfo->rows * (TD_ROW_HEAD_LEN + pBlkInfo->rowSize + BitmapLen(numOfCols));
bufSize += sizeof(SSubmitBlk);
}
@@ -1579,10 +1844,10 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks
for (int32_t i = 0; i < sz; ++i) {
SSDataBlock* pDataBlock = taosArrayGet(pDataBlocks, i);
- int32_t colNum = pDataBlock->info.numOfCols;
+ int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
int32_t rows = pDataBlock->info.rows;
- int32_t rowSize = pDataBlock->info.rowSize;
- int64_t groupId = pDataBlock->info.groupId;
+ // int32_t rowSize = pDataBlock->info.rowSize;
+ // int64_t groupId = pDataBlock->info.groupId;
if (colNum <= 1) {
// invalid if only with TS col
@@ -1597,6 +1862,7 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks
pSubmitBlk->suid = suid;
pSubmitBlk->uid = pDataBlock->info.groupId;
pSubmitBlk->numOfRows = rows;
+ pSubmitBlk->sversion = pTSchema->version;
msgLen += sizeof(SSubmitBlk);
int32_t dataLen = 0;
@@ -1741,8 +2007,7 @@ char* buildCtbNameByGroupId(const char* stbName, uint64_t groupId) {
return rname.childTableName;
}
-void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols,
- int8_t needCompress) {
+void blockEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols, int8_t needCompress) {
// todo extract method
int32_t* actualLen = (int32_t*)data;
data += sizeof(int32_t);
@@ -1752,6 +2017,7 @@ void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+
*((int16_t*)data) = pColInfoData->info.type;
data += sizeof(int16_t);
@@ -1799,9 +2065,7 @@ void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen
*groupId = pBlock->info.groupId;
}
-const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData) {
- blockDataEnsureCapacity(pBlock, numOfRows);
-
+const char* blockDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData) {
const char* pStart = pData;
int32_t dataLen = *(int32_t*)pStart;
@@ -1815,9 +2079,6 @@ const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t
taosArraySetSize(pBlock->pDataBlock, numOfCols);
}
- pBlock->info.numOfCols = taosArrayGetSize(pBlock->pDataBlock);
- ASSERT(pBlock->pDataBlock->size >= numOfCols);
-
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
pColInfoData->info.type = *(int16_t*)pStart;
@@ -1842,28 +2103,26 @@ const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
- pColInfoData->varmeta.length = colLen[i];
- pColInfoData->varmeta.allocLen = colLen[i];
-
memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
pStart += sizeof(int32_t) * numOfRows;
- if (colLen[i] > 0) {
- taosMemoryFreeClear(pColInfoData->pData);
- pColInfoData->pData = taosMemoryMalloc(colLen[i]);
+ if (colLen[i] > 0 && pColInfoData->varmeta.allocLen < colLen[i]) {
+ char* tmp = taosMemoryRealloc(pColInfoData->pData, colLen[i]);
+ if (tmp == NULL) {
+ return NULL;
+ }
+
+ pColInfoData->pData = tmp;
+ pColInfoData->varmeta.allocLen = colLen[i];
}
+
+ pColInfoData->varmeta.length = colLen[i];
} else {
- if (pColInfoData->nullbitmap == NULL) {
- pColInfoData->nullbitmap = taosMemoryCalloc(1, BitmapLen(numOfRows));
- }
memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
pStart += BitmapLen(numOfRows);
}
if (colLen[i] > 0) {
- if (pColInfoData->pData == NULL) {
- pColInfoData->pData = taosMemoryCalloc(1, colLen[i]);
- }
memcpy(pColInfoData->pData, pStart, colLen[i]);
}
@@ -1878,3 +2137,4 @@ const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t
ASSERT(pStart - pData == dataLen);
return pStart;
}
+
diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c
index 1ddb606ccfa2f721e5de4b704a2c63ff2fd4fe6e..8eeab77a157993bd8d89479b221982d3b1e5c336 100644
--- a/source/common/src/tdataformat.c
+++ b/source/common/src/tdataformat.c
@@ -29,15 +29,9 @@ typedef struct {
#pragma pack(pop)
#define TSROW_IS_KV_ROW(r) ((r)->flags & TSROW_KV_ROW)
-#define BIT1_SIZE(n) (((n)-1) / 8 + 1)
-#define BIT2_SIZE(n) (((n)-1) / 4 + 1)
-#define SET_BIT1(p, i, v) ((p)[(i) / 8] = (p)[(i) / 8] & (~(((uint8_t)1) << ((i) % 8))) | ((v) << ((i) % 8)))
-#define SET_BIT2(p, i, v) ((p)[(i) / 4] = (p)[(i) / 4] & (~(((uint8_t)3) << ((i) % 4))) | ((v) << ((i) % 4)))
-#define GET_BIT1(p, i) (((p)[(i) / 8] >> ((i) % 8)) & ((uint8_t)1))
-#define GET_BIT2(p, i) (((p)[(i) / 4] >> ((i) % 4)) & ((uint8_t)3))
// SValue
-static FORCE_INLINE int32_t tPutValue(uint8_t *p, SValue *pValue, int8_t type) {
+int32_t tPutValue(uint8_t *p, SValue *pValue, int8_t type) {
int32_t n = 0;
if (IS_VAR_DATA_TYPE(type)) {
@@ -88,7 +82,7 @@ static FORCE_INLINE int32_t tPutValue(uint8_t *p, SValue *pValue, int8_t type) {
return n;
}
-static FORCE_INLINE int32_t tGetValue(uint8_t *p, SValue *pValue, int8_t type) {
+int32_t tGetValue(uint8_t *p, SValue *pValue, int8_t type) {
int32_t n = 0;
if (IS_VAR_DATA_TYPE(type)) {
@@ -181,7 +175,8 @@ static void setBitMap(uint8_t *pb, uint8_t v, int32_t idx, uint8_t flags) {
} while (0)
int32_t tTSRowNew(STSRowBuilder *pBuilder, SArray *pArray, STSchema *pTSchema, STSRow2 **ppRow) {
- int32_t code = 0;
+ int32_t code = 0;
+#if 0
STColumn *pTColumn;
SColVal *pColVal;
int32_t nColVal = taosArrayGetSize(pArray);
@@ -421,7 +416,7 @@ int32_t tTSRowNew(STSRowBuilder *pBuilder, SArray *pArray, STSchema *pTSchema, S
_set_none:
if ((flags & 0xf0) == 0) {
setBitMap(pb, 0, iColumn - 1, flags);
- if (flags & TSROW_HAS_VAL) { // set 0
+ if (flags & TSROW_HAS_VAL) { // set 0
if (IS_VAR_DATA_TYPE(pTColumn->type)) {
*(VarDataOffsetT *)(pf + pTColumn->offset) = 0;
} else {
@@ -434,7 +429,7 @@ int32_t tTSRowNew(STSRowBuilder *pBuilder, SArray *pArray, STSchema *pTSchema, S
_set_null:
if ((flags & 0xf0) == 0) {
setBitMap(pb, 1, iColumn - 1, flags);
- if (flags & TSROW_HAS_VAL) { // set 0
+ if (flags & TSROW_HAS_VAL) { // set 0
if (IS_VAR_DATA_TYPE(pTColumn->type)) {
*(VarDataOffsetT *)(pf + pTColumn->offset) = 0;
} else {
@@ -468,30 +463,22 @@ int32_t tTSRowNew(STSRowBuilder *pBuilder, SArray *pArray, STSchema *pTSchema, S
}
}
+#endif
_exit:
return code;
}
int32_t tTSRowClone(const STSRow2 *pRow, STSRow2 **ppRow) {
int32_t code = 0;
+ int32_t rLen;
- (*ppRow) = (STSRow2 *)taosMemoryMalloc(sizeof(**ppRow));
+ TSROW_LEN(pRow, rLen);
+ (*ppRow) = (STSRow2 *)taosMemoryMalloc(rLen);
if (*ppRow == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
goto _exit;
}
- **ppRow = *pRow;
- (*ppRow)->pData = NULL;
-
- if (pRow->nData) {
- (*ppRow)->pData = taosMemoryMalloc(pRow->nData);
- if ((*ppRow)->pData == NULL) {
- taosMemoryFree(*ppRow);
- code = TSDB_CODE_OUT_OF_MEMORY;
- goto _exit;
- }
- memcpy((*ppRow)->pData, pRow->pData, pRow->nData);
- }
+ memcpy(*ppRow, pRow, rLen);
_exit:
return code;
@@ -499,12 +486,12 @@ _exit:
void tTSRowFree(STSRow2 *pRow) {
if (pRow) {
- if (pRow->pData) taosMemoryFree(pRow->pData);
taosMemoryFree(pRow);
}
}
void tTSRowGet(STSRow2 *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) {
+#if 0
uint8_t isTuple = ((pRow->flags & 0xf0) == 0) ? 1 : 0;
STColumn *pTColumn = &pTSchema->columns[iCol];
uint8_t flags = pRow->flags & (uint8_t)0xf;
@@ -639,20 +626,22 @@ void tTSRowGet(STSRow2 *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal
}
_return_none:
- *pColVal = COL_VAL_NONE(pTColumn->colId);
+ *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type);
return;
_return_null:
- *pColVal = COL_VAL_NULL(pTColumn->colId);
+ *pColVal = COL_VAL_NULL(pTColumn->colId, pTColumn->type);
return;
_return_value:
- *pColVal = COL_VAL_VALUE(pTColumn->colId, value);
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, value);
return;
+#endif
}
int32_t tTSRowToArray(STSRow2 *pRow, STSchema *pTSchema, SArray **ppArray) {
int32_t code = 0;
+#if 0
SColVal cv;
(*ppArray) = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal));
@@ -666,52 +655,27 @@ int32_t tTSRowToArray(STSRow2 *pRow, STSchema *pTSchema, SArray **ppArray) {
taosArrayPush(*ppArray, &cv);
}
+#endif
_exit:
return code;
}
int32_t tPutTSRow(uint8_t *p, STSRow2 *pRow) {
- int32_t n = 0;
-
- n += tPutI64(p ? p + n : p, pRow->ts);
- n += tPutI8(p ? p + n : p, pRow->flags);
- n += tPutI32v(p ? p + n : p, pRow->sver);
+ int32_t n;
- ASSERT(pRow->flags & 0xf);
-
- switch (pRow->flags & 0xf) {
- case TSROW_HAS_NONE:
- case TSROW_HAS_NULL:
- ASSERT(pRow->nData == 0);
- ASSERT(pRow->pData == NULL);
- break;
- default:
- ASSERT(pRow->nData && pRow->pData);
- n += tPutBinary(p ? p + n : p, pRow->pData, pRow->nData);
- break;
+ TSROW_LEN(pRow, n);
+ if (p) {
+ memcpy(p, pRow, n);
}
return n;
}
-int32_t tGetTSRow(uint8_t *p, STSRow2 *pRow) {
- int32_t n = 0;
-
- n += tGetI64(p + n, &pRow->ts);
- n += tGetI8(p + n, &pRow->flags);
- n += tGetI32v(p + n, &pRow->sver);
+int32_t tGetTSRow(uint8_t *p, STSRow2 **ppRow) {
+ int32_t n;
- ASSERT(pRow->flags);
- switch (pRow->flags & 0xf) {
- case TSROW_HAS_NONE:
- case TSROW_HAS_NULL:
- pRow->nData = 0;
- pRow->pData = NULL;
- break;
- default:
- n += tGetBinary(p + n, &pRow->pData, &pRow->nData);
- break;
- }
+ *ppRow = (STSRow2 *)p;
+ TSROW_LEN(*ppRow, n);
return n;
}
@@ -862,21 +826,6 @@ void debugPrintSTag(STag *pTag, const char *tag, int32_t ln) {
printf("\n");
}
-void debugCheckTags(STag *pTag) {
- switch (pTag->flags) {
- case 0x0:
- case 0x20:
- case 0x40:
- case 0x60:
- break;
- default:
- ASSERT(0);
- }
-
- ASSERT(pTag->nTag <= 128 && pTag->nTag >= 0);
- ASSERT(pTag->ver <= 512 && pTag->ver >= 0); // temp condition for pTag->ver
-}
-
static int32_t tPutTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson) {
int32_t n = 0;
@@ -924,6 +873,16 @@ static int32_t tGetTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson) {
return n;
}
+
+bool tTagIsJson(const void *pTag) { return (((const STag *)pTag)->flags & TD_TAG_JSON); }
+
+bool tTagIsJsonNull(void *data) {
+ STag *pTag = (STag *)data;
+ int8_t isJson = tTagIsJson(pTag);
+ if (!isJson) return false;
+ return ((STag *)data)->nTag == 0;
+}
+
int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag) {
int32_t code = 0;
uint8_t *p = NULL;
@@ -934,9 +893,9 @@ int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag) {
// sort
if (isJson) {
- qsort(pArray->pData, nTag, sizeof(STagVal), tTagValJsonCmprFn);
+ taosSort(pArray->pData, nTag, sizeof(STagVal), tTagValJsonCmprFn);
} else {
- qsort(pArray->pData, nTag, sizeof(STagVal), tTagValCmprFn);
+ taosSort(pArray->pData, nTag, sizeof(STagVal), tTagValCmprFn);
}
// get size
@@ -987,7 +946,6 @@ int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag) {
debugPrintSTag(*ppTag, __func__, __LINE__);
#endif
- debugCheckTags(*ppTag); // TODO: remove this line after debug
return code;
_err:
@@ -1107,112 +1065,6 @@ _err:
}
#if 1 // ===================================================================================================================
-static void dataColSetNEleNull(SDataCol *pCol, int nEle);
-int tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
- int spaceNeeded = pCol->bytes * maxPoints;
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- spaceNeeded += sizeof(VarDataOffsetT) * maxPoints;
- }
-#ifdef TD_SUPPORT_BITMAP
- int32_t nBitmapBytes = (int32_t)TD_BITMAP_BYTES(maxPoints);
- spaceNeeded += (int)nBitmapBytes;
- // TODO: Currently, the compression of bitmap parts is affiliated to the column data parts, thus allocate 1 more
- // TYPE_BYTES as to comprise complete TYPE_BYTES. Otherwise, invalid read/write would be triggered.
- // spaceNeeded += TYPE_BYTES[pCol->type]; // the bitmap part is append as a single part since 2022.04.03, thus
- // remove the additional space
-#endif
-
- if (pCol->spaceSize < spaceNeeded) {
- void *ptr = taosMemoryRealloc(pCol->pData, spaceNeeded);
- if (ptr == NULL) {
- uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)spaceNeeded, strerror(errno));
- return -1;
- } else {
- pCol->pData = ptr;
- pCol->spaceSize = spaceNeeded;
- }
- }
-#ifdef TD_SUPPORT_BITMAP
-
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pCol->pBitmap = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
- pCol->dataOff = POINTER_SHIFT(pCol->pBitmap, nBitmapBytes);
- } else {
- pCol->pBitmap = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
- }
-#else
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pCol->dataOff = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
- }
-#endif
- return 0;
-}
-
-/**
- * Duplicate the schema and return a new object
- */
-STSchema *tdDupSchema(const STSchema *pSchema) {
- int tlen = sizeof(STSchema) + sizeof(STColumn) * schemaNCols(pSchema);
- STSchema *tSchema = (STSchema *)taosMemoryMalloc(tlen);
- if (tSchema == NULL) return NULL;
-
- memcpy((void *)tSchema, (void *)pSchema, tlen);
-
- return tSchema;
-}
-
-/**
- * Encode a schema to dst, and return the next pointer
- */
-int tdEncodeSchema(void **buf, STSchema *pSchema) {
- int tlen = 0;
- tlen += taosEncodeFixedI32(buf, schemaVersion(pSchema));
- tlen += taosEncodeFixedI32(buf, schemaNCols(pSchema));
-
- for (int i = 0; i < schemaNCols(pSchema); i++) {
- STColumn *pCol = schemaColAt(pSchema, i);
- tlen += taosEncodeFixedI8(buf, colType(pCol));
- tlen += taosEncodeFixedI8(buf, colFlags(pCol));
- tlen += taosEncodeFixedI16(buf, colColId(pCol));
- tlen += taosEncodeFixedI16(buf, colBytes(pCol));
- }
-
- return tlen;
-}
-
-/**
- * Decode a schema from a binary.
- */
-void *tdDecodeSchema(void *buf, STSchema **pRSchema) {
- int version = 0;
- int numOfCols = 0;
- STSchemaBuilder schemaBuilder;
-
- buf = taosDecodeFixedI32(buf, &version);
- buf = taosDecodeFixedI32(buf, &numOfCols);
-
- if (tdInitTSchemaBuilder(&schemaBuilder, version) < 0) return NULL;
-
- for (int i = 0; i < numOfCols; i++) {
- col_type_t type = 0;
- int8_t flags = 0;
- col_id_t colId = 0;
- col_bytes_t bytes = 0;
- buf = taosDecodeFixedI8(buf, &type);
- buf = taosDecodeFixedI8(buf, &flags);
- buf = taosDecodeFixedI16(buf, &colId);
- buf = taosDecodeFixedI32(buf, &bytes);
- if (tdAddColToSchema(&schemaBuilder, type, flags, colId, bytes) < 0) {
- tdDestroyTSchemaBuilder(&schemaBuilder);
- return NULL;
- }
- }
-
- *pRSchema = tdGetSchemaFromBuilder(&schemaBuilder);
- tdDestroyTSchemaBuilder(&schemaBuilder);
- return buf;
-}
-
int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) {
if (pBuilder == NULL) return -1;
@@ -1249,22 +1101,22 @@ int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, c
}
STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]);
- colSetType(pCol, type);
- colSetColId(pCol, colId);
- colSetFlags(pCol, flags);
+ pCol->type = type;
+ pCol->colId = colId;
+ pCol->flags = flags;
if (pBuilder->nCols == 0) {
- colSetOffset(pCol, 0);
+ pCol->offset = 0;
} else {
STColumn *pTCol = &(pBuilder->columns[pBuilder->nCols - 1]);
- colSetOffset(pCol, pTCol->offset + TYPE_BYTES[pTCol->type]);
+ pCol->offset = pTCol->offset + TYPE_BYTES[pTCol->type];
}
if (IS_VAR_DATA_TYPE(type)) {
- colSetBytes(pCol, bytes);
+ pCol->bytes = bytes;
pBuilder->tlen += (TYPE_BYTES[type] + bytes);
pBuilder->vlen += bytes - sizeof(VarDataLenT);
} else {
- colSetBytes(pCol, TYPE_BYTES[type]);
+ pCol->bytes = TYPE_BYTES[type];
pBuilder->tlen += TYPE_BYTES[type];
pBuilder->vlen += TYPE_BYTES[type];
}
@@ -1285,151 +1137,19 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) {
STSchema *pSchema = (STSchema *)taosMemoryMalloc(tlen);
if (pSchema == NULL) return NULL;
- schemaVersion(pSchema) = pBuilder->version;
- schemaNCols(pSchema) = pBuilder->nCols;
- schemaTLen(pSchema) = pBuilder->tlen;
- schemaFLen(pSchema) = pBuilder->flen;
- schemaVLen(pSchema) = pBuilder->vlen;
+ pSchema->version = pBuilder->version;
+ pSchema->numOfCols = pBuilder->nCols;
+ pSchema->tlen = pBuilder->tlen;
+ pSchema->flen = pBuilder->flen;
+ pSchema->vlen = pBuilder->vlen;
#ifdef TD_SUPPORT_BITMAP
- schemaTLen(pSchema) += (int)TD_BITMAP_BYTES(schemaNCols(pSchema));
+ pSchema->tlen += (int)TD_BITMAP_BYTES(pSchema->numOfCols);
#endif
- memcpy(schemaColAt(pSchema, 0), pBuilder->columns, sizeof(STColumn) * pBuilder->nCols);
+ memcpy(&pSchema->columns[0], pBuilder->columns, sizeof(STColumn) * pBuilder->nCols);
return pSchema;
}
-void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints) {
- pDataCol->type = colType(pCol);
- pDataCol->colId = colColId(pCol);
- pDataCol->bytes = colBytes(pCol);
- pDataCol->offset = colOffset(pCol) + 0; // TD_DATA_ROW_HEAD_SIZE;
-
- pDataCol->len = 0;
-}
-
-static FORCE_INLINE const void *tdGetColDataOfRowUnsafe(SDataCol *pCol, int row) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
- } else {
- return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
- }
-}
-
-bool isNEleNull(SDataCol *pCol, int nEle) {
- if (isAllRowsNull(pCol)) return true;
- for (int i = 0; i < nEle; ++i) {
- if (!isNull(tdGetColDataOfRowUnsafe(pCol, i), pCol->type)) return false;
- }
- return true;
-}
-
-void *dataColSetOffset(SDataCol *pCol, int nEle) {
- ASSERT(((pCol->type == TSDB_DATA_TYPE_BINARY) || (pCol->type == TSDB_DATA_TYPE_NCHAR)));
-
- void *tptr = pCol->pData;
- // char *tptr = (char *)(pCol->pData);
-
- VarDataOffsetT offset = 0;
- for (int i = 0; i < nEle; ++i) {
- pCol->dataOff[i] = offset;
- offset += varDataTLen(tptr);
- tptr = POINTER_SHIFT(tptr, varDataTLen(tptr));
- }
- return POINTER_SHIFT(tptr, varDataTLen(tptr));
-}
-
-SDataCols *tdNewDataCols(int maxCols, int maxRows) {
- SDataCols *pCols = (SDataCols *)taosMemoryCalloc(1, sizeof(SDataCols));
- if (pCols == NULL) {
- uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
- return NULL;
- }
-
- pCols->maxPoints = maxRows;
- pCols->maxCols = maxCols;
- pCols->numOfRows = 0;
- pCols->numOfCols = 0;
- pCols->bitmapMode = TSDB_BITMODE_DEFAULT;
-
- if (maxCols > 0) {
- pCols->cols = (SDataCol *)taosMemoryCalloc(maxCols, sizeof(SDataCol));
- if (pCols->cols == NULL) {
- uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCol) * maxCols,
- strerror(errno));
- tdFreeDataCols(pCols);
- return NULL;
- }
-#if 0 // no need as calloc used
- int i;
- for (i = 0; i < maxCols; i++) {
- pCols->cols[i].spaceSize = 0;
- pCols->cols[i].len = 0;
- pCols->cols[i].pData = NULL;
- pCols->cols[i].dataOff = NULL;
- }
-#endif
- }
-
- return pCols;
-}
-
-int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
- int i;
- int oldMaxCols = pCols->maxCols;
- if (schemaNCols(pSchema) > oldMaxCols) {
- pCols->maxCols = schemaNCols(pSchema);
- void *ptr = (SDataCol *)taosMemoryRealloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols);
- if (ptr == NULL) return -1;
- pCols->cols = ptr;
- for (i = oldMaxCols; i < pCols->maxCols; ++i) {
- pCols->cols[i].pData = NULL;
- pCols->cols[i].dataOff = NULL;
- pCols->cols[i].pBitmap = NULL;
- pCols->cols[i].spaceSize = 0;
- }
- }
-#if 0
- tdResetDataCols(pCols); // redundant loop to reset len/blen to 0, already reset in following dataColInit(...)
-#endif
-
- pCols->numOfRows = 0;
- pCols->bitmapMode = TSDB_BITMODE_DEFAULT;
- pCols->numOfCols = schemaNCols(pSchema);
-
- for (i = 0; i < schemaNCols(pSchema); ++i) {
- dataColInit(pCols->cols + i, schemaColAt(pSchema, i), pCols->maxPoints);
- }
-
- return 0;
-}
-
-SDataCols *tdFreeDataCols(SDataCols *pCols) {
- int i;
- if (pCols) {
- if (pCols->cols) {
- int maxCols = pCols->maxCols;
- for (i = 0; i < maxCols; ++i) {
- SDataCol *pCol = &pCols->cols[i];
- taosMemoryFreeClear(pCol->pData);
- }
- taosMemoryFree(pCols->cols);
- pCols->cols = NULL;
- }
- taosMemoryFree(pCols);
- }
- return NULL;
-}
-
-void tdResetDataCols(SDataCols *pCols) {
- if (pCols != NULL) {
- pCols->numOfRows = 0;
- pCols->bitmapMode = 0;
- for (int i = 0; i < pCols->maxCols; ++i) {
- dataColReset(pCols->cols + i);
- }
- }
-}
-
#endif
\ No newline at end of file
diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c
index 269c92a670ffed95c2cd2b5d1f76bf97d5615f1b..e4032118c668a34df552698017eb4aa2d03b4e13 100644
--- a/source/common/src/tglobal.c
+++ b/source/common/src/tglobal.c
@@ -55,12 +55,12 @@ int32_t tsNumOfMnodeQueryThreads = 2;
int32_t tsNumOfMnodeFetchThreads = 1;
int32_t tsNumOfMnodeReadThreads = 1;
int32_t tsNumOfVnodeQueryThreads = 2;
-int32_t tsNumOfVnodeFetchThreads = 1;
+int32_t tsNumOfVnodeStreamThreads = 2;
+int32_t tsNumOfVnodeFetchThreads = 4;
int32_t tsNumOfVnodeWriteThreads = 2;
int32_t tsNumOfVnodeSyncThreads = 2;
-int32_t tsNumOfVnodeMergeThreads = 2;
int32_t tsNumOfQnodeQueryThreads = 2;
-int32_t tsNumOfQnodeFetchThreads = 1;
+int32_t tsNumOfQnodeFetchThreads = 4;
int32_t tsNumOfSnodeSharedThreads = 2;
int32_t tsNumOfSnodeUniqueThreads = 2;
@@ -106,11 +106,6 @@ int32_t tsCompressMsgSize = -1;
*/
int32_t tsCompressColData = -1;
-/*
- * denote if 3.0 query pattern compatible for 2.0
- */
-int32_t tsCompatibleModel = 1;
-
// count/hyperloglog function always return values in case of all NULL data or Empty data set.
int32_t tsCountAlwaysReturnValue = 1;
@@ -120,7 +115,7 @@ int32_t tsMinSlidingTime = 10;
// the maxinum number of distict query result
int32_t tsMaxNumOfDistinctResults = 1000 * 10000;
-// 1 us for interval time range, changed accordingly
+// 1 database precision unit for interval time range, changed accordingly
int32_t tsMinIntervalTime = 1;
// 20sec, the maximum value of stream computing delay, changed accordingly
@@ -187,6 +182,8 @@ bool tsStartUdfd = true;
// internal
int32_t tsTransPullupInterval = 2;
int32_t tsMqRebalanceInterval = 2;
+int32_t tsTtlUnit = 86400;
+int32_t tsTtlPushInterval = 60;
void taosAddDataDir(int32_t index, char *v1, int32_t level, int32_t primary) {
tstrncpy(tsDiskCfg[index].dir, v1, TSDB_FILENAME_LEN);
@@ -289,15 +286,14 @@ int32_t taosAddClientLogCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "numOfLogLines", tsNumOfLogLines, 1000, 2000000000, 1) != 0) return -1;
if (cfgAddBool(pCfg, "asyncLog", tsAsyncLog, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "logKeepDays", 0, -365000, 365000, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "cDebugFlag", cDebugFlag, 0, 255, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "debugFlag", 0, 0, 255, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "simDebugFlag", 143, 0, 255, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "tmrDebugFlag", tmrDebugFlag, 0, 255, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "uDebugFlag", uDebugFlag, 0, 255, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "rpcDebugFlag", rpcDebugFlag, 0, 255, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "qDebugFlag", qDebugFlag, 0, 255, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "tmrDebugFlag", tmrDebugFlag, 0, 255, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "jniDebugFlag", jniDebugFlag, 0, 255, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "simDebugFlag", 143, 0, 255, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "debugFlag", 0, 0, 255, 1) != 0) return -1;
- if (cfgAddInt32(pCfg, "idxDebugFlag", idxDebugFlag, 0, 255, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "qDebugFlag", qDebugFlag, 0, 255, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "cDebugFlag", cDebugFlag, 0, 255, 1) != 0) return -1;
return 0;
}
@@ -305,13 +301,12 @@ static int32_t taosAddServerLogCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "dDebugFlag", dDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "vDebugFlag", vDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "mDebugFlag", mDebugFlag, 0, 255, 0) != 0) return -1;
- if (cfgAddInt32(pCfg, "qDebugFlag", qDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "wDebugFlag", wDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "sDebugFlag", sDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "tsdbDebugFlag", tsdbDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "tqDebugFlag", tqDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "fsDebugFlag", fsDebugFlag, 0, 255, 0) != 0) return -1;
- if (cfgAddInt32(pCfg, "fnDebugFlag", fnDebugFlag, 0, 255, 0) != 0) return -1;
+ if (cfgAddInt32(pCfg, "udfDebugFlag", udfDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "smaDebugFlag", smaDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "idxDebugFlag", idxDebugFlag, 0, 255, 0) != 0) return -1;
return 0;
@@ -414,30 +409,32 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
tsNumOfMnodeReadThreads = TRANGE(tsNumOfMnodeReadThreads, 1, 4);
if (cfgAddInt32(pCfg, "numOfMnodeReadThreads", tsNumOfMnodeReadThreads, 1, 1024, 0) != 0) return -1;
- tsNumOfVnodeQueryThreads = tsNumOfCores / 2;
- tsNumOfVnodeQueryThreads = TMAX(tsNumOfVnodeQueryThreads, 1);
+ tsNumOfVnodeQueryThreads = tsNumOfCores / 4;
+ tsNumOfVnodeQueryThreads = TMAX(tsNumOfVnodeQueryThreads, 2);
if (cfgAddInt32(pCfg, "numOfVnodeQueryThreads", tsNumOfVnodeQueryThreads, 1, 1024, 0) != 0) return -1;
- tsNumOfVnodeFetchThreads = TRANGE(tsNumOfVnodeFetchThreads, 1, 1);
+ tsNumOfVnodeStreamThreads = tsNumOfCores / 4;
+ tsNumOfVnodeStreamThreads = TMAX(tsNumOfVnodeStreamThreads, 4);
+ if (cfgAddInt32(pCfg, "numOfVnodeStreamThreads", tsNumOfVnodeStreamThreads, 1, 1024, 0) != 0) return -1;
+
+ tsNumOfVnodeFetchThreads = tsNumOfCores / 4;
+ tsNumOfVnodeFetchThreads = TMAX(tsNumOfVnodeFetchThreads, 4);
if (cfgAddInt32(pCfg, "numOfVnodeFetchThreads", tsNumOfVnodeFetchThreads, 1, 1024, 0) != 0) return -1;
tsNumOfVnodeWriteThreads = tsNumOfCores;
tsNumOfVnodeWriteThreads = TMAX(tsNumOfVnodeWriteThreads, 1);
if (cfgAddInt32(pCfg, "numOfVnodeWriteThreads", tsNumOfVnodeWriteThreads, 1, 1024, 0) != 0) return -1;
- tsNumOfVnodeSyncThreads = tsNumOfCores / 2;
+ tsNumOfVnodeSyncThreads = tsNumOfCores;
tsNumOfVnodeSyncThreads = TMAX(tsNumOfVnodeSyncThreads, 1);
if (cfgAddInt32(pCfg, "numOfVnodeSyncThreads", tsNumOfVnodeSyncThreads, 1, 1024, 0) != 0) return -1;
- tsNumOfVnodeMergeThreads = tsNumOfCores / 8;
- tsNumOfVnodeMergeThreads = TRANGE(tsNumOfVnodeMergeThreads, 1, 1);
- if (cfgAddInt32(pCfg, "numOfVnodeMergeThreads", tsNumOfVnodeMergeThreads, 1, 1024, 0) != 0) return -1;
-
tsNumOfQnodeQueryThreads = tsNumOfCores / 2;
tsNumOfQnodeQueryThreads = TMAX(tsNumOfQnodeQueryThreads, 1);
if (cfgAddInt32(pCfg, "numOfQnodeQueryThreads", tsNumOfQnodeQueryThreads, 1, 1024, 0) != 0) return -1;
- tsNumOfQnodeFetchThreads = TRANGE(tsNumOfQnodeFetchThreads, 1, 1);
+ tsNumOfQnodeFetchThreads = tsNumOfCores / 2;
+ tsNumOfQnodeFetchThreads = TMAX(tsNumOfQnodeFetchThreads, 4);
if (cfgAddInt32(pCfg, "numOfQnodeFetchThreads", tsNumOfQnodeFetchThreads, 1, 1024, 0) != 0) return -1;
tsNumOfSnodeSharedThreads = tsNumOfCores / 4;
@@ -467,6 +464,8 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "transPullupInterval", tsTransPullupInterval, 1, 10000, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "mqRebalanceInterval", tsMqRebalanceInterval, 1, 10000, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "ttlUnit", tsTtlUnit, 1, 86400 * 365, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "ttlPushInterval", tsTtlPushInterval, 1, 10000, 1) != 0) return -1;
if (cfgAddBool(pCfg, "udf", tsStartUdfd, 0) != 0) return -1;
return 0;
@@ -480,26 +479,24 @@ static void taosSetClientLogCfg(SConfig *pCfg) {
tsNumOfLogLines = cfgGetItem(pCfg, "numOfLogLines")->i32;
tsAsyncLog = cfgGetItem(pCfg, "asyncLog")->bval;
tsLogKeepDays = cfgGetItem(pCfg, "logKeepDays")->i32;
- cDebugFlag = cfgGetItem(pCfg, "cDebugFlag")->i32;
- uDebugFlag = cfgGetItem(pCfg, "uDebugFlag")->i32;
- qDebugFlag = cfgGetItem(pCfg, "qDebugFlag")->i32;
- rpcDebugFlag = cfgGetItem(pCfg, "rpcDebugFlag")->i32;
tmrDebugFlag = cfgGetItem(pCfg, "tmrDebugFlag")->i32;
+ uDebugFlag = cfgGetItem(pCfg, "uDebugFlag")->i32;
jniDebugFlag = cfgGetItem(pCfg, "jniDebugFlag")->i32;
- idxDebugFlag = cfgGetItem(pCfg, "idxDebugFlag")->i32;
+ rpcDebugFlag = cfgGetItem(pCfg, "rpcDebugFlag")->i32;
+ qDebugFlag = cfgGetItem(pCfg, "qDebugFlag")->i32;
+ cDebugFlag = cfgGetItem(pCfg, "cDebugFlag")->i32;
}
static void taosSetServerLogCfg(SConfig *pCfg) {
dDebugFlag = cfgGetItem(pCfg, "dDebugFlag")->i32;
vDebugFlag = cfgGetItem(pCfg, "vDebugFlag")->i32;
mDebugFlag = cfgGetItem(pCfg, "mDebugFlag")->i32;
- qDebugFlag = cfgGetItem(pCfg, "qDebugFlag")->i32;
wDebugFlag = cfgGetItem(pCfg, "wDebugFlag")->i32;
sDebugFlag = cfgGetItem(pCfg, "sDebugFlag")->i32;
tsdbDebugFlag = cfgGetItem(pCfg, "tsdbDebugFlag")->i32;
tqDebugFlag = cfgGetItem(pCfg, "tqDebugFlag")->i32;
fsDebugFlag = cfgGetItem(pCfg, "fsDebugFlag")->i32;
- fnDebugFlag = cfgGetItem(pCfg, "fnDebugFlag")->i32;
+ udfDebugFlag = cfgGetItem(pCfg, "udfDebugFlag")->i32;
smaDebugFlag = cfgGetItem(pCfg, "smaDebugFlag")->i32;
idxDebugFlag = cfgGetItem(pCfg, "idxDebugFlag")->i32;
}
@@ -595,10 +592,10 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
tsNumOfMnodeQueryThreads = cfgGetItem(pCfg, "numOfMnodeQueryThreads")->i32;
tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32;
tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32;
+ tsNumOfVnodeStreamThreads = cfgGetItem(pCfg, "numOfVnodeStreamThreads")->i32;
tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32;
tsNumOfVnodeWriteThreads = cfgGetItem(pCfg, "numOfVnodeWriteThreads")->i32;
tsNumOfVnodeSyncThreads = cfgGetItem(pCfg, "numOfVnodeSyncThreads")->i32;
- tsNumOfVnodeMergeThreads = cfgGetItem(pCfg, "numOfVnodeMergeThreads")->i32;
tsNumOfQnodeQueryThreads = cfgGetItem(pCfg, "numOfQnodeQueryThreads")->i32;
tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32;
tsNumOfSnodeSharedThreads = cfgGetItem(pCfg, "numOfSnodeSharedThreads")->i32;
@@ -619,6 +616,8 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
tsTransPullupInterval = cfgGetItem(pCfg, "transPullupInterval")->i32;
tsMqRebalanceInterval = cfgGetItem(pCfg, "mqRebalanceInterval")->i32;
+ tsTtlUnit = cfgGetItem(pCfg, "ttlUnit")->i32;
+ tsTtlPushInterval = cfgGetItem(pCfg, "ttlPushInterval")->i32;
tsStartUdfd = cfgGetItem(pCfg, "udf")->bval;
@@ -629,9 +628,377 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
return 0;
}
+int32_t taosSetCfg(SConfig *pCfg, char *name) {
+ int32_t len = strlen(name);
+ char lowcaseName[CFG_NAME_MAX_LEN + 1] = {0};
+ strntolower(lowcaseName, name, TMIN(CFG_NAME_MAX_LEN, len));
+
+ switch (lowcaseName[0]) {
+ case 'a': {
+ if (strcasecmp("asyncLog", name) == 0) {
+ tsAsyncLog = cfgGetItem(pCfg, "asyncLog")->bval;
+ }
+ break;
+ }
+ case 'b': {
+ if (strcasecmp("bnodeShmSize", name) == 0) {
+ tsBnodeShmSize = cfgGetItem(pCfg, "bnodeShmSize")->i32;
+ }
+ break;
+ }
+ case 'c': {
+ if (strcasecmp("charset", name) == 0) {
+ const char *locale = cfgGetItem(pCfg, "locale")->str;
+ const char *charset = cfgGetItem(pCfg, "charset")->str;
+ taosSetSystemLocale(locale, charset);
+ osSetSystemLocale(locale, charset);
+ } else if (strcasecmp("compressMsgSize", name) == 0) {
+ tsCompressMsgSize = cfgGetItem(pCfg, "compressMsgSize")->i32;
+ } else if (strcasecmp("compressColData", name) == 0) {
+ tsCompressColData = cfgGetItem(pCfg, "compressColData")->i32;
+ } else if (strcasecmp("countAlwaysReturnValue", name) == 0) {
+ tsCountAlwaysReturnValue = cfgGetItem(pCfg, "countAlwaysReturnValue")->i32;
+ } else if (strcasecmp("cDebugFlag", name) == 0) {
+ cDebugFlag = cfgGetItem(pCfg, "cDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'd': {
+ if (strcasecmp("deadLockKillQuery", name) == 0) {
+ tsDeadLockKillQuery = cfgGetItem(pCfg, "deadLockKillQuery")->i32;
+ } else if (strcasecmp("dDebugFlag", name) == 0) {
+ dDebugFlag = cfgGetItem(pCfg, "dDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'e': {
+ if (strcasecmp("enableCoreFile", name) == 0) {
+ bool enableCore = cfgGetItem(pCfg, "enableCoreFile")->bval;
+ taosSetConsoleEcho(enableCore);
+ }
+ break;
+ }
+ case 'f': {
+ if (strcasecmp("fqdn", name) == 0) {
+ tstrncpy(tsLocalFqdn, cfgGetItem(pCfg, "fqdn")->str, TSDB_FQDN_LEN);
+ tsServerPort = (uint16_t)cfgGetItem(pCfg, "serverPort")->i32;
+ snprintf(tsLocalEp, sizeof(tsLocalEp), "%s:%u", tsLocalFqdn, tsServerPort);
+
+ char defaultFirstEp[TSDB_EP_LEN] = {0};
+ snprintf(defaultFirstEp, TSDB_EP_LEN, "%s:%u", tsLocalFqdn, tsServerPort);
+
+ SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
+ SEp firstEp = {0};
+ taosGetFqdnPortFromEp(strlen(pFirstEpItem->str) == 0 ? defaultFirstEp : pFirstEpItem->str, &firstEp);
+ snprintf(tsFirst, sizeof(tsFirst), "%s:%u", firstEp.fqdn, firstEp.port);
+ cfgSetItem(pCfg, "firstEp", tsFirst, pFirstEpItem->stype);
+ } else if (strcasecmp("firstEp", name) == 0) {
+ tstrncpy(tsLocalFqdn, cfgGetItem(pCfg, "fqdn")->str, TSDB_FQDN_LEN);
+ tsServerPort = (uint16_t)cfgGetItem(pCfg, "serverPort")->i32;
+ snprintf(tsLocalEp, sizeof(tsLocalEp), "%s:%u", tsLocalFqdn, tsServerPort);
+
+ char defaultFirstEp[TSDB_EP_LEN] = {0};
+ snprintf(defaultFirstEp, TSDB_EP_LEN, "%s:%u", tsLocalFqdn, tsServerPort);
+
+ SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
+ SEp firstEp = {0};
+ taosGetFqdnPortFromEp(strlen(pFirstEpItem->str) == 0 ? defaultFirstEp : pFirstEpItem->str, &firstEp);
+ snprintf(tsFirst, sizeof(tsFirst), "%s:%u", firstEp.fqdn, firstEp.port);
+ cfgSetItem(pCfg, "firstEp", tsFirst, pFirstEpItem->stype);
+ } else if (strcasecmp("fsDebugFlag", name) == 0) {
+ fsDebugFlag = cfgGetItem(pCfg, "fsDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'i': {
+ if (strcasecmp("idxDebugFlag", name) == 0) {
+ idxDebugFlag = cfgGetItem(pCfg, "idxDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'j': {
+ if (strcasecmp("jniDebugFlag", name) == 0) {
+ jniDebugFlag = cfgGetItem(pCfg, "jniDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'k': {
+ if (strcasecmp("keepColumnName", name) == 0) {
+ tsKeepOriginalColumnName = cfgGetItem(pCfg, "keepColumnName")->bval;
+ }
+ break;
+ }
+ case 'l': {
+ if (strcasecmp("locale", name) == 0) {
+ const char *locale = cfgGetItem(pCfg, "locale")->str;
+ const char *charset = cfgGetItem(pCfg, "charset")->str;
+ taosSetSystemLocale(locale, charset);
+ osSetSystemLocale(locale, charset);
+ } else if (strcasecmp("logDir", name) == 0) {
+ tstrncpy(tsLogDir, cfgGetItem(pCfg, "logDir")->str, PATH_MAX);
+ taosExpandDir(tsLogDir, tsLogDir, PATH_MAX);
+ } else if (strcasecmp("logKeepDays", name) == 0) {
+ tsLogKeepDays = cfgGetItem(pCfg, "logKeepDays")->i32;
+ }
+ break;
+ }
+ case 'm': {
+ switch (lowcaseName[1]) {
+ case 'a': {
+ if (strcasecmp("maxShellConns", name) == 0) {
+ tsMaxShellConns = cfgGetItem(pCfg, "maxShellConns")->i32;
+ } else if (strcasecmp("maxNumOfDistinctRes", name) == 0) {
+ tsMaxNumOfDistinctResults = cfgGetItem(pCfg, "maxNumOfDistinctRes")->i32;
+ } else if (strcasecmp("maxStreamCompDelay", name) == 0) {
+ tsMaxStreamComputDelay = cfgGetItem(pCfg, "maxStreamCompDelay")->i32;
+ } else if (strcasecmp("maxFirstStreamCompDelay", name) == 0) {
+ tsStreamCompStartDelay = cfgGetItem(pCfg, "maxFirstStreamCompDelay")->i32;
+ }
+ break;
+ }
+ case 'd': {
+ if (strcasecmp("mDebugFlag", name) == 0) {
+ mDebugFlag = cfgGetItem(pCfg, "mDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'i': {
+ if (strcasecmp("minimalTempDirGB", name) == 0) {
+ tsTempSpace.reserved = cfgGetItem(pCfg, "minimalTempDirGB")->fval;
+ } else if (strcasecmp("minimalDataDirGB", name) == 0) {
+ tsDataSpace.reserved = cfgGetItem(pCfg, "minimalDataDirGB")->fval;
+ } else if (strcasecmp("minSlidingTime", name) == 0) {
+ tsMinSlidingTime = cfgGetItem(pCfg, "minSlidingTime")->i32;
+ } else if (strcasecmp("minIntervalTime", name) == 0) {
+ tsMinIntervalTime = cfgGetItem(pCfg, "minIntervalTime")->i32;
+ } else if (strcasecmp("minimalLogDirGB", name) == 0) {
+ tsLogSpace.reserved = cfgGetItem(pCfg, "minimalLogDirGB")->fval;
+ }
+ break;
+ }
+ case 'n': {
+ if (strcasecmp("mnodeShmSize", name) == 0) {
+ tsMnodeShmSize = cfgGetItem(pCfg, "mnodeShmSize")->i32;
+ }
+ break;
+ }
+ case 'o': {
+ if (strcasecmp("monitor", name) == 0) {
+ tsEnableMonitor = cfgGetItem(pCfg, "monitor")->bval;
+ } else if (strcasecmp("monitorInterval", name) == 0) {
+ tsMonitorInterval = cfgGetItem(pCfg, "monitorInterval")->i32;
+ } else if (strcasecmp("monitorFqdn", name) == 0) {
+ tstrncpy(tsMonitorFqdn, cfgGetItem(pCfg, "monitorFqdn")->str, TSDB_FQDN_LEN);
+ } else if (strcasecmp("monitorPort", name) == 0) {
+ tsMonitorPort = (uint16_t)cfgGetItem(pCfg, "monitorPort")->i32;
+ } else if (strcasecmp("monitorMaxLogs", name) == 0) {
+ tsMonitorMaxLogs = cfgGetItem(pCfg, "monitorMaxLogs")->i32;
+ } else if (strcasecmp("monitorComp", name) == 0) {
+ tsMonitorComp = cfgGetItem(pCfg, "monitorComp")->bval;
+ }
+ break;
+ }
+ case 'q': {
+ if (strcasecmp("mqRebalanceInterval", name) == 0) {
+ tsMqRebalanceInterval = cfgGetItem(pCfg, "mqRebalanceInterval")->i32;
+ }
+ break;
+ }
+ case 'u': {
+ if (strcasecmp("multiProcess", name) == 0) {
+ tsMultiProcess = cfgGetItem(pCfg, "multiProcess")->bval;
+ } else if (strcasecmp("udfDebugFlag", name) == 0) {
+ udfDebugFlag = cfgGetItem(pCfg, "udfDebugFlag")->i32;
+ }
+ break;
+ }
+ default:
+ terrno = TSDB_CODE_CFG_NOT_FOUND;
+ return -1;
+ }
+ break;
+ }
+ case 'n': {
+ if (strcasecmp("numOfTaskQueueThreads", name) == 0) {
+ tsNumOfTaskQueueThreads = cfgGetItem(pCfg, "numOfTaskQueueThreads")->i32;
+ } else if (strcasecmp("numOfRpcThreads", name) == 0) {
+ 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) {
+ tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32;
+ } else if (strcasecmp("numOfVnodeFetchThreads", name) == 0) {
+ tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32;
+ } else if (strcasecmp("numOfVnodeWriteThreads", name) == 0) {
+ tsNumOfVnodeWriteThreads = cfgGetItem(pCfg, "numOfVnodeWriteThreads")->i32;
+ } else if (strcasecmp("numOfVnodeSyncThreads", name) == 0) {
+ tsNumOfVnodeSyncThreads = cfgGetItem(pCfg, "numOfVnodeSyncThreads")->i32;
+ } else if (strcasecmp("numOfQnodeQueryThreads", name) == 0) {
+ tsNumOfQnodeQueryThreads = cfgGetItem(pCfg, "numOfQnodeQueryThreads")->i32;
+ } else if (strcasecmp("numOfQnodeFetchThreads", name) == 0) {
+ tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32;
+ } else if (strcasecmp("numOfSnodeSharedThreads", name) == 0) {
+ tsNumOfSnodeSharedThreads = cfgGetItem(pCfg, "numOfSnodeSharedThreads")->i32;
+ } else if (strcasecmp("numOfSnodeUniqueThreads", name) == 0) {
+ tsNumOfSnodeUniqueThreads = cfgGetItem(pCfg, "numOfSnodeUniqueThreads")->i32;
+ } else if (strcasecmp("numOfLogLines", name) == 0) {
+ tsNumOfLogLines = cfgGetItem(pCfg, "numOfLogLines")->i32;
+ }
+ break;
+ }
+ case 'p': {
+ if (strcasecmp("printAuth", name) == 0) {
+ tsPrintAuth = cfgGetItem(pCfg, "printAuth")->bval;
+ }
+ break;
+ }
+ case 'q': {
+ if (strcasecmp("queryPolicy", name) == 0) {
+ tsQueryPolicy = cfgGetItem(pCfg, "queryPolicy")->i32;
+ } else if (strcasecmp("querySmaOptimize", name) == 0) {
+ tsQuerySmaOptimize = cfgGetItem(pCfg, "querySmaOptimize")->i32;
+ } else if (strcasecmp("queryBufferSize", name) == 0) {
+ tsQueryBufferSize = cfgGetItem(pCfg, "queryBufferSize")->i32;
+ if (tsQueryBufferSize >= 0) {
+ tsQueryBufferSizeBytes = tsQueryBufferSize * 1048576UL;
+ }
+ } else if (strcasecmp("qnodeShmSize", name) == 0) {
+ tsQnodeShmSize = cfgGetItem(pCfg, "qnodeShmSize")->i32;
+ } else if (strcasecmp("qDebugFlag", name) == 0) {
+ qDebugFlag = cfgGetItem(pCfg, "qDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'r': {
+ if (strcasecmp("retryStreamCompDelay", name) == 0) {
+ tsRetryStreamCompDelay = cfgGetItem(pCfg, "retryStreamCompDelay")->i32;
+ } else if (strcasecmp("retrieveBlockingModel", name) == 0) {
+ tsRetrieveBlockingModel = cfgGetItem(pCfg, "retrieveBlockingModel")->bval;
+ } else if (strcasecmp("rpcQueueMemoryAllowed", name) == 0) {
+ tsRpcQueueMemoryAllowed = cfgGetItem(pCfg, "rpcQueueMemoryAllowed")->i64;
+ } else if (strcasecmp("rpcDebugFlag", name) == 0) {
+ rpcDebugFlag = cfgGetItem(pCfg, "rpcDebugFlag")->i32;
+ }
+ break;
+ }
+ case 's': {
+ if (strcasecmp("secondEp", name) == 0) {
+ SConfigItem *pSecondpItem = cfgGetItem(pCfg, "secondEp");
+ SEp secondEp = {0};
+ taosGetFqdnPortFromEp(strlen(pSecondpItem->str) == 0 ? tsFirst : pSecondpItem->str, &secondEp);
+ snprintf(tsSecond, sizeof(tsSecond), "%s:%u", secondEp.fqdn, secondEp.port);
+ cfgSetItem(pCfg, "secondEp", tsSecond, pSecondpItem->stype);
+ } else if (strcasecmp("smlChildTableName", name) == 0) {
+ tstrncpy(tsSmlChildTableName, cfgGetItem(pCfg, "smlChildTableName")->str, TSDB_TABLE_NAME_LEN);
+ } else if (strcasecmp("smlTagName", name) == 0) {
+ tstrncpy(tsSmlTagName, cfgGetItem(pCfg, "smlTagName")->str, TSDB_COL_NAME_LEN);
+ } else if (strcasecmp("smlDataFormat", name) == 0) {
+ tsSmlDataFormat = cfgGetItem(pCfg, "smlDataFormat")->bval;
+ } else if (strcasecmp("shellActivityTimer", name) == 0) {
+ tsShellActivityTimer = cfgGetItem(pCfg, "shellActivityTimer")->i32;
+ } else if (strcasecmp("supportVnodes", name) == 0) {
+ tsNumOfSupportVnodes = cfgGetItem(pCfg, "supportVnodes")->i32;
+ } else if (strcasecmp("statusInterval", name) == 0) {
+ tsStatusInterval = cfgGetItem(pCfg, "statusInterval")->i32;
+ } else if (strcasecmp("streamCompDelayRatio", name) == 0) {
+ tsStreamComputDelayRatio = cfgGetItem(pCfg, "streamCompDelayRatio")->fval;
+ } 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) {
+ tstrncpy(tsLocalFqdn, cfgGetItem(pCfg, "fqdn")->str, TSDB_FQDN_LEN);
+ tsServerPort = (uint16_t)cfgGetItem(pCfg, "serverPort")->i32;
+ snprintf(tsLocalEp, sizeof(tsLocalEp), "%s:%u", tsLocalFqdn, tsServerPort);
+
+ char defaultFirstEp[TSDB_EP_LEN] = {0};
+ snprintf(defaultFirstEp, TSDB_EP_LEN, "%s:%u", tsLocalFqdn, tsServerPort);
+
+ SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
+ SEp firstEp = {0};
+ taosGetFqdnPortFromEp(strlen(pFirstEpItem->str) == 0 ? defaultFirstEp : pFirstEpItem->str, &firstEp);
+ snprintf(tsFirst, sizeof(tsFirst), "%s:%u", firstEp.fqdn, firstEp.port);
+ cfgSetItem(pCfg, "firstEp", tsFirst, pFirstEpItem->stype);
+ } else if (strcasecmp("sDebugFlag", name) == 0) {
+ sDebugFlag = cfgGetItem(pCfg, "sDebugFlag")->i32;
+ } else if (strcasecmp("smaDebugFlag", name) == 0) {
+ smaDebugFlag = cfgGetItem(pCfg, "smaDebugFlag")->i32;
+ }
+ break;
+ }
+ case 't': {
+ if (strcasecmp("timezone", name) == 0) {
+ SConfigItem *pItem = cfgGetItem(pCfg, "timezone");
+ osSetTimezone(pItem->str);
+ uDebug("timezone format changed from %s to %s", pItem->str, tsTimezoneStr);
+ cfgSetItem(pCfg, "timezone", tsTimezoneStr, pItem->stype);
+ } else if (strcasecmp("tempDir", name) == 0) {
+ tstrncpy(tsTempDir, cfgGetItem(pCfg, "tempDir")->str, PATH_MAX);
+ taosExpandDir(tsTempDir, tsTempDir, PATH_MAX);
+ if (taosMulMkDir(tsTempDir) != 0) {
+ uError("failed to create tempDir:%s since %s", tsTempDir, terrstr());
+ return -1;
+ }
+ } else if (strcasecmp("telemetryReporting", name) == 0) {
+ tsEnableTelem = cfgGetItem(pCfg, "telemetryReporting")->bval;
+ } else if (strcasecmp("telemetryInterval", name) == 0) {
+ tsTelemInterval = cfgGetItem(pCfg, "telemetryInterval")->i32;
+ } else if (strcasecmp("telemetryServer", name) == 0) {
+ tstrncpy(tsTelemServer, cfgGetItem(pCfg, "telemetryServer")->str, TSDB_FQDN_LEN);
+ } else if (strcasecmp("telemetryPort", name) == 0) {
+ tsTelemPort = (uint16_t)cfgGetItem(pCfg, "telemetryPort")->i32;
+ } else if (strcasecmp("transPullupInterval", name) == 0) {
+ tsTransPullupInterval = cfgGetItem(pCfg, "transPullupInterval")->i32;
+ } else if (strcasecmp("ttlUnit", name) == 0) {
+ tsTtlUnit = cfgGetItem(pCfg, "ttlUnit")->i32;
+ } else if (strcasecmp("ttlPushInterval", name) == 0) {
+ tsTtlPushInterval = cfgGetItem(pCfg, "ttlPushInterval")->i32;
+ } else if (strcasecmp("tmrDebugFlag", name) == 0) {
+ tmrDebugFlag = cfgGetItem(pCfg, "tmrDebugFlag")->i32;
+ } else if (strcasecmp("tsdbDebugFlag", name) == 0) {
+ tsdbDebugFlag = cfgGetItem(pCfg, "tsdbDebugFlag")->i32;
+ } else if (strcasecmp("tqDebugFlag", name) == 0) {
+ tqDebugFlag = cfgGetItem(pCfg, "tqDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'u': {
+ if (strcasecmp("udf", name) == 0) {
+ tsStartUdfd = cfgGetItem(pCfg, "udf")->bval;
+ } else if (strcasecmp("uDebugFlag", name) == 0) {
+ uDebugFlag = cfgGetItem(pCfg, "uDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'v': {
+ if (strcasecmp("vnodeShmSize", name) == 0) {
+ tsVnodeShmSize = cfgGetItem(pCfg, "vnodeShmSize")->i32;
+ } else if (strcasecmp("vDebugFlag", name) == 0) {
+ vDebugFlag = cfgGetItem(pCfg, "vDebugFlag")->i32;
+ }
+ break;
+ }
+ case 'w': {
+ if (strcasecmp("wDebugFlag", name) == 0) {
+ wDebugFlag = cfgGetItem(pCfg, "wDebugFlag")->i32;
+ }
+ break;
+ }
+ default:
+ terrno = TSDB_CODE_CFG_NOT_FOUND;
+ return -1;
+ }
+
+ return 0;
+}
+
int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDir, const char **envCmd,
const char *envFile, char *apolloUrl, SArray *pArgs, bool tsc) {
- osDefaultInit();
+ if (tsCfg == NULL) osDefaultInit();
SConfig *pCfg = cfgInit();
if (pCfg == NULL) return -1;
@@ -753,13 +1120,47 @@ void taosCleanupCfg() {
}
void taosCfgDynamicOptions(const char *option, const char *value) {
- if (strcasecmp(option, "debugFlag") == 0) {
- int32_t debugFlag = atoi(value);
- taosSetAllDebugFlag(debugFlag);
+ if (strncasecmp(option, "debugFlag", 9) == 0) {
+ int32_t flag = atoi(value);
+ taosSetAllDebugFlag(flag);
+ return;
}
if (strcasecmp(option, "resetlog") == 0) {
taosResetLog();
cfgDumpCfg(tsCfg, 0, false);
+ return;
}
+
+ if (strcasecmp(option, "monitor") == 0) {
+ int32_t monitor = atoi(value);
+ uInfo("monitor set from %d to %d", tsEnableMonitor, monitor);
+ tsEnableMonitor = monitor;
+ return;
+ }
+
+ const char *options[] = {
+ "dDebugFlag", "vDebugFlag", "mDebugFlag", "wDebugFlag", "sDebugFlag", "tsdbDebugFlag",
+ "tqDebugFlag", "fsDebugFlag", "udfDebugFlag", "smaDebugFlag", "idxDebugFlag", "tmrDebugFlag",
+ "uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag",
+ };
+ int32_t *optionVars[] = {
+ &dDebugFlag, &vDebugFlag, &mDebugFlag, &wDebugFlag, &sDebugFlag, &tsdbDebugFlag,
+ &tqDebugFlag, &fsDebugFlag, &udfDebugFlag, &smaDebugFlag, &idxDebugFlag, &tmrDebugFlag,
+ &uDebugFlag, &smaDebugFlag, &rpcDebugFlag, &qDebugFlag,
+ };
+
+ int32_t optionSize = tListLen(options);
+ for (int32_t d = 0; d < optionSize; ++d) {
+ const char *optName = options[d];
+ int32_t optLen = strlen(optName);
+ if (strncasecmp(option, optName, optLen) != 0) continue;
+
+ int32_t flag = atoi(value);
+ uInfo("%s set from %d to %d", optName, *optionVars[d], flag);
+ *optionVars[d] = flag;
+ return;
+ }
+
+ uError("failed to cfg dynamic option:%s value:%s", option, value);
}
diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c
index cc987ad6a175e83c35a478e9f64b906719654490..9ebfa78b80d3e986c3b79a84f15e4b81032a465e 100644
--- a/source/common/src/tmsg.c
+++ b/source/common/src/tmsg.c
@@ -127,7 +127,7 @@ int32_t tEncodeSEpSet(SEncoder *pEncoder, const SEpSet *pEp) {
if (tEncodeI8(pEncoder, pEp->numOfEps) < 0) return -1;
for (int32_t i = 0; i < TSDB_MAX_REPLICA; i++) {
if (tEncodeU16(pEncoder, pEp->eps[i].port) < 0) return -1;
- if (tEncodeCStr(pEncoder, pEp->eps[i].fqdn) < 0) return -1;
+ if (tEncodeCStrWithLen(pEncoder, pEp->eps[i].fqdn, TSDB_FQDN_LEN) < 0) return -1;
}
return 0;
}
@@ -381,9 +381,11 @@ static int32_t tDeserializeSClientHbRsp(SDecoder *pDecoder, SClientHbRsp *pRsp)
if (pQnodeNum > 0) {
pRsp->query->pQnodeList = taosArrayInit(pQnodeNum, sizeof(SQueryNodeLoad));
if (NULL == pRsp->query->pQnodeList) return -1;
- SQueryNodeLoad load = {0};
- if (tDecodeSQueryNodeLoad(pDecoder, &load) < 0) return -1;
- taosArrayPush(pRsp->query->pQnodeList, &load);
+ for (int32_t i = 0; i < pQnodeNum; ++i) {
+ SQueryNodeLoad load = {0};
+ if (tDecodeSQueryNodeLoad(pDecoder, &load) < 0) return -1;
+ taosArrayPush(pRsp->query->pQnodeList, &load);
+ }
}
}
@@ -496,13 +498,21 @@ int32_t tSerializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pReq
if (tStartEncode(&encoder) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->name) < 0) return -1;
if (tEncodeI8(&encoder, pReq->igExists) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->source) < 0) return -1;
+ for (int32_t i = 0; i < sizeof(pReq->reserved) / sizeof(int8_t); ++i) {
+ if (tEncodeI8(&encoder, pReq->reserved[i]) < 0) return -1;
+ }
+ if (tEncodeI64(&encoder, pReq->suid) < 0) return -1;
if (tEncodeI64(&encoder, pReq->delay1) < 0) return -1;
if (tEncodeI64(&encoder, pReq->delay2) < 0) return -1;
if (tEncodeI64(&encoder, pReq->watermark1) < 0) return -1;
if (tEncodeI64(&encoder, pReq->watermark2) < 0) return -1;
if (tEncodeI32(&encoder, pReq->ttl) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->colVer) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->tagVer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->numOfColumns) < 0) return -1;
if (tEncodeI32(&encoder, pReq->numOfTags) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->numOfFuncs) < 0) return -1;
if (tEncodeI32(&encoder, pReq->commentLen) < 0) return -1;
if (tEncodeI32(&encoder, pReq->ast1Len) < 0) return -1;
if (tEncodeI32(&encoder, pReq->ast2Len) < 0) return -1;
@@ -510,21 +520,26 @@ int32_t tSerializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pReq
for (int32_t i = 0; i < pReq->numOfColumns; ++i) {
SField *pField = taosArrayGet(pReq->pColumns, i);
if (tEncodeI8(&encoder, pField->type) < 0) return -1;
+ if (tEncodeI8(&encoder, pField->flags) < 0) return -1;
if (tEncodeI32(&encoder, pField->bytes) < 0) return -1;
if (tEncodeCStr(&encoder, pField->name) < 0) return -1;
- if (tEncodeI8(&encoder, pField->flags) < 0) return -1;
}
for (int32_t i = 0; i < pReq->numOfTags; ++i) {
SField *pField = taosArrayGet(pReq->pTags, i);
if (tEncodeI8(&encoder, pField->type) < 0) return -1;
+ if (tEncodeI8(&encoder, pField->flags) < 0) return -1;
if (tEncodeI32(&encoder, pField->bytes) < 0) return -1;
if (tEncodeCStr(&encoder, pField->name) < 0) return -1;
- if (tEncodeI8(&encoder, pField->flags) < 0) return -1;
+ }
+
+ for (int32_t i = 0; i < pReq->numOfFuncs; ++i) {
+ const char *pFunc = taosArrayGet(pReq->pFuncs, i);
+ if (tEncodeCStr(&encoder, pFunc) < 0) return -1;
}
if (pReq->commentLen > 0) {
- if (tEncodeCStr(&encoder, pReq->comment) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->pComment) < 0) return -1;
}
if (pReq->ast1Len > 0) {
if (tEncodeBinary(&encoder, pReq->pAst1, pReq->ast1Len) < 0) return -1;
@@ -532,6 +547,7 @@ int32_t tSerializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pReq
if (pReq->ast2Len > 0) {
if (tEncodeBinary(&encoder, pReq->pAst2, pReq->ast2Len) < 0) return -1;
}
+
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -546,20 +562,29 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
if (tStartDecode(&decoder) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->name) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->igExists) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->source) < 0) return -1;
+ for (int32_t i = 0; i < sizeof(pReq->reserved) / sizeof(int8_t); ++i) {
+ if (tDecodeI8(&decoder, &pReq->reserved[i]) < 0) return -1;
+ }
+ if (tDecodeI64(&decoder, &pReq->suid) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->delay1) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->delay2) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->watermark1) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->watermark2) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->ttl) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->colVer) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->tagVer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->numOfColumns) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->numOfTags) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->numOfFuncs) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->commentLen) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->ast1Len) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->ast2Len) < 0) return -1;
pReq->pColumns = taosArrayInit(pReq->numOfColumns, sizeof(SField));
pReq->pTags = taosArrayInit(pReq->numOfTags, sizeof(SField));
- if (pReq->pColumns == NULL || pReq->pTags == NULL) {
+ pReq->pFuncs = taosArrayInit(pReq->numOfFuncs, TSDB_FUNC_NAME_LEN);
+ if (pReq->pColumns == NULL || pReq->pTags == NULL || pReq->pFuncs == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
@@ -567,9 +592,9 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
for (int32_t i = 0; i < pReq->numOfColumns; ++i) {
SField field = {0};
if (tDecodeI8(&decoder, &field.type) < 0) return -1;
+ if (tDecodeI8(&decoder, &field.flags) < 0) return -1;
if (tDecodeI32(&decoder, &field.bytes) < 0) return -1;
if (tDecodeCStrTo(&decoder, field.name) < 0) return -1;
- if (tDecodeI8(&decoder, &field.flags) < 0) return -1;
if (taosArrayPush(pReq->pColumns, &field) == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
@@ -579,19 +604,28 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
for (int32_t i = 0; i < pReq->numOfTags; ++i) {
SField field = {0};
if (tDecodeI8(&decoder, &field.type) < 0) return -1;
+ if (tDecodeI8(&decoder, &field.flags) < 0) return -1;
if (tDecodeI32(&decoder, &field.bytes) < 0) return -1;
if (tDecodeCStrTo(&decoder, field.name) < 0) return -1;
- if (tDecodeI8(&decoder, &field.flags) < 0) return -1;
if (taosArrayPush(pReq->pTags, &field) == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
}
+ for (int32_t i = 0; i < pReq->numOfFuncs; ++i) {
+ char pFunc[TSDB_FUNC_NAME_LEN] = {0};
+ if (tDecodeCStrTo(&decoder, pFunc) < 0) return -1;
+ if (taosArrayPush(pReq->pFuncs, pFunc) == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
if (pReq->commentLen > 0) {
- pReq->comment = taosMemoryMalloc(pReq->commentLen + 1);
- if (pReq->comment == NULL) return -1;
- if (tDecodeCStrTo(&decoder, pReq->comment) < 0) return -1;
+ pReq->pComment = taosMemoryMalloc(pReq->commentLen + 1);
+ if (pReq->pComment == NULL) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->pComment) < 0) return -1;
}
if (pReq->ast1Len > 0) {
@@ -607,7 +641,6 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
}
tEndDecode(&decoder);
-
tDecoderClear(&decoder);
return 0;
}
@@ -615,11 +648,10 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
void tFreeSMCreateStbReq(SMCreateStbReq *pReq) {
taosArrayDestroy(pReq->pColumns);
taosArrayDestroy(pReq->pTags);
- taosMemoryFreeClear(pReq->comment);
+ taosArrayDestroy(pReq->pFuncs);
+ taosMemoryFreeClear(pReq->pComment);
taosMemoryFreeClear(pReq->pAst1);
taosMemoryFreeClear(pReq->pAst2);
- pReq->pColumns = NULL;
- pReq->pTags = NULL;
}
int32_t tSerializeSMDropStbReq(void *buf, int32_t bufLen, SMDropStbReq *pReq) {
@@ -629,6 +661,11 @@ int32_t tSerializeSMDropStbReq(void *buf, int32_t bufLen, SMDropStbReq *pReq) {
if (tStartEncode(&encoder) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->name) < 0) return -1;
if (tEncodeI8(&encoder, pReq->igNotExists) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->source) < 0) return -1;
+ for (int32_t i = 0; i < sizeof(pReq->reserved) / sizeof(int8_t); ++i) {
+ if (tEncodeI8(&encoder, pReq->reserved[i]) < 0) return -1;
+ }
+ if (tEncodeI64(&encoder, pReq->suid) < 0) return -1;
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -643,6 +680,12 @@ int32_t tDeserializeSMDropStbReq(void *buf, int32_t bufLen, SMDropStbReq *pReq)
if (tStartDecode(&decoder) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->name) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->igNotExists) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->source) < 0) return -1;
+ for (int32_t i = 0; i < sizeof(pReq->reserved) / sizeof(int8_t); ++i) {
+ if (tDecodeI8(&decoder, &pReq->reserved[i]) < 0) return -1;
+ }
+ if (tDecodeI64(&decoder, &pReq->suid) < 0) return -1;
+
tEndDecode(&decoder);
tDecoderClear(&decoder);
@@ -656,8 +699,6 @@ int32_t tSerializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq)
if (tStartEncode(&encoder) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->name) < 0) return -1;
if (tEncodeI8(&encoder, pReq->alterType) < 0) return -1;
- if (tEncodeI32(&encoder, pReq->tagVer) < 0) return -1;
- if (tEncodeI32(&encoder, pReq->colVer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->numOfFields) < 0) return -1;
for (int32_t i = 0; i < pReq->numOfFields; ++i) {
SField *pField = taosArrayGet(pReq->pFields, i);
@@ -684,8 +725,6 @@ int32_t tDeserializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq
if (tStartDecode(&decoder) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->name) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->alterType) < 0) return -1;
- if (tDecodeI32(&decoder, &pReq->tagVer) < 0) return -1;
- if (tDecodeI32(&decoder, &pReq->colVer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->numOfFields) < 0) return -1;
pReq->pFields = taosArrayInit(pReq->numOfFields, sizeof(SField));
if (pReq->pFields == NULL) {
@@ -761,6 +800,8 @@ int32_t tSerializeSMCreateSmaReq(void *buf, int32_t bufLen, SMCreateSmaReq *pReq
if (tEncodeI64(&encoder, pReq->interval) < 0) return -1;
if (tEncodeI64(&encoder, pReq->offset) < 0) return -1;
if (tEncodeI64(&encoder, pReq->sliding) < 0) return -1;
+ if (tEncodeI64(&encoder, pReq->watermark) < 0) return -1;
+ if (tEncodeI64(&encoder, pReq->maxDelay) < 0) return -1;
if (tEncodeI32(&encoder, pReq->exprLen) < 0) return -1;
if (tEncodeI32(&encoder, pReq->tagsFilterLen) < 0) return -1;
if (tEncodeI32(&encoder, pReq->sqlLen) < 0) return -1;
@@ -799,6 +840,8 @@ int32_t tDeserializeSMCreateSmaReq(void *buf, int32_t bufLen, SMCreateSmaReq *pR
if (tDecodeI64(&decoder, &pReq->interval) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->offset) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->sliding) < 0) return -1;
+ if (tDecodeI64(&decoder, &pReq->watermark) < 0) return -1;
+ if (tDecodeI64(&decoder, &pReq->maxDelay) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->exprLen) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->tagsFilterLen) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->sqlLen) < 0) return -1;
@@ -927,8 +970,10 @@ int32_t tSerializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) {
if (tEncodeI64(&encoder, pReq->clusterId) < 0) return -1;
if (tEncodeI64(&encoder, pReq->rebootTime) < 0) return -1;
if (tEncodeI64(&encoder, pReq->updateTime) < 0) return -1;
- if (tEncodeI32(&encoder, pReq->numOfCores) < 0) return -1;
+ if (tEncodeFloat(&encoder, pReq->numOfCores) < 0) return -1;
if (tEncodeI32(&encoder, pReq->numOfSupportVnodes) < 0) return -1;
+ if (tEncodeI64(&encoder, pReq->memTotal) < 0) return -1;
+ if (tEncodeI64(&encoder, pReq->memAvail) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->dnodeEp) < 0) return -1;
// cluster cfg
@@ -988,8 +1033,10 @@ int32_t tDeserializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) {
if (tDecodeI64(&decoder, &pReq->clusterId) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->rebootTime) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->updateTime) < 0) return -1;
- if (tDecodeI32(&decoder, &pReq->numOfCores) < 0) return -1;
+ if (tDecodeFloat(&decoder, &pReq->numOfCores) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->numOfSupportVnodes) < 0) return -1;
+ if (tDecodeI64(&decoder, &pReq->memTotal) < 0) return -1;
+ if (tDecodeI64(&decoder, &pReq->memAvail) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->dnodeEp) < 0) return -1;
// cluster cfg
@@ -1478,6 +1525,33 @@ int32_t tDeserializeSMCfgDnodeReq(void *buf, int32_t bufLen, SMCfgDnodeReq *pReq
return 0;
}
+int32_t tSerializeSDCfgDnodeReq(void *buf, int32_t bufLen, SDCfgDnodeReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->config) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->value) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSDCfgDnodeReq(void *buf, int32_t bufLen, SDCfgDnodeReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->config) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->value) < 0) return -1;
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
int32_t tSerializeSCreateDnodeReq(void *buf, int32_t bufLen, SCreateDnodeReq *pReq) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -1757,6 +1831,165 @@ void tFreeSRetrieveFuncRsp(SRetrieveFuncRsp *pRsp) {
taosArrayDestroy(pRsp->pFuncInfos);
}
+int32_t tSerializeSTableCfgReq(void *buf, int32_t bufLen, STableCfgReq *pReq) {
+ int32_t headLen = sizeof(SMsgHead);
+ if (buf != NULL) {
+ buf = (char *)buf + headLen;
+ bufLen -= headLen;
+ }
+
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->dbFName) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->tbName) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+
+ if (buf != NULL) {
+ SMsgHead *pHead = (SMsgHead *)((char *)buf - headLen);
+ pHead->vgId = htonl(pReq->header.vgId);
+ pHead->contLen = htonl(tlen + headLen);
+ }
+
+ return tlen + headLen;
+}
+
+int32_t tDeserializeSTableCfgReq(void *buf, int32_t bufLen, STableCfgReq *pReq) {
+ int32_t headLen = sizeof(SMsgHead);
+
+ SMsgHead *pHead = buf;
+ pHead->vgId = pReq->header.vgId;
+ pHead->contLen = pReq->header.contLen;
+
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, (char *)buf + headLen, bufLen - headLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->dbFName) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->tbName) < 0) return -1;
+
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tSerializeSTableCfgRsp(void *buf, int32_t bufLen, STableCfgRsp *pRsp) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->tbName) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->stbName) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->dbFName) < 0) return -1;
+ if (tEncodeI32(&encoder, pRsp->numOfTags) < 0) return -1;
+ if (tEncodeI32(&encoder, pRsp->numOfColumns) < 0) return -1;
+ if (tEncodeI8(&encoder, pRsp->tableType) < 0) return -1;
+ if (tEncodeI64(&encoder, pRsp->delay1) < 0) return -1;
+ if (tEncodeI64(&encoder, pRsp->delay2) < 0) return -1;
+ if (tEncodeI64(&encoder, pRsp->watermark1) < 0) return -1;
+ if (tEncodeI64(&encoder, pRsp->watermark2) < 0) return -1;
+ if (tEncodeI32(&encoder, pRsp->ttl) < 0) return -1;
+
+ int32_t numOfFuncs = taosArrayGetSize(pRsp->pFuncs);
+ if (tEncodeI32(&encoder, numOfFuncs) < 0) return -1;
+ for (int32_t i = 0; i < numOfFuncs; ++i) {
+ const char *pFunc = taosArrayGet(pRsp->pFuncs, i);
+ if (tEncodeCStr(&encoder, pFunc) < 0) return -1;
+ }
+
+ if (tEncodeI32(&encoder, pRsp->commentLen) < 0) return -1;
+ if (pRsp->commentLen > 0) {
+ if (tEncodeCStr(&encoder, pRsp->pComment) < 0) return -1;
+ }
+
+ for (int32_t i = 0; i < pRsp->numOfColumns + pRsp->numOfTags; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i];
+ if (tEncodeSSchema(&encoder, pSchema) < 0) return -1;
+ }
+
+ if (tEncodeI32(&encoder, pRsp->tagsLen) < 0) return -1;
+ if (tEncodeBinary(&encoder, pRsp->pTags, pRsp->tagsLen) < 0) return -1;
+
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSTableCfgRsp(void *buf, int32_t bufLen, STableCfgRsp *pRsp) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->tbName) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->stbName) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->dbFName) < 0) return -1;
+ if (tDecodeI32(&decoder, &pRsp->numOfTags) < 0) return -1;
+ if (tDecodeI32(&decoder, &pRsp->numOfColumns) < 0) return -1;
+ if (tDecodeI8(&decoder, &pRsp->tableType) < 0) return -1;
+ if (tDecodeI64(&decoder, &pRsp->delay1) < 0) return -1;
+ if (tDecodeI64(&decoder, &pRsp->delay2) < 0) return -1;
+ if (tDecodeI64(&decoder, &pRsp->watermark1) < 0) return -1;
+ if (tDecodeI64(&decoder, &pRsp->watermark2) < 0) return -1;
+ if (tDecodeI32(&decoder, &pRsp->ttl) < 0) return -1;
+
+ int32_t numOfFuncs = 0;
+ if (tDecodeI32(&decoder, &numOfFuncs) < 0) return -1;
+ if (numOfFuncs > 0) {
+ pRsp->pFuncs = taosArrayInit(numOfFuncs, TSDB_FUNC_NAME_LEN);
+ if (NULL == pRsp->pFuncs) return -1;
+ }
+ for (int32_t i = 0; i < numOfFuncs; ++i) {
+ char pFunc[TSDB_FUNC_NAME_LEN];
+ if (tDecodeCStrTo(&decoder, pFunc) < 0) return -1;
+ if (taosArrayPush(pRsp->pFuncs, pFunc) == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ if (tDecodeI32(&decoder, &pRsp->commentLen) < 0) return -1;
+ if (pRsp->commentLen > 0) {
+ if (tDecodeCStrAlloc(&decoder, &pRsp->pComment) < 0) return -1;
+ } else {
+ pRsp->pComment = NULL;
+ }
+
+ int32_t totalCols = pRsp->numOfTags + pRsp->numOfColumns;
+ pRsp->pSchemas = taosMemoryMalloc(sizeof(SSchema) * totalCols);
+ if (pRsp->pSchemas == NULL) return -1;
+
+ for (int32_t i = 0; i < totalCols; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i];
+ if (tDecodeSSchema(&decoder, pSchema) < 0) return -1;
+ }
+
+ if (tDecodeI32(&decoder, &pRsp->tagsLen) < 0) return -1;
+ if (tDecodeBinaryAlloc(&decoder, (void **)&pRsp->pTags, NULL) < 0) return -1;
+
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+void tFreeSTableCfgRsp(STableCfgRsp *pRsp) {
+ if (NULL == pRsp) {
+ return;
+ }
+
+ taosMemoryFreeClear(pRsp->pComment);
+ taosMemoryFreeClear(pRsp->pSchemas);
+ taosMemoryFreeClear(pRsp->pTags);
+
+ taosArrayDestroy(pRsp->pFuncs);
+}
+
int32_t tSerializeSCreateDbReq(void *buf, int32_t bufLen, SCreateDbReq *pReq) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -1768,6 +2001,7 @@ int32_t tSerializeSCreateDbReq(void *buf, int32_t bufLen, SCreateDbReq *pReq) {
if (tEncodeI32(&encoder, pReq->buffer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pageSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pages) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->cacheLastSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysPerFile) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep0) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep1) < 0) return -1;
@@ -1780,7 +2014,7 @@ int32_t tSerializeSCreateDbReq(void *buf, int32_t bufLen, SCreateDbReq *pReq) {
if (tEncodeI8(&encoder, pReq->compression) < 0) return -1;
if (tEncodeI8(&encoder, pReq->replications) < 0) return -1;
if (tEncodeI8(&encoder, pReq->strict) < 0) return -1;
- if (tEncodeI8(&encoder, pReq->cacheLastRow) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->cacheLast) < 0) return -1;
if (tEncodeI8(&encoder, pReq->schemaless) < 0) return -1;
if (tEncodeI8(&encoder, pReq->ignoreExist) < 0) return -1;
if (tEncodeI32(&encoder, pReq->numOfRetensions) < 0) return -1;
@@ -1809,6 +2043,7 @@ int32_t tDeserializeSCreateDbReq(void *buf, int32_t bufLen, SCreateDbReq *pReq)
if (tDecodeI32(&decoder, &pReq->buffer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pageSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pages) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->cacheLastSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysPerFile) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep0) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep1) < 0) return -1;
@@ -1821,7 +2056,7 @@ int32_t tDeserializeSCreateDbReq(void *buf, int32_t bufLen, SCreateDbReq *pReq)
if (tDecodeI8(&decoder, &pReq->compression) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->replications) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->strict) < 0) return -1;
- if (tDecodeI8(&decoder, &pReq->cacheLastRow) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->cacheLast) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->schemaless) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->ignoreExist) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->numOfRetensions) < 0) return -1;
@@ -1863,6 +2098,7 @@ int32_t tSerializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) {
if (tEncodeI32(&encoder, pReq->buffer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pageSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pages) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->cacheLastSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysPerFile) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep0) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep1) < 0) return -1;
@@ -1870,7 +2106,7 @@ int32_t tSerializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) {
if (tEncodeI32(&encoder, pReq->fsyncPeriod) < 0) return -1;
if (tEncodeI8(&encoder, pReq->walLevel) < 0) return -1;
if (tEncodeI8(&encoder, pReq->strict) < 0) return -1;
- if (tEncodeI8(&encoder, pReq->cacheLastRow) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->cacheLast) < 0) return -1;
if (tEncodeI8(&encoder, pReq->replications) < 0) return -1;
tEndEncode(&encoder);
@@ -1888,6 +2124,7 @@ int32_t tDeserializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) {
if (tDecodeI32(&decoder, &pReq->buffer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pageSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pages) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->cacheLastSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysPerFile) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep0) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep1) < 0) return -1;
@@ -1895,7 +2132,7 @@ int32_t tDeserializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) {
if (tDecodeI32(&decoder, &pReq->fsyncPeriod) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->walLevel) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->strict) < 0) return -1;
- if (tDecodeI8(&decoder, &pReq->cacheLastRow) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->cacheLast) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->replications) < 0) return -1;
tEndDecode(&decoder);
@@ -2013,6 +2250,81 @@ int32_t tDeserializeSQnodeListReq(void *buf, int32_t bufLen, SQnodeListReq *pReq
return 0;
}
+int32_t tSerializeSDnodeListReq(void *buf, int32_t bufLen, SDnodeListReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->rowNum) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSDnodeListReq(void *buf, int32_t bufLen, SDnodeListReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->rowNum) < 0) return -1;
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tSerializeSServerVerReq(void *buf, int32_t bufLen, SServerVerReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->useless) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSServerVerReq(void *buf, int32_t bufLen, SServerVerReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->useless) < 0) return -1;
+
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tSerializeSServerVerRsp(void *buf, int32_t bufLen, SServerVerRsp *pRsp) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->ver) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSServerVerRsp(void *buf, int32_t bufLen, SServerVerRsp *pRsp) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->ver) < 0) return -1;
+
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
int32_t tSerializeSQnodeListRsp(void *buf, int32_t bufLen, SQnodeListRsp *pRsp) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -2056,6 +2368,49 @@ int32_t tDeserializeSQnodeListRsp(void *buf, int32_t bufLen, SQnodeListRsp *pRsp
void tFreeSQnodeListRsp(SQnodeListRsp *pRsp) { taosArrayDestroy(pRsp->qnodeList); }
+int32_t tSerializeSDnodeListRsp(void *buf, int32_t bufLen, SDnodeListRsp *pRsp) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ int32_t num = taosArrayGetSize(pRsp->dnodeList);
+ if (tEncodeI32(&encoder, num) < 0) return -1;
+ for (int32_t i = 0; i < num; ++i) {
+ SEpSet *pEpSet = taosArrayGet(pRsp->dnodeList, i);
+ if (tEncodeSEpSet(&encoder, pEpSet) < 0) return -1;
+ }
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSDnodeListRsp(void *buf, int32_t bufLen, SDnodeListRsp *pRsp) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ int32_t num = 0;
+ if (tDecodeI32(&decoder, &num) < 0) return -1;
+ if (NULL == pRsp->dnodeList) {
+ pRsp->dnodeList = taosArrayInit(num, sizeof(SEpSet));
+ if (NULL == pRsp->dnodeList) return -1;
+ }
+
+ for (int32_t i = 0; i < num; ++i) {
+ SEpSet epSet = {0};
+ if (tDecodeSEpSet(&decoder, &epSet) < 0) return -1;
+ taosArrayPush(pRsp->dnodeList, &epSet);
+ }
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+void tFreeSDnodeListRsp(SDnodeListRsp *pRsp) { taosArrayDestroy(pRsp->dnodeList); }
+
int32_t tSerializeSCompactDbReq(void *buf, int32_t bufLen, SCompactDbReq *pReq) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -2292,6 +2647,81 @@ int32_t tDeserializeSDbCfgReq(void *buf, int32_t bufLen, SDbCfgReq *pReq) {
return 0;
}
+int32_t tSerializeSTrimDbReq(void *buf, int32_t bufLen, STrimDbReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->db) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSTrimDbReq(void *buf, int32_t bufLen, STrimDbReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1;
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tSerializeSVTrimDbReq(void *buf, int32_t bufLen, SVTrimDbReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->timestamp) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSVTrimDbReq(void *buf, int32_t bufLen, SVTrimDbReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->timestamp) < 0) return -1;
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tSerializeSVDropTtlTableReq(void *buf, int32_t bufLen, SVDropTtlTableReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->timestamp) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSVDropTtlTableReq(void *buf, int32_t bufLen, SVDropTtlTableReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->timestamp) < 0) return -1;
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
int32_t tSerializeSDbCfgRsp(void *buf, int32_t bufLen, const SDbCfgRsp *pRsp) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -2314,7 +2744,7 @@ int32_t tSerializeSDbCfgRsp(void *buf, int32_t bufLen, const SDbCfgRsp *pRsp) {
if (tEncodeI8(&encoder, pRsp->compression) < 0) return -1;
if (tEncodeI8(&encoder, pRsp->replications) < 0) return -1;
if (tEncodeI8(&encoder, pRsp->strict) < 0) return -1;
- if (tEncodeI8(&encoder, pRsp->cacheLastRow) < 0) return -1;
+ if (tEncodeI8(&encoder, pRsp->cacheLast) < 0) return -1;
if (tEncodeI32(&encoder, pRsp->numOfRetensions) < 0) return -1;
for (int32_t i = 0; i < pRsp->numOfRetensions; ++i) {
SRetention *pRetension = taosArrayGet(pRsp->pRetensions, i);
@@ -2353,12 +2783,14 @@ int32_t tDeserializeSDbCfgRsp(void *buf, int32_t bufLen, SDbCfgRsp *pRsp) {
if (tDecodeI8(&decoder, &pRsp->compression) < 0) return -1;
if (tDecodeI8(&decoder, &pRsp->replications) < 0) return -1;
if (tDecodeI8(&decoder, &pRsp->strict) < 0) return -1;
- if (tDecodeI8(&decoder, &pRsp->cacheLastRow) < 0) return -1;
+ if (tDecodeI8(&decoder, &pRsp->cacheLast) < 0) return -1;
if (tDecodeI32(&decoder, &pRsp->numOfRetensions) < 0) return -1;
- pRsp->pRetensions = taosArrayInit(pRsp->numOfRetensions, sizeof(SRetention));
- if (pRsp->pRetensions == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
+ if (pRsp->numOfRetensions > 0) {
+ pRsp->pRetensions = taosArrayInit(pRsp->numOfRetensions, sizeof(SRetention));
+ if (pRsp->pRetensions == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
}
for (int32_t i = 0; i < pRsp->numOfRetensions; ++i) {
@@ -2552,6 +2984,91 @@ void tFreeSTableIndexInfo(void *info) {
taosMemoryFree(pInfo->expr);
}
+int32_t tSerializeSShowVariablesReq(void *buf, int32_t bufLen, SShowVariablesReq *pReq) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->useless) < 0) return -1;
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSShowVariablesReq(void *buf, int32_t bufLen, SShowVariablesReq *pReq) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->useless) < 0) return -1;
+
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tEncodeSVariablesInfo(SEncoder *pEncoder, SVariablesInfo *pInfo) {
+ if (tEncodeCStr(pEncoder, pInfo->name) < 0) return -1;
+ if (tEncodeCStr(pEncoder, pInfo->value) < 0) return -1;
+ return 0;
+}
+
+int32_t tDecodeSVariablesInfo(SDecoder *pDecoder, SVariablesInfo *pInfo) {
+ if (tDecodeCStrTo(pDecoder, pInfo->name) < 0) return -1;
+ if (tDecodeCStrTo(pDecoder, pInfo->value) < 0) return -1;
+ return 0;
+}
+
+int32_t tSerializeSShowVariablesRsp(void *buf, int32_t bufLen, SShowVariablesRsp *pRsp) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+ int32_t varNum = taosArrayGetSize(pRsp->variables);
+ if (tEncodeI32(&encoder, varNum) < 0) return -1;
+ for (int32_t i = 0; i < varNum; ++i) {
+ SVariablesInfo *pInfo = taosArrayGet(pRsp->variables, i);
+ if (tEncodeSVariablesInfo(&encoder, pInfo) < 0) return -1;
+ }
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSShowVariablesRsp(void *buf, int32_t bufLen, SShowVariablesRsp *pRsp) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ int32_t varNum = 0;
+ if (tDecodeI32(&decoder, &varNum) < 0) return -1;
+ if (varNum > 0) {
+ pRsp->variables = taosArrayInit(varNum, sizeof(SVariablesInfo));
+ if (NULL == pRsp->variables) return -1;
+ for (int32_t i = 0; i < varNum; ++i) {
+ SVariablesInfo info = {0};
+ if (tDecodeSVariablesInfo(&decoder, &info) < 0) return -1;
+ if (NULL == taosArrayPush(pRsp->variables, &info)) return -1;
+ }
+ }
+
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+void tFreeSShowVariablesRsp(SShowVariablesRsp *pRsp) {
+ if (NULL == pRsp) {
+ return;
+ }
+
+ taosArrayDestroy(pRsp->variables);
+}
+
int32_t tSerializeSShowReq(void *buf, int32_t bufLen, SShowReq *pReq) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -2599,6 +3116,7 @@ int32_t tSerializeSRetrieveTableReq(void *buf, int32_t bufLen, SRetrieveTableReq
if (tEncodeI64(&encoder, pReq->showId) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->db) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->tb) < 0) return -1;
+ if (tEncodeCStr(&encoder, pReq->user) < 0) return -1;
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -2614,6 +3132,8 @@ int32_t tDeserializeSRetrieveTableReq(void *buf, int32_t bufLen, SRetrieveTableR
if (tDecodeI64(&decoder, &pReq->showId) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->tb) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pReq->user) < 0) return -1;
+
tEndDecode(&decoder);
tDecoderClear(&decoder);
return 0;
@@ -2956,6 +3476,7 @@ int32_t tSerializeSCMCreateTopicReq(void *buf, int32_t bufLen, const SCMCreateTo
if (tEncodeCStr(&encoder, pReq->name) < 0) return -1;
if (tEncodeI8(&encoder, pReq->igExists) < 0) return -1;
if (tEncodeI8(&encoder, pReq->subType) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->withMeta) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->subDbName) < 0) return -1;
if (TOPIC_SUB_TYPE__DB == pReq->subType) {
} else if (TOPIC_SUB_TYPE__TABLE == pReq->subType) {
@@ -2985,6 +3506,7 @@ int32_t tDeserializeSCMCreateTopicReq(void *buf, int32_t bufLen, SCMCreateTopicR
if (tDecodeCStrTo(&decoder, pReq->name) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->igExists) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->subType) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->withMeta) < 0) return -1;
if (tDecodeCStrTo(&decoder, pReq->subDbName) < 0) return -1;
if (TOPIC_SUB_TYPE__DB == pReq->subType) {
} else if (TOPIC_SUB_TYPE__TABLE == pReq->subType) {
@@ -3052,7 +3574,7 @@ int32_t tSerializeSConnectReq(void *buf, int32_t bufLen, SConnectReq *pReq) {
if (tEncodeCStr(&encoder, pReq->app) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->db) < 0) return -1;
if (tEncodeCStr(&encoder, pReq->user) < 0) return -1;
- if (tEncodeCStr(&encoder, pReq->passwd) < 0) return -1;
+ if (tEncodeCStrWithLen(&encoder, pReq->passwd, TSDB_PASSWORD_LEN) < 0) return -1;
if (tEncodeI64(&encoder, pReq->startTime) < 0) return -1;
tEndEncode(&encoder);
@@ -3091,7 +3613,8 @@ int32_t tSerializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
if (tEncodeI8(&encoder, pRsp->superUser) < 0) return -1;
if (tEncodeI8(&encoder, pRsp->connType) < 0) return -1;
if (tEncodeSEpSet(&encoder, &pRsp->epSet) < 0) return -1;
- if (tEncodeCStr(&encoder, pRsp->sVersion) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->sVer) < 0) return -1;
+ if (tEncodeCStr(&encoder, pRsp->sDetailVer) < 0) return -1;
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -3111,7 +3634,8 @@ int32_t tDeserializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
if (tDecodeI8(&decoder, &pRsp->superUser) < 0) return -1;
if (tDecodeI8(&decoder, &pRsp->connType) < 0) return -1;
if (tDecodeSEpSet(&decoder, &pRsp->epSet) < 0) return -1;
- if (tDecodeCStrTo(&decoder, pRsp->sVersion) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->sVer) < 0) return -1;
+ if (tDecodeCStrTo(&decoder, pRsp->sDetailVer) < 0) return -1;
tEndDecode(&decoder);
tDecoderClear(&decoder);
@@ -3170,6 +3694,7 @@ int32_t tSerializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *pR
if (tEncodeI32(&encoder, pReq->buffer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pageSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pages) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->cacheLastSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysPerFile) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep0) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep1) < 0) return -1;
@@ -3184,7 +3709,7 @@ int32_t tSerializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *pR
if (tEncodeI8(&encoder, pReq->precision) < 0) return -1;
if (tEncodeI8(&encoder, pReq->compression) < 0) return -1;
if (tEncodeI8(&encoder, pReq->strict) < 0) return -1;
- if (tEncodeI8(&encoder, pReq->cacheLastRow) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->cacheLast) < 0) return -1;
if (tEncodeI8(&encoder, pReq->standby) < 0) return -1;
if (tEncodeI8(&encoder, pReq->replica) < 0) return -1;
if (tEncodeI8(&encoder, pReq->selfIndex) < 0) return -1;
@@ -3227,6 +3752,7 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
if (tDecodeI32(&decoder, &pReq->buffer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pageSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pages) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->cacheLastSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysPerFile) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep0) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep1) < 0) return -1;
@@ -3241,7 +3767,7 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
if (tDecodeI8(&decoder, &pReq->precision) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->compression) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->strict) < 0) return -1;
- if (tDecodeI8(&decoder, &pReq->cacheLastRow) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->cacheLast) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->standby) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->replica) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->selfIndex) < 0) return -1;
@@ -3249,7 +3775,6 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
SReplica *pReplica = &pReq->replicas[i];
if (tDecodeSReplica(&decoder, pReplica) < 0) return -1;
}
-
if (tDecodeI32(&decoder, &pReq->numOfRetensions) < 0) return -1;
pReq->pRetensions = taosArrayInit(pReq->numOfRetensions, sizeof(SRetention));
if (pReq->pRetensions == NULL) {
@@ -3271,7 +3796,7 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
if (tDecodeI8(&decoder, &pReq->isTsma) < 0) return -1;
if (pReq->isTsma) {
- if (tDecodeBinaryAlloc(&decoder, &pReq->pTsma, NULL) < 0) return -1;
+ if (tDecodeBinary(&decoder, (uint8_t **)&pReq->pTsma, NULL) < 0) return -1;
}
tEndDecode(&decoder);
@@ -3282,9 +3807,6 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
int32_t tFreeSCreateVnodeReq(SCreateVnodeReq *pReq) {
taosArrayDestroy(pReq->pRetensions);
pReq->pRetensions = NULL;
- if (pReq->isTsma) {
- taosMemoryFreeClear(pReq->pTsma);
- }
return 0;
}
@@ -3355,6 +3877,7 @@ int32_t tSerializeSAlterVnodeReq(void *buf, int32_t bufLen, SAlterVnodeReq *pReq
if (tEncodeI32(&encoder, pReq->buffer) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pageSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->pages) < 0) return -1;
+ if (tEncodeI32(&encoder, pReq->cacheLastSize) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysPerFile) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep0) < 0) return -1;
if (tEncodeI32(&encoder, pReq->daysToKeep1) < 0) return -1;
@@ -3362,14 +3885,13 @@ int32_t tSerializeSAlterVnodeReq(void *buf, int32_t bufLen, SAlterVnodeReq *pReq
if (tEncodeI32(&encoder, pReq->fsyncPeriod) < 0) return -1;
if (tEncodeI8(&encoder, pReq->walLevel) < 0) return -1;
if (tEncodeI8(&encoder, pReq->strict) < 0) return -1;
- if (tEncodeI8(&encoder, pReq->cacheLastRow) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->cacheLast) < 0) return -1;
if (tEncodeI8(&encoder, pReq->selfIndex) < 0) return -1;
if (tEncodeI8(&encoder, pReq->replica) < 0) return -1;
for (int32_t i = 0; i < TSDB_MAX_REPLICA; ++i) {
SReplica *pReplica = &pReq->replicas[i];
if (tEncodeSReplica(&encoder, pReplica) < 0) return -1;
}
-
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -3386,6 +3908,7 @@ int32_t tDeserializeSAlterVnodeReq(void *buf, int32_t bufLen, SAlterVnodeReq *pR
if (tDecodeI32(&decoder, &pReq->buffer) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pageSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->pages) < 0) return -1;
+ if (tDecodeI32(&decoder, &pReq->cacheLastSize) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysPerFile) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep0) < 0) return -1;
if (tDecodeI32(&decoder, &pReq->daysToKeep1) < 0) return -1;
@@ -3393,7 +3916,7 @@ int32_t tDeserializeSAlterVnodeReq(void *buf, int32_t bufLen, SAlterVnodeReq *pR
if (tDecodeI32(&decoder, &pReq->fsyncPeriod) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->walLevel) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->strict) < 0) return -1;
- if (tDecodeI8(&decoder, &pReq->cacheLastRow) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->cacheLast) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->selfIndex) < 0) return -1;
if (tDecodeI8(&decoder, &pReq->replica) < 0) return -1;
for (int32_t i = 0; i < TSDB_MAX_REPLICA; ++i) {
@@ -3890,6 +4413,7 @@ int32_t tSerializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *pR
if (tEncodeU64(&encoder, status->queryId) < 0) return -1;
if (tEncodeU64(&encoder, status->taskId) < 0) return -1;
if (tEncodeI64(&encoder, status->refId) < 0) return -1;
+ if (tEncodeI32(&encoder, status->execId) < 0) return -1;
if (tEncodeI8(&encoder, status->status) < 0) return -1;
}
} else {
@@ -3920,6 +4444,7 @@ int32_t tDeserializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *
if (tDecodeU64(&decoder, &status.queryId) < 0) return -1;
if (tDecodeU64(&decoder, &status.taskId) < 0) return -1;
if (tDecodeI64(&decoder, &status.refId) < 0) return -1;
+ if (tDecodeI32(&decoder, &status.execId) < 0) return -1;
if (tDecodeI8(&decoder, &status.status) < 0) return -1;
taosArrayPush(pRsp->taskStatus, &status);
}
@@ -4222,6 +4747,7 @@ int32_t tSerializeSCMCreateStreamReq(void *buf, int32_t bufLen, const SCMCreateS
if (tEncodeI8(&encoder, pReq->triggerType) < 0) return -1;
if (tEncodeI64(&encoder, pReq->maxDelay) < 0) return -1;
if (tEncodeI64(&encoder, pReq->watermark) < 0) return -1;
+ if (tEncodeI8(&encoder, pReq->igExpired) < 0) return -1;
if (sqlLen > 0 && tEncodeCStr(&encoder, pReq->sql) < 0) return -1;
if (astLen > 0 && tEncodeCStr(&encoder, pReq->ast) < 0) return -1;
@@ -4249,6 +4775,7 @@ int32_t tDeserializeSCMCreateStreamReq(void *buf, int32_t bufLen, SCMCreateStrea
if (tDecodeI8(&decoder, &pReq->triggerType) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->maxDelay) < 0) return -1;
if (tDecodeI64(&decoder, &pReq->watermark) < 0) return -1;
+ if (tDecodeI8(&decoder, &pReq->igExpired) < 0) return -1;
if (sqlLen > 0) {
pReq->sql = taosMemoryCalloc(1, sqlLen + 1);
@@ -4322,9 +4849,8 @@ int32_t tDecodeSRSmaParam(SDecoder *pCoder, SRSmaParam *pRSmaParam) {
if (tDecodeI64v(pCoder, &pRSmaParam->watermark[i]) < 0) return -1;
if (tDecodeI32v(pCoder, &pRSmaParam->qmsgLen[i]) < 0) return -1;
if (pRSmaParam->qmsgLen[i] > 0) {
- uint64_t len;
- if (tDecodeBinaryAlloc(pCoder, (void **)&pRSmaParam->qmsg[i], &len) < 0)
- return -1; // qmsgLen contains len of '\0'
+ tDecoderMalloc(pCoder, pRSmaParam->qmsgLen[i]);
+ if (tDecodeBinary(pCoder, (uint8_t **)&pRSmaParam->qmsg[i], NULL) < 0) return -1; // qmsgLen contains len of '\0'
} else {
pRSmaParam->qmsg[i] = NULL;
}
@@ -4342,7 +4868,12 @@ int tEncodeSVCreateStbReq(SEncoder *pCoder, const SVCreateStbReq *pReq) {
if (tEncodeSSchemaWrapper(pCoder, &pReq->schemaRow) < 0) return -1;
if (tEncodeSSchemaWrapper(pCoder, &pReq->schemaTag) < 0) return -1;
if (pReq->rollup) {
- if (tEncodeSRSmaParam(pCoder, &pReq->pRSmaParam) < 0) return -1;
+ if (tEncodeSRSmaParam(pCoder, &pReq->rsmaParam) < 0) return -1;
+ }
+
+ if (tEncodeI32(pCoder, pReq->alterOriDataLen) < 0) return -1;
+ if (pReq->alterOriDataLen > 0) {
+ if (tEncodeBinary(pCoder, pReq->alterOriData, pReq->alterOriDataLen) < 0) return -1;
}
tEndEncode(pCoder);
@@ -4358,7 +4889,12 @@ int tDecodeSVCreateStbReq(SDecoder *pCoder, SVCreateStbReq *pReq) {
if (tDecodeSSchemaWrapper(pCoder, &pReq->schemaRow) < 0) return -1;
if (tDecodeSSchemaWrapper(pCoder, &pReq->schemaTag) < 0) return -1;
if (pReq->rollup) {
- if (tDecodeSRSmaParam(pCoder, &pReq->pRSmaParam) < 0) return -1;
+ if (tDecodeSRSmaParam(pCoder, &pReq->rsmaParam) < 0) return -1;
+ }
+
+ if (tDecodeI32(pCoder, &pReq->alterOriDataLen) < 0) return -1;
+ if (pReq->alterOriDataLen > 0) {
+ if (tDecodeBinary(pCoder, (uint8_t **)&pReq->alterOriData, NULL) < 0) return -1;
}
tEndDecode(pCoder);
@@ -4404,8 +4940,15 @@ int tEncodeSVCreateTbReq(SEncoder *pCoder, const SVCreateTbReq *pReq) {
}
if (pReq->type == TSDB_CHILD_TABLE) {
+ if (tEncodeCStr(pCoder, pReq->ctb.name) < 0) return -1;
if (tEncodeI64(pCoder, pReq->ctb.suid) < 0) return -1;
if (tEncodeTag(pCoder, (const STag *)pReq->ctb.pTag) < 0) return -1;
+ int32_t len = taosArrayGetSize(pReq->ctb.tagName);
+ if (tEncodeI32(pCoder, len) < 0) return -1;
+ for (int32_t i = 0; i < len; i++){
+ char* name = taosArrayGet(pReq->ctb.tagName, i);
+ if (tEncodeCStr(pCoder, name) < 0) return -1;
+ }
} else if (pReq->type == TSDB_NORMAL_TABLE) {
if (tEncodeSSchemaWrapper(pCoder, &pReq->ntb.schemaRow) < 0) return -1;
} else {
@@ -4433,10 +4976,22 @@ int tDecodeSVCreateTbReq(SDecoder *pCoder, SVCreateTbReq *pReq) {
}
if (pReq->type == TSDB_CHILD_TABLE) {
+ if (tDecodeCStr(pCoder, &pReq->ctb.name) < 0) return -1;
if (tDecodeI64(pCoder, &pReq->ctb.suid) < 0) return -1;
if (tDecodeTag(pCoder, (STag **)&pReq->ctb.pTag) < 0) return -1;
+ int32_t len = 0;
+ if (tDecodeI32(pCoder, &len) < 0) return -1;
+ pReq->ctb.tagName = taosArrayInit(len, TSDB_COL_NAME_LEN);
+ if(pReq->ctb.tagName == NULL) return -1;
+ for (int32_t i = 0; i < len; i++){
+ char name[TSDB_COL_NAME_LEN] = {0};
+ char *tmp = NULL;
+ if (tDecodeCStr(pCoder, &tmp) < 0) return -1;
+ strcpy(name, tmp);
+ taosArrayPush(pReq->ctb.tagName, name);
+ }
} else if (pReq->type == TSDB_NORMAL_TABLE) {
- if (tDecodeSSchemaWrapper(pCoder, &pReq->ntb.schemaRow) < 0) return -1;
+ if (tDecodeSSchemaWrapperEx(pCoder, &pReq->ntb.schemaRow) < 0) return -1;
} else {
ASSERT(0);
}
@@ -4766,6 +5321,7 @@ int32_t tEncodeSVAlterTbReq(SEncoder *pEncoder, const SVAlterTbReq *pReq) {
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
if (tEncodeCStr(pEncoder, pReq->colName) < 0) return -1;
+ if (tEncodeI8(pEncoder, pReq->colModType) < 0) return -1;
if (tEncodeI32v(pEncoder, pReq->colModBytes) < 0) return -1;
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
@@ -4775,6 +5331,7 @@ int32_t tEncodeSVAlterTbReq(SEncoder *pEncoder, const SVAlterTbReq *pReq) {
case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
if (tEncodeCStr(pEncoder, pReq->tagName) < 0) return -1;
if (tEncodeI8(pEncoder, pReq->isNull) < 0) return -1;
+ if (tEncodeI8(pEncoder, pReq->tagType) < 0) return -1;
if (!pReq->isNull) {
if (tEncodeBinary(pEncoder, pReq->pTagVal, pReq->nTagVal) < 0) return -1;
}
@@ -4814,6 +5371,7 @@ int32_t tDecodeSVAlterTbReq(SDecoder *pDecoder, SVAlterTbReq *pReq) {
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
if (tDecodeCStr(pDecoder, &pReq->colName) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pReq->colModType) < 0) return -1;
if (tDecodeI32v(pDecoder, &pReq->colModBytes) < 0) return -1;
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
@@ -4823,6 +5381,7 @@ int32_t tDecodeSVAlterTbReq(SDecoder *pDecoder, SVAlterTbReq *pReq) {
case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
if (tDecodeCStr(pDecoder, &pReq->tagName) < 0) return -1;
if (tDecodeI8(pDecoder, &pReq->isNull) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pReq->tagType) < 0) return -1;
if (!pReq->isNull) {
if (tDecodeBinary(pDecoder, &pReq->pTagVal, &pReq->nTagVal) < 0) return -1;
}
@@ -4939,30 +5498,184 @@ void tFreeSMAlterStbRsp(SMAlterStbRsp *pRsp) {
}
}
-int32_t tEncodeSTqOffset(SEncoder *pEncoder, const STqOffset *pOffset) {
- if (tEncodeI8(pEncoder, pOffset->type) < 0) return -1;
- if (pOffset->type == TMQ_OFFSET__SNAPSHOT) {
- if (tEncodeI64(pEncoder, pOffset->uid) < 0) return -1;
- if (tEncodeI64(pEncoder, pOffset->ts) < 0) return -1;
- } else if (pOffset->type == TMQ_OFFSET__LOG) {
- if (tEncodeI64(pEncoder, pOffset->version) < 0) return -1;
+int32_t tEncodeSTqOffsetVal(SEncoder *pEncoder, const STqOffsetVal *pOffsetVal) {
+ if (tEncodeI8(pEncoder, pOffsetVal->type) < 0) return -1;
+ if (pOffsetVal->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ if (tEncodeI64(pEncoder, pOffsetVal->uid) < 0) return -1;
+ if (tEncodeI64(pEncoder, pOffsetVal->ts) < 0) return -1;
+ } else if (pOffsetVal->type == TMQ_OFFSET__LOG) {
+ if (tEncodeI64(pEncoder, pOffsetVal->version) < 0) return -1;
+ } else if (pOffsetVal->type < 0) {
+ // do nothing
} else {
ASSERT(0);
}
- if (tEncodeCStr(pEncoder, pOffset->subKey) < 0) return -1;
return 0;
}
-int32_t tDecodeSTqOffset(SDecoder *pDecoder, STqOffset *pOffset) {
- if (tDecodeI8(pDecoder, &pOffset->type) < 0) return -1;
- if (pOffset->type == TMQ_OFFSET__SNAPSHOT) {
- if (tDecodeI64(pDecoder, &pOffset->uid) < 0) return -1;
- if (tDecodeI64(pDecoder, &pOffset->ts) < 0) return -1;
- } else if (pOffset->type == TMQ_OFFSET__LOG) {
- if (tDecodeI64(pDecoder, &pOffset->version) < 0) return -1;
+int32_t tDecodeSTqOffsetVal(SDecoder *pDecoder, STqOffsetVal *pOffsetVal) {
+ if (tDecodeI8(pDecoder, &pOffsetVal->type) < 0) return -1;
+ if (pOffsetVal->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ if (tDecodeI64(pDecoder, &pOffsetVal->uid) < 0) return -1;
+ if (tDecodeI64(pDecoder, &pOffsetVal->ts) < 0) return -1;
+ } else if (pOffsetVal->type == TMQ_OFFSET__LOG) {
+ if (tDecodeI64(pDecoder, &pOffsetVal->version) < 0) return -1;
+ } else if (pOffsetVal->type < 0) {
+ // do nothing
} else {
ASSERT(0);
}
+ return 0;
+}
+
+#if 1
+int32_t tFormatOffset(char *buf, int32_t maxLen, const STqOffsetVal *pVal) {
+ if (pVal->type == TMQ_OFFSET__RESET_NONE) {
+ snprintf(buf, maxLen, "offset(reset to none)");
+ } else if (pVal->type == TMQ_OFFSET__RESET_EARLIEAST) {
+ snprintf(buf, maxLen, "offset(reset to earlieast)");
+ } else if (pVal->type == TMQ_OFFSET__RESET_LATEST) {
+ snprintf(buf, maxLen, "offset(reset to latest)");
+ } else if (pVal->type == TMQ_OFFSET__LOG) {
+ snprintf(buf, maxLen, "offset(log) ver:%" PRId64, pVal->version);
+ } else if (pVal->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ snprintf(buf, maxLen, "offset(ss data) uid:%" PRId64 ", ts:%" PRId64, pVal->uid, pVal->ts);
+ } else if (pVal->type == TMQ_OFFSET__SNAPSHOT_META) {
+ snprintf(buf, maxLen, "offset(ss meta) uid:%" PRId64 ", ts:%" PRId64, pVal->uid, pVal->ts);
+ } else {
+ ASSERT(0);
+ }
+ return 0;
+}
+#endif
+
+bool tOffsetEqual(const STqOffsetVal *pLeft, const STqOffsetVal *pRight) {
+ if (pLeft->type == pRight->type) {
+ if (pLeft->type == TMQ_OFFSET__LOG) {
+ return pLeft->version == pRight->version;
+ } else if (pLeft->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ return pLeft->uid == pRight->uid && pLeft->ts == pRight->ts;
+ } else if (pLeft->type == TMQ_OFFSET__SNAPSHOT_META) {
+ ASSERT(0);
+ // TODO
+ return pLeft->uid == pRight->uid && pLeft->ts == pRight->ts;
+ } else {
+ ASSERT(0);
+ /*ASSERT(pLeft->type == TMQ_OFFSET__RESET_NONE || pLeft->type == TMQ_OFFSET__RESET_EARLIEAST ||*/
+ /*pLeft->type == TMQ_OFFSET__RESET_LATEST);*/
+ /*return true;*/
+ }
+ }
+ return false;
+}
+
+int32_t tEncodeSTqOffset(SEncoder *pEncoder, const STqOffset *pOffset) {
+ if (tEncodeSTqOffsetVal(pEncoder, &pOffset->val) < 0) return -1;
+ if (tEncodeCStr(pEncoder, pOffset->subKey) < 0) return -1;
+ return 0;
+}
+
+int32_t tDecodeSTqOffset(SDecoder *pDecoder, STqOffset *pOffset) {
+ if (tDecodeSTqOffsetVal(pDecoder, &pOffset->val) < 0) return -1;
if (tDecodeCStrTo(pDecoder, pOffset->subKey) < 0) return -1;
return 0;
}
+
+int32_t tEncodeDeleteRes(SEncoder *pCoder, const SDeleteRes *pRes) {
+ int32_t nUid = taosArrayGetSize(pRes->uidList);
+
+ if (tEncodeU64(pCoder, pRes->suid) < 0) return -1;
+ if (tEncodeI32v(pCoder, nUid) < 0) return -1;
+ for (int32_t iUid = 0; iUid < nUid; iUid++) {
+ if (tEncodeU64(pCoder, *(uint64_t *)taosArrayGet(pRes->uidList, iUid)) < 0) return -1;
+ }
+ if (tEncodeI64(pCoder, pRes->skey) < 0) return -1;
+ if (tEncodeI64(pCoder, pRes->ekey) < 0) return -1;
+ if (tEncodeI64v(pCoder, pRes->affectedRows) < 0) return -1;
+
+ return 0;
+}
+
+int32_t tDecodeDeleteRes(SDecoder *pCoder, SDeleteRes *pRes) {
+ int32_t nUid;
+ uint64_t uid;
+
+ if (tDecodeU64(pCoder, &pRes->suid) < 0) return -1;
+ if (tDecodeI32v(pCoder, &nUid) < 0) return -1;
+ for (int32_t iUid = 0; iUid < nUid; iUid++) {
+ if (tDecodeU64(pCoder, &uid) < 0) return -1;
+ taosArrayPush(pRes->uidList, &uid);
+ }
+ if (tDecodeI64(pCoder, &pRes->skey) < 0) return -1;
+ if (tDecodeI64(pCoder, &pRes->ekey) < 0) return -1;
+ if (tDecodeI64v(pCoder, &pRes->affectedRows) < 0) return -1;
+
+ return 0;
+}
+int32_t tEncodeSMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
+ if (tEncodeSTqOffsetVal(pEncoder, &pRsp->reqOffset) < 0) return -1;
+ if (tEncodeSTqOffsetVal(pEncoder, &pRsp->rspOffset) < 0) return -1;
+ if (tEncodeI32(pEncoder, pRsp->skipLogNum) < 0) return -1;
+ if (tEncodeI32(pEncoder, pRsp->blockNum) < 0) return -1;
+ if (pRsp->blockNum != 0) {
+ if (tEncodeI8(pEncoder, pRsp->withTbName) < 0) return -1;
+ if (tEncodeI8(pEncoder, pRsp->withSchema) < 0) return -1;
+
+ for (int32_t i = 0; i < pRsp->blockNum; i++) {
+ int32_t bLen = *(int32_t *)taosArrayGet(pRsp->blockDataLen, i);
+ void *data = taosArrayGetP(pRsp->blockData, i);
+ if (tEncodeBinary(pEncoder, (const uint8_t *)data, bLen) < 0) return -1;
+ if (pRsp->withSchema) {
+ SSchemaWrapper *pSW = (SSchemaWrapper *)taosArrayGetP(pRsp->blockSchema, i);
+ if (tEncodeSSchemaWrapper(pEncoder, pSW) < 0) return -1;
+ }
+ if (pRsp->withTbName) {
+ char *tbName = (char *)taosArrayGetP(pRsp->blockTbName, i);
+ if (tEncodeCStr(pEncoder, tbName) < 0) return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
+ if (tDecodeSTqOffsetVal(pDecoder, &pRsp->reqOffset) < 0) return -1;
+ if (tDecodeSTqOffsetVal(pDecoder, &pRsp->rspOffset) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pRsp->skipLogNum) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pRsp->blockNum) < 0) return -1;
+ if (pRsp->blockNum != 0) {
+ pRsp->blockData = taosArrayInit(pRsp->blockNum, sizeof(void *));
+ pRsp->blockDataLen = taosArrayInit(pRsp->blockNum, sizeof(int32_t));
+ if (tDecodeI8(pDecoder, &pRsp->withTbName) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pRsp->withSchema) < 0) return -1;
+ if (pRsp->withTbName) {
+ pRsp->blockTbName = taosArrayInit(pRsp->blockNum, sizeof(void *));
+ }
+ if (pRsp->withSchema) {
+ pRsp->blockSchema = taosArrayInit(pRsp->blockNum, sizeof(void *));
+ }
+
+ for (int32_t i = 0; i < pRsp->blockNum; i++) {
+ void *data;
+ uint64_t bLen;
+ if (tDecodeBinaryAlloc(pDecoder, &data, &bLen) < 0) return -1;
+ taosArrayPush(pRsp->blockData, &data);
+ int32_t len = bLen;
+ taosArrayPush(pRsp->blockDataLen, &len);
+
+ if (pRsp->withSchema) {
+ SSchemaWrapper *pSW = (SSchemaWrapper *)taosMemoryCalloc(1, sizeof(SSchemaWrapper));
+ if (pSW == NULL) return -1;
+ if (tDecodeSSchemaWrapper(pDecoder, pSW) < 0) return -1;
+ taosArrayPush(pRsp->blockSchema, &pSW);
+ }
+
+ if (pRsp->withTbName) {
+ char *tbName;
+ if (tDecodeCStrAlloc(pDecoder, &tbName) < 0) return -1;
+ taosArrayPush(pRsp->blockTbName, &tbName);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/source/common/src/tname.c b/source/common/src/tname.c
index b67b3ca1f15e9129b7de4ce6a42db20adbfa36e4..7183153824de9192b02674045241bafe80b07545 100644
--- a/source/common/src/tname.c
+++ b/source/common/src/tname.c
@@ -115,6 +115,14 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, in
#endif
+SName* toName(int32_t acctId, const char* pDbName, const char* pTableName, SName* pName) {
+ pName->type = TSDB_TABLE_NAME_T;
+ pName->acctId = acctId;
+ strcpy(pName->dbname, pDbName);
+ strcpy(pName->tname, pTableName);
+ return pName;
+}
+
int32_t tNameExtractFullName(const SName* name, char* dst) {
assert(name != NULL && dst != NULL);
@@ -214,6 +222,20 @@ int32_t tNameSetDbName(SName* dst, int32_t acct, const char* dbName, size_t name
return 0;
}
+int32_t tNameAddTbName(SName* dst, const char* tbName, size_t nameLen) {
+ assert(dst != NULL && tbName != NULL && nameLen > 0);
+
+ // too long account id or too long db name
+ if (nameLen >= tListLen(dst->tname) || nameLen <= 0) {
+ return -1;
+ }
+
+ dst->type = TSDB_TABLE_NAME_T;
+ tstrncpy(dst->tname, tbName, nameLen + 1);
+ return 0;
+}
+
+
int32_t tNameSetAcctId(SName* dst, int32_t acctId) {
assert(dst != NULL);
dst->acctId = acctId;
@@ -240,6 +262,15 @@ bool tNameDBNameEqual(SName* left, SName* right) {
return (0 == strcmp(left->dbname, right->dbname));
}
+bool tNameTbNameEqual(SName* left, SName* right) {
+ bool equal = tNameDBNameEqual(left, right);
+ if (equal) {
+ return (0 == strcmp(left->tname, right->tname));
+ }
+
+ return equal;
+}
+
int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
assert(dst != NULL && str != NULL && strlen(str) > 0);
diff --git a/source/common/src/trow.c b/source/common/src/trow.c
index c8a28d7f28f747b65fae3802bc392ac6163e5e1e..f64250bce61210bf94f116512c19885aebf3f42b 100644
--- a/source/common/src/trow.c
+++ b/source/common/src/trow.c
@@ -32,26 +32,9 @@ const uint8_t tdVTypeByte[2][3] = {{
};
// declaration
-static uint8_t tdGetBitmapByte(uint8_t byte);
-static int32_t tdCompareColId(const void *arg1, const void *arg2);
-
-// static void dataColSetNEleNull(SDataCol *pCol, int nEle);
-
-/**
- * @brief src2 data has more priority than src1
- *
- * @param target
- * @param src1
- * @param iter1
- * @param limit1
- * @param src2
- * @param iter2
- * @param limit2
- * @param tRows
- * @param update
- */
-static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
- int limit2, int tRows, bool update);
+static uint8_t tdGetBitmapByte(uint8_t byte);
+static int32_t tdCompareColId(const void *arg1, const void *arg2);
+static FORCE_INLINE int32_t compareKvRowColId(const void *key1, const void *key2);
// implementation
/**
@@ -286,33 +269,6 @@ void tdMergeBitmap(uint8_t *srcBitmap, int32_t nBits, uint8_t *dstBitmap) {
}
}
-static FORCE_INLINE void dataColSetNullAt(SDataCol *pCol, int index, bool setBitmap, int8_t bitmapMode) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pCol->dataOff[index] = pCol->len;
- char *ptr = POINTER_SHIFT(pCol->pData, pCol->len);
- setVardataNull(ptr, pCol->type);
- pCol->len += varDataTLen(ptr);
- } else {
- setNull(POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * index), pCol->type, pCol->bytes);
- pCol->len += TYPE_BYTES[pCol->type];
- }
- if (setBitmap) {
- tdSetBitmapValType(pCol->pBitmap, index, TD_VTYPE_NONE, bitmapMode);
- }
-}
-
-// static void dataColSetNEleNull(SDataCol *pCol, int nEle) {
-// if (IS_VAR_DATA_TYPE(pCol->type)) {
-// pCol->len = 0;
-// for (int i = 0; i < nEle; i++) {
-// dataColSetNullAt(pCol, i);
-// }
-// } else {
-// setNullN(pCol->pData, pCol->type, pCol->bytes, nEle);
-// pCol->len = TYPE_BYTES[pCol->type] * nEle;
-// }
-// }
-
/**
* @brief Set bitmap area by byte preferentially and then by bit.
*
@@ -339,9 +295,9 @@ int32_t tdSetBitmapValTypeN(void *pBitmap, int16_t nEle, TDRowValT valType, int8
}
bool tdIsBitmapBlkNorm(const void *pBitmap, int32_t numOfBits, int8_t bitmapMode) {
- int32_t nBytes = (bitmapMode == 0 ? numOfBits / TD_VTYPE_PARTS : numOfBits / TD_VTYPE_PARTS_I);
- uint8_t vTypeByte = tdVTypeByte[bitmapMode][TD_VTYPE_NORM];
- uint8_t *qBitmap = (uint8_t*)pBitmap;
+ int32_t nBytes = (bitmapMode == 0 ? numOfBits / TD_VTYPE_PARTS : numOfBits / TD_VTYPE_PARTS_I);
+ uint8_t vTypeByte = tdVTypeByte[bitmapMode][TD_VTYPE_NORM];
+ uint8_t *qBitmap = (uint8_t *)pBitmap;
for (int i = 0; i < nBytes; ++i) {
if (*qBitmap != vTypeByte) {
return false;
@@ -361,56 +317,6 @@ bool tdIsBitmapBlkNorm(const void *pBitmap, int32_t numOfBits, int8_t bitmapMode
return true;
}
-static FORCE_INLINE void dataColSetNoneAt(SDataCol *pCol, int index, bool setBitmap, int8_t bitmapMode) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pCol->dataOff[index] = pCol->len;
- char *ptr = POINTER_SHIFT(pCol->pData, pCol->len);
- setVardataNull(ptr, pCol->type);
- pCol->len += varDataTLen(ptr);
- } else {
- setNull(POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * index), pCol->type, pCol->bytes);
- pCol->len += TYPE_BYTES[pCol->type];
- }
- if (setBitmap) {
- tdSetBitmapValType(pCol->pBitmap, index, TD_VTYPE_NONE, bitmapMode);
- }
-}
-
-static void dataColSetNEleNone(SDataCol *pCol, int nEle, int8_t bitmapMode) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pCol->len = 0;
- for (int i = 0; i < nEle; ++i) {
- dataColSetNoneAt(pCol, i, false, bitmapMode);
- }
- } else {
- setNullN(pCol->pData, pCol->type, pCol->bytes, nEle);
- pCol->len = TYPE_BYTES[pCol->type] * nEle;
- }
-#ifdef TD_SUPPORT_BITMAP
- tdSetBitmapValTypeN(pCol->pBitmap, nEle, TD_VTYPE_NONE, bitmapMode);
-#endif
-}
-
-#if 0
-void trbSetRowInfo(SRowBuilder *pRB, bool del, uint16_t sver) {
- // TODO
-}
-
-void trbSetRowVersion(SRowBuilder *pRB, uint64_t ver) {
- // TODO
-}
-
-void trbSetRowTS(SRowBuilder *pRB, TSKEY ts) {
- // TODO
-}
-
-int trbWriteCol(SRowBuilder *pRB, void *pData, col_id_t cid) {
- // TODO
- return 0;
-}
-
-#endif
-
STSRow *tdRowDup(STSRow *row) {
STSRow *trow = taosMemoryMalloc(TD_ROW_LEN(row));
if (trow == NULL) return NULL;
@@ -419,511 +325,6 @@ STSRow *tdRowDup(STSRow *row) {
return trow;
}
-/**
- * @brief
- *
- * @param pCol
- * @param valType
- * @param val
- * @param numOfRows
- * @param maxPoints
- * @param bitmapMode default is 0(2 bits), otherwise 1(1 bit)
- * @param isMerge merge to current row
- * @return int
- */
-int tdAppendValToDataCol(SDataCol *pCol, TDRowValT valType, const void *val, int numOfRows, int maxPoints,
- int8_t bitmapMode, bool isMerge) {
- TASSERT(pCol != NULL);
-
- // Assume that the columns not specified during insert/upsert mean None.
- if (isAllRowsNone(pCol)) {
- if (tdValIsNone(valType)) {
- // all None value yet, just return
- return 0;
- }
-
- if (tdAllocMemForCol(pCol, maxPoints) < 0) return -1;
- if (numOfRows > 0) {
- // Find the first not None value, fill all previous values as None
- dataColSetNEleNone(pCol, numOfRows, bitmapMode);
- }
- }
- const void *value = val;
- if (!tdValTypeIsNorm(valType) || !val) {
- // TODO:
- // 1. back compatibility and easy to debug with codes of 2.0 to save NULL values.
- // 2. later on, considering further optimization, don't save Null/None for VarType.
- value = getNullValue(pCol->type);
- }
- if (!isMerge) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- // set offset
- pCol->dataOff[numOfRows] = pCol->len;
- // Copy data
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, varDataTLen(value));
- // Update the length
- pCol->len += varDataTLen(value);
- } else {
- ASSERT(pCol->len == TYPE_BYTES[pCol->type] * numOfRows);
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes);
- pCol->len += pCol->bytes;
- }
- } else if (!tdValTypeIsNone(valType)) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- // keep the last offset
- // discard the last var data
- int32_t lastVarLen = varDataTLen(POINTER_SHIFT(pCol->pData, pCol->dataOff[numOfRows]));
- pCol->len -= lastVarLen;
- // Copy data
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, varDataTLen(value));
- // Update the length
- pCol->len += varDataTLen(value);
- } else {
- ASSERT(pCol->len - TYPE_BYTES[pCol->type] == TYPE_BYTES[pCol->type] * numOfRows);
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len - TYPE_BYTES[pCol->type]), value, pCol->bytes);
- }
- }
-
-#ifdef TD_SUPPORT_BITMAP
- if (!isMerge || !tdValTypeIsNone(valType)) {
- tdSetBitmapValType(pCol->pBitmap, numOfRows, valType, bitmapMode);
- }
-#endif
- return 0;
-}
-
-// internal
-static int32_t tdAppendTpRowToDataCol(STSRow *pRow, STSchema *pSchema, SDataCols *pCols, bool isMerge) {
-#if 0
- ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < TD_ROW_KEY(pRow));
-#endif
-
- // Multi-Version rows with the same key and different versions supported
- ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) <= TD_ROW_KEY(pRow));
-
- int rcol = 1;
- int dcol = 1;
- void *pBitmap = tdGetBitmapAddrTp(pRow, pSchema->flen);
-
- SDataCol *pDataCol = &(pCols->cols[0]);
- ASSERT(pDataCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NORM, &pRow->ts, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
-
- while (dcol < pCols->numOfCols) {
- pDataCol = &(pCols->cols[dcol]);
- if (rcol >= schemaNCols(pSchema)) {
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NULL, NULL, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- continue;
- }
-
- STColumn *pRowCol = schemaColAt(pSchema, rcol);
- SCellVal sVal = {0};
- if (pRowCol->colId == pDataCol->colId) {
- if (tdGetTpRowValOfCol(&sVal, pRow, pBitmap, pRowCol->type, pRowCol->offset - sizeof(TSKEY), rcol - 1) < 0) {
- return terrno;
- }
- tdAppendValToDataCol(pDataCol, sVal.valType, sVal.val, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- ++rcol;
- } else if (pRowCol->colId < pDataCol->colId) {
- ++rcol;
- } else {
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NULL, NULL, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- }
- }
-#if 0
- ++pCols->numOfRows;
-#endif
-
- return TSDB_CODE_SUCCESS;
-}
-// internal
-static int32_t tdAppendKvRowToDataCol(STSRow *pRow, STSchema *pSchema, SDataCols *pCols, bool isMerge) {
- ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < TD_ROW_KEY(pRow));
-
- int rcol = 0;
- int dcol = 1;
- int tRowCols = tdRowGetNCols(pRow) - 1; // the primary TS key not included in kvRowColIdx part
- int tSchemaCols = schemaNCols(pSchema) - 1;
- void *pBitmap = tdGetBitmapAddrKv(pRow, tdRowGetNCols(pRow));
-
- SDataCol *pDataCol = &(pCols->cols[0]);
- ASSERT(pDataCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NORM, &pRow->ts, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
-
- while (dcol < pCols->numOfCols) {
- pDataCol = &(pCols->cols[dcol]);
- if (rcol >= tRowCols || rcol >= tSchemaCols) {
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NULL, NULL, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- continue;
- }
-
- SKvRowIdx *pIdx = tdKvRowColIdxAt(pRow, rcol);
- int16_t colIdx = -1;
- if (pIdx) {
- colIdx = POINTER_DISTANCE(pIdx, TD_ROW_COL_IDX(pRow)) / sizeof(SKvRowIdx);
- }
- TASSERT(colIdx >= 0);
- SCellVal sVal = {0};
- if (pIdx->colId == pDataCol->colId) {
- if (tdGetKvRowValOfCol(&sVal, pRow, pBitmap, pIdx->offset, colIdx) < 0) {
- return terrno;
- }
- tdAppendValToDataCol(pDataCol, sVal.valType, sVal.val, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- ++rcol;
- } else if (pIdx->colId < pDataCol->colId) {
- ++rcol;
- } else {
- tdAppendValToDataCol(pDataCol, TD_VTYPE_NULL, NULL, pCols->numOfRows, pCols->maxPoints, pCols->bitmapMode,
- isMerge);
- ++dcol;
- }
- }
-#if 0
- ++pCols->numOfRows;
-#endif
-
- return TSDB_CODE_SUCCESS;
-}
-
-/**
- * @brief exposed
- *
- * @param pRow
- * @param pSchema
- * @param pCols
- */
-int32_t tdAppendSTSRowToDataCol(STSRow *pRow, STSchema *pSchema, SDataCols *pCols, bool isMerge) {
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printf("%s:%d ts: %" PRIi64 " sver:%d maxCols:%" PRIi16 " nCols:%" PRIi16 ", nRows:%d\n", __func__, __LINE__,
- TD_ROW_KEY(pRow), TD_ROW_SVER(pRow), pCols->maxCols, pCols->numOfCols, pCols->numOfRows);
-#endif
- if (TD_IS_TP_ROW(pRow)) {
- return tdAppendTpRowToDataCol(pRow, pSchema, pCols, isMerge);
- } else if (TD_IS_KV_ROW(pRow)) {
- return tdAppendKvRowToDataCol(pRow, pSchema, pCols, isMerge);
- } else {
- ASSERT(0);
- }
- return TSDB_CODE_SUCCESS;
-}
-
-/**
- * @brief source data has more priority than target
- *
- * @param target
- * @param source
- * @param rowsToMerge
- * @param pOffset
- * @param update
- * @param maxVer
- * @return int
- */
-int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset, bool update,
- TDRowVerT maxVer) {
- ASSERT(rowsToMerge > 0 && rowsToMerge <= source->numOfRows);
- ASSERT(target->numOfCols == source->numOfCols);
- int offset = 0;
-
- if (pOffset == NULL) {
- pOffset = &offset;
- }
-
- SDataCols *pTarget = NULL;
-
- if ((target->numOfRows == 0) || (dataColsKeyLast(target) < dataColsKeyAtRow(source, *pOffset))) { // No overlap
- ASSERT(target->numOfRows + rowsToMerge <= target->maxPoints);
- // TODO: filter the maxVer
- TSKEY lastKey = TSKEY_INITIAL_VAL;
- for (int i = 0; i < rowsToMerge; ++i) {
- bool merge = false;
- for (int j = 0; j < source->numOfCols; j++) {
- if (source->cols[j].len > 0 || target->cols[j].len > 0) {
- SCellVal sVal = {0};
- if (tdGetColDataOfRow(&sVal, source->cols + j, i + (*pOffset), source->bitmapMode) < 0) {
- TASSERT(0);
- }
-
- if (j == 0) {
- if (lastKey == *(TSKEY *)sVal.val) {
- if (!update) {
- break;
- }
- merge = true;
- } else if (lastKey != TSKEY_INITIAL_VAL) {
- ++target->numOfRows;
- }
-
- lastKey = *(TSKEY *)sVal.val;
- }
- if (i == 0) {
- (target->cols + j)->bitmap = (source->cols + j)->bitmap;
- }
-
- tdAppendValToDataCol(target->cols + j, sVal.valType, sVal.val, target->numOfRows, target->maxPoints,
- target->bitmapMode, merge);
- }
- }
- }
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++target->numOfRows;
- }
- (*pOffset) += rowsToMerge;
- } else {
- pTarget = tdDupDataCols(target, true);
- if (pTarget == NULL) goto _err;
-
- int iter1 = 0;
- tdMergeTwoDataCols(target, pTarget, &iter1, pTarget->numOfRows, source, pOffset, source->numOfRows,
- pTarget->numOfRows + rowsToMerge, update);
- }
-
- tdFreeDataCols(pTarget);
- return 0;
-
-_err:
- tdFreeDataCols(pTarget);
- return -1;
-}
-
-static void tdAppendValToDataCols(SDataCols *target, SDataCols *src, int iter, bool isMerge) {
- for (int i = 0; i < src->numOfCols; ++i) {
- ASSERT(target->cols[i].type == src->cols[i].type);
- if (src->cols[i].len > 0 || target->cols[i].len > 0) {
- SCellVal sVal = {0};
- if (tdGetColDataOfRow(&sVal, src->cols + i, iter, src->bitmapMode) < 0) {
- TASSERT(0);
- }
- if (isMerge) {
- if (!tdValTypeIsNone(sVal.valType)) {
- tdAppendValToDataCol(&(target->cols[i]), sVal.valType, sVal.val, target->numOfRows, target->maxPoints,
- target->bitmapMode, isMerge);
- } else {
- // Keep the origin value for None
- }
- } else {
- tdAppendValToDataCol(&(target->cols[i]), sVal.valType, sVal.val, target->numOfRows, target->maxPoints,
- target->bitmapMode, isMerge);
- }
- }
- }
-}
-/**
- * @brief src2 data has more priority than src1
- *
- * @param target
- * @param src1
- * @param iter1
- * @param limit1
- * @param src2
- * @param iter2
- * @param limit2
- * @param tRows
- * @param update
- */
-static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
- int limit2, int tRows, bool update) {
- tdResetDataCols(target);
- target->bitmapMode = src1->bitmapMode;
- ASSERT(limit1 <= src1->numOfRows && limit2 <= src2->numOfRows);
- int32_t nRows = 0;
-
- // TODO: filter the maxVer
- // TODO: handle the delete function
- TSKEY lastKey = TSKEY_INITIAL_VAL;
- while (nRows < tRows) {
- if (*iter1 >= limit1 && *iter2 >= limit2) break;
-
- TSKEY key1 = (*iter1 >= limit1) ? INT64_MAX : dataColsKeyAt(src1, *iter1);
- // TKEY tkey1 = (*iter1 >= limit1) ? TKEY_NULL : dataColsTKeyAt(src1, *iter1);
- TSKEY key2 = (*iter2 >= limit2) ? INT64_MAX : dataColsKeyAt(src2, *iter2);
- // TKEY tkey2 = (*iter2 >= limit2) ? TKEY_NULL : dataColsTKeyAt(src2, *iter2);
-
- // ASSERT(tkey1 == TKEY_NULL || (!TKEY_IS_DELETED(tkey1)));
-
- if (key1 <= key2) {
- // select key1 if not delete
- if (update && (lastKey == key1)) {
- tdAppendValToDataCols(target, src1, *iter1, true);
- } else if (lastKey != key1) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++target->numOfRows;
- }
- tdAppendValToDataCols(target, src1, *iter1, false);
- }
- ++nRows;
- ++(*iter1);
- lastKey = key1;
- } else {
- // use key2 if not deleted
- // TODO: handle the delete function
- if (update && (lastKey == key2)) {
- tdAppendValToDataCols(target, src2, *iter2, true);
- } else if (lastKey != key2) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++target->numOfRows;
- }
- tdAppendValToDataCols(target, src2, *iter2, false);
- }
-
- ++nRows;
- ++(*iter2);
- lastKey = key2;
- }
-
- ASSERT(target->numOfRows <= target->maxPoints - 1);
- }
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++target->numOfRows;
- }
-}
-
-STSRow *mergeTwoRows(void *buffer, STSRow *row1, STSRow *row2, STSchema *pSchema1, STSchema *pSchema2) {
-#if 0
- ASSERT(TD_ROW_KEY(row1) == TD_ROW_KEY(row2));
- ASSERT(schemaVersion(pSchema1) == TD_ROW_SVER(row1));
- ASSERT(schemaVersion(pSchema2) == TD_ROW_SVER(row2));
- ASSERT(schemaVersion(pSchema1) >= schemaVersion(pSchema2));
-#endif
-
-#if 0
- SArray *stashRow = taosArrayInit(pSchema1->numOfCols, sizeof(SColInfo));
- if (stashRow == NULL) {
- return NULL;
- }
-
- STSRow pRow = buffer;
- STpRow dataRow = memRowDataBody(pRow);
- memRowSetType(pRow, SMEM_ROW_DATA);
- dataRowSetVersion(dataRow, schemaVersion(pSchema1)); // use latest schema version
- dataRowSetLen(dataRow, (TDRowLenT)(TD_DATA_ROW_HEAD_SIZE + pSchema1->flen));
-
- TDRowLenT dataLen = 0, kvLen = TD_MEM_ROW_KV_HEAD_SIZE;
-
- int32_t i = 0; // row1
- int32_t j = 0; // row2
- int32_t nCols1 = schemaNCols(pSchema1);
- int32_t nCols2 = schemaNCols(pSchema2);
- SColInfo colInfo = {0};
- int32_t kvIdx1 = 0, kvIdx2 = 0;
-
- while (i < nCols1) {
- STColumn *pCol = schemaColAt(pSchema1, i);
- void * val1 = tdGetMemRowDataOfColEx(row1, pCol->colId, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset, &kvIdx1);
- // if val1 != NULL, use val1;
- if (val1 != NULL && !isNull(val1, pCol->type)) {
- tdAppendColVal(dataRow, val1, pCol->type, pCol->offset);
- kvLen += tdGetColAppendLen(SMEM_ROW_KV, val1, pCol->type);
- setSColInfo(&colInfo, pCol->colId, pCol->type, val1);
- taosArrayPush(stashRow, &colInfo);
- ++i; // next col
- continue;
- }
-
- void *val2 = NULL;
- while (j < nCols2) {
- STColumn *tCol = schemaColAt(pSchema2, j);
- if (tCol->colId < pCol->colId) {
- ++j;
- continue;
- }
- if (tCol->colId == pCol->colId) {
- val2 = tdGetMemRowDataOfColEx(row2, tCol->colId, tCol->type, TD_DATA_ROW_HEAD_SIZE + tCol->offset, &kvIdx2);
- } else if (tCol->colId > pCol->colId) {
- // set NULL
- }
- break;
- } // end of while(jtype);
- }
- tdAppendColVal(dataRow, val2, pCol->type, pCol->offset);
- if (!isNull(val2, pCol->type)) {
- kvLen += tdGetColAppendLen(SMEM_ROW_KV, val2, pCol->type);
- setSColInfo(&colInfo, pCol->colId, pCol->type, val2);
- taosArrayPush(stashRow, &colInfo);
- }
-
- ++i; // next col
- }
-
- dataLen = TD_ROW_LEN(pRow);
-
- if (kvLen < dataLen) {
- // scan stashRow and generate SKVRow
- memset(buffer, 0, sizeof(dataLen));
- STSRow tRow = buffer;
- memRowSetType(tRow, SMEM_ROW_KV);
- SKVRow kvRow = (SKVRow)memRowKvBody(tRow);
- int16_t nKvNCols = (int16_t) taosArrayGetSize(stashRow);
- kvRowSetLen(kvRow, (TDRowLenT)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nKvNCols));
- kvRowSetNCols(kvRow, nKvNCols);
- memRowSetKvVersion(tRow, pSchema1->version);
-
- int32_t toffset = 0;
- int16_t k;
- for (k = 0; k < nKvNCols; ++k) {
- SColInfo *pColInfo = taosArrayGet(stashRow, k);
- tdAppendKvColVal(kvRow, pColInfo->colVal, true, pColInfo->colId, pColInfo->colType, toffset);
- toffset += sizeof(SColIdx);
- }
- ASSERT(kvLen == TD_ROW_LEN(tRow));
- }
- taosArrayDestroy(stashRow);
- return buffer;
-#endif
- return NULL;
-}
-
-SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
- SDataCols *pRet = tdNewDataCols(pDataCols->maxCols, pDataCols->maxPoints);
- if (pRet == NULL) return NULL;
-
- pRet->numOfCols = pDataCols->numOfCols;
- pRet->bitmapMode = pDataCols->bitmapMode;
- pRet->sversion = pDataCols->sversion;
- if (keepData) pRet->numOfRows = pDataCols->numOfRows;
-
- for (int i = 0; i < pDataCols->numOfCols; ++i) {
- pRet->cols[i].type = pDataCols->cols[i].type;
- pRet->cols[i].bitmap = pDataCols->cols[i].bitmap;
- pRet->cols[i].colId = pDataCols->cols[i].colId;
- pRet->cols[i].bytes = pDataCols->cols[i].bytes;
- pRet->cols[i].offset = pDataCols->cols[i].offset;
-
- if (keepData) {
- if (pDataCols->cols[i].len > 0) {
- if (tdAllocMemForCol(&pRet->cols[i], pRet->maxPoints) < 0) {
- tdFreeDataCols(pRet);
- return NULL;
- }
- pRet->cols[i].len = pDataCols->cols[i].len;
- memcpy(pRet->cols[i].pData, pDataCols->cols[i].pData, pDataCols->cols[i].len);
- if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) {
- int dataOffSize = sizeof(VarDataOffsetT) * pDataCols->maxPoints;
- memcpy(pRet->cols[i].dataOff, pDataCols->cols[i].dataOff, dataOffSize);
- }
- if (!TD_COL_ROWS_NORM(pRet->cols + i)) {
- memcpy(pRet->cols[i].pBitmap, pDataCols->cols[i].pBitmap, TD_BITMAP_BYTES(pDataCols->numOfRows));
- }
- }
- }
- }
-
- return pRet;
-}
-
void tdSRowPrint(STSRow *row, STSchema *pSchema, const char *tag) {
STSRowIter iter = {0};
tdSTSRowIterInit(&iter, pSchema);
@@ -1019,39 +420,28 @@ void tdSCellValPrint(SCellVal *pVal, int8_t colType) {
}
}
-int32_t dataColGetNEleLen(SDataCol *pDataCol, int32_t rows, int8_t bitmapMode) {
- ASSERT(rows > 0);
- int32_t result = 0;
-
- if (IS_VAR_DATA_TYPE(pDataCol->type)) {
- result += pDataCol->dataOff[rows - 1];
- SCellVal val = {0};
- if (tdGetColDataOfRow(&val, pDataCol, rows - 1, bitmapMode) < 0) {
- TASSERT(0);
- }
-
- // Currently, count the varDataTLen in of Null/None cols considering back compatibility test for 2.4
- result += varDataTLen(val.val);
- // TODO: later on, don't save Null/None for VarDataT for 3.0
- // if (tdValTypeIsNorm(val.valType)) {
- // result += varDataTLen(val.val);
- // }
- } else {
- result += TYPE_BYTES[pDataCol->type] * rows;
+bool tdSKvRowGetVal(STSRow *pRow, col_id_t colId, col_id_t colIdx, SCellVal *pVal) {
+ if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
+ tdRowSetVal(pVal, TD_VTYPE_NORM, TD_ROW_KEY_ADDR(pRow));
+ return true;
+ }
+ int16_t nCols = tdRowGetNCols(pRow) - 1;
+ if (nCols <= 0) {
+ pVal->valType = TD_VTYPE_NONE;
+ return true;
}
- ASSERT(pDataCol->len == result);
-
- return result;
-}
+ SKvRowIdx *pColIdx =
+ (SKvRowIdx *)taosbsearch(&colId, TD_ROW_COL_IDX(pRow), nCols, sizeof(SKvRowIdx), compareKvRowColId, TD_EQ);
-bool tdSKvRowGetVal(STSRow *pRow, col_id_t colId, uint32_t offset, col_id_t colIdx, SCellVal *pVal) {
- if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
- tdRowSetVal(pVal, TD_VTYPE_NORM, TD_ROW_KEY_ADDR(pRow));
+ if (!pColIdx) {
+ pVal->valType = TD_VTYPE_NONE;
return true;
}
+
void *pBitmap = tdGetBitmapAddrKv(pRow, tdRowGetNCols(pRow));
- tdGetKvRowValOfCol(pVal, pRow, pBitmap, offset, colIdx);
+ tdGetKvRowValOfCol(pVal, pRow, pBitmap, pColIdx->offset,
+ POINTER_DISTANCE(pColIdx, TD_ROW_COL_IDX(pRow)) / sizeof(SKvRowIdx));
return true;
}
@@ -1066,40 +456,6 @@ bool tdSTpRowGetVal(STSRow *pRow, col_id_t colId, col_type_t colType, int32_t fl
return true;
}
-int32_t tdGetColDataOfRow(SCellVal *pVal, SDataCol *pCol, int32_t row, int8_t bitmapMode) {
- if (isAllRowsNone(pCol)) {
- pVal->valType = TD_VTYPE_NONE;
-#ifdef TD_SUPPORT_READ2
- pVal->val = (void *)getNullValue(pCol->type);
-#else
- pVal->val = NULL;
-#endif
- return TSDB_CODE_SUCCESS;
- }
-
- if (TD_COL_ROWS_NORM(pCol)) {
- pVal->valType = TD_VTYPE_NORM;
- } else if (tdGetBitmapValType(pCol->pBitmap, row, &(pVal->valType), bitmapMode) < 0) {
- return terrno;
- }
-
- if (tdValTypeIsNorm(pVal->valType)) {
- if (IS_VAR_DATA_TYPE(pCol->type)) {
- pVal->val = POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
- } else {
- pVal->val = POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
- }
- } else {
- pVal->valType = TD_VTYPE_NULL;
-#ifdef TD_SUPPORT_READ2
- pVal->val = (void *)getNullValue(pCol->type);
-#else
- pVal->val = NULL;
-#endif
- }
- return TSDB_CODE_SUCCESS;
-}
-
bool tdSTSRowIterNext(STSRowIter *pIter, col_id_t colId, col_type_t colType, SCellVal *pVal) {
if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
pVal->val = &pIter->pRow->ts;
@@ -1204,6 +560,112 @@ static FORCE_INLINE int32_t compareKvRowColId(const void *key1, const void *key2
}
}
+int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow) {
+ STColumn *pTColumn;
+ SColVal *pColVal;
+ int32_t nColVal = taosArrayGetSize(pArray);
+ int32_t varDataLen = 0;
+ int32_t maxVarDataLen = 0;
+ int32_t iColVal = 0;
+ void *varBuf = NULL;
+
+ ASSERT(nColVal > 1);
+
+ for (int32_t iColumn = 0; iColumn < pTSchema->numOfCols; ++iColumn) {
+ pTColumn = &pTSchema->columns[iColumn];
+ if (iColVal < nColVal) {
+ pColVal = (SColVal *)taosArrayGet(pArray, iColVal);
+ } else {
+ pColVal = NULL;
+ }
+
+ if (iColumn == 0) {
+ ASSERT(pColVal->cid == pTColumn->colId);
+ ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP);
+ ASSERT(pTColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
+ } else {
+ if (IS_VAR_DATA_TYPE(pTColumn->type)) {
+ if (pColVal) {
+ varDataLen += (pColVal->value.nData + sizeof(VarDataLenT));
+ if (maxVarDataLen < (pColVal->value.nData + sizeof(VarDataLenT))) {
+ maxVarDataLen = pColVal->value.nData + sizeof(VarDataLenT);
+ }
+ } else {
+ varDataLen += sizeof(VarDataLenT);
+ if (pTColumn->type == TSDB_DATA_TYPE_VARCHAR) {
+ varDataLen += CHAR_BYTES;
+ if (maxVarDataLen < CHAR_BYTES + sizeof(VarDataLenT)) {
+ maxVarDataLen = CHAR_BYTES + sizeof(VarDataLenT);
+ }
+ } else {
+ varDataLen += INT_BYTES;
+ if (maxVarDataLen < INT_BYTES + sizeof(VarDataLenT)) {
+ maxVarDataLen = INT_BYTES + sizeof(VarDataLenT);
+ }
+ }
+ }
+ }
+ }
+
+ ++iColVal;
+ }
+
+ *ppRow = (STSRow *)taosMemoryCalloc(
+ 1, sizeof(STSRow) + pTSchema->flen + varDataLen + TD_BITMAP_BYTES(pTSchema->numOfCols - 1));
+
+ if (!(*ppRow)) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ if (maxVarDataLen > 0) {
+ varBuf = taosMemoryMalloc(maxVarDataLen);
+ if (!varBuf) {
+ taosMemoryFreeClear(*ppRow);
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ SRowBuilder rb = {0};
+ tdSRowInit(&rb, pTSchema->version);
+ tdSRowSetInfo(&rb, pTSchema->numOfCols, pTSchema->numOfCols, pTSchema->flen);
+ tdSRowResetBuf(&rb, *ppRow);
+
+ iColVal = 0;
+ for (int32_t iColumn = 0; iColumn < pTSchema->numOfCols; ++iColumn) {
+ pTColumn = &pTSchema->columns[iColumn];
+
+ TDRowValT valType = TD_VTYPE_NORM;
+ const void *val = NULL;
+ if (iColVal < nColVal) {
+ pColVal = (SColVal *)taosArrayGet(pArray, iColVal);
+ if (pColVal->isNone) {
+ valType = TD_VTYPE_NONE;
+ } else if (pColVal->isNull) {
+ valType = TD_VTYPE_NULL;
+ } else if (IS_VAR_DATA_TYPE(pTColumn->type)) {
+ varDataSetLen(varBuf, pColVal->value.nData);
+ memcpy(varDataVal(varBuf), pColVal->value.pData, pColVal->value.nData);
+ val = varBuf;
+ } else {
+ val = (const void *)&pColVal->value.i64;
+ }
+ } else {
+ pColVal = NULL;
+ valType = TD_VTYPE_NONE;
+ }
+
+ tdAppendColValToRow(&rb, pTColumn->colId, pTColumn->type, valType, val, true, pTColumn->offset, iColVal);
+
+ ++iColVal;
+ }
+
+ taosMemoryFreeClear(varBuf);
+
+ return 0;
+}
+
bool tdSTSRowGetVal(STSRowIter *pIter, col_id_t colId, col_type_t colType, SCellVal *pVal) {
if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
pVal->val = &pIter->pRow->ts;
@@ -1593,7 +1055,6 @@ int32_t tdSRowSetExtendedInfo(SRowBuilder *pBuilder, int32_t nCols, int32_t nBou
} else {
pBuilder->rowType = TD_ROW_TP;
}
-
pBuilder->flen = flen;
pBuilder->nCols = nCols;
pBuilder->nBoundCols = nBoundCols;
@@ -1855,4 +1316,36 @@ void tdSTSRowIterReset(STSRowIter *pIter, STSRow *pRow) {
void tdSTSRowIterInit(STSRowIter *pIter, STSchema *pSchema) {
pIter->pSchema = pSchema;
pIter->maxColId = pSchema->columns[pSchema->numOfCols - 1].colId;
-}
\ No newline at end of file
+}
+
+void tTSRowGetVal(STSRow *pRow, STSchema *pTSchema, int16_t iCol, SColVal *pColVal) {
+ STColumn *pTColumn = &pTSchema->columns[iCol];
+ SCellVal cv;
+ SValue value;
+
+ ASSERT(iCol > 0);
+
+ if (TD_IS_TP_ROW(pRow)) {
+ tdSTpRowGetVal(pRow, pTColumn->colId, pTColumn->type, pTSchema->flen, pTColumn->offset, iCol - 1, &cv);
+ } else if (TD_IS_KV_ROW(pRow)) {
+ ASSERT(iCol > 0);
+ tdSKvRowGetVal(pRow, pTColumn->colId, iCol - 1, &cv);
+ } else {
+ ASSERT(0);
+ }
+
+ if (tdValTypeIsNone(cv.valType)) {
+ *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type);
+ } else if (tdValTypeIsNull(cv.valType)) {
+ *pColVal = COL_VAL_NULL(pTColumn->colId, pTColumn->type);
+ } else {
+ if (IS_VAR_DATA_TYPE(pTColumn->type)) {
+ value.nData = varDataLen(cv.val);
+ value.pData = varDataVal(cv.val);
+ } else {
+ tGetValue(cv.val, &value, pTColumn->type);
+ }
+
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, value);
+ }
+}
diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c
index 0b59e9b6cc611a9da3362fbef3da410376c0ea58..d728bbe49e9aecda349c34e5d9ec8528172ec271 100644
--- a/source/common/src/ttime.c
+++ b/source/common/src/ttime.c
@@ -76,22 +76,28 @@ void deltaToUtcInitOnce() {
static int64_t parseFraction(char* str, char** end, int32_t timePrec);
static int32_t parseTimeWithTz(const char* timestr, int64_t* time, int32_t timePrec, char delim);
-static int32_t parseLocaltime(char* timestr, int32_t len, int64_t* utime, int32_t timePrec);
-static int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec);
+static int32_t parseLocaltime(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim);
+static int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim);
static char* forwardToTimeStringEnd(char* str);
static bool checkTzPresent(const char* str, int32_t len);
-static int32_t (*parseLocaltimeFp[])(char* timestr, int32_t len, int64_t* utime, int32_t timePrec) = {parseLocaltime,
- parseLocaltimeDst};
+static int32_t (*parseLocaltimeFp[])(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim) = {parseLocaltime,
+ parseLocaltimeDst};
int32_t taosParseTime(const char* timestr, int64_t* utime, int32_t len, int32_t timePrec, int8_t day_light) {
/* parse datatime string in with tz */
if (strnchr(timestr, 'T', len, false) != NULL) {
- return parseTimeWithTz(timestr, utime, timePrec, 'T');
- } else if (checkTzPresent(timestr, len)) {
- return parseTimeWithTz(timestr, utime, timePrec, 0);
+ if (checkTzPresent(timestr, len)) {
+ return parseTimeWithTz(timestr, utime, timePrec, 'T');
+ } else {
+ return (*parseLocaltimeFp[day_light])((char*)timestr, len, utime, timePrec, 'T');
+ }
} else {
- return (*parseLocaltimeFp[day_light])((char*)timestr, len, utime, timePrec);
+ if (checkTzPresent(timestr, len)) {
+ return parseTimeWithTz(timestr, utime, timePrec, 0);
+ } else {
+ return (*parseLocaltimeFp[day_light])((char*)timestr, len, utime, timePrec, 0);
+ }
}
}
@@ -333,13 +339,25 @@ static FORCE_INLINE bool validateTm(struct tm* pTm) {
return true;
}
-int32_t parseLocaltime(char* timestr, int32_t len, int64_t* time, int32_t timePrec) {
+int32_t parseLocaltime(char* timestr, int32_t len, int64_t* time, int32_t timePrec, char delim) {
*time = 0;
struct tm tm = {0};
- char* str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
+ char *str;
+ if (delim == 'T') {
+ str = taosStrpTime(timestr, "%Y-%m-%dT%H:%M:%S", &tm);
+ } else if (delim == 0) {
+ str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
+ } else {
+ str = NULL;
+ }
+
if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
- return -1;
+ //if parse failed, try "%Y-%m-%d" format
+ str = taosStrpTime(timestr, "%Y-%m-%d", &tm);
+ if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
+ return -1;
+ }
}
#ifdef _MSC_VER
@@ -367,14 +385,26 @@ int32_t parseLocaltime(char* timestr, int32_t len, int64_t* time, int32_t timePr
return 0;
}
-int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* time, int32_t timePrec) {
+int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* time, int32_t timePrec, char delim) {
*time = 0;
struct tm tm = {0};
tm.tm_isdst = -1;
- char* str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
+ char *str;
+ if (delim == 'T') {
+ str = taosStrpTime(timestr, "%Y-%m-%dT%H:%M:%S", &tm);
+ } else if (delim == 0) {
+ str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
+ } else {
+ str = NULL;
+ }
+
if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
- return -1;
+ //if parse failed, try "%Y-%m-%d" format
+ str = taosStrpTime(timestr, "%Y-%m-%d", &tm);
+ if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
+ return -1;
+ }
}
/* mktime will be affected by TZ, set by using taos_options */
@@ -559,7 +589,7 @@ int32_t convertStringToTimestamp(int16_t type, char *inputData, int64_t timePrec
return TSDB_CODE_FAILED;
}
newColData[len] = 0;
- int32_t ret = taosParseTime(newColData, timeVal, len + 1, (int32_t)timePrec, tsDaylight);
+ int32_t ret = taosParseTime(newColData, timeVal, len, (int32_t)timePrec, tsDaylight);
if (ret != TSDB_CODE_SUCCESS) {
taosMemoryFree(newColData);
return ret;
@@ -680,6 +710,32 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) {
return (int64_t)(taosMktime(&tm) * TSDB_TICK_PER_SECOND(precision));
}
+int64_t taosTimeSub(int64_t t, int64_t duration, char unit, int32_t precision) {
+ if (duration == 0) {
+ return t;
+ }
+
+ if (unit != 'n' && unit != 'y') {
+ return t - duration;
+ }
+
+ // The following code handles the y/n time duration
+ int64_t numOfMonth = duration;
+ if (unit == 'y') {
+ numOfMonth *= 12;
+ }
+
+ struct tm tm;
+ time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision));
+ taosLocalTime(&tt, &tm);
+ int32_t mon = tm.tm_year * 12 + tm.tm_mon - (int32_t)numOfMonth;
+ tm.tm_year = mon / 12;
+ tm.tm_mon = mon % 12;
+
+ return (int64_t)(taosMktime(&tm) * TSDB_TICK_PER_SECOND(precision));
+}
+
+
int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char unit, int32_t precision) {
if (ekey < skey) {
int64_t tmp = ekey;
diff --git a/source/common/src/ttszip.c b/source/common/src/ttszip.c
index 3160d64c12b7e18a5af98f497e8d66d4c5a985d1..03353b0de633c32cfbd5ff89ce800617d9603f57 100644
--- a/source/common/src/ttszip.c
+++ b/source/common/src/ttszip.c
@@ -845,11 +845,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf) {
int64_t offset = getDataStartOffset();
int32_t size = (int32_t)pSrcBuf->fileSize - (int32_t)offset;
-#if defined(_TD_DARWIN_64)
- int64_t written = taosFSendFile(pDestBuf->pFile->fp, pSrcBuf->pFile->fp, &offset, size);
-#else
int64_t written = taosFSendFile(pDestBuf->pFile, pSrcBuf->pFile, &offset, size);
-#endif
if (written == -1 || written != size) {
return -1;
diff --git a/source/common/src/tvariant.c b/source/common/src/tvariant.c
index 7b0bef4918394b777ff8836245e1d22c14d156a8..0810be149716e58fdac74b67db6946fde7db62e9 100644
--- a/source/common/src/tvariant.c
+++ b/source/common/src/tvariant.c
@@ -155,7 +155,8 @@ void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uin
void taosVariantDestroy(SVariant *pVar) {
if (pVar == NULL) return;
- if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR) {
+ if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR
+ || pVar->nType == TSDB_DATA_TYPE_JSON) {
taosMemoryFreeClear(pVar->pz);
pVar->nLen = 0;
}
@@ -184,7 +185,8 @@ void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
if (pSrc == NULL || pDst == NULL) return;
pDst->nType = pSrc->nType;
- if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
+ if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR
+ || pSrc->nType == TSDB_DATA_TYPE_JSON) {
int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
char *p = taosMemoryRealloc(pDst->pz, len);
assert(p);
@@ -976,6 +978,7 @@ char *taosVariantGet(SVariant *pVar, int32_t type) {
case TSDB_DATA_TYPE_FLOAT:
return (char *)&pVar->d;
case TSDB_DATA_TYPE_BINARY:
+ case TSDB_DATA_TYPE_JSON:
return (char *)pVar->pz;
case TSDB_DATA_TYPE_NCHAR:
return (char *)pVar->ucs4;
diff --git a/source/common/test/commonTests.cpp b/source/common/test/commonTests.cpp
index 2adb558d011aadc5e75c3f04d6c5ab6dfb4888d6..8460d71e56ea70b5b5bc5c5a536476c98e007716 100644
--- a/source/common/test/commonTests.cpp
+++ b/source/common/test/commonTests.cpp
@@ -88,26 +88,15 @@ TEST(testCase, toInteger_test) {
}
TEST(testCase, Datablock_test) {
- SSDataBlock* b = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
- b->info.numOfCols = 2;
- b->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
-
- SColumnInfoData infoData = {0};
- infoData.info.bytes = 4;
- infoData.info.type = TSDB_DATA_TYPE_INT;
- infoData.info.colId = 1;
+ SSDataBlock* b = createDataBlock();
- infoData.pData = (char*)taosMemoryCalloc(40, infoData.info.bytes);
- infoData.nullbitmap = (char*)taosMemoryCalloc(1, sizeof(char) * (40 / 8));
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_INT, 4, 1);
taosArrayPush(b->pDataBlock, &infoData);
+ blockDataAppendColInfo(b, &infoData);
- SColumnInfoData infoData1 = {0};
- infoData1.info.bytes = 40;
- infoData1.info.type = TSDB_DATA_TYPE_BINARY;
- infoData1.info.colId = 2;
-
- infoData1.varmeta.offset = (int32_t*)taosMemoryCalloc(40, sizeof(uint32_t));
- taosArrayPush(b->pDataBlock, &infoData1);
+ SColumnInfoData infoData1 = createColumnInfoData(TSDB_DATA_TYPE_BINARY, 40, 2);
+ blockDataAppendColInfo(b, &infoData1);
+ blockDataEnsureCapacity(b, 40);
char* str = "the value of: %d";
char buf[128] = {0};
@@ -222,28 +211,17 @@ TEST(testCase, non_var_dataBlock_split_test) {
#endif
TEST(testCase, var_dataBlock_split_test) {
- SSDataBlock* b = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
- b->info.numOfCols = 2;
- b->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
-
int32_t numOfRows = 1000000;
- SColumnInfoData infoData = {0};
- infoData.info.bytes = 4;
- infoData.info.type = TSDB_DATA_TYPE_INT;
- infoData.info.colId = 1;
+ SSDataBlock* b = createDataBlock();
- infoData.pData = (char*)taosMemoryCalloc(numOfRows, infoData.info.bytes);
- infoData.nullbitmap = (char*)taosMemoryCalloc(1, sizeof(char) * (numOfRows / 8));
- taosArrayPush(b->pDataBlock, &infoData);
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_INT, 4, 1);
+ blockDataAppendColInfo(b, &infoData);
- SColumnInfoData infoData1 = {0};
- infoData1.info.bytes = 40;
- infoData1.info.type = TSDB_DATA_TYPE_BINARY;
- infoData1.info.colId = 2;
+ SColumnInfoData infoData1 = createColumnInfoData(TSDB_DATA_TYPE_BINARY, 40, 2);
+ blockDataAppendColInfo(b, &infoData1);
- infoData1.varmeta.offset = (int32_t*)taosMemoryCalloc(numOfRows, sizeof(uint32_t));
- taosArrayPush(b->pDataBlock, &infoData1);
+ blockDataEnsureCapacity(b, numOfRows);
char buf[41] = {0};
char buf1[100] = {0};
diff --git a/source/common/test/dataformatTest.cpp b/source/common/test/dataformatTest.cpp
index a52bb6b516f06953150873647634f3db82d563b0..d16e35ff073d5f1928dc3ee17f5a0f4f657da99e 100644
--- a/source/common/test/dataformatTest.cpp
+++ b/source/common/test/dataformatTest.cpp
@@ -285,8 +285,8 @@ int32_t debugPrintSColVal(SColVal *cv, int8_t type) {
}
void debugPrintTSRow(STSRow2 *row, STSchema *pTSchema, const char *tags, int32_t ln) {
- printf("%s:%d %s:v%d:%d ", tags, ln, (row->flags & 0xf0) ? "KV" : "TP", row->sver, row->nData);
- for (int16_t i = 0; i < schemaNCols(pTSchema); ++i) {
+ // printf("%s:%d %s:v%d:%d ", tags, ln, (row->flags & 0xf0) ? "KV" : "TP", row->sver, row->nData);
+ for (int16_t i = 0; i < pTSchema->numOfCols; ++i) {
SColVal cv = {0};
tTSRowGet(row, pTSchema, i, &cv);
debugPrintSColVal(&cv, pTSchema->columns[i].type);
@@ -393,7 +393,7 @@ static int32_t checkSColVal(const char *rawVal, SColVal *cv, int8_t type) {
}
static void checkTSRow(const char **data, STSRow2 *row, STSchema *pTSchema) {
- for (int16_t i = 0; i < schemaNCols(pTSchema); ++i) {
+ for (int16_t i = 0; i < pTSchema->numOfCols; ++i) {
SColVal cv = {0};
tTSRowGet(row, pTSchema, i, &cv);
checkSColVal(data[i], &cv, pTSchema->columns[i].type);
diff --git a/source/dnode/mgmt/exe/dmMain.c b/source/dnode/mgmt/exe/dmMain.c
index 2b0f6a01a0b87cdee8d071d1e53bad398ea90f97..00c32e19907e488c915d4e10ab6865de603716d3 100644
--- a/source/dnode/mgmt/exe/dmMain.c
+++ b/source/dnode/mgmt/exe/dmMain.c
@@ -216,7 +216,7 @@ int main(int argc, char const *argv[]) {
return -1;
}
- dInfo("start to open dnode");
+ dInfo("start to init service");
dmSetSignalHandle();
int32_t code = dmRun();
dInfo("shutting down the service");
diff --git a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h
index ee811c0071cbd07c03edb7aaf117c3c4461adebb..4479c06bea5b16701790c43472bb9201e61e57a6 100644
--- a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h
+++ b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h
@@ -45,6 +45,7 @@ int32_t dmProcessConfigReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t dmProcessAuthRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t dmProcessGrantRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t dmProcessServerRunStatus(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
+int32_t dmProcessRetrieve(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
// dmWorker.c
int32_t dmPutNodeMsgToMgmtQueue(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c
index 3e55469a4a3a7d551b6015b051cac184d38944f7..5f982ad3a45ed7ab5b6c81925acc8226ba9936fc 100644
--- a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c
+++ b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c
@@ -15,10 +15,13 @@
#define _DEFAULT_SOURCE
#include "dmInt.h"
+#include "systable.h"
+
+extern SConfig *tsCfg;
static void dmUpdateDnodeCfg(SDnodeMgmt *pMgmt, SDnodeCfg *pCfg) {
if (pMgmt->pData->dnodeId == 0 || pMgmt->pData->clusterId == 0) {
- dInfo("set dnodeId:%d clusterId:%" PRId64, pCfg->dnodeId, pCfg->clusterId);
+ dInfo("set local info, dnodeId:%d clusterId:%" PRId64, pCfg->dnodeId, pCfg->clusterId);
taosThreadRwlockWrlock(&pMgmt->pData->lock);
pMgmt->pData->dnodeId = pCfg->dnodeId;
pMgmt->pData->clusterId = pCfg->clusterId;
@@ -64,6 +67,8 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) {
req.updateTime = pMgmt->pData->updateTime;
req.numOfCores = tsNumOfCores;
req.numOfSupportVnodes = tsNumOfSupportVnodes;
+ req.memTotal = tsTotalMemoryKB * 1024;
+ req.memAvail = req.memTotal - tsRpcQueueMemoryAllowed - 16 * 1024 * 1024;
tstrncpy(req.dnodeEp, tsLocalEp, TSDB_EP_LEN);
req.clusterCfg.statusInterval = tsStatusInterval;
@@ -79,7 +84,7 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) {
(*pMgmt->getVnodeLoadsFp)(&vinfo);
req.pVloads = vinfo.pVloads;
- SMonMloadInfo minfo = {0};
+ SMonMloadInfo minfo = {0};
(*pMgmt->getMnodeLoadsFp)(&minfo);
req.mload = minfo.load;
@@ -119,8 +124,15 @@ int32_t dmProcessGrantRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
}
int32_t dmProcessConfigReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
- dError("config req is received, but not supported yet");
- return TSDB_CODE_OPS_NOT_SUPPORT;
+ SDCfgDnodeReq cfgReq = {0};
+ if (tDeserializeSDCfgDnodeReq(pMsg->pCont, pMsg->contLen, &cfgReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ dInfo("start to config, option:%s, value:%s", cfgReq.config, cfgReq.value);
+ taosCfgDynamicOptions(cfgReq.config, cfgReq.value);
+ return 0;
}
static void dmGetServerRunStatus(SDnodeMgmt *pMgmt, SServerStatusRsp *pStatus) {
@@ -175,6 +187,131 @@ int32_t dmProcessServerRunStatus(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
return 0;
}
+SSDataBlock *dmBuildVariablesBlock(void) {
+ SSDataBlock *pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ size_t size = 0;
+ const SSysTableMeta *pMeta = NULL;
+ getInfosDbMeta(&pMeta, &size);
+
+ int32_t index = 0;
+ for (int32_t i = 0; i < size; ++i) {
+ if (strcmp(pMeta[i].name, TSDB_INS_TABLE_DNODE_VARIABLES) == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ pBlock->pDataBlock = taosArrayInit(pMeta[index].colNum, sizeof(SColumnInfoData));
+
+ for (int32_t i = 0; i < pMeta[index].colNum; ++i) {
+ SColumnInfoData colInfoData = {0};
+ colInfoData.info.colId = i + 1;
+ colInfoData.info.type = pMeta[index].schema[i].type;
+ colInfoData.info.bytes = pMeta[index].schema[i].bytes;
+ taosArrayPush(pBlock->pDataBlock, &colInfoData);
+ }
+
+ pBlock->info.hasVarCol = true;
+
+ return pBlock;
+}
+
+int32_t dmAppendVariablesToBlock(SSDataBlock *pBlock, int32_t dnodeId) {
+ int32_t numOfCfg = taosArrayGetSize(tsCfg->array);
+ int32_t numOfRows = 0;
+ blockDataEnsureCapacity(pBlock, numOfCfg);
+
+ for (int32_t i = 0, c = 0; i < numOfCfg; ++i, c = 0) {
+ SConfigItem *pItem = taosArrayGet(tsCfg->array, i);
+
+ SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, (const char *)&dnodeId, false);
+
+ char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_WITH_MAXSIZE_TO_VARSTR(name, pItem->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, name, false);
+
+ char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
+ int32_t valueLen = 0;
+ cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen);
+ varDataSetLen(value, valueLen);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, value, false);
+
+ numOfRows++;
+ }
+
+ pBlock->info.rows = numOfRows;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t dmProcessRetrieve(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
+ int32_t size = 0;
+ int32_t rowsRead = 0;
+
+ SRetrieveTableReq retrieveReq = {0};
+ if (tDeserializeSRetrieveTableReq(pMsg->pCont, pMsg->contLen, &retrieveReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ if (strcmp(retrieveReq.user, TSDB_DEFAULT_USER) != 0) {
+ terrno = TSDB_CODE_MND_NO_RIGHTS;
+ return -1;
+ }
+
+ if (strcasecmp(retrieveReq.tb, TSDB_INS_TABLE_DNODE_VARIABLES)) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ SSDataBlock *pBlock = dmBuildVariablesBlock();
+
+ dmAppendVariablesToBlock(pBlock, pMgmt->pData->dnodeId);
+
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ size = sizeof(SRetrieveMetaTableRsp) + sizeof(int32_t) + sizeof(SSysTableSchema) * numOfCols +
+ blockDataGetSize(pBlock) + blockDataGetSerialMetaSize(numOfCols);
+
+ SRetrieveMetaTableRsp *pRsp = rpcMallocCont(size);
+ if (pRsp == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ dError("failed to retrieve data since %s", terrstr());
+ blockDataDestroy(pBlock);
+ return -1;
+ }
+
+ char *pStart = pRsp->data;
+ *(int32_t *)pStart = htonl(numOfCols);
+ pStart += sizeof(int32_t); // number of columns
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SSysTableSchema *pSchema = (SSysTableSchema *)pStart;
+ SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, i);
+
+ pSchema->bytes = htonl(pColInfo->info.bytes);
+ pSchema->colId = htons(pColInfo->info.colId);
+ pSchema->type = pColInfo->info.type;
+
+ pStart += sizeof(SSysTableSchema);
+ }
+
+ int32_t len = 0;
+ blockEncode(pBlock, pStart, &len, numOfCols, false);
+
+ pRsp->numOfRows = htonl(pBlock->info.rows);
+ pRsp->precision = TSDB_TIME_PRECISION_MILLI; // millisecond time precision
+ pRsp->completed = 1;
+ pMsg->info.rsp = pRsp;
+ pMsg->info.rspLen = size;
+ dDebug("dnode variables retrieve completed");
+
+ blockDataDestroy(pBlock);
+ return TSDB_CODE_SUCCESS;
+}
+
SArray *dmGetMsgHandles() {
int32_t code = -1;
SArray *pArray = taosArrayInit(16, sizeof(SMgmtHandle));
@@ -191,6 +328,7 @@ SArray *dmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_DND_DROP_BNODE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_CONFIG_DNODE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_SERVER_STATUS, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_DND_SYSTABLE_RETRIEVE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
// Requests handled by MNODE
if (dmSetMgmtHandle(pArray, TDMT_MND_GRANT_RSP, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c
index 9ffa0e606a6e597e247afa24356794b421e30e5f..89e8aa976ef33b03749a95e55b9640d414a9dca8 100644
--- a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c
+++ b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c
@@ -141,6 +141,9 @@ static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
case TDMT_DND_SERVER_STATUS:
code = dmProcessServerRunStatus(pMgmt, pMsg);
break;
+ case TDMT_DND_SYSTABLE_RETRIEVE:
+ code = dmProcessRetrieve(pMgmt, pMsg);
+ break;
default:
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
break;
diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c
index 0112feedd21a52c78abe505b3e5ae6bce382f97f..b9a02728fc74e66b181954d98b6af0d4e94b50a6 100644
--- a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c
+++ b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c
@@ -17,7 +17,7 @@
#include "mmInt.h"
void mmGetMonitorInfo(SMnodeMgmt *pMgmt, SMonMmInfo *pInfo) {
- mndGetMonitorInfo(pMgmt->pMnode, &pInfo->cluster, &pInfo->vgroup, &pInfo->grant);
+ mndGetMonitorInfo(pMgmt->pMnode, &pInfo->cluster, &pInfo->vgroup, &pInfo->stb, &pInfo->grant);
}
int32_t mmProcessGetMonitorInfoReq(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
@@ -73,6 +73,7 @@ int32_t mmProcessGetLoadsReq(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
}
int32_t mmProcessCreateReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
+ const STraceId *trace = &pMsg->info.traceId;
SDCreateMnodeReq createReq = {0};
if (tDeserializeSDCreateMnodeReq(pMsg->pCont, pMsg->contLen, &createReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -81,7 +82,7 @@ int32_t mmProcessCreateReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
if (createReq.replica != 1) {
terrno = TSDB_CODE_INVALID_OPTION;
- dError("failed to create mnode since %s", terrstr());
+ dGError("failed to create mnode since %s", terrstr());
return -1;
}
@@ -91,7 +92,7 @@ int32_t mmProcessCreateReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
mgmt.path = pInput->path;
mgmt.name = pInput->name;
if (mmWriteFile(&mgmt, &createReq.replicas[0], deployed) != 0) {
- dError("failed to write mnode file since %s", terrstr());
+ dGError("failed to write mnode file since %s", terrstr());
return -1;
}
@@ -99,7 +100,8 @@ int32_t mmProcessCreateReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
}
int32_t mmProcessDropReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
- SDDropMnodeReq dropReq = {0};
+ const STraceId *trace = &pMsg->info.traceId;
+ SDDropMnodeReq dropReq = {0};
if (tDeserializeSCreateDropMQSBNodeReq(pMsg->pCont, pMsg->contLen, &dropReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
return -1;
@@ -107,7 +109,7 @@ int32_t mmProcessDropReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
if (pInput->pData->dnodeId != 0 && dropReq.dnodeId != pInput->pData->dnodeId) {
terrno = TSDB_CODE_INVALID_OPTION;
- dError("failed to drop mnode since %s", terrstr());
+ dGError("failed to drop mnode since %s", terrstr());
return -1;
}
@@ -117,7 +119,7 @@ int32_t mmProcessDropReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
mgmt.path = pInput->path;
mgmt.name = pInput->name;
if (mmWriteFile(&mgmt, NULL, deployed) != 0) {
- dError("failed to write mnode file since %s", terrstr());
+ dGError("failed to write mnode file since %s", terrstr());
return -1;
}
@@ -159,6 +161,7 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_QNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_QNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_QNODE_LIST, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_MND_DNODE_LIST, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_SNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_SNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_BNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -168,6 +171,7 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MND_USE_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_ALTER_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_COMPACT_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_MND_TRIM_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_GET_DB_CFG, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_VGROUP_LIST, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_REDISTRIBUTE_VGROUP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -180,6 +184,7 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MND_ALTER_STB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_STB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_TABLE_META, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_MND_TABLE_CFG, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_SMA, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_SMA, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_STREAM, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -202,11 +207,15 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MND_SYSTABLE_RETRIEVE, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_GRANT, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_AUTH, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_MND_SHOW_VARIABLES, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_MND_SERVER_VERSION, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_CONTINUE, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_HEARTBEAT, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_FETCH, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_QUERY, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_CONTINUE, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_HEARTBEAT, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_FETCH, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_FETCH, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_CREATE_STB_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_STB_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_STB_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -214,9 +223,9 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_SMA_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_MQ_VG_CHANGE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_MQ_VG_DELETE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_TASK, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_DROP_TASK, mmPutMsgToFetchQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DEPLOY_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TASK_DROP_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DROP_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIG_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_REPLICA_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIRM_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -230,10 +239,12 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_SYNC_PING, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_PING_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_BATCH, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_REQUEST_VOTE, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_REQUEST_VOTE_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_BATCH, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_SEND, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER;
diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmInt.c b/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
index 012e61d23964300df42b79fd52ed48c3af6ee4ce..84491a82b061f7a83232d88e6846472d2ac398da 100644
--- a/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
+++ b/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
@@ -150,6 +150,7 @@ static void mmStop(SMnodeMgmt *pMgmt) {
dDebug("mnode-mgmt start to stop");
taosThreadRwlockWrlock(&pMgmt->lock);
pMgmt->stopped = 1;
+ mndPreClose(pMgmt->pMnode);
taosThreadRwlockUnlock(&pMgmt->lock);
mndStop(pMgmt->pMnode);
diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c
index 32477febebcf35f851f9a915022ec6358ba27b79..d2b071ec61d7343f826ed9975cd6b07745399357 100644
--- a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c
+++ b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c
@@ -18,7 +18,6 @@
static inline int32_t mmAcquire(SMnodeMgmt *pMgmt) {
int32_t code = 0;
-
taosThreadRwlockRdlock(&pMgmt->lock);
if (pMgmt->stopped) {
code = -1;
@@ -48,7 +47,8 @@ static inline void mmSendRsp(SRpcMsg *pMsg, int32_t code) {
static void mmProcessRpcMsg(SQueueInfo *pInfo, SRpcMsg *pMsg) {
SMnodeMgmt *pMgmt = pInfo->ahandle;
int32_t code = -1;
- STraceId * trace = &pMsg->info.traceId;
+
+ const STraceId *trace = &pMsg->info.traceId;
dGTrace("msg:%p, get from mnode queue", pMsg);
switch (pMsg->msgType) {
@@ -72,7 +72,7 @@ static void mmProcessRpcMsg(SQueueInfo *pInfo, SRpcMsg *pMsg) {
mndPostProcessQueryMsg(pMsg);
}
- dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
+ dGTrace("msg:%p, is freed, code:0x%x", pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
@@ -80,7 +80,9 @@ static void mmProcessRpcMsg(SQueueInfo *pInfo, SRpcMsg *pMsg) {
static void mmProcessSyncMsg(SQueueInfo *pInfo, SRpcMsg *pMsg) {
SMnodeMgmt *pMgmt = pInfo->ahandle;
pMsg->info.node = pMgmt->pMnode;
- dTrace("msg:%p, get from mnode-sync queue", pMsg);
+
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("msg:%p, get from mnode-sync queue", pMsg);
SMsgHead *pHead = pMsg->pCont;
pHead->contLen = ntohl(pHead->contLen);
@@ -88,20 +90,22 @@ static void mmProcessSyncMsg(SQueueInfo *pInfo, SRpcMsg *pMsg) {
int32_t code = mndProcessSyncMsg(pMsg);
- dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
+ dGTrace("msg:%p, is freed, code:0x%x", pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
static inline int32_t mmPutMsgToWorker(SMnodeMgmt *pMgmt, SSingleWorker *pWorker, SRpcMsg *pMsg) {
+ const STraceId *trace = &pMsg->info.traceId;
+
if (mmAcquire(pMgmt) == 0) {
- dTrace("msg:%p, put into %s queue, type:%s", pMsg, pWorker->name, TMSG_INFO(pMsg->msgType));
+ dGTrace("msg:%p, put into %s queue, type:%s", pMsg, pWorker->name, TMSG_INFO(pMsg->msgType));
taosWriteQitem(pWorker->queue, pMsg);
mmRelease(pMgmt);
return 0;
} else {
- dTrace("msg:%p, failed to put into %s queue since %s, type:%s", pMsg, pWorker->name, terrstr(),
- TMSG_INFO(pMsg->msgType));
+ dGTrace("msg:%p, failed to put into %s queue since %s, type:%s", pMsg, pWorker->name, terrstr(),
+ TMSG_INFO(pMsg->msgType));
return -1;
}
}
@@ -121,19 +125,17 @@ int32_t mmPutMsgToReadQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
int32_t mmPutMsgToQueryQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
pMsg->info.node = pMgmt->pMnode;
if (mndPreProcessQueryMsg(pMsg) != 0) {
- dError("msg:%p, failed to pre-process in mnode since %s, type:%s", pMsg, terrstr(), TMSG_INFO(pMsg->msgType));
+ const STraceId *trace = &pMsg->info.traceId;
+ dGError("msg:%p, failed to pre-process in mnode since %s, type:%s", pMsg, terrstr(), TMSG_INFO(pMsg->msgType));
return -1;
}
return mmPutMsgToWorker(pMgmt, &pMgmt->queryWorker, pMsg);
}
int32_t mmPutMsgToFetchQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
- pMsg->info.node = pMgmt->pMnode;
-
return mmPutMsgToWorker(pMgmt, &pMgmt->fetchWorker, pMsg);
}
-
int32_t mmPutMsgToMonitorQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) {
return mmPutMsgToWorker(pMgmt, &pMgmt->monitorWorker, pMsg);
}
@@ -165,8 +167,13 @@ int32_t mmPutMsgToQueue(SMnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc) {
if (pMsg == NULL) return -1;
memcpy(pMsg, pRpc, sizeof(SRpcMsg));
- dTrace("msg:%p, is created and will put int %s queue", pMsg, pWorker->name);
- return mmPutMsgToWorker(pMgmt, pWorker, pMsg);
+ dTrace("msg:%p, is created and will put into %s queue, type:%s", pMsg, pWorker->name, TMSG_INFO(pRpc->msgType));
+ int32_t code = mmPutMsgToWorker(pMgmt, pWorker, pMsg);
+ if (code != 0) {
+ dTrace("msg:%p, is freed", pMsg);
+ taosFreeQitem(pMsg);
+ }
+ return code;
}
int32_t mmStartWorker(SMnodeMgmt *pMgmt) {
diff --git a/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c b/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c
index 864f5b485afdea2c798cbc35a12466ecfa1b69b8..14cb1bd533416c96ef16b39c2fbb53a15883bcbf 100644
--- a/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c
+++ b/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c
@@ -107,14 +107,16 @@ SArray *qmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MON_QM_INFO, qmPutNodeMsgToMonitorQueue, 0) == NULL) goto _OVER;
// Requests handled by VNODE
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY, qmPutNodeMsgToQueryQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_CONTINUE, qmPutNodeMsgToQueryQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_FETCH, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_FETCH_RSP, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_HEARTBEAT, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
-
- if (dmSetMgmtHandle(pArray, TDMT_VND_CANCEL_TASK, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_TASK, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY, qmPutNodeMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_QUERY, qmPutNodeMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_CONTINUE, qmPutNodeMsgToQueryQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_FETCH, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_FETCH, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_FETCH_RSP, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_HEARTBEAT, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_CANCEL_TASK, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_DROP_TASK, qmPutNodeMsgToFetchQueue, 1) == NULL) goto _OVER;
code = 0;
_OVER:
diff --git a/source/dnode/mgmt/mgmt_snode/src/smHandle.c b/source/dnode/mgmt/mgmt_snode/src/smHandle.c
index 81576e153e35c490860c4b0b9272dcaa2d798418..7cb41ca77cb77f7069ab8e375cef64840b058615 100644
--- a/source/dnode/mgmt/mgmt_snode/src/smHandle.c
+++ b/source/dnode/mgmt/mgmt_snode/src/smHandle.c
@@ -95,12 +95,14 @@ SArray *smGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MON_SM_INFO, smPutNodeMsgToMonitorQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DEPLOY, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TASK_DROP, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DROP, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RUN, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH_RSP, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER_RSP, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_RETRIEVE, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_RETRIEVE_RSP, smPutNodeMsgToSharedQueue, 1) == NULL) goto _OVER;
code = 0;
_OVER:
diff --git a/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h b/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h
index 6f00767eb0301cff76b891e6873abf7e2ef755ea..ebbb9fa5d4f820cbdc46f92590dabc56161c80b2 100644
--- a/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h
+++ b/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h
@@ -31,7 +31,8 @@ typedef struct SVnodeMgmt {
const char *path;
const char *name;
SQWorkerPool queryPool;
- SQWorkerPool fetchPool;
+ SQWorkerPool streamPool;
+ SWWorkerPool fetchPool;
SWWorkerPool syncPool;
SWWorkerPool writePool;
SWWorkerPool applyPool;
@@ -61,6 +62,7 @@ typedef struct {
STaosQueue *pSyncQ;
STaosQueue *pApplyQ;
STaosQueue *pQueryQ;
+ STaosQueue *pStreamQ;
STaosQueue *pFetchQ;
} SVnodeObj;
@@ -105,6 +107,7 @@ int32_t vmPutMsgToWriteQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToSyncQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToQueryQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToFetchQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
+int32_t vmPutMsgToStreamQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToMergeQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToMgmtQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t vmPutMsgToMonitorQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmFile.c b/source/dnode/mgmt/mgmt_vnode/src/vmFile.c
index 613f3fb994da4fca90842b971ca65b3e6db7fbc7..cbcb541200c899260a265872f625cb306987f7ae 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmFile.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmFile.c
@@ -31,9 +31,8 @@ SVnodeObj **vmGetVnodeListFromHash(SVnodeMgmt *pMgmt, int32_t *numOfVnodes) {
SVnodeObj *pVnode = *ppVnode;
if (pVnode && num < size) {
int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
- // dTrace("vgId:%d, acquire vnode, refCount:%d", pVnode->vgId, refCount);
- pVnodes[num] = (*ppVnode);
- num++;
+ // dTrace("vgId:%d, acquire vnode list, ref:%d", pVnode->vgId, refCount);
+ pVnodes[num++] = (*ppVnode);
pIter = taosHashIterate(pMgmt->hash, pIter);
} else {
taosHashCancelIterate(pMgmt->hash, pIter);
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
index c3ed6d781cc8238ee9c901dc53466ec68da74095..9571a83116eeb56aa731a3d2c3a938a8428ba371 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
@@ -138,6 +138,8 @@ static void vmGenerateVnodeCfg(SCreateVnodeReq *pCreate, SVnodeCfg *pCfg) {
pCfg->dbId = pCreate->dbUid;
pCfg->szPage = pCreate->pageSize * 1024;
pCfg->szCache = pCreate->pages;
+ pCfg->cacheLast = pCreate->cacheLast;
+ pCfg->cacheLastSize = pCreate->cacheLastSize;
pCfg->szBuf = (uint64_t)pCreate->buffer * 1024 * 1024;
pCfg->isWeak = true;
pCfg->isTsma = pCreate->isTsma;
@@ -210,7 +212,8 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
return -1;
}
- dDebug("vgId:%d, start to create vnode, tsma:%d standby:%d", createReq.vgId, createReq.isTsma, createReq.standby);
+ dDebug("vgId:%d, start to create vnode, tsma:%d standby:%d cacheLast:%d cacheLastSize:%d", createReq.vgId,
+ createReq.isTsma, createReq.standby, createReq.cacheLast, createReq.cacheLastSize);
vmGenerateVnodeCfg(&createReq, &vnodeCfg);
if (vmTsmaAdjustDays(&vnodeCfg, &createReq) < 0) {
@@ -324,15 +327,18 @@ SArray *vmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_MON_VM_LOAD, vmPutMsgToMonitorQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_SUBMIT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_CONTINUE, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_FETCH, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_QUERY, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_CONTINUE, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_FETCH, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_FETCH, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_TABLE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_UPDATE_TAG_VAL, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TABLE_META, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_TABLE_CFG, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TABLES_META, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_CANCEL_TASK, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_TASK, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_CANCEL_TASK, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_DROP_TASK, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_CREATE_STB, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_TTL_TABLE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_STB, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
@@ -348,22 +354,26 @@ SArray *vmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_VND_MQ_COMMIT_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_CONSUME, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_DELETE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_QUERY_HEARTBEAT, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_COMMIT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_HEARTBEAT, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TRIGGER, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TASK_DROP, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TRIGGER, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DROP, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DEPLOY, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RUN, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH_RSP, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
- if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER_RSP, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RUN, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH_RSP, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RECOVER_RSP, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_RETRIEVE, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_STREAM_RETRIEVE_RSP, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_REPLICA, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIG, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIRM, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_HASHRANGE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_COMPACT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_TRIM, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_CREATE_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_DROP_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER;
@@ -371,11 +381,15 @@ SArray *vmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_SYNC_PING, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_PING_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_BATCH, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_REQUEST_VOTE, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_REQUEST_VOTE_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_BATCH, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_SEND, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_SET_VNODE_STANDBY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
code = 0;
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c
index 3f053639aab740119721c5b67419648f95a50d73..1f981cc9e0fbc6b119542980e241e20bb06b1fde 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c
@@ -21,8 +21,9 @@ SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId) {
taosThreadRwlockRdlock(&pMgmt->lock);
taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
- if (pVnode == NULL) {
+ if (pVnode == NULL || pVnode->dropped) {
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
+ pVnode = NULL;
} else {
int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
// dTrace("vgId:%d, acquire vnode, ref:%d", pVnode->vgId, refCount);
@@ -75,22 +76,28 @@ int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) {
void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
char path[TSDB_FILENAME_LEN] = {0};
+ vnodePreClose(pVnode->pImpl);
+
taosThreadRwlockWrlock(&pMgmt->lock);
taosHashRemove(pMgmt->hash, &pVnode->vgId, sizeof(int32_t));
taosThreadRwlockUnlock(&pMgmt->lock);
-
vmReleaseVnode(pMgmt, pVnode);
+
+ dTrace("vgId:%d, wait for vnode ref become 0", pVnode->vgId);
while (pVnode->refCount > 0) taosMsleep(10);
+ dTrace("vgId:%d, wait for vnode queue is empty", pVnode->vgId);
+
while (!taosQueueEmpty(pVnode->pWriteQ)) taosMsleep(10);
while (!taosQueueEmpty(pVnode->pSyncQ)) taosMsleep(10);
while (!taosQueueEmpty(pVnode->pApplyQ)) taosMsleep(10);
while (!taosQueueEmpty(pVnode->pQueryQ)) taosMsleep(10);
while (!taosQueueEmpty(pVnode->pFetchQ)) taosMsleep(10);
+ while (!taosQueueEmpty(pVnode->pStreamQ)) taosMsleep(10);
+ dTrace("vgId:%d, vnode queue is empty", pVnode->vgId);
vmFreeQueue(pMgmt, pVnode);
vnodeClose(pVnode->pImpl);
pVnode->pImpl = NULL;
-
dDebug("vgId:%d, vnode is closed", pVnode->vgId);
if (pVnode->dropped) {
@@ -138,7 +145,7 @@ static void *vmOpenVnodeInThread(void *param) {
}
static int32_t vmOpenVnodes(SVnodeMgmt *pMgmt) {
- pMgmt->hash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
+ pMgmt->hash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
if (pMgmt->hash == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
dError("failed to init vnode hash since %s", terrstr());
@@ -154,7 +161,8 @@ static int32_t vmOpenVnodes(SVnodeMgmt *pMgmt) {
pMgmt->state.totalVnodes = numOfVnodes;
- int32_t threadNum = 1;
+ int32_t threadNum = tsNumOfCores / 2;
+ if (threadNum < 1) threadNum = 1;
int32_t vnodesPerThread = numOfVnodes / threadNum + 1;
SVnodeThread *threads = taosMemoryCalloc(threadNum, sizeof(SVnodeThread));
@@ -170,7 +178,7 @@ static int32_t vmOpenVnodes(SVnodeMgmt *pMgmt) {
pThread->pCfgs[pThread->vnodeNum++] = pCfgs[v];
}
- dInfo("start %d threads to open %d vnodes", threadNum, numOfVnodes);
+ dInfo("open %d vnodes with %d threads", numOfVnodes, threadNum);
for (int32_t t = 0; t < threadNum; ++t) {
SVnodeThread *pThread = &threads[t];
@@ -201,7 +209,7 @@ static int32_t vmOpenVnodes(SVnodeMgmt *pMgmt) {
dError("there are total vnodes:%d, opened:%d", pMgmt->state.totalVnodes, pMgmt->state.openVnodes);
return -1;
} else {
- dInfo("total vnodes:%d open successfully", pMgmt->state.totalVnodes);
+ dInfo("successfully opened %d vnodes", pMgmt->state.totalVnodes);
return 0;
}
}
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
index 71bbc8ddd43aaf6583bcf4758ca018fe798108d4..4a60dbfe0fbbc8e207f42a3399495bb173ca49dc 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
@@ -28,10 +28,10 @@ static inline void vmSendRsp(SRpcMsg *pMsg, int32_t code) {
}
static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
- SVnodeMgmt *pMgmt = pInfo->ahandle;
- int32_t code = -1;
+ SVnodeMgmt *pMgmt = pInfo->ahandle;
+ int32_t code = -1;
+ const STraceId *trace = &pMsg->info.traceId;
- STraceId *trace = &pMsg->info.traceId;
dGTrace("msg:%p, get from vnode-mgmt queue", pMsg);
switch (pMsg->msgType) {
case TDMT_MON_VM_INFO:
@@ -48,130 +48,133 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
break;
default:
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
- dError("msg:%p, not processed in vnode-mgmt queue", pMsg);
+ dGError("msg:%p, not processed in vnode-mgmt queue", pMsg);
}
if (IsReq(pMsg)) {
if (code != 0) {
if (terrno != 0) code = terrno;
- dError("msg:%p, failed to process since %s", pMsg, terrstr());
+ dGError("msg:%p, failed to process since %s", pMsg, terrstr());
}
vmSendRsp(pMsg, code);
}
- dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
+ dGTrace("msg:%p, is freed, code:0x%x", pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
static void vmProcessQueryQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
- SVnodeObj *pVnode = pInfo->ahandle;
+ SVnodeObj *pVnode = pInfo->ahandle;
+ const STraceId *trace = &pMsg->info.traceId;
- dTrace("vgId:%d, msg:%p get from vnode-query queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p get from vnode-query queue", pVnode->vgId, pMsg);
int32_t code = vnodeProcessQueryMsg(pVnode->pImpl, pMsg);
if (code != 0) {
if (terrno != 0) code = terrno;
- dError("vgId:%d, msg:%p failed to query since %s", pVnode->vgId, pMsg, terrstr());
+ dGError("vgId:%d, msg:%p failed to query since %s", pVnode->vgId, pMsg, terrstr());
vmSendRsp(pMsg, code);
}
- dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
+ dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
-static void vmProcessFetchQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
- SVnodeObj *pVnode = pInfo->ahandle;
+static void vmProcessStreamQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
+ SVnodeObj *pVnode = pInfo->ahandle;
+ const STraceId *trace = &pMsg->info.traceId;
- dTrace("vgId:%d, msg:%p get from vnode-fetch queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p get from vnode-stream queue", pVnode->vgId, pMsg);
int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
if (code != 0) {
if (terrno != 0) code = terrno;
- dError("vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr());
+ dGError("vgId:%d, msg:%p failed to stream since %s", pVnode->vgId, pMsg, terrstr());
vmSendRsp(pMsg, code);
}
- dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
+ dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
-static void vmProcessSyncQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
+static void vmProcessFetchQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
SVnodeObj *pVnode = pInfo->ahandle;
SRpcMsg *pMsg = NULL;
for (int32_t i = 0; i < numOfMsgs; ++i) {
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
- dTrace("vgId:%d, msg:%p get from vnode-sync queue", pVnode->vgId, pMsg);
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("vgId:%d, msg:%p get from vnode-fetch queue", pVnode->vgId, pMsg);
- int32_t code = vnodeProcessSyncReq(pVnode->pImpl, pMsg, NULL);
+ int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
if (code != 0) {
if (terrno != 0) code = terrno;
- dError("vgId:%d, msg:%p failed to sync since %s", pVnode->vgId, pMsg, terrstr());
+ dGError("vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr());
vmSendRsp(pMsg, code);
}
- dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
+ dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
}
-static void vmProcessMergeQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
+static void vmProcessSyncQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
SVnodeObj *pVnode = pInfo->ahandle;
SRpcMsg *pMsg = NULL;
for (int32_t i = 0; i < numOfMsgs; ++i) {
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
- dTrace("vgId:%d, msg:%p get from vnode-merge queue", pVnode->vgId, pMsg);
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("vgId:%d, msg:%p get from vnode-sync queue", pVnode->vgId, pMsg);
- int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
- if (code != 0) {
- if (terrno != 0) code = terrno;
- dError("vgId:%d, msg:%p failed to merge since %s", pVnode->vgId, pMsg, terrstr());
- vmSendRsp(pMsg, code);
- }
-
- dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
+ int32_t code = vnodeProcessSyncMsg(pVnode->pImpl, pMsg, NULL); // no response here
+ dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
}
}
static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtype) {
- SMsgHead *pHead = pMsg->pCont;
- int32_t code = 0;
+ const STraceId *trace = &pMsg->info.traceId;
+ SMsgHead *pHead = pMsg->pCont;
+ int32_t code = 0;
pHead->contLen = ntohl(pHead->contLen);
pHead->vgId = ntohl(pHead->vgId);
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, pHead->vgId);
if (pVnode == NULL) {
- dError("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s", pHead->vgId, pMsg, terrstr(),
- TMSG_INFO(pMsg->msgType));
+ dGError("vgId:%d, msg:%p failed to put into vnode queue since %s, msgtype:%s qtype:%d", pHead->vgId, pMsg,
+ terrstr(), TMSG_INFO(pMsg->msgType), qtype);
return terrno != 0 ? terrno : -1;
}
switch (qtype) {
case QUERY_QUEUE:
vnodePreprocessQueryMsg(pVnode->pImpl, pMsg);
- dTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg);
taosWriteQitem(pVnode->pQueryQ, pMsg);
break;
+ case STREAM_QUEUE:
+ dGTrace("vgId:%d, msg:%p put into vnode-stream queue", pVnode->vgId, pMsg);
+ taosWriteQitem(pVnode->pStreamQ, pMsg);
+ break;
case FETCH_QUEUE:
- dTrace("vgId:%d, msg:%p put into vnode-fetch queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p put into vnode-fetch queue", pVnode->vgId, pMsg);
taosWriteQitem(pVnode->pFetchQ, pMsg);
break;
case WRITE_QUEUE:
- dTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg);
taosWriteQitem(pVnode->pWriteQ, pMsg);
break;
case SYNC_QUEUE:
- dTrace("vgId:%d, msg:%p put into vnode-sync queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p put into vnode-sync queue", pVnode->vgId, pMsg);
taosWriteQitem(pVnode->pSyncQ, pMsg);
break;
case APPLY_QUEUE:
- dTrace("vgId:%d, msg:%p put into vnode-apply queue", pVnode->vgId, pMsg);
+ dGTrace("vgId:%d, msg:%p put into vnode-apply queue", pVnode->vgId, pMsg);
taosWriteQitem(pVnode->pApplyQ, pMsg);
break;
default:
@@ -192,21 +195,29 @@ int32_t vmPutMsgToQueryQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsg
int32_t vmPutMsgToFetchQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsgToQueue(pMgmt, pMsg, FETCH_QUEUE); }
+int32_t vmPutMsgToStreamQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsgToQueue(pMgmt, pMsg, STREAM_QUEUE); }
+
int32_t vmPutMsgToMgmtQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
- dTrace("msg:%p, put into vnode-mgmt queue", pMsg);
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("msg:%p, put into vnode-mgmt queue", pMsg);
taosWriteQitem(pMgmt->mgmtWorker.queue, pMsg);
return 0;
}
int32_t vmPutMsgToMonitorQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
- dTrace("msg:%p, put into vnode-monitor queue", pMsg);
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("msg:%p, put into vnode-monitor queue", pMsg);
taosWriteQitem(pMgmt->monitorWorker.queue, pMsg);
return 0;
}
int32_t vmPutRpcMsgToQueue(SVnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc) {
SRpcMsg *pMsg = taosAllocateQitem(sizeof(SRpcMsg), RPC_QITEM);
- if (pMsg == NULL) return -1;
+ if (pMsg == NULL) {
+ rpcFreeCont(pMsg->pCont);
+ pRpc->pCont = NULL;
+ return -1;
+ }
SMsgHead *pHead = pRpc->pCont;
dTrace("vgId:%d, msg:%p is created, type:%s", pHead->vgId, pMsg, TMSG_INFO(pRpc->msgType));
@@ -214,7 +225,16 @@ int32_t vmPutRpcMsgToQueue(SVnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc) {
pHead->contLen = htonl(pHead->contLen);
pHead->vgId = htonl(pHead->vgId);
memcpy(pMsg, pRpc, sizeof(SRpcMsg));
- return vmPutMsgToQueue(pMgmt, pMsg, qtype);
+
+ int32_t code = vmPutMsgToQueue(pMgmt, pMsg, qtype);
+ if (code != 0) {
+ dTrace("msg:%p, is freed", pMsg);
+ rpcFreeCont(pMsg->pCont);
+ pRpc->pCont = NULL;
+ taosFreeQitem(pMsg);
+ }
+
+ return code;
}
int32_t vmGetQueueSize(SVnodeMgmt *pMgmt, int32_t vgId, EQueueType qtype) {
@@ -237,28 +257,37 @@ int32_t vmGetQueueSize(SVnodeMgmt *pMgmt, int32_t vgId, EQueueType qtype) {
case FETCH_QUEUE:
size = taosQueueItemSize(pVnode->pFetchQ);
break;
+ case STREAM_QUEUE:
+ size = taosQueueItemSize(pVnode->pStreamQ);
+ break;
default:
break;
}
+ vmReleaseVnode(pMgmt, pVnode);
}
- vmReleaseVnode(pMgmt, pVnode);
return size;
}
int32_t vmAllocQueue(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
- pVnode->pWriteQ = tWWorkerAllocQueue(&pMgmt->writePool, pVnode->pImpl, (FItems)vnodeProposeMsg);
+ pVnode->pWriteQ = tWWorkerAllocQueue(&pMgmt->writePool, pVnode->pImpl, (FItems)vnodeProposeWriteMsg);
pVnode->pSyncQ = tWWorkerAllocQueue(&pMgmt->syncPool, pVnode, (FItems)vmProcessSyncQueue);
- pVnode->pApplyQ = tWWorkerAllocQueue(&pMgmt->applyPool, pVnode->pImpl, (FItems)vnodeApplyMsg);
+ pVnode->pApplyQ = tWWorkerAllocQueue(&pMgmt->applyPool, pVnode->pImpl, (FItems)vnodeApplyWriteMsg);
pVnode->pQueryQ = tQWorkerAllocQueue(&pMgmt->queryPool, pVnode, (FItem)vmProcessQueryQueue);
- pVnode->pFetchQ = tQWorkerAllocQueue(&pMgmt->fetchPool, pVnode, (FItem)vmProcessFetchQueue);
+ pVnode->pStreamQ = tQWorkerAllocQueue(&pMgmt->streamPool, pVnode, (FItem)vmProcessStreamQueue);
+ pVnode->pFetchQ = tWWorkerAllocQueue(&pMgmt->fetchPool, pVnode, (FItems)vmProcessFetchQueue);
if (pVnode->pWriteQ == NULL || pVnode->pSyncQ == NULL || pVnode->pApplyQ == NULL || pVnode->pQueryQ == NULL ||
- pVnode->pFetchQ == NULL) {
+ pVnode->pStreamQ == NULL || pVnode->pFetchQ == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
- dDebug("vgId:%d, queue is alloced", pVnode->vgId);
+ dDebug("vgId:%d, write-queue:%p is alloced", pVnode->vgId, pVnode->pWriteQ);
+ dDebug("vgId:%d, sync-queue:%p is alloced", pVnode->vgId, pVnode->pSyncQ);
+ dDebug("vgId:%d, apply-queue:%p is alloced", pVnode->vgId, pVnode->pApplyQ);
+ dDebug("vgId:%d, query-queue:%p is alloced", pVnode->vgId, pVnode->pQueryQ);
+ dDebug("vgId:%d, stream-queue:%p is alloced", pVnode->vgId, pVnode->pStreamQ);
+ dDebug("vgId:%d, fetch-queue:%p is alloced", pVnode->vgId, pVnode->pFetchQ);
return 0;
}
@@ -267,11 +296,13 @@ void vmFreeQueue(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
tWWorkerFreeQueue(&pMgmt->applyPool, pVnode->pApplyQ);
tWWorkerFreeQueue(&pMgmt->syncPool, pVnode->pSyncQ);
tQWorkerFreeQueue(&pMgmt->queryPool, pVnode->pQueryQ);
- tQWorkerFreeQueue(&pMgmt->fetchPool, pVnode->pFetchQ);
+ tQWorkerFreeQueue(&pMgmt->streamPool, pVnode->pStreamQ);
+ tWWorkerFreeQueue(&pMgmt->fetchPool, pVnode->pFetchQ);
pVnode->pWriteQ = NULL;
pVnode->pSyncQ = NULL;
pVnode->pApplyQ = NULL;
pVnode->pQueryQ = NULL;
+ pVnode->pStreamQ = NULL;
pVnode->pFetchQ = NULL;
dDebug("vgId:%d, queue is freed", pVnode->vgId);
}
@@ -283,11 +314,16 @@ int32_t vmStartWorker(SVnodeMgmt *pMgmt) {
pQPool->max = tsNumOfVnodeQueryThreads;
if (tQWorkerInit(pQPool) != 0) return -1;
- SQWorkerPool *pFPool = &pMgmt->fetchPool;
+ SQWorkerPool *pStreamPool = &pMgmt->streamPool;
+ pStreamPool->name = "vnode-stream";
+ pStreamPool->min = tsNumOfVnodeStreamThreads;
+ pStreamPool->max = tsNumOfVnodeStreamThreads;
+ if (tQWorkerInit(pStreamPool) != 0) return -1;
+
+ SWWorkerPool *pFPool = &pMgmt->fetchPool;
pFPool->name = "vnode-fetch";
- pFPool->min = tsNumOfVnodeFetchThreads;
pFPool->max = tsNumOfVnodeFetchThreads;
- if (tQWorkerInit(pFPool) != 0) return -1;
+ if (tWWorkerInit(pFPool) != 0) return -1;
SWWorkerPool *pWPool = &pMgmt->writePool;
pWPool->name = "vnode-write";
@@ -333,6 +369,7 @@ void vmStopWorker(SVnodeMgmt *pMgmt) {
tWWorkerCleanup(&pMgmt->applyPool);
tWWorkerCleanup(&pMgmt->syncPool);
tQWorkerCleanup(&pMgmt->queryPool);
- tQWorkerCleanup(&pMgmt->fetchPool);
+ tQWorkerCleanup(&pMgmt->streamPool);
+ tWWorkerCleanup(&pMgmt->fetchPool);
dDebug("vnode workers are closed");
}
diff --git a/source/dnode/mgmt/node_mgmt/src/dmMgmt.c b/source/dnode/mgmt/node_mgmt/src/dmMgmt.c
index ee27f27f06fe0ce502fdfd729a2b573ddb221c37..c2e8a552717041798dea4f7ac61045eb198c170d 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmMgmt.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmMgmt.c
@@ -16,6 +16,7 @@
#define _DEFAULT_SOURCE
#include "dmMgmt.h"
#include "dmNodes.h"
+#include "index.h"
#include "qworker.h"
static bool dmRequireNode(SDnode *pDnode, SMgmtWrapper *pWrapper) {
@@ -127,7 +128,7 @@ static void dmClearVars(SDnode *pDnode) {
}
int32_t dmInitDnode(SDnode *pDnode, EDndNodeType rtype) {
- dInfo("start to create dnode");
+ dDebug("start to create dnode");
int32_t code = -1;
char path[PATH_MAX + 100] = {0};
@@ -212,6 +213,8 @@ void dmCleanupDnode(SDnode *pDnode) {
dmCleanupClient(pDnode);
dmCleanupServer(pDnode);
dmClearVars(pDnode);
+ rpcCleanup();
+ indexCleanup();
dDebug("dnode is closed, ptr:%p", pDnode);
}
diff --git a/source/dnode/mgmt/node_mgmt/src/dmNodes.c b/source/dnode/mgmt/node_mgmt/src/dmNodes.c
index ab9d3f67e7a6c14e94ec46844a12154e567035a2..ecbb695e02edaef6a2546a608d0dedbee61afc91 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmNodes.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmNodes.c
@@ -277,7 +277,7 @@ int32_t dmRunDnode(SDnode *pDnode) {
while (1) {
if (pDnode->stop) {
- dInfo("dnode is about to stop");
+ dInfo("TDengine is about to stop");
dmSetStatus(pDnode, DND_STAT_STOPPED);
dmStopNodes(pDnode);
dmCloseNodes(pDnode);
diff --git a/source/dnode/mgmt/node_mgmt/src/dmProc.c b/source/dnode/mgmt/node_mgmt/src/dmProc.c
index 72878d0d853e2067bdd73d42bb4b001ccfdb5295..cbf13924d73e9f2c6b5366e9f6be6254062e84b3 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmProc.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmProc.c
@@ -87,8 +87,8 @@ static SProcQueue *dmInitProcQueue(SProc *proc, char *ptr, int32_t size) {
static void dmCleanupProcQueue(SProcQueue *queue) {}
static inline int32_t dmPushToProcQueue(SProc *proc, SProcQueue *queue, SRpcMsg *pMsg, EProcFuncType ftype) {
- const void *pHead = pMsg;
- const void *pBody = pMsg->pCont;
+ const void * pHead = pMsg;
+ const void * pBody = pMsg->pCont;
const int16_t rawHeadLen = sizeof(SRpcMsg);
const int32_t rawBodyLen = pMsg->contLen;
const int16_t headLen = CEIL8(rawHeadLen);
@@ -257,7 +257,7 @@ int32_t dmInitProc(struct SMgmtWrapper *pWrapper) {
proc->wrapper = pWrapper;
proc->name = pWrapper->name;
- SShm *shm = &proc->shm;
+ SShm * shm = &proc->shm;
int32_t cstart = 0;
int32_t csize = CEIL8(shm->size / 2);
int32_t pstart = csize;
@@ -281,13 +281,13 @@ int32_t dmInitProc(struct SMgmtWrapper *pWrapper) {
}
static void *dmConsumChildQueue(void *param) {
- SProc *proc = param;
+ SProc * proc = param;
SMgmtWrapper *pWrapper = proc->wrapper;
- SProcQueue *queue = proc->cqueue;
+ SProcQueue * queue = proc->cqueue;
int32_t numOfMsgs = 0;
int32_t code = 0;
EProcFuncType ftype = DND_FUNC_REQ;
- SRpcMsg *pMsg = NULL;
+ SRpcMsg * pMsg = NULL;
dDebug("node:%s, start to consume from cqueue", proc->name);
do {
@@ -324,13 +324,13 @@ static void *dmConsumChildQueue(void *param) {
}
static void *dmConsumParentQueue(void *param) {
- SProc *proc = param;
+ SProc * proc = param;
SMgmtWrapper *pWrapper = proc->wrapper;
- SProcQueue *queue = proc->pqueue;
+ SProcQueue * queue = proc->pqueue;
int32_t numOfMsgs = 0;
int32_t code = 0;
EProcFuncType ftype = DND_FUNC_REQ;
- SRpcMsg *pMsg = NULL;
+ SRpcMsg * pMsg = NULL;
dDebug("node:%s, start to consume from pqueue", proc->name);
do {
@@ -353,7 +353,7 @@ static void *dmConsumParentQueue(void *param) {
rpcRegisterBrokenLinkArg(pMsg);
} else if (ftype == DND_FUNC_RELEASE) {
dmRemoveProcRpcHandle(proc, pMsg->info.handle);
- rpcReleaseHandle(pMsg->info.handle, (int8_t)pMsg->code);
+ rpcReleaseHandle(&pMsg->info, TAOS_CONN_SERVER);
} else {
dError("node:%s, invalid ftype:%d from pqueue", proc->name, ftype);
rpcFreeCont(pMsg->pCont);
diff --git a/source/dnode/mgmt/node_mgmt/src/dmTransport.c b/source/dnode/mgmt/node_mgmt/src/dmTransport.c
index 660f512fc520c5657d12c0db11aae58085defc9f..9052fb20cabfa304429b5198d8ddfb4214a2a85b 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmTransport.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmTransport.c
@@ -17,9 +17,45 @@
#include "dmMgmt.h"
#include "qworker.h"
-static void dmSendRedirectRsp(SRpcMsg *pMsg, const SEpSet *pNewEpSet);
-static void dmSendRsp(SRpcMsg *pMsg);
-static void dmBuildMnodeRedirectRsp(SDnode *pDnode, SRpcMsg *pMsg);
+static inline void dmSendRsp(SRpcMsg *pMsg) {
+ SMgmtWrapper *pWrapper = pMsg->info.wrapper;
+ if (InChildProc(pWrapper)) {
+ dmPutToProcPQueue(&pWrapper->proc, pMsg, DND_FUNC_RSP);
+ } else {
+ rpcSendResponse(pMsg);
+ }
+}
+
+static inline void dmBuildMnodeRedirectRsp(SDnode *pDnode, SRpcMsg *pMsg) {
+ SEpSet epSet = {0};
+ dmGetMnodeEpSetForRedirect(&pDnode->data, pMsg, &epSet);
+
+ const int32_t contLen = tSerializeSEpSet(NULL, 0, &epSet);
+ pMsg->pCont = rpcMallocCont(contLen);
+ if (pMsg->pCont == NULL) {
+ pMsg->code = TSDB_CODE_OUT_OF_MEMORY;
+ } else {
+ tSerializeSEpSet(pMsg->pCont, contLen, &epSet);
+ pMsg->contLen = contLen;
+ }
+}
+
+static inline void dmSendRedirectRsp(SRpcMsg *pMsg, const SEpSet *pNewEpSet) {
+ pMsg->info.hasEpSet = 1;
+ SRpcMsg rsp = {.code = TSDB_CODE_RPC_REDIRECT, .info = pMsg->info, .msgType = pMsg->msgType};
+ int32_t contLen = tSerializeSEpSet(NULL, 0, pNewEpSet);
+
+ rsp.pCont = rpcMallocCont(contLen);
+ if (rsp.pCont == NULL) {
+ pMsg->code = TSDB_CODE_OUT_OF_MEMORY;
+ } else {
+ tSerializeSEpSet(rsp.pCont, contLen, pNewEpSet);
+ rsp.contLen = contLen;
+ }
+ dmSendRsp(&rsp);
+ rpcFreeCont(pMsg->pCont);
+ pMsg->pCont = NULL;
+}
int32_t dmProcessNodeMsg(SMgmtWrapper *pWrapper, SRpcMsg *pMsg) {
NodeMsgFp msgFp = pWrapper->msgFps[TMSG_INDEX(pMsg->msgType)];
@@ -28,31 +64,41 @@ int32_t dmProcessNodeMsg(SMgmtWrapper *pWrapper, SRpcMsg *pMsg) {
return -1;
}
- dTrace("msg:%p, will be processed by %s", pMsg, pWrapper->name);
+ const STraceId *trace = &pMsg->info.traceId;
+ dGTrace("msg:%p, will be processed by %s", pMsg, pWrapper->name);
pMsg->info.wrapper = pWrapper;
return (*msgFp)(pWrapper->pMgmt, pMsg);
}
static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) {
- SDnodeTrans * pTrans = &pDnode->trans;
+ SDnodeTrans *pTrans = &pDnode->trans;
int32_t code = -1;
- SRpcMsg * pMsg = NULL;
+ SRpcMsg *pMsg = NULL;
SMgmtWrapper *pWrapper = NULL;
SDnodeHandle *pHandle = &pTrans->msgHandles[TMSG_INDEX(pRpc->msgType)];
- STraceId *trace = &pRpc->info.traceId;
+ const STraceId *trace = &pRpc->info.traceId;
dGTrace("msg:%s is received, handle:%p len:%d code:0x%x app:%p refId:%" PRId64, TMSG_INFO(pRpc->msgType),
pRpc->info.handle, pRpc->contLen, pRpc->code, pRpc->info.ahandle, pRpc->info.refId);
- if (pRpc->msgType == TDMT_DND_NET_TEST) {
- dmProcessNetTestReq(pDnode, pRpc);
- return;
- } else if (pRpc->msgType == TDMT_MND_SYSTABLE_RETRIEVE_RSP || pRpc->msgType == TDMT_VND_FETCH_RSP) {
- qWorkerProcessFetchRsp(NULL, NULL, pRpc, 0);
- return;
- } else if (pRpc->msgType == TDMT_MND_STATUS_RSP && pEpSet != NULL) {
- dmSetMnodeEpSet(&pDnode->data, pEpSet);
- } else {
+ switch (pRpc->msgType) {
+ case TDMT_DND_NET_TEST:
+ dmProcessNetTestReq(pDnode, pRpc);
+ return;
+ case TDMT_MND_SYSTABLE_RETRIEVE_RSP:
+ case TDMT_DND_SYSTABLE_RETRIEVE_RSP:
+ case TDMT_SCH_FETCH_RSP:
+ case TDMT_SCH_MERGE_FETCH_RSP:
+ case TDMT_VND_SUBMIT_RSP:
+ qWorkerProcessRspMsg(NULL, NULL, pRpc, 0);
+ return;
+ case TDMT_MND_STATUS_RSP:
+ if (pEpSet != NULL) {
+ dmSetMnodeEpSet(&pDnode->data, pEpSet);
+ }
+ break;
+ default:
+ break;
}
if (pDnode->status != DND_STAT_RUNNING) {
@@ -73,39 +119,43 @@ static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) {
if (pHandle->defaultNtype == NODE_END) {
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
goto _OVER;
- } else {
- pWrapper = &pDnode->wrappers[pHandle->defaultNtype];
- if (pHandle->needCheckVgId) {
- if (pRpc->contLen > 0) {
- SMsgHead *pHead = pRpc->pCont;
- int32_t vgId = ntohl(pHead->vgId);
- if (vgId == QNODE_HANDLE) {
+ }
+
+ pWrapper = &pDnode->wrappers[pHandle->defaultNtype];
+ if (pHandle->needCheckVgId) {
+ if (pRpc->contLen > 0) {
+ const SMsgHead *pHead = pRpc->pCont;
+ const int32_t vgId = ntohl(pHead->vgId);
+ switch (vgId) {
+ case QNODE_HANDLE:
pWrapper = &pDnode->wrappers[QNODE];
- } else if (vgId == SNODE_HANDLE) {
+ break;
+ case SNODE_HANDLE:
pWrapper = &pDnode->wrappers[SNODE];
- } else if (vgId == MNODE_HANDLE) {
+ break;
+ case MNODE_HANDLE:
pWrapper = &pDnode->wrappers[MNODE];
- } else {
- }
- } else {
- terrno = TSDB_CODE_INVALID_MSG_LEN;
- goto _OVER;
+ break;
+ default:
+ break;
}
+ } else {
+ terrno = TSDB_CODE_INVALID_MSG_LEN;
+ goto _OVER;
}
}
if (dmMarkWrapper(pWrapper) != 0) {
pWrapper = NULL;
goto _OVER;
- } else {
- pRpc->info.wrapper = pWrapper;
}
+ pRpc->info.wrapper = pWrapper;
pMsg = taosAllocateQitem(sizeof(SRpcMsg), RPC_QITEM);
if (pMsg == NULL) goto _OVER;
- memcpy(pMsg, pRpc, sizeof(SRpcMsg));
- dTrace("msg:%p, is created, type:%s handle:%p", pMsg, TMSG_INFO(pRpc->msgType), pMsg->info.handle);
+ memcpy(pMsg, pRpc, sizeof(SRpcMsg));
+ dGTrace("msg:%p, is created, type:%s handle:%p", pMsg, TMSG_INFO(pRpc->msgType), pMsg->info.handle);
if (InParentProc(pWrapper)) {
code = dmPutToProcCQueue(&pWrapper->proc, pMsg, DND_FUNC_REQ);
@@ -115,13 +165,11 @@ static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) {
_OVER:
if (code != 0) {
- dTrace("failed to process msg:%p since %s, handle:%p", pMsg, terrstr(), pRpc->info.handle);
-
if (terrno != 0) code = terrno;
+ dGTrace("msg:%p, failed to process since %s", pMsg, terrstr());
if (IsReq(pRpc)) {
SRpcMsg rsp = {.code = code, .info = pRpc->info};
-
if ((code == TSDB_CODE_NODE_NOT_DEPLOYED || code == TSDB_CODE_APP_NOT_READY) && pRpc->msgType > TDMT_MND_MSG &&
pRpc->msgType < TDMT_VND_MSG) {
dmBuildMnodeRedirectRsp(pDnode, &rsp);
@@ -135,10 +183,11 @@ _OVER:
}
if (pMsg != NULL) {
- dTrace("msg:%p, is freed", pMsg);
+ dGTrace("msg:%p, is freed", pMsg);
taosFreeQitem(pMsg);
}
rpcFreeCont(pRpc->pCont);
+ pRpc->pCont = NULL;
}
dmReleaseWrapper(pWrapper);
@@ -149,11 +198,11 @@ int32_t dmInitMsgHandle(SDnode *pDnode) {
for (EDndNodeType ntype = DNODE; ntype < NODE_END; ++ntype) {
SMgmtWrapper *pWrapper = &pDnode->wrappers[ntype];
- SArray * pArray = (*pWrapper->func.getHandlesFp)();
+ SArray *pArray = (*pWrapper->func.getHandlesFp)();
if (pArray == NULL) return -1;
for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
- SMgmtHandle * pMgmt = taosArrayGet(pArray, i);
+ SMgmtHandle *pMgmt = taosArrayGet(pArray, i);
SDnodeHandle *pHandle = &pTrans->msgHandles[TMSG_INDEX(pMgmt->msgType)];
if (pMgmt->needCheckVgId) {
pHandle->needCheckVgId = pMgmt->needCheckVgId;
@@ -184,45 +233,6 @@ static inline int32_t dmSendReq(const SEpSet *pEpSet, SRpcMsg *pMsg) {
}
}
-static inline void dmSendRsp(SRpcMsg *pMsg) {
- SMgmtWrapper *pWrapper = pMsg->info.wrapper;
- if (InChildProc(pWrapper)) {
- dmPutToProcPQueue(&pWrapper->proc, pMsg, DND_FUNC_RSP);
- } else {
- rpcSendResponse(pMsg);
- }
-}
-
-static void dmBuildMnodeRedirectRsp(SDnode *pDnode, SRpcMsg *pMsg) {
- SEpSet epSet = {0};
- dmGetMnodeEpSetForRedirect(&pDnode->data, pMsg, &epSet);
-
- int32_t contLen = tSerializeSEpSet(NULL, 0, &epSet);
- pMsg->pCont = rpcMallocCont(contLen);
- if (pMsg->pCont == NULL) {
- pMsg->code = TSDB_CODE_OUT_OF_MEMORY;
- } else {
- tSerializeSEpSet(pMsg->pCont, contLen, &epSet);
- pMsg->contLen = contLen;
- }
-}
-
-static inline void dmSendRedirectRsp(SRpcMsg *pMsg, const SEpSet *pNewEpSet) {
- SRpcMsg rsp = {.code = TSDB_CODE_RPC_REDIRECT, .info = pMsg->info};
- int32_t contLen = tSerializeSEpSet(NULL, 0, pNewEpSet);
-
- rsp.pCont = rpcMallocCont(contLen);
- if (rsp.pCont == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- } else {
- tSerializeSEpSet(rsp.pCont, contLen, pNewEpSet);
- rsp.contLen = contLen;
- }
- dmSendRsp(&rsp);
- rpcFreeCont(pMsg->pCont);
- pMsg->pCont = NULL;
-}
-
static inline void dmRegisterBrokenLinkArg(SRpcMsg *pMsg) {
SMgmtWrapper *pWrapper = pMsg->info.wrapper;
if (InChildProc(pWrapper)) {
@@ -238,17 +248,27 @@ static inline void dmReleaseHandle(SRpcHandleInfo *pHandle, int8_t type) {
SRpcMsg msg = {.code = type, .info = *pHandle};
dmPutToProcPQueue(&pWrapper->proc, &msg, DND_FUNC_RELEASE);
} else {
- rpcReleaseHandle(pHandle->handle, type);
+ rpcReleaseHandle(pHandle, type);
}
}
-static bool rpcRfp(int32_t code) { return code == TSDB_CODE_RPC_REDIRECT; }
+static bool rpcRfp(int32_t code, tmsg_t msgType) {
+ if (code == TSDB_CODE_RPC_REDIRECT || code == TSDB_CODE_RPC_NETWORK_UNAVAIL || code == TSDB_CODE_NODE_NOT_DEPLOYED ||
+ code == TSDB_CODE_SYN_NOT_LEADER || code == TSDB_CODE_APP_NOT_READY || code == TSDB_CODE_RPC_BROKEN_LINK) {
+ if (msgType == TDMT_SCH_QUERY || msgType == TDMT_SCH_MERGE_QUERY || msgType == TDMT_SCH_FETCH || msgType == TDMT_SCH_MERGE_FETCH) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
int32_t dmInitClient(SDnode *pDnode) {
SDnodeTrans *pTrans = &pDnode->trans;
SRpcInit rpcInit = {0};
- rpcInit.label = "DND";
+ rpcInit.label = "DND-C";
rpcInit.numOfThreads = 1;
rpcInit.cfp = (RpcCfp)dmProcessRpcMsg;
rpcInit.sessions = 1024;
@@ -282,7 +302,7 @@ int32_t dmInitServer(SDnode *pDnode) {
SRpcInit rpcInit = {0};
strncpy(rpcInit.localFqdn, tsLocalFqdn, strlen(tsLocalFqdn));
rpcInit.localPort = tsServerPort;
- rpcInit.label = "DND";
+ rpcInit.label = "DND-S";
rpcInit.numOfThreads = tsNumOfRpcThreads;
rpcInit.cfp = (RpcCfp)dmProcessRpcMsg;
rpcInit.sessions = tsMaxShellConns;
diff --git a/source/dnode/mgmt/node_util/inc/dmUtil.h b/source/dnode/mgmt/node_util/inc/dmUtil.h
index 7897f62f62ec9dd99b27568e6c7f4a74ac6463ca..01958aa05355e489371679c56f74d73bf2f2db0b 100644
--- a/source/dnode/mgmt/node_util/inc/dmUtil.h
+++ b/source/dnode/mgmt/node_util/inc/dmUtil.h
@@ -40,18 +40,28 @@
#include "wal.h"
#include "libs/function/function.h"
-// clang-format off
#ifdef __cplusplus
extern "C" {
#endif
-#define dFatal(...) { if (dDebugFlag & DEBUG_FATAL) { taosPrintLog("DND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
-#define dError(...) { if (dDebugFlag & DEBUG_ERROR) { taosPrintLog("DND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
-#define dWarn(...) { if (dDebugFlag & DEBUG_WARN) { taosPrintLog("DND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
-#define dInfo(...) { if (dDebugFlag & DEBUG_INFO) { taosPrintLog("DND ", DEBUG_INFO, 255, __VA_ARGS__); }}
-#define dDebug(...) { if (dDebugFlag & DEBUG_DEBUG) { taosPrintLog("DND ", DEBUG_DEBUG, dDebugFlag, __VA_ARGS__); }}
-#define dTrace(...) { if (dDebugFlag & DEBUG_TRACE) { taosPrintLog("DND ", DEBUG_TRACE, dDebugFlag, __VA_ARGS__); }}
-#define dGTrace(param, ...) do { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dTrace(param ",GTID: %s", __VA_ARGS__, buf);} while(0)
+
+// clang-format off
+
+#define dFatal(...) { if (dDebugFlag & DEBUG_FATAL) { taosPrintLog("DND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
+#define dError(...) { if (dDebugFlag & DEBUG_ERROR) { taosPrintLog("DND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
+#define dWarn(...) { if (dDebugFlag & DEBUG_WARN) { taosPrintLog("DND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
+#define dInfo(...) { if (dDebugFlag & DEBUG_INFO) { taosPrintLog("DND ", DEBUG_INFO, 255, __VA_ARGS__); }}
+#define dDebug(...) { if (dDebugFlag & DEBUG_DEBUG) { taosPrintLog("DND ", DEBUG_DEBUG, dDebugFlag, __VA_ARGS__); }}
+#define dTrace(...) { if (dDebugFlag & DEBUG_TRACE) { taosPrintLog("DND ", DEBUG_TRACE, dDebugFlag, __VA_ARGS__); }}
+
+#define dGFatal(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dFatal(param ", gtid:%s", __VA_ARGS__, buf);}
+#define dGError(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dError(param ", gtid:%s", __VA_ARGS__, buf);}
+#define dGWarn(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dWarn (param ", gtid:%s", __VA_ARGS__, buf);}
+#define dGInfo(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dInfo (param ", gtid:%s", __VA_ARGS__, buf);}
+#define dGDebug(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dDebug(param ", gtid:%s", __VA_ARGS__, buf);}
+#define dGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dTrace(param ", gtid:%s", __VA_ARGS__, buf);}
+
+// clang-format on
typedef enum {
DNODE = 0,
@@ -185,4 +195,3 @@ void dmSetMnodeEpSet(SDnodeData *pData, SEpSet *pEpSet);
#endif
#endif /*_TD_DM_INT_H_*/
-// clang-format on
diff --git a/source/dnode/mgmt/node_util/src/dmEps.c b/source/dnode/mgmt/node_util/src/dmEps.c
index 096fc753b2eca69d3c99c7d80b2901cfbfedbc79..7fe7d448270385c01bf0612942f608b0a662a948 100644
--- a/source/dnode/mgmt/node_util/src/dmEps.c
+++ b/source/dnode/mgmt/node_util/src/dmEps.c
@@ -280,7 +280,7 @@ static void dmPrintEps(SDnodeData *pData) {
dDebug("print dnode list, num:%d", numOfEps);
for (int32_t i = 0; i < numOfEps; i++) {
SDnodeEp *pEp = taosArrayGet(pData->dnodeEps, i);
- dDebug("dnode:%d, fqdn:%s port:%u is_mnode:%d", pEp->id, pEp->ep.fqdn, pEp->ep.port, pEp->isMnode);
+ dDebug("dnode:%d, fqdn:%s port:%u isMnode:%d", pEp->id, pEp->ep.fqdn, pEp->ep.port, pEp->isMnode);
}
}
diff --git a/source/dnode/mgmt/node_util/src/dmFile.c b/source/dnode/mgmt/node_util/src/dmFile.c
index 78e706f90814950287aed067103690f9c215e8e3..9ec17a18b57ac2ce28dfb7c65704748719bc2e0a 100644
--- a/source/dnode/mgmt/node_util/src/dmFile.c
+++ b/source/dnode/mgmt/node_util/src/dmFile.c
@@ -127,14 +127,24 @@ TdFilePtr dmCheckRunning(const char *dataDir) {
return NULL;
}
- int32_t ret = taosLockFile(pFile);
- if (ret != 0) {
+ int32_t retryTimes = 0;
+ int32_t ret = 0;
+ do {
+ ret = taosLockFile(pFile);
+ if (ret == 0) break;
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ taosMsleep(1000);
+ retryTimes++;
+ dError("failed to lock file:%s since %s, retryTimes:%d", filepath, terrstr(), retryTimes);
+ } while (retryTimes < 12);
+
+ if (ret < 0) {
terrno = TAOS_SYSTEM_ERROR(errno);
- dError("failed to lock file:%s since %s", filepath, terrstr());
taosCloseFile(&pFile);
return NULL;
}
+ terrno = 0;
dDebug("lock file:%s to prevent repeated starts", filepath);
return pFile;
}
diff --git a/source/dnode/mgmt/test/sut/src/sut.cpp b/source/dnode/mgmt/test/sut/src/sut.cpp
index 6ef94481ea8edd66317f4d2a7b01bc3234ccd4d9..572c57284a9516a8f469f4de1b79d92946a63314 100644
--- a/source/dnode/mgmt/test/sut/src/sut.cpp
+++ b/source/dnode/mgmt/test/sut/src/sut.cpp
@@ -30,17 +30,22 @@ void Testbase::InitLog(const char* path) {
tsdbDebugFlag = 0;
tsLogEmbedded = 1;
tsAsyncLog = 0;
- tsRpcQueueMemoryAllowed = 1024 * 1024 * 64;
-
+
taosRemoveDir(path);
taosMkDir(path);
tstrncpy(tsLogDir, path, PATH_MAX);
- if (taosInitLog("taosdlog", 1) != 0) {
+
+ taosGetSystemInfo();
+ tsRpcQueueMemoryAllowed = tsTotalMemoryKB * 0.1;
+if (taosInitLog("taosdlog", 1) != 0) {
printf("failed to init log file\n");
}
}
void Testbase::Init(const char* path, int16_t port) {
+#ifdef _TD_DARWIN_64
+ osDefaultInit();
+#endif
tsServerPort = port;
strcpy(tsLocalFqdn, "localhost");
snprintf(tsLocalEp, TSDB_EP_LEN, "%s:%u", tsLocalFqdn, tsServerPort);
@@ -102,6 +107,7 @@ int32_t Testbase::SendShowReq(int8_t showType, const char* tb, const char* db) {
ASSERT(pRsp->pCont != nullptr);
if (pRsp->contLen == 0) return -1;
+ if (pRsp->code != 0) return -1;
showRsp = (SRetrieveMetaTableRsp*)pRsp->pCont;
showRsp->handle = htobe64(showRsp->handle); // show Id
diff --git a/source/dnode/mgmt/test/vnode/vnode.cpp b/source/dnode/mgmt/test/vnode/vnode.cpp
index 8aba4f81b59ee35ff61616f0ada5056c8d76074a..520d844dbd2abaf07346bb1a1269c2e1ad85ad8d 100644
--- a/source/dnode/mgmt/test/vnode/vnode.cpp
+++ b/source/dnode/mgmt/test/vnode/vnode.cpp
@@ -45,7 +45,7 @@ TEST_F(DndTestVnode, 01_Create_Vnode) {
createReq.compression = 2;
createReq.replica = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.selfIndex = 0;
for (int r = 0; r < createReq.replica; ++r) {
SReplica* pReplica = &createReq.replicas[r];
@@ -80,7 +80,7 @@ TEST_F(DndTestVnode, 02_Alter_Vnode) {
alterReq.walLevel = 1;
alterReq.replica = 1;
alterReq.strict = 1;
- alterReq.cacheLastRow = 0;
+ alterReq.cacheLast = 0;
alterReq.selfIndex = 0;
for (int r = 0; r < alterReq.replica; ++r) {
SReplica* pReplica = &alterReq.replicas[r];
diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h
index 987b01b96a202ca4e485fe45bf6684e839fc9e37..7ac991451eb920ae93aea5ba588af20038dd3d2e 100644
--- a/source/dnode/mnode/impl/inc/mndDef.h
+++ b/source/dnode/mnode/impl/inc/mndDef.h
@@ -148,7 +148,10 @@ typedef struct {
int32_t accessTimes;
int32_t numOfVnodes;
int32_t numOfSupportVnodes;
- int32_t numOfCores;
+ float numOfCores;
+ int64_t memTotal;
+ int64_t memAvail;
+ int64_t memUsed;
EDndReason offlineReason;
uint16_t port;
char fqdn[TSDB_FQDN_LEN];
@@ -243,6 +246,7 @@ typedef struct {
int32_t buffer;
int32_t pageSize;
int32_t pages;
+ int32_t cacheLastSize;
int32_t daysPerFile;
int32_t daysToKeep0;
int32_t daysToKeep1;
@@ -255,8 +259,8 @@ typedef struct {
int8_t compression;
int8_t replications;
int8_t strict;
- int8_t cacheLastRow;
int8_t hashMethod; // default is 1
+ int8_t cacheLast;
int32_t numOfRetensions;
SArray* pRetensions;
int8_t schemaless;
@@ -341,14 +345,16 @@ typedef struct {
int32_t colVer;
int32_t smaVer;
int32_t nextColId;
- int64_t watermark[2];
int64_t maxdelay[2];
+ int64_t watermark[2];
int32_t ttl;
int32_t numOfColumns;
int32_t numOfTags;
+ int32_t numOfFuncs;
int32_t commentLen;
int32_t ast1Len;
int32_t ast2Len;
+ SArray* pFuncs;
SSchema* pColumns;
SSchema* pTags;
char* comment;
@@ -420,7 +426,8 @@ typedef struct {
int64_t uid;
int64_t dbUid;
int32_t version;
- int8_t subType; // column, db or stable
+ int8_t subType; // column, db or stable
+ int8_t withMeta; // TODO
SRWLatch lock;
int32_t sqlLen;
int32_t astLen;
@@ -487,6 +494,7 @@ typedef struct {
int64_t dbUid;
int32_t vgNum;
int8_t subType;
+ int8_t withMeta;
int64_t stbUid;
SHashObj* consumerHash; // consumerId -> SMqConsumerEp
SArray* unassignedVgs; // SArray
@@ -552,7 +560,7 @@ typedef struct {
int64_t uid;
int8_t status;
// config
- int8_t dropPolicy;
+ int8_t igExpired;
int8_t trigger;
int64_t triggerParam;
int64_t watermark;
diff --git a/source/dnode/mnode/impl/inc/mndInfoSchema.h b/source/dnode/mnode/impl/inc/mndInfoSchema.h
index 43d934c43101161bc63a487c644a5f6f3b218348..b10d92ee3de1a0e06d801c9a8840751a9f52f37c 100644
--- a/source/dnode/mnode/impl/inc/mndInfoSchema.h
+++ b/source/dnode/mnode/impl/inc/mndInfoSchema.h
@@ -25,6 +25,7 @@ extern "C" {
int32_t mndInitInfos(SMnode *pMnode);
void mndCleanupInfos(SMnode *pMnode);
int32_t mndBuildInsTableSchema(SMnode *pMnode, const char *dbFName, const char *tbName, STableMetaRsp *pRsp);
+int32_t mndBuildInsTableCfg(SMnode *pMnode, const char *dbFName, const char *tbName, STableCfgRsp *pRsp);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h
index c810a0cbc75474154c9f19b5872656bb7fc2dfbe..b94c60c4abf923e4bb2fbf7caffaa5ebafe7b47c 100644
--- a/source/dnode/mnode/impl/inc/mndInt.h
+++ b/source/dnode/mnode/impl/inc/mndInt.h
@@ -34,14 +34,19 @@ extern "C" {
#endif
// clang-format off
-#define mFatal(...) { if (mDebugFlag & DEBUG_FATAL) { taosPrintLog("MND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
-#define mError(...) { if (mDebugFlag & DEBUG_ERROR) { taosPrintLog("MND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
-#define mWarn(...) { if (mDebugFlag & DEBUG_WARN) { taosPrintLog("MND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
-#define mInfo(...) { if (mDebugFlag & DEBUG_INFO) { taosPrintLog("MND ", DEBUG_INFO, 255, __VA_ARGS__); }}
-#define mDebug(...) { if (mDebugFlag & DEBUG_DEBUG) { taosPrintLog("MND ", DEBUG_DEBUG, mDebugFlag, __VA_ARGS__); }}
-#define mTrace(...) { if (mDebugFlag & DEBUG_TRACE) { taosPrintLog("MND ", DEBUG_TRACE, mDebugFlag, __VA_ARGS__); }}
-#define mGTrace(param, ...) do { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mTrace(param ", GTID: %s", __VA_ARGS__, buf);} while(0)
-
+#define mFatal(...) { if (mDebugFlag & DEBUG_FATAL) { taosPrintLog("MND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
+#define mError(...) { if (mDebugFlag & DEBUG_ERROR) { taosPrintLog("MND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
+#define mWarn(...) { if (mDebugFlag & DEBUG_WARN) { taosPrintLog("MND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
+#define mInfo(...) { if (mDebugFlag & DEBUG_INFO) { taosPrintLog("MND ", DEBUG_INFO, 255, __VA_ARGS__); }}
+#define mDebug(...) { if (mDebugFlag & DEBUG_DEBUG) { taosPrintLog("MND ", DEBUG_DEBUG, mDebugFlag, __VA_ARGS__); }}
+#define mTrace(...) { if (mDebugFlag & DEBUG_TRACE) { taosPrintLog("MND ", DEBUG_TRACE, mDebugFlag, __VA_ARGS__); }}
+
+#define mGFatal(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mFatal(param ", gtid:%s", __VA_ARGS__, buf);}
+#define mGError(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mError(param ", gtid:%s", __VA_ARGS__, buf);}
+#define mGWarn(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mWarn (param ", gtid:%s", __VA_ARGS__, buf);}
+#define mGInfo(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mInfo (param ", gtid:%s", __VA_ARGS__, buf);}
+#define mGDebug(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mDebug(param ", gtid:%s", __VA_ARGS__, buf);}
+#define mGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mTrace(param ", gtid:%s", __VA_ARGS__, buf);}
// clang-format on
#define SYSTABLE_SCH_TABLE_NAME_LEN ((TSDB_TABLE_NAME_LEN - 1) + VARSTR_HEADER_SIZE)
@@ -70,7 +75,7 @@ typedef struct {
typedef struct {
SCacheObj *connCache;
- SCacheObj *appCache;
+ SCacheObj *appCache;
} SProfileMgmt;
typedef struct {
@@ -79,7 +84,7 @@ typedef struct {
} STelemMgmt;
typedef struct {
- sem_t syncSem;
+ tsem_t syncSem;
int64_t sync;
bool standby;
SReplica replica;
diff --git a/source/dnode/mnode/impl/inc/mndPerfSchema.h b/source/dnode/mnode/impl/inc/mndPerfSchema.h
index 19f60229f926583f321ab350f6ac6043f6c9b096..87b4626e83fb400e45083ea5d3380dee0f543c75 100644
--- a/source/dnode/mnode/impl/inc/mndPerfSchema.h
+++ b/source/dnode/mnode/impl/inc/mndPerfSchema.h
@@ -23,6 +23,7 @@ extern "C" {
#endif
int32_t mndBuildPerfsTableSchema(SMnode *pMnode, const char *dbFName, const char *tbName, STableMetaRsp *pRsp);
+int32_t mndBuildPerfsTableCfg(SMnode *pMnode, const char *dbFName, const char *tbName, STableCfgRsp *pRsp);
int32_t mndInitPerfs(SMnode *pMnode);
void mndCleanupPerfs(SMnode *pMnode);
diff --git a/source/dnode/mnode/impl/inc/mndAuth.h b/source/dnode/mnode/impl/inc/mndPrivilege.h
similarity index 58%
rename from source/dnode/mnode/impl/inc/mndAuth.h
rename to source/dnode/mnode/impl/inc/mndPrivilege.h
index 45841ca367c880f93caf35cee57a197c87d3fea3..a149c0f0e276103abd5f133fec133ce8845c6fe0 100644
--- a/source/dnode/mnode/impl/inc/mndAuth.h
+++ b/source/dnode/mnode/impl/inc/mndPrivilege.h
@@ -13,8 +13,8 @@
* along with this program. If not, see .
*/
-#ifndef _TD_MND_AUTH_H_
-#define _TD_MND_AUTH_H_
+#ifndef _TD_MND_PRIVILEGE_H
+#define _TD_MND_PRIVILEGE_H
#include "mndInt.h"
@@ -23,13 +23,18 @@ extern "C" {
#endif
typedef enum {
- MND_OPER_CREATE_USER = 1,
+ MND_OPER_CONNECT = 1,
+ MND_OPER_CREATE_ACCT,
+ MND_OPER_DROP_ACCT,
+ MND_OPER_ALTER_ACCT,
+ MND_OPER_CREATE_USER,
MND_OPER_DROP_USER,
MND_OPER_ALTER_USER,
MND_OPER_CREATE_BNODE,
MND_OPER_DROP_BNODE,
MND_OPER_CREATE_DNODE,
MND_OPER_DROP_DNODE,
+ MND_OPER_CONFIG_DNODE,
MND_OPER_CREATE_MNODE,
MND_OPER_DROP_MNODE,
MND_OPER_CREATE_QNODE,
@@ -37,30 +42,37 @@ typedef enum {
MND_OPER_CREATE_SNODE,
MND_OPER_DROP_SNODE,
MND_OPER_REDISTRIBUTE_VGROUP,
+ MND_OPER_MERGE_VGROUP,
MND_OPER_SPLIT_VGROUP,
MND_OPER_BALANCE_VGROUP,
MND_OPER_CREATE_FUNC,
MND_OPER_DROP_FUNC,
MND_OPER_KILL_TRANS,
+ MND_OPER_KILL_CONN,
+ MND_OPER_KILL_QUERY,
MND_OPER_CREATE_DB,
MND_OPER_ALTER_DB,
MND_OPER_DROP_DB,
MND_OPER_COMPACT_DB,
+ MND_OPER_TRIM_DB,
MND_OPER_USE_DB,
MND_OPER_WRITE_DB,
MND_OPER_READ_DB,
+ MND_OPER_READ_OR_WRITE_DB,
+ MND_OPER_SHOW_VARIBALES,
} EOperType;
-int32_t mndInitAuth(SMnode *pMnode);
-void mndCleanupAuth(SMnode *pMnode);
+int32_t mndInitPrivilege(SMnode *pMnode);
+void mndCleanupPrivilege(SMnode *pMnode);
-int32_t mndCheckOperAuth(SMnode *pMnode, const char *user, EOperType operType);
-int32_t mndCheckDbAuth(SMnode *pMnode, const char *user, EOperType operType, SDbObj *pDb);
-int32_t mndCheckShowAuth(SMnode *pMnode, const char *user, int32_t showType);
-int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SAlterUserReq *pAlter);
+int32_t mndCheckOperPrivilege(SMnode *pMnode, const char *user, EOperType operType);
+int32_t mndCheckDbPrivilege(SMnode *pMnode, const char *user, EOperType operType, SDbObj *pDb);
+int32_t mndCheckDbPrivilegeByName(SMnode *pMnode, const char *user, EOperType operType, const char *dbname);
+int32_t mndCheckShowPrivilege(SMnode *pMnode, const char *user, EShowType showType, const char *dbname);
+int32_t mndCheckAlterUserPrivilege(SUserObj *pOperUser, SUserObj *pUser, SAlterUserReq *pAlter);
#ifdef __cplusplus
}
#endif
-#endif /*_TD_MND_AUTH_H_*/
+#endif /*_TD_MND_PRIVILEGE_H*/
diff --git a/source/dnode/mnode/impl/inc/mndQnode.h b/source/dnode/mnode/impl/inc/mndQnode.h
index 3e38565a4fe67b93d8ba8b9d30160ce54b13dee5..17615500c47abc2ea0dcad21b5a70ec8a1310892 100644
--- a/source/dnode/mnode/impl/inc/mndQnode.h
+++ b/source/dnode/mnode/impl/inc/mndQnode.h
@@ -24,12 +24,12 @@ extern "C" {
#define QNODE_LOAD_VALUE(pQnode) (pQnode ? (pQnode->load.numOfQueryInQueue + pQnode->load.numOfFetchInQueue) : 0)
-int32_t mndInitQnode(SMnode *pMnode);
-void mndCleanupQnode(SMnode *pMnode);
-
+int32_t mndInitQnode(SMnode *pMnode);
+void mndCleanupQnode(SMnode *pMnode);
SQnodeObj *mndAcquireQnode(SMnode *pMnode, int32_t qnodeId);
-void mndReleaseQnode(SMnode *pMnode, SQnodeObj *pObj);
-int32_t mndCreateQnodeList(SMnode *pMnode, SArray** pList, int32_t limit);
+void mndReleaseQnode(SMnode *pMnode, SQnodeObj *pObj);
+int32_t mndCreateQnodeList(SMnode *pMnode, SArray **pList, int32_t limit);
+int32_t mndSetDropQnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SQnodeObj *pObj);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/inc/mndScheduler.h b/source/dnode/mnode/impl/inc/mndScheduler.h
index 15d2c6cd5e213955f81e6203b63e2ba26125e44e..db81d8843e5415b4bf11fd33a013fb700f5914bc 100644
--- a/source/dnode/mnode/impl/inc/mndScheduler.h
+++ b/source/dnode/mnode/impl/inc/mndScheduler.h
@@ -27,12 +27,10 @@ void mndCleanupScheduler(SMnode* pMnode);
int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscribeObj* pSub);
-int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream);
-
int32_t mndConvertRsmaTask(char** pDst, int32_t* pDstLen, const char* ast, int64_t uid, int8_t triggerType,
int64_t watermark);
-int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream);
+int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/inc/mndSnode.h b/source/dnode/mnode/impl/inc/mndSnode.h
index 180f18a6ddc68a5cd93987714c3d2b42349a529f..ec7bb02ca7cd86ad5f677fa229f7a575ace6086a 100644
--- a/source/dnode/mnode/impl/inc/mndSnode.h
+++ b/source/dnode/mnode/impl/inc/mndSnode.h
@@ -22,9 +22,12 @@
extern "C" {
#endif
-int32_t mndInitSnode(SMnode *pMnode);
-void mndCleanupSnode(SMnode *pMnode);
-SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode);
+int32_t mndInitSnode(SMnode *pMnode);
+void mndCleanupSnode(SMnode *pMnode);
+SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t qnodeId);
+void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj);
+SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode);
+int32_t mndSetDropSnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SSnodeObj *pObj);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/inc/mndStream.h b/source/dnode/mnode/impl/inc/mndStream.h
index 69385c3a46b7f129bc1704385a0b723f4671a2d0..d873df621e8b44dca5adc9b4c4affaddc78730c2 100644
--- a/source/dnode/mnode/impl/inc/mndStream.h
+++ b/source/dnode/mnode/impl/inc/mndStream.h
@@ -33,6 +33,12 @@ SSdbRow *mndStreamActionDecode(SSdbRaw *pRaw);
int32_t mndDropStreamByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb);
int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream);
+// for sma
+// TODO refactor
+int32_t mndDropStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream);
+int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream);
+
+int32_t mndDropStreamByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/inc/mndTrans.h b/source/dnode/mnode/impl/inc/mndTrans.h
index bc2d5c82b1410af66f758408b442912d02b2fd79..1497bba11c232c2cca215043b71a03a52e7a6977 100644
--- a/source/dnode/mnode/impl/inc/mndTrans.h
+++ b/source/dnode/mnode/impl/inc/mndTrans.h
@@ -39,8 +39,10 @@ typedef struct {
int32_t id;
int32_t errCode;
int32_t acceptableCode;
- ETrnStage stage;
+ int32_t retryCode;
ETrnAct actionType;
+ ETrnStage stage;
+ int8_t reserved;
int8_t rawWritten;
int8_t msgSent;
int8_t msgReceived;
diff --git a/source/dnode/mnode/impl/inc/mndVgroup.h b/source/dnode/mnode/impl/inc/mndVgroup.h
index e0ff7a70d7bbd8d120982f1696689533c92f5ab9..c8237d17d8e37808f82c4569ee235e9d1ac5d45a 100644
--- a/source/dnode/mnode/impl/inc/mndVgroup.h
+++ b/source/dnode/mnode/impl/inc/mndVgroup.h
@@ -30,6 +30,8 @@ SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup);
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup);
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId);
void mndSortVnodeGid(SVgObj *pVgroup);
+int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId);
+int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup);
SArray *mndBuildDnodesArray(SMnode *, int32_t exceptDnodeId);
int32_t mndAllocSmaVgroup(SMnode *, SDbObj *pDb, SVgObj *pVgroup);
@@ -47,6 +49,7 @@ int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, S
void *mndBuildCreateVnodeReq(SMnode *, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *cntlen, bool standby);
void *mndBuildDropVnodeReq(SMnode *, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen);
void *mndBuildAlterVnodeReq(SMnode *, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen);
+bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid);
#ifdef __cplusplus
}
diff --git a/source/dnode/mnode/impl/src/mndAcct.c b/source/dnode/mnode/impl/src/mndAcct.c
index 0ce4a8c76e72ce2f2513819139b00a01c67f5231..33f0bb7a34d667b8f25fb10b06e6e6a00e669d60 100644
--- a/source/dnode/mnode/impl/src/mndAcct.c
+++ b/source/dnode/mnode/impl/src/mndAcct.c
@@ -15,6 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndAcct.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndTrans.h"
@@ -212,18 +213,30 @@ static int32_t mndAcctActionUpdate(SSdb *pSdb, SAcctObj *pOld, SAcctObj *pNew) {
}
static int32_t mndProcessCreateAcctReq(SRpcMsg *pReq) {
+ if (mndCheckOperPrivilege(pReq->info.node, pReq->info.conn.user, MND_OPER_CREATE_ACCT) != 0) {
+ return -1;
+ }
+
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
mError("failed to process create acct request since %s", terrstr());
return -1;
}
static int32_t mndProcessAlterAcctReq(SRpcMsg *pReq) {
+ if (mndCheckOperPrivilege(pReq->info.node, pReq->info.conn.user, MND_OPER_ALTER_ACCT) != 0) {
+ return -1;
+ }
+
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
mError("failed to process create acct request since %s", terrstr());
return -1;
}
static int32_t mndProcessDropAcctReq(SRpcMsg *pReq) {
+ if (mndCheckOperPrivilege(pReq->info.node, pReq->info.conn.user, MND_OPER_DROP_ACCT) != 0) {
+ return -1;
+ }
+
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
mError("failed to process create acct request since %s", terrstr());
return -1;
diff --git a/source/dnode/mnode/impl/src/mndBnode.c b/source/dnode/mnode/impl/src/mndBnode.c
index 0de40ca67192d9394b44d13b9041b308ab7b3208..aafcd1999230e71a03c05422cfb538958f4d27c7 100644
--- a/source/dnode/mnode/impl/src/mndBnode.c
+++ b/source/dnode/mnode/impl/src/mndBnode.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndBnode.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDnode.h"
#include "mndShow.h"
#include "mndTrans.h"
@@ -277,6 +277,9 @@ static int32_t mndProcessCreateBnodeReq(SRpcMsg *pReq) {
}
mDebug("bnode:%d, start to create", createReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_BNODE) != 0) {
+ goto _OVER;
+ }
pObj = mndAcquireBnode(pMnode, createReq.dnodeId);
if (pObj != NULL) {
@@ -292,10 +295,6 @@ static int32_t mndProcessCreateBnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_BNODE) != 0) {
- goto _OVER;
- }
-
code = mndCreateBnode(pMnode, pReq, pDnode, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -383,6 +382,9 @@ static int32_t mndProcessDropBnodeReq(SRpcMsg *pReq) {
}
mDebug("bnode:%d, start to drop", dropReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_BNODE) != 0) {
+ goto _OVER;
+ }
if (dropReq.dnodeId <= 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -394,10 +396,6 @@ static int32_t mndProcessDropBnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_BNODE) != 0) {
- goto _OVER;
- }
-
code = mndDropBnode(pMnode, pReq, pObj);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c
index 4da3c906d77e48cee0ba863f1dccbc2a72d71431..27b785f4d221802ed2d4e4235a08c8a9f6e14e16 100644
--- a/source/dnode/mnode/impl/src/mndConsumer.c
+++ b/source/dnode/mnode/impl/src/mndConsumer.c
@@ -15,11 +15,11 @@
#define _DEFAULT_SOURCE
#include "mndConsumer.h"
-#include "mndAuth.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
#include "mndOffset.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndStb.h"
#include "mndSubscribe.h"
@@ -92,7 +92,7 @@ static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) {
SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pLostMsg->consumerId);
ASSERT(pConsumer);
- mInfo("receive consumer lost msg, consumer id %ld, status %s", pLostMsg->consumerId,
+ mInfo("receive consumer lost msg, consumer id %" PRId64 ", status %s", pLostMsg->consumerId,
mndConsumerStatusName(pConsumer->status));
if (pConsumer->status != MQ_CONSUMER_STATUS__READY) {
@@ -124,7 +124,7 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) {
SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pRecoverMsg->consumerId);
ASSERT(pConsumer);
- mInfo("receive consumer recover msg, consumer id %ld, status %s", pRecoverMsg->consumerId,
+ mInfo("receive consumer recover msg, consumer id %" PRId64 ", status %s", pRecoverMsg->consumerId,
mndConsumerStatusName(pConsumer->status));
if (pConsumer->status != MQ_CONSUMER_STATUS__READY) {
@@ -296,7 +296,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
// 2. check epoch, only send ep info when epoches do not match
if (epoch != serverEpoch) {
taosRLockLatch(&pConsumer->lock);
- mInfo("process ask ep, consumer %ld(epoch %d), server epoch %d", consumerId, epoch, serverEpoch);
+ mInfo("process ask ep, consumer:%" PRId64 "(epoch %d), server epoch %d", consumerId, epoch, serverEpoch);
int32_t numOfTopics = taosArrayGetSize(pConsumer->currentTopics);
rsp.topics = taosArrayInit(numOfTopics, sizeof(SMqSubTopicEp));
@@ -431,23 +431,16 @@ static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
goto SUBSCRIBE_OVER;
}
-#if 0
- // ref topic to prevent drop
- // TODO make topic complete
- SMqTopicObj topicObj = {0};
- memcpy(&topicObj, pTopic, sizeof(SMqTopicObj));
- topicObj.refConsumerCnt = pTopic->refConsumerCnt + 1;
- mInfo("subscribe topic %s by consumer %ld cgroup %s, refcnt %d", pTopic->name, consumerId, cgroup,
- topicObj.refConsumerCnt);
- if (mndSetTopicCommitLogs(pMnode, pTrans, &topicObj) != 0) goto SUBSCRIBE_OVER;
-#endif
+ if (mndCheckDbPrivilegeByName(pMnode, pMsg->info.conn.user, MND_OPER_READ_DB, pTopic->db) != 0) {
+ goto SUBSCRIBE_OVER;
+ }
mndReleaseTopic(pMnode, pTopic);
}
pConsumerOld = mndAcquireConsumer(pMnode, consumerId);
if (pConsumerOld == NULL) {
- mInfo("receive subscribe request from new consumer: %ld", consumerId);
+ mInfo("receive subscribe request from new consumer:%" PRId64, consumerId);
pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup);
tstrncpy(pConsumerNew->clientId, subscribe.clientId, 256);
@@ -468,8 +461,8 @@ static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
int32_t status = atomic_load_32(&pConsumerOld->status);
- mInfo("receive subscribe request from old consumer: %ld, current status: %s", consumerId,
- mndConsumerStatusName(status));
+ mInfo("receive subscribe request from existing consumer:%" PRId64 ", current status: %s, subscribe topic num: %d",
+ consumerId, mndConsumerStatusName(status), newTopicNum);
if (status != MQ_CONSUMER_STATUS__READY) {
terrno = TSDB_CODE_MND_CONSUMER_NOT_READY;
@@ -845,12 +838,15 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *
pShow->pIter = sdbFetch(pSdb, SDB_CONSUMER, pShow->pIter, (void **)&pConsumer);
if (pShow->pIter == NULL) break;
if (taosArrayGetSize(pConsumer->assignedTopics) == 0) {
+ mDebug("showing consumer %ld no assigned topic, skip", pConsumer->consumerId);
sdbRelease(pSdb, pConsumer);
continue;
}
taosRLockLatch(&pConsumer->lock);
+ mDebug("showing consumer %ld", pConsumer->consumerId);
+
int32_t topicSz = taosArrayGetSize(pConsumer->assignedTopics);
bool hasTopic = true;
if (topicSz == 0) {
diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c
index 345464399eef3b75153e9cc6d6634ade49225b00..b1c2b0e27768e93de64214e7a9b5816102bdcae0 100644
--- a/source/dnode/mnode/impl/src/mndDb.c
+++ b/source/dnode/mnode/impl/src/mndDb.c
@@ -15,12 +15,13 @@
#define _DEFAULT_SOURCE
#include "mndDb.h"
-#include "mndAuth.h"
#include "mndDnode.h"
#include "mndOffset.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndSma.h"
#include "mndStb.h"
+#include "mndStream.h"
#include "mndSubscribe.h"
#include "mndTopic.h"
#include "mndTrans.h"
@@ -41,6 +42,7 @@ static int32_t mndProcessAlterDbReq(SRpcMsg *pReq);
static int32_t mndProcessDropDbReq(SRpcMsg *pReq);
static int32_t mndProcessUseDbReq(SRpcMsg *pReq);
static int32_t mndProcessCompactDbReq(SRpcMsg *pReq);
+static int32_t mndProcessTrimDbReq(SRpcMsg *pReq);
static int32_t mndRetrieveDbs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity);
static void mndCancelGetNextDb(SMnode *pMnode, void *pIter);
static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq);
@@ -61,6 +63,7 @@ int32_t mndInitDb(SMnode *pMnode) {
mndSetMsgHandle(pMnode, TDMT_MND_DROP_DB, mndProcessDropDbReq);
mndSetMsgHandle(pMnode, TDMT_MND_USE_DB, mndProcessUseDbReq);
mndSetMsgHandle(pMnode, TDMT_MND_COMPACT_DB, mndProcessCompactDbReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_TRIM_DB, mndProcessTrimDbReq);
mndSetMsgHandle(pMnode, TDMT_MND_GET_DB_CFG, mndProcessGetDbCfgReq);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_DB, mndRetrieveDbs);
@@ -92,6 +95,7 @@ static SSdbRaw *mndDbActionEncode(SDbObj *pDb) {
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.buffer, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.pageSize, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.pages, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pDb->cfg.cacheLastSize, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.daysPerFile, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.daysToKeep0, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.daysToKeep1, _OVER)
@@ -104,7 +108,7 @@ static SSdbRaw *mndDbActionEncode(SDbObj *pDb) {
SDB_SET_INT8(pRaw, dataPos, pDb->cfg.compression, _OVER)
SDB_SET_INT8(pRaw, dataPos, pDb->cfg.replications, _OVER)
SDB_SET_INT8(pRaw, dataPos, pDb->cfg.strict, _OVER)
- SDB_SET_INT8(pRaw, dataPos, pDb->cfg.cacheLastRow, _OVER)
+ SDB_SET_INT8(pRaw, dataPos, pDb->cfg.cacheLast, _OVER)
SDB_SET_INT8(pRaw, dataPos, pDb->cfg.hashMethod, _OVER)
SDB_SET_INT32(pRaw, dataPos, pDb->cfg.numOfRetensions, _OVER)
for (int32_t i = 0; i < pDb->cfg.numOfRetensions; ++i) {
@@ -164,6 +168,7 @@ static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.buffer, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.pageSize, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.pages, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.cacheLastSize, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.daysPerFile, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.daysToKeep0, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.daysToKeep1, _OVER)
@@ -176,7 +181,7 @@ static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.compression, _OVER)
SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.replications, _OVER)
SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.strict, _OVER)
- SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.cacheLastRow, _OVER)
+ SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.cacheLast, _OVER)
SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.hashMethod, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.numOfRetensions, _OVER)
if (pDb->cfg.numOfRetensions > 0) {
@@ -229,8 +234,9 @@ static int32_t mndDbActionUpdate(SSdb *pSdb, SDbObj *pOld, SDbObj *pNew) {
pOld->cfgVersion = pNew->cfgVersion;
pOld->vgVersion = pNew->vgVersion;
pOld->cfg.buffer = pNew->cfg.buffer;
- pOld->cfg.pages = pNew->cfg.pages;
pOld->cfg.pageSize = pNew->cfg.pageSize;
+ pOld->cfg.pages = pNew->cfg.pages;
+ pOld->cfg.cacheLastSize = pNew->cfg.cacheLastSize;
pOld->cfg.daysPerFile = pNew->cfg.daysPerFile;
pOld->cfg.daysToKeep0 = pNew->cfg.daysToKeep0;
pOld->cfg.daysToKeep1 = pNew->cfg.daysToKeep1;
@@ -238,7 +244,7 @@ static int32_t mndDbActionUpdate(SSdb *pSdb, SDbObj *pOld, SDbObj *pNew) {
pOld->cfg.fsyncPeriod = pNew->cfg.fsyncPeriod;
pOld->cfg.walLevel = pNew->cfg.walLevel;
pOld->cfg.strict = pNew->cfg.strict;
- pOld->cfg.cacheLastRow = pNew->cfg.cacheLastRow;
+ pOld->cfg.cacheLast = pNew->cfg.cacheLast;
pOld->cfg.replications = pNew->cfg.replications;
taosWUnLockLatch(&pOld->lock);
return 0;
@@ -287,6 +293,7 @@ static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) {
if (pCfg->buffer < TSDB_MIN_BUFFER_PER_VNODE || pCfg->buffer > TSDB_MAX_BUFFER_PER_VNODE) return -1;
if (pCfg->pageSize < TSDB_MIN_PAGESIZE_PER_VNODE || pCfg->pageSize > TSDB_MAX_PAGESIZE_PER_VNODE) return -1;
if (pCfg->pages < TSDB_MIN_PAGES_PER_VNODE || pCfg->pages > TSDB_MAX_PAGES_PER_VNODE) return -1;
+ if (pCfg->cacheLastSize < TSDB_MIN_DB_CACHE_LAST_SIZE || pCfg->cacheLastSize > TSDB_MAX_DB_CACHE_LAST_SIZE) return -1;
if (pCfg->daysPerFile < TSDB_MIN_DAYS_PER_FILE || pCfg->daysPerFile > TSDB_MAX_DAYS_PER_FILE) return -1;
if (pCfg->daysToKeep0 < TSDB_MIN_KEEP || pCfg->daysToKeep0 > TSDB_MAX_KEEP) return -1;
if (pCfg->daysToKeep1 < TSDB_MIN_KEEP || pCfg->daysToKeep1 > TSDB_MAX_KEEP) return -1;
@@ -305,7 +312,7 @@ static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) {
if (pCfg->replications != 1 && pCfg->replications != 3) return -1;
if (pCfg->strict < TSDB_DB_STRICT_OFF || pCfg->strict > TSDB_DB_STRICT_ON) return -1;
if (pCfg->schemaless < TSDB_DB_SCHEMALESS_OFF || pCfg->schemaless > TSDB_DB_SCHEMALESS_ON) return -1;
- if (pCfg->cacheLastRow < TSDB_MIN_DB_CACHE_LAST_ROW || pCfg->cacheLastRow > TSDB_MAX_DB_CACHE_LAST_ROW) return -1;
+ if (pCfg->cacheLast < TSDB_MIN_DB_CACHE_LAST || pCfg->cacheLast > TSDB_MAX_DB_CACHE_LAST) return -1;
if (pCfg->hashMethod != 1) return -1;
if (pCfg->replications > mndGetDnodeSize(pMnode)) {
terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
@@ -334,7 +341,8 @@ static void mndSetDefaultDbCfg(SDbCfg *pCfg) {
if (pCfg->compression < 0) pCfg->compression = TSDB_DEFAULT_COMP_LEVEL;
if (pCfg->replications < 0) pCfg->replications = TSDB_DEFAULT_DB_REPLICA;
if (pCfg->strict < 0) pCfg->strict = TSDB_DEFAULT_DB_STRICT;
- if (pCfg->cacheLastRow < 0) pCfg->cacheLastRow = TSDB_DEFAULT_CACHE_LAST_ROW;
+ if (pCfg->cacheLast < 0) pCfg->cacheLast = TSDB_DEFAULT_CACHE_LAST;
+ if (pCfg->cacheLastSize <= 0) pCfg->cacheLastSize = TSDB_DEFAULT_CACHE_LAST_SIZE;
if (pCfg->numOfRetensions < 0) pCfg->numOfRetensions = 0;
if (pCfg->schemaless < 0) pCfg->schemaless = TSDB_DB_SCHEMALESS_OFF;
}
@@ -433,6 +441,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate,
.buffer = pCreate->buffer,
.pageSize = pCreate->pageSize,
.pages = pCreate->pages,
+ .cacheLastSize = pCreate->cacheLastSize,
.daysPerFile = pCreate->daysPerFile,
.daysToKeep0 = pCreate->daysToKeep0,
.daysToKeep1 = pCreate->daysToKeep1,
@@ -445,7 +454,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate,
.compression = pCreate->compression,
.replications = pCreate->replications,
.strict = pCreate->strict,
- .cacheLastRow = pCreate->cacheLastRow,
+ .cacheLast = pCreate->cacheLast,
.hashMethod = 1,
.schemaless = pCreate->schemaless,
};
@@ -474,7 +483,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate,
int32_t code = -1;
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq);
if (pTrans == NULL) goto _OVER;
-
+ // mndTransSetSerial(pTrans);
mDebug("trans:%d, used to create db:%s", pTrans->id, pCreate->db);
mndTransSetDbName(pTrans, dbObj.name, NULL);
@@ -506,6 +515,9 @@ static int32_t mndProcessCreateDbReq(SRpcMsg *pReq) {
}
mDebug("db:%s, start to create, vgroups:%d", createReq.db, createReq.numOfVgroups);
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_DB, NULL) != 0) {
+ goto _OVER;
+ }
pDb = mndAcquireDb(pMnode, createReq.db);
if (pDb != NULL) {
@@ -526,10 +538,6 @@ static int32_t mndProcessCreateDbReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_DB, NULL) != 0) {
- goto _OVER;
- }
-
code = mndCreateDb(pMnode, pReq, &createReq, pUser);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -549,18 +557,33 @@ static int32_t mndSetDbCfgFromAlterDbReq(SDbObj *pDb, SAlterDbReq *pAlter) {
terrno = TSDB_CODE_MND_DB_OPTION_UNCHANGED;
if (pAlter->buffer > 0 && pAlter->buffer != pDb->cfg.buffer) {
+#if 1
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
+ return terrno;
+#else
pDb->cfg.buffer = pAlter->buffer;
terrno = 0;
+#endif
}
if (pAlter->pages > 0 && pAlter->pages != pDb->cfg.pages) {
+#if 1
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
+ return terrno;
+#else
pDb->cfg.pages = pAlter->pages;
terrno = 0;
+#endif
}
if (pAlter->pageSize > 0 && pAlter->pageSize != pDb->cfg.pageSize) {
+#if 1
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
+ return terrno;
+#else
pDb->cfg.pageSize = pAlter->pageSize;
terrno = 0;
+#endif
}
if (pAlter->daysPerFile > 0 && pAlter->daysPerFile != pDb->cfg.daysPerFile) {
@@ -594,19 +617,32 @@ static int32_t mndSetDbCfgFromAlterDbReq(SDbObj *pDb, SAlterDbReq *pAlter) {
}
if (pAlter->strict >= 0 && pAlter->strict != pDb->cfg.strict) {
+#if 1
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
+#else
pDb->cfg.strict = pAlter->strict;
terrno = 0;
+#endif
+ }
+
+ if (pAlter->cacheLast >= 0 && pAlter->cacheLast != pDb->cfg.cacheLast) {
+ pDb->cfg.cacheLast = pAlter->cacheLast;
+ terrno = 0;
}
- if (pAlter->cacheLastRow >= 0 && pAlter->cacheLastRow != pDb->cfg.cacheLastRow) {
- pDb->cfg.cacheLastRow = pAlter->cacheLastRow;
+ if (pAlter->cacheLastSize > 0 && pAlter->cacheLastSize != pDb->cfg.cacheLastSize) {
+ pDb->cfg.cacheLastSize = pAlter->cacheLastSize;
terrno = 0;
}
if (pAlter->replications > 0 && pAlter->replications != pDb->cfg.replications) {
+#if 1
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
+#else
pDb->cfg.replications = pAlter->replications;
pDb->vgVersion++;
terrno = 0;
+#endif
}
return terrno;
@@ -646,7 +682,7 @@ static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid == pNew->uid) {
+ if (mndVgroupInDb(pVgroup, pNew->uid)) {
if (mndBuildAlterVgroupAction(pMnode, pTrans, pNew, pVgroup, pArray) != 0) {
sdbCancelFetch(pSdb, pIter);
sdbRelease(pSdb, pVgroup);
@@ -700,7 +736,7 @@ static int32_t mndProcessAlterDbReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_ALTER_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_ALTER_DB, pDb) != 0) {
goto _OVER;
}
@@ -767,7 +803,7 @@ static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq) {
cfgRsp.compression = pDb->cfg.compression;
cfgRsp.replications = pDb->cfg.replications;
cfgRsp.strict = pDb->cfg.strict;
- cfgRsp.cacheLastRow = pDb->cfg.cacheLastRow;
+ cfgRsp.cacheLast = pDb->cfg.cacheLast;
cfgRsp.numOfRetensions = pDb->cfg.numOfRetensions;
cfgRsp.pRetensions = pDb->cfg.pRetensions;
cfgRsp.schemaless = pDb->cfg.schemaless;
@@ -928,6 +964,7 @@ static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) {
if (mndDropOffsetByDB(pMnode, pTrans, pDb) != 0) goto _OVER;
if (mndDropSubByDB(pMnode, pTrans, pDb) != 0) goto _OVER;
if (mndDropTopicByDB(pMnode, pTrans, pDb) != 0) goto _OVER;
+ if (mndDropStreamByDb(pMnode, pTrans, pDb) != 0) goto _OVER;
if (mndDropSmasByDb(pMnode, pTrans, pDb) != 0) goto _OVER;
if (mndSetDropDbRedoActions(pMnode, pTrans, pDb) != 0) goto _OVER;
@@ -948,7 +985,6 @@ static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) {
mndTransSetRpcRsp(pTrans, pRsp, rspLen);
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
-
code = 0;
_OVER:
@@ -980,7 +1016,7 @@ static int32_t mndProcessDropDbReq(SRpcMsg *pReq) {
}
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_DB, pDb) != 0) {
goto _OVER;
}
@@ -1007,7 +1043,7 @@ static int32_t mndGetDBTableNum(SDbObj *pDb, SMnode *pMnode) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid == pDb->uid) {
+ if (mndVgroupInDb(pVgroup, pDb->uid)) {
numOfTables += pVgroup->numOfTables / TSDB_TABLE_NUM_UNIT;
vindex++;
}
@@ -1127,7 +1163,7 @@ static int32_t mndProcessUseDbReq(SRpcMsg *pReq) {
mError("db:%s, failed to process use db req since %s", usedbReq.db, terrstr());
} else {
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_USE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_USE_DB, pDb) != 0) {
goto _OVER;
}
@@ -1234,6 +1270,8 @@ int32_t mndValidateDbInfo(SMnode *pMnode, SDbVgVersion *pDbs, int32_t numOfDbs,
return 0;
}
+static int32_t mndCompactDb(SMnode *pMnode, SDbObj *pDb) { return 0; }
+
static int32_t mndProcessCompactDbReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
@@ -1245,18 +1283,18 @@ static int32_t mndProcessCompactDbReq(SRpcMsg *pReq) {
goto _OVER;
}
- mDebug("db:%s, start to sync", compactReq.db);
+ mDebug("db:%s, start to compact", compactReq.db);
pDb = mndAcquireDb(pMnode, compactReq.db);
if (pDb == NULL) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_COMPACT_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_COMPACT_DB, pDb) != 0) {
goto _OVER;
}
- // code = mndCompactDb();
+ code = mndCompactDb(pMnode, pDb);
_OVER:
if (code != 0) {
@@ -1267,6 +1305,75 @@ _OVER:
return code;
}
+static int32_t mndTrimDb(SMnode *pMnode, SDbObj *pDb) {
+ SSdb *pSdb = pMnode->pSdb;
+ SVgObj *pVgroup = NULL;
+ void *pIter = NULL;
+ SVTrimDbReq trimReq = {.timestamp = taosGetTimestampSec()};
+ int32_t reqLen = tSerializeSVTrimDbReq(NULL, 0, &trimReq);
+ int32_t contLen = reqLen + sizeof(SMsgHead);
+
+ while (1) {
+ pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
+ if (pIter == NULL) break;
+
+ SMsgHead *pHead = rpcMallocCont(contLen);
+ if (pHead == NULL) {
+ sdbCancelFetch(pSdb, pVgroup);
+ sdbRelease(pSdb, pVgroup);
+ continue;
+ }
+ pHead->contLen = htonl(contLen);
+ pHead->vgId = htonl(pVgroup->vgId);
+ tSerializeSVTrimDbReq((char *)pHead + sizeof(SMsgHead), contLen, &trimReq);
+
+ SRpcMsg rpcMsg = {.msgType = TDMT_VND_TRIM, .pCont = pHead, .contLen = contLen};
+ SEpSet epSet = mndGetVgroupEpset(pMnode, pVgroup);
+ int32_t code = tmsgSendReq(&epSet, &rpcMsg);
+ if (code != 0) {
+ mError("vgId:%d, failed to send vnode-trim request to vnode since 0x%x", pVgroup->vgId, code);
+ } else {
+ mDebug("vgId:%d, send vnode-trim request to vnode, time:%d", pVgroup->vgId, trimReq.timestamp);
+ }
+ sdbRelease(pSdb, pVgroup);
+ }
+
+ return 0;
+}
+
+static int32_t mndProcessTrimDbReq(SRpcMsg *pReq) {
+ SMnode *pMnode = pReq->info.node;
+ int32_t code = -1;
+ SDbObj *pDb = NULL;
+ STrimDbReq trimReq = {0};
+
+ if (tDeserializeSTrimDbReq(pReq->pCont, pReq->contLen, &trimReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ goto _OVER;
+ }
+
+ mDebug("db:%s, start to trim", trimReq.db);
+
+ pDb = mndAcquireDb(pMnode, trimReq.db);
+ if (pDb == NULL) {
+ goto _OVER;
+ }
+
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_TRIM_DB, pDb) != 0) {
+ goto _OVER;
+ }
+
+ code = mndTrimDb(pMnode, pDb);
+
+_OVER:
+ if (code != 0) {
+ mError("db:%s, failed to process trim db req since %s", trimReq.db, terrstr());
+ }
+
+ mndReleaseDb(pMnode, pDb);
+ return code;
+}
+
const char *mndGetDbStr(const char *src) {
char *pos = strstr(src, TS_PATH_DELIMITER);
if (pos != NULL) ++pos;
@@ -1337,11 +1444,11 @@ char *buildRetension(SArray *pRetension) {
}
static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, int32_t rows, int64_t numOfTables,
- bool sysDb, ESdbStatus objStatus) {
+ bool sysDb, ESdbStatus objStatus, bool sysinfo) {
int32_t cols = 0;
+ int32_t bytes = pShow->pMeta->pSchemas[cols].bytes;
+ char *buf = taosMemoryMalloc(bytes);
- int32_t bytes = pShow->pMeta->pSchemas[cols].bytes;
- char *buf = taosMemoryMalloc(bytes);
const char *name = mndGetDbStr(pDb->name);
if (name != NULL) {
STR_WITH_MAXSIZE_TO_VARSTR(buf, name, bytes);
@@ -1349,13 +1456,13 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
STR_WITH_MAXSIZE_TO_VARSTR(buf, "NULL", bytes);
}
- char *status = "ready";
- if (objStatus == SDB_STATUS_CREATING) status = "creating";
- if (objStatus == SDB_STATUS_DROPPING) status = "dropping";
- char statusB[24] = {0};
- STR_WITH_SIZE_TO_VARSTR(statusB, status, strlen(status));
+ char *statusStr = "ready";
+ if (objStatus == SDB_STATUS_CREATING) statusStr = "creating";
+ if (objStatus == SDB_STATUS_DROPPING) statusStr = "dropping";
+ char statusVstr[24] = {0};
+ STR_WITH_SIZE_TO_VARSTR(statusVstr, statusStr, strlen(statusStr));
- if (sysDb) {
+ if (sysDb || !sysinfo) {
for (int32_t i = 0; i < pShow->numOfColumns; ++i) {
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, i);
if (i == 0) {
@@ -1363,7 +1470,7 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
} else if (i == 3) {
colDataAppend(pColInfo, rows, (const char *)&numOfTables, false);
} else if (i == 20) {
- colDataAppend(pColInfo, rows, statusB, false);
+ colDataAppend(pColInfo, rows, statusVstr, false);
} else {
colDataAppendNULL(pColInfo, rows);
}
@@ -1371,7 +1478,6 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
} else {
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, buf, false);
- taosMemoryFree(buf);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->createdTime, false);
@@ -1385,30 +1491,29 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.replications, false);
- const char *src = pDb->cfg.strict ? "strict" : "no_strict";
- char strict[24] = {0};
- STR_WITH_SIZE_TO_VARSTR(strict, src, strlen(src));
+ const char *strictStr = pDb->cfg.strict ? "strict" : "no_strict";
+ char strictVstr[24] = {0};
+ STR_WITH_SIZE_TO_VARSTR(strictVstr, strictStr, strlen(strictStr));
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, rows, (const char *)strict, false);
+ colDataAppend(pColInfo, rows, (const char *)strictVstr, false);
- char tmp[128] = {0};
- int32_t len = 0;
- len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%dm", pDb->cfg.daysPerFile);
- varDataSetLen(tmp, len);
+ char durationVstr[128] = {0};
+ int32_t len = sprintf(&durationVstr[VARSTR_HEADER_SIZE], "%dm", pDb->cfg.daysPerFile);
+ varDataSetLen(durationVstr, len);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, rows, (const char *)tmp, false);
+ colDataAppend(pColInfo, rows, (const char *)durationVstr, false);
+ char keepVstr[128] = {0};
if (pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep1 || pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep2) {
- len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep1, pDb->cfg.daysToKeep2,
+ len = sprintf(&keepVstr[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep1, pDb->cfg.daysToKeep2,
pDb->cfg.daysToKeep0);
} else {
- len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep0, pDb->cfg.daysToKeep1,
+ len = sprintf(&keepVstr[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep0, pDb->cfg.daysToKeep1,
pDb->cfg.daysToKeep2);
}
-
- varDataSetLen(tmp, len);
+ varDataSetLen(keepVstr, len);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, rows, (const char *)tmp, false);
+ colDataAppend(pColInfo, rows, (const char *)keepVstr, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.buffer, false);
@@ -1435,68 +1540,49 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.compression, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.cacheLast, false);
- STR_WITH_SIZE_TO_VARSTR(strict, src, strlen(src));
-#if 0
- char cacheModel[24] = {0};
- bool null = false;
- if (pDb->cfg.cacheLastRow == 0) {
- STR_TO_VARSTR(cacheModel, "no_cache");
- } else if (pDb->cfg.cacheLastRow == 1) {
- STR_TO_VARSTR(cacheModel, "last_row_cache")
- } else {
- null = true;
- }
- colDataAppend(pColInfo, rows, cacheModel, null);
-#endif
- colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.cacheLastRow, false);
-
- char *prec = NULL;
+ const char *precStr = NULL;
switch (pDb->cfg.precision) {
case TSDB_TIME_PRECISION_MILLI:
- prec = TSDB_TIME_PRECISION_MILLI_STR;
+ precStr = TSDB_TIME_PRECISION_MILLI_STR;
break;
case TSDB_TIME_PRECISION_MICRO:
- prec = TSDB_TIME_PRECISION_MICRO_STR;
+ precStr = TSDB_TIME_PRECISION_MICRO_STR;
break;
case TSDB_TIME_PRECISION_NANO:
- prec = TSDB_TIME_PRECISION_NANO_STR;
+ precStr = TSDB_TIME_PRECISION_NANO_STR;
break;
default:
- prec = "none";
+ precStr = "none";
break;
}
-
- char t[10] = {0};
- STR_WITH_SIZE_TO_VARSTR(t, prec, 2);
+ char precVstr[10] = {0};
+ STR_WITH_SIZE_TO_VARSTR(precVstr, precStr, 2);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, rows, (const char *)t, false);
+ colDataAppend(pColInfo, rows, (const char *)precVstr, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.numOfStables, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, rows, (const char *)statusB, false);
-
- // pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- // colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.schemaless, false);
-
- char *p = buildRetension(pDb->cfg.pRetensions);
+ colDataAppend(pColInfo, rows, (const char *)statusVstr, false);
+ char *rentensionVstr = buildRetension(pDb->cfg.pRetensions);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
- if (p == NULL) {
+ if (rentensionVstr == NULL) {
colDataAppendNULL(pColInfo, rows);
} else {
- colDataAppend(pColInfo, rows, (const char *)p, false);
- taosMemoryFree(p);
+ colDataAppend(pColInfo, rows, (const char *)rentensionVstr, false);
+ taosMemoryFree(rentensionVstr);
}
}
+
+ taosMemoryFree(buf);
}
static void setInformationSchemaDbCfg(SDbObj *pDbObj) {
- ASSERT(pDbObj != NULL);
- strncpy(pDbObj->name, TSDB_INFORMATION_SCHEMA_DB, tListLen(pDbObj->name));
-
+ tstrncpy(pDbObj->name, TSDB_INFORMATION_SCHEMA_DB, tListLen(pDbObj->name));
pDbObj->createdTime = 0;
pDbObj->cfg.numOfVgroups = 0;
pDbObj->cfg.strict = 1;
@@ -1505,9 +1591,7 @@ static void setInformationSchemaDbCfg(SDbObj *pDbObj) {
}
static void setPerfSchemaDbCfg(SDbObj *pDbObj) {
- ASSERT(pDbObj != NULL);
- strncpy(pDbObj->name, TSDB_PERFORMANCE_SCHEMA_DB, tListLen(pDbObj->name));
-
+ tstrncpy(pDbObj->name, TSDB_PERFORMANCE_SCHEMA_DB, tListLen(pDbObj->name));
pDbObj->createdTime = 0;
pDbObj->cfg.numOfVgroups = 0;
pDbObj->cfg.strict = 1;
@@ -1529,17 +1613,21 @@ static int32_t mndRetrieveDbs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
SDbObj *pDb = NULL;
ESdbStatus objStatus = 0;
+ SUserObj *pUser = mndAcquireUser(pMnode, pReq->info.conn.user);
+ if (pUser == NULL) return 0;
+ bool sysinfo = pUser->sysInfo;
+
// Append the information_schema database into the result.
if (!pShow->sysDbRsp) {
SDbObj infoschemaDb = {0};
setInformationSchemaDbCfg(&infoschemaDb);
- dumpDbInfoData(pBlock, &infoschemaDb, pShow, numOfRows, 14, true, 0);
+ dumpDbInfoData(pBlock, &infoschemaDb, pShow, numOfRows, 14, true, 0, 1);
numOfRows += 1;
SDbObj perfschemaDb = {0};
setPerfSchemaDbCfg(&perfschemaDb);
- dumpDbInfoData(pBlock, &perfschemaDb, pShow, numOfRows, 3, true, 0);
+ dumpDbInfoData(pBlock, &perfschemaDb, pShow, numOfRows, 3, true, 0, 1);
numOfRows += 1;
pShow->sysDbRsp = true;
@@ -1547,20 +1635,20 @@ static int32_t mndRetrieveDbs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
while (numOfRows < rowsCapacity) {
pShow->pIter = sdbFetchAll(pSdb, SDB_DB, pShow->pIter, (void **)&pDb, &objStatus);
- if (pShow->pIter == NULL) {
- break;
- }
+ if (pShow->pIter == NULL) break;
- int32_t numOfTables = 0;
- sdbTraverse(pSdb, SDB_VGROUP, mndGetTablesOfDbFp, &numOfTables, NULL, NULL);
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_READ_OR_WRITE_DB, pDb) == 0) {
+ int32_t numOfTables = 0;
+ sdbTraverse(pSdb, SDB_VGROUP, mndGetTablesOfDbFp, &numOfTables, NULL, NULL);
+ dumpDbInfoData(pBlock, pDb, pShow, numOfRows, numOfTables, false, objStatus, sysinfo);
+ numOfRows++;
+ }
- dumpDbInfoData(pBlock, pDb, pShow, numOfRows, numOfTables, false, objStatus);
- numOfRows++;
sdbRelease(pSdb, pDb);
}
pShow->numOfRows += numOfRows;
-
+ mndReleaseUser(pMnode, pUser);
return numOfRows;
}
diff --git a/source/dnode/mnode/impl/src/mndDef.c b/source/dnode/mnode/impl/src/mndDef.c
index 20ba71992eeaa9f847d991f0c2dcda5009284e29..727b20ef8a2376a5ee7cc286eb505182d3e9d81e 100644
--- a/source/dnode/mnode/impl/src/mndDef.c
+++ b/source/dnode/mnode/impl/src/mndDef.c
@@ -28,7 +28,7 @@ int32_t tEncodeSStreamObj(SEncoder *pEncoder, const SStreamObj *pObj) {
if (tEncodeI64(pEncoder, pObj->uid) < 0) return -1;
if (tEncodeI8(pEncoder, pObj->status) < 0) return -1;
- if (tEncodeI8(pEncoder, pObj->dropPolicy) < 0) return -1;
+ if (tEncodeI8(pEncoder, pObj->igExpired) < 0) return -1;
if (tEncodeI8(pEncoder, pObj->trigger) < 0) return -1;
if (tEncodeI64(pEncoder, pObj->triggerParam) < 0) return -1;
if (tEncodeI64(pEncoder, pObj->watermark) < 0) return -1;
@@ -73,7 +73,7 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj) {
if (tDecodeI64(pDecoder, &pObj->uid) < 0) return -1;
if (tDecodeI8(pDecoder, &pObj->status) < 0) return -1;
- if (tDecodeI8(pDecoder, &pObj->dropPolicy) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pObj->igExpired) < 0) return -1;
if (tDecodeI8(pDecoder, &pObj->trigger) < 0) return -1;
if (tDecodeI64(pDecoder, &pObj->triggerParam) < 0) return -1;
if (tDecodeI64(pDecoder, &pObj->watermark) < 0) return -1;
@@ -381,6 +381,7 @@ SMqSubscribeObj *tCloneSubscribeObj(const SMqSubscribeObj *pSub) {
pSubNew->dbUid = pSub->dbUid;
pSubNew->stbUid = pSub->stbUid;
pSubNew->subType = pSub->subType;
+ pSubNew->withMeta = pSub->withMeta;
pSubNew->vgNum = pSub->vgNum;
pSubNew->consumerHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
@@ -414,6 +415,7 @@ int32_t tEncodeSubscribeObj(void **buf, const SMqSubscribeObj *pSub) {
tlen += taosEncodeFixedI64(buf, pSub->dbUid);
tlen += taosEncodeFixedI32(buf, pSub->vgNum);
tlen += taosEncodeFixedI8(buf, pSub->subType);
+ tlen += taosEncodeFixedI8(buf, pSub->withMeta);
tlen += taosEncodeFixedI64(buf, pSub->stbUid);
void *pIter = NULL;
@@ -440,6 +442,7 @@ void *tDecodeSubscribeObj(const void *buf, SMqSubscribeObj *pSub) {
buf = taosDecodeFixedI64(buf, &pSub->dbUid);
buf = taosDecodeFixedI32(buf, &pSub->vgNum);
buf = taosDecodeFixedI8(buf, &pSub->subType);
+ buf = taosDecodeFixedI8(buf, &pSub->withMeta);
buf = taosDecodeFixedI64(buf, &pSub->stbUid);
int32_t sz;
diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c
index 58c3570c3631ec0ceee76163d4afd50e047245ad..3e5d378bb11959da0155a1aa31a3f7ea77307819 100644
--- a/source/dnode/mnode/impl/src/mndDnode.c
+++ b/source/dnode/mnode/impl/src/mndDnode.c
@@ -15,10 +15,11 @@
#define _DEFAULT_SOURCE
#include "mndDnode.h"
-#include "mndAuth.h"
#include "mndMnode.h"
+#include "mndPrivilege.h"
#include "mndQnode.h"
#include "mndShow.h"
+#include "mndSnode.h"
#include "mndTrans.h"
#include "mndUser.h"
#include "mndVgroup.h"
@@ -46,6 +47,8 @@ static SSdbRow *mndDnodeActionDecode(SSdbRaw *pRaw);
static int32_t mndDnodeActionInsert(SSdb *pSdb, SDnodeObj *pDnode);
static int32_t mndDnodeActionDelete(SSdb *pSdb, SDnodeObj *pDnode);
static int32_t mndDnodeActionUpdate(SSdb *pSdb, SDnodeObj *pOld, SDnodeObj *pNew);
+static int32_t mndProcessDnodeListReq(SRpcMsg *pReq);
+static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq);
static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq);
static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq);
@@ -75,6 +78,8 @@ int32_t mndInitDnode(SMnode *pMnode) {
mndSetMsgHandle(pMnode, TDMT_MND_CONFIG_DNODE, mndProcessConfigDnodeReq);
mndSetMsgHandle(pMnode, TDMT_DND_CONFIG_DNODE_RSP, mndProcessConfigDnodeRsp);
mndSetMsgHandle(pMnode, TDMT_MND_STATUS, mndProcessStatusReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_DNODE_LIST, mndProcessDnodeListReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_SHOW_VARIABLES, mndProcessShowVariablesReq);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CONFIGS, mndRetrieveConfigs);
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CONFIGS, mndCancelGetNextConfig);
@@ -269,15 +274,14 @@ static void mndGetDnodeData(SMnode *pMnode, SArray *pDnodeEps) {
SDnodeEp dnodeEp = {0};
dnodeEp.id = pDnode->id;
- dnodeEp.isMnode = 0;
dnodeEp.ep.port = pDnode->port;
memcpy(dnodeEp.ep.fqdn, pDnode->fqdn, TSDB_FQDN_LEN);
+ sdbRelease(pSdb, pDnode);
+ dnodeEp.isMnode = 0;
if (mndIsMnode(pMnode, pDnode->id)) {
dnodeEp.isMnode = 1;
}
-
- sdbRelease(pSdb, pDnode);
taosArrayPush(pDnodeEps, &dnodeEp);
}
}
@@ -370,7 +374,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
SMnodeObj *pObj = mndAcquireMnode(pMnode, pDnode->id);
if (pObj != NULL) {
if (pObj->state != statusReq.mload.syncState) {
- mInfo("dnode:%d, mnode syncstate from %s to %s", pObj->id, syncStr(pObj->state), syncStr(statusReq.mload.syncState));
+ mInfo("dnode:%d, mnode syncstate from %s to %s", pObj->id, syncStr(pObj->state),
+ syncStr(statusReq.mload.syncState));
pObj->state = statusReq.mload.syncState;
pObj->stateStartTime = taosGetTimestampMs();
}
@@ -401,7 +406,7 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
}
if (statusReq.dnodeId == 0) {
- mInfo("dnode:%d, %s first access, set clusterId %" PRId64, pDnode->id, pDnode->ep, pMnode->clusterId);
+ mInfo("dnode:%d, %s first access, clusterId:%" PRId64, pDnode->id, pDnode->ep, pMnode->clusterId);
} else {
if (statusReq.clusterId != pMnode->clusterId) {
if (pDnode != NULL) {
@@ -426,7 +431,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
}
if (!online) {
- mInfo("dnode:%d, from offline to online", pDnode->id);
+ mInfo("dnode:%d, from offline to online, memory avail:%" PRId64 " total:%" PRId64 " cores:%.2f", pDnode->id,
+ statusReq.memAvail, statusReq.memTotal, statusReq.numOfCores);
} else {
mDebug("dnode:%d, send dnode epset, online:%d dnodeVer:%" PRId64 ":%" PRId64 " reboot:%d", pDnode->id, online,
statusReq.dnodeVer, dnodeVer, reboot);
@@ -435,6 +441,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
pDnode->rebootTime = statusReq.rebootTime;
pDnode->numOfCores = statusReq.numOfCores;
pDnode->numOfSupportVnodes = statusReq.numOfSupportVnodes;
+ pDnode->memAvail = statusReq.memAvail;
+ pDnode->memTotal = statusReq.memTotal;
SStatusRsp statusRsp = {0};
statusRsp.dnodeVer = dnodeVer;
@@ -497,6 +505,116 @@ _OVER:
return code;
}
+static int32_t mndProcessDnodeListReq(SRpcMsg *pReq) {
+ SMnode *pMnode = pReq->info.node;
+ SSdb *pSdb = pMnode->pSdb;
+ SDnodeObj *pObj = NULL;
+ void *pIter = NULL;
+ SDnodeListRsp rsp = {0};
+ int32_t code = -1;
+
+ rsp.dnodeList = taosArrayInit(5, sizeof(SEpSet));
+ if (NULL == rsp.dnodeList) {
+ mError("failed to alloc epSet while process dnode list req");
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+
+ while (1) {
+ pIter = sdbFetch(pSdb, SDB_DNODE, pIter, (void **)&pObj);
+ if (pIter == NULL) break;
+
+ SEpSet epSet = {0};
+ epSet.numOfEps = 1;
+ tstrncpy(epSet.eps[0].fqdn, pObj->fqdn, TSDB_FQDN_LEN);
+ epSet.eps[0].port = pObj->port;
+
+ (void)taosArrayPush(rsp.dnodeList, &epSet);
+
+ sdbRelease(pSdb, pObj);
+ }
+
+ int32_t rspLen = tSerializeSDnodeListRsp(NULL, 0, &rsp);
+ void *pRsp = rpcMallocCont(rspLen);
+ if (pRsp == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+
+ tSerializeSDnodeListRsp(pRsp, rspLen, &rsp);
+
+ pReq->info.rspLen = rspLen;
+ pReq->info.rsp = pRsp;
+ code = 0;
+
+_OVER:
+
+ if (code != 0) {
+ mError("failed to get dnode list since %s", terrstr());
+ }
+
+ tFreeSDnodeListRsp(&rsp);
+
+ return code;
+}
+
+static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq) {
+ SShowVariablesRsp rsp = {0};
+ int32_t code = -1;
+
+ if (mndCheckOperPrivilege(pReq->info.node, pReq->info.conn.user, MND_OPER_SHOW_VARIBALES) != 0) {
+ goto _OVER;
+ }
+
+ rsp.variables = taosArrayInit(4, sizeof(SVariablesInfo));
+ if (NULL == rsp.variables) {
+ mError("failed to alloc SVariablesInfo array while process show variables req");
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+
+ SVariablesInfo info = {0};
+
+ strcpy(info.name, "statusInterval");
+ snprintf(info.value, TSDB_CONFIG_VALUE_LEN, "%d", tsStatusInterval);
+ taosArrayPush(rsp.variables, &info);
+
+ strcpy(info.name, "timezone");
+ snprintf(info.value, TSDB_CONFIG_VALUE_LEN, "%s", tsTimezoneStr);
+ taosArrayPush(rsp.variables, &info);
+
+ strcpy(info.name, "locale");
+ snprintf(info.value, TSDB_CONFIG_VALUE_LEN, "%s", tsLocale);
+ taosArrayPush(rsp.variables, &info);
+
+ strcpy(info.name, "charset");
+ snprintf(info.value, TSDB_CONFIG_VALUE_LEN, "%s", tsCharset);
+ taosArrayPush(rsp.variables, &info);
+
+ int32_t rspLen = tSerializeSShowVariablesRsp(NULL, 0, &rsp);
+ void *pRsp = rpcMallocCont(rspLen);
+ if (pRsp == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+
+ tSerializeSShowVariablesRsp(pRsp, rspLen, &rsp);
+
+ pReq->info.rspLen = rspLen;
+ pReq->info.rsp = pRsp;
+ code = 0;
+
+_OVER:
+
+ if (code != 0) {
+ mError("failed to get show variables info since %s", terrstr());
+ }
+
+ tFreeSShowVariablesRsp(&rsp);
+
+ return code;
+}
+
static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
@@ -508,7 +626,10 @@ static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- mDebug("dnode:%s:%d, start to create", createReq.fqdn, createReq.port);
+ mInfo("dnode:%s:%d, start to create", createReq.fqdn, createReq.port);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_DNODE) != 0) {
+ goto _OVER;
+ }
if (createReq.fqdn[0] == 0 || createReq.port <= 0 || createReq.port > UINT16_MAX) {
terrno = TSDB_CODE_MND_INVALID_DNODE_EP;
@@ -522,10 +643,6 @@ static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_DNODE) != 0) {
- goto _OVER;
- }
-
code = mndCreateDnode(pMnode, pReq, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -538,7 +655,8 @@ _OVER:
return code;
}
-static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SMnodeObj *pMObj, int32_t numOfVnodes) {
+static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SMnodeObj *pMObj, SQnodeObj *pQObj,
+ SSnodeObj *pSObj, int32_t numOfVnodes) {
int32_t code = -1;
SSdbRaw *pRaw = NULL;
STrans *pTrans = NULL;
@@ -546,7 +664,7 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SM
pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq);
if (pTrans == NULL) goto _OVER;
mndTransSetSerial(pTrans);
- mDebug("trans:%d, used to drop dnode:%d", pTrans->id, pDnode->id);
+ mInfo("trans:%d, used to drop dnode:%d", pTrans->id, pDnode->id);
pRaw = mndDnodeActionEncode(pDnode);
if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) goto _OVER;
@@ -559,13 +677,25 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SM
pRaw = NULL;
if (pMObj != NULL) {
- mDebug("trans:%d, mnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
+ mInfo("trans:%d, mnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
if (mndSetDropMnodeInfoToTrans(pMnode, pTrans, pMObj) != 0) goto _OVER;
}
+
+ if (pQObj != NULL) {
+ mInfo("trans:%d, qnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
+ if (mndSetDropQnodeInfoToTrans(pMnode, pTrans, pQObj) != 0) goto _OVER;
+ }
+
+ if (pSObj != NULL) {
+ mInfo("trans:%d, snode on dnode:%d will be dropped", pTrans->id, pDnode->id);
+ if (mndSetDropSnodeInfoToTrans(pMnode, pTrans, pSObj) != 0) goto _OVER;
+ }
+
if (numOfVnodes > 0) {
- mDebug("trans:%d, %d vnodes on dnode:%d will be dropped", pTrans->id, numOfVnodes, pDnode->id);
+ mInfo("trans:%d, %d vnodes on dnode:%d will be dropped", pTrans->id, numOfVnodes, pDnode->id);
if (mndSetMoveVgroupsInfoToTrans(pMnode, pTrans, pDnode->id) != 0) goto _OVER;
}
+
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
code = 0;
@@ -577,30 +707,37 @@ _OVER:
}
static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
- SMnode *pMnode = pReq->info.node;
- int32_t code = -1;
- SDnodeObj *pDnode = NULL;
- SMnodeObj *pMObj = NULL;
- SMDropMnodeReq dropReq = {0};
-
- if (tDeserializeSCreateDropMQSBNodeReq(pReq->pCont, pReq->contLen, &dropReq) != 0) {
+ SMnode *pMnode = pReq->info.node;
+ int32_t code = -1;
+ SDnodeObj *pDnode = NULL;
+ SMnodeObj *pMObj = NULL;
+ SQnodeObj *pQObj = NULL;
+ SSnodeObj *pSObj = NULL;
+ SDropDnodeReq dropReq = {0};
+
+ if (tDeserializeSDropDnodeReq(pReq->pCont, pReq->contLen, &dropReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
goto _OVER;
}
- mDebug("dnode:%d, start to drop", dropReq.dnodeId);
-
- if (dropReq.dnodeId <= 0) {
- terrno = TSDB_CODE_MND_INVALID_DNODE_ID;
+ mInfo("dnode:%d, start to drop, ep:%s:%d", dropReq.dnodeId, dropReq.fqdn, dropReq.port);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_MNODE) != 0) {
goto _OVER;
}
pDnode = mndAcquireDnode(pMnode, dropReq.dnodeId);
if (pDnode == NULL) {
- terrno = TSDB_CODE_MND_DNODE_NOT_EXIST;
- goto _OVER;
+ char ep[TSDB_EP_LEN + 1] = {0};
+ snprintf(ep, sizeof(ep), dropReq.fqdn, dropReq.port);
+ pDnode = mndAcquireDnodeByEp(pMnode, ep);
+ if (pDnode == NULL) {
+ terrno = TSDB_CODE_MND_DNODE_NOT_EXIST;
+ goto _OVER;
+ }
}
+ pQObj = mndAcquireQnode(pMnode, dropReq.dnodeId);
+ pSObj = mndAcquireSnode(pMnode, dropReq.dnodeId);
pMObj = mndAcquireMnode(pMnode, dropReq.dnodeId);
if (pMObj != NULL) {
if (sdbGetSize(pMnode->pSdb, SDB_MNODE) <= 1) {
@@ -623,11 +760,12 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
}
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_MNODE) != 0) {
+ if (numOfVnodes > 0) {
+ terrno = TSDB_CODE_OPS_NOT_SUPPORT;
goto _OVER;
}
- code = mndDropDnode(pMnode, pReq, pDnode, pMObj, numOfVnodes);
+ code = mndDropDnode(pMnode, pReq, pDnode, pMObj, pQObj, pSObj, numOfVnodes);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
_OVER:
@@ -637,11 +775,19 @@ _OVER:
mndReleaseDnode(pMnode, pDnode);
mndReleaseMnode(pMnode, pMObj);
+ mndReleaseQnode(pMnode, pQObj);
+ mndReleaseSnode(pMnode, pSObj);
return code;
}
static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
- SMnode *pMnode = pReq->info.node;
+ SMnode *pMnode = pReq->info.node;
+ const char *options[] = {
+ "debugFlag", "dDebugFlag", "vDebugFlag", "mDebugFlag", "wDebugFlag", "sDebugFlag",
+ "tsdbDebugFlag", "tqDebugFlag", "fsDebugFlag", "udfDebugFlag", "smaDebugFlag", "idxDebugFlag",
+ "tmrDebugFlag", "uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag",
+ };
+ int32_t optionSize = tListLen(options);
SMCfgDnodeReq cfgReq = {0};
if (tDeserializeSMCfgDnodeReq(pReq->pCont, pReq->contLen, &cfgReq) != 0) {
@@ -649,28 +795,81 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
return -1;
}
+ mInfo("dnode:%d, start to config, option:%s, value:%s", cfgReq.dnodeId, cfgReq.config, cfgReq.value);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CONFIG_DNODE) != 0) {
+ return -1;
+ }
+
SDnodeObj *pDnode = mndAcquireDnode(pMnode, cfgReq.dnodeId);
if (pDnode == NULL) {
mError("dnode:%d, failed to config since %s ", cfgReq.dnodeId, terrstr());
return -1;
}
-
SEpSet epSet = mndGetDnodeEpset(pDnode);
mndReleaseDnode(pMnode, pDnode);
- int32_t bufLen = tSerializeSMCfgDnodeReq(NULL, 0, &cfgReq);
+
+ SDCfgDnodeReq dcfgReq = {0};
+ if (strcasecmp(cfgReq.config, "resetlog") == 0) {
+ strcpy(dcfgReq.config, "resetlog");
+ } else if (strncasecmp(cfgReq.config, "monitor", 7) == 0) {
+ const char *value = cfgReq.value;
+ int32_t flag = atoi(value);
+ if (flag <= 0) {
+ flag = atoi(cfgReq.config + 8);
+ }
+ if (flag < 0 || flag > 2) {
+ mError("dnode:%d, failed to config monitor since value:%d", cfgReq.dnodeId, flag);
+ terrno = TSDB_CODE_INVALID_CFG;
+ return -1;
+ }
+
+ strcpy(dcfgReq.config, "monitor");
+ snprintf(dcfgReq.value, TSDB_DNODE_VALUE_LEN, "%d", flag);
+ } else {
+ bool findOpt = false;
+ for (int32_t d = 0; d < optionSize; ++d) {
+ const char *optName = options[d];
+ int32_t optLen = strlen(optName);
+ if (strncasecmp(cfgReq.config, optName, optLen) != 0) continue;
+
+ const char *value = cfgReq.value;
+ int32_t flag = atoi(value);
+ if (flag <= 0) {
+ flag = atoi(cfgReq.config + optLen + 1);
+ }
+ if (flag <= 0 || flag > 255) {
+ mError("dnode:%d, failed to config %s since value:%d", cfgReq.dnodeId, optName, flag);
+ terrno = TSDB_CODE_INVALID_CFG;
+ return -1;
+ }
+
+ tstrncpy(dcfgReq.config, optName, optLen + 1);
+ snprintf(dcfgReq.value, TSDB_DNODE_VALUE_LEN, "%d", flag);
+ findOpt = true;
+ }
+
+ if (!findOpt) {
+ terrno = TSDB_CODE_INVALID_CFG;
+ mError("dnode:%d, failed to config since %s", cfgReq.dnodeId, terrstr());
+ return -1;
+ }
+ }
+
+ int32_t bufLen = tSerializeSDCfgDnodeReq(NULL, 0, &dcfgReq);
void *pBuf = rpcMallocCont(bufLen);
if (pBuf == NULL) return -1;
- tSerializeSMCfgDnodeReq(pBuf, bufLen, &cfgReq);
+ tSerializeSDCfgDnodeReq(pBuf, bufLen, &dcfgReq);
- mDebug("dnode:%d, send config req to dnode, app:%p", cfgReq.dnodeId, pReq->info.ahandle);
- SRpcMsg rpcMsg = {.msgType = TDMT_DND_CONFIG_DNODE, .pCont = pBuf, .contLen = bufLen, .info = pReq->info};
+ mInfo("dnode:%d, send config req to dnode, app:%p config:%s value:%s", cfgReq.dnodeId, pReq->info.ahandle,
+ dcfgReq.config, dcfgReq.value);
+ SRpcMsg rpcMsg = {.msgType = TDMT_DND_CONFIG_DNODE, .pCont = pBuf, .contLen = bufLen};
return tmsgSendReq(&epSet, &rpcMsg);
}
static int32_t mndProcessConfigDnodeRsp(SRpcMsg *pRsp) {
- mDebug("config rsp from dnode, app:%p", pRsp->info.ahandle);
+ mInfo("config rsp from dnode, app:%p", pRsp->info.ahandle);
return 0;
}
@@ -679,28 +878,28 @@ static int32_t mndRetrieveConfigs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p
int32_t totalRows = 0;
int32_t numOfRows = 0;
char *cfgOpts[TSDB_CONFIG_NUMBER] = {0};
- char cfgVals[TSDB_CONFIG_NUMBER][TSDB_CONIIG_VALUE_LEN + 1] = {0};
+ char cfgVals[TSDB_CONFIG_NUMBER][TSDB_CONFIG_VALUE_LEN + 1] = {0};
char *pWrite = NULL;
int32_t cols = 0;
cfgOpts[totalRows] = "statusInterval";
- snprintf(cfgVals[totalRows], TSDB_CONIIG_VALUE_LEN, "%d", tsStatusInterval);
+ snprintf(cfgVals[totalRows], TSDB_CONFIG_VALUE_LEN, "%d", tsStatusInterval);
totalRows++;
cfgOpts[totalRows] = "timezone";
- snprintf(cfgVals[totalRows], TSDB_CONIIG_VALUE_LEN, "%s", tsTimezoneStr);
+ snprintf(cfgVals[totalRows], TSDB_CONFIG_VALUE_LEN, "%s", tsTimezoneStr);
totalRows++;
cfgOpts[totalRows] = "locale";
- snprintf(cfgVals[totalRows], TSDB_CONIIG_VALUE_LEN, "%s", tsLocale);
+ snprintf(cfgVals[totalRows], TSDB_CONFIG_VALUE_LEN, "%s", tsLocale);
totalRows++;
cfgOpts[totalRows] = "charset";
- snprintf(cfgVals[totalRows], TSDB_CONIIG_VALUE_LEN, "%s", tsCharset);
+ snprintf(cfgVals[totalRows], TSDB_CONFIG_VALUE_LEN, "%s", tsCharset);
totalRows++;
char buf[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0};
- char bufVal[TSDB_CONIIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
+ char bufVal[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
for (int32_t i = 0; i < totalRows; i++) {
cols = 0;
@@ -709,7 +908,7 @@ static int32_t mndRetrieveConfigs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)buf, false);
- STR_WITH_MAXSIZE_TO_VARSTR(bufVal, cfgVals[i], TSDB_CONIIG_VALUE_LEN);
+ STR_WITH_MAXSIZE_TO_VARSTR(bufVal, cfgVals[i], TSDB_CONFIG_VALUE_LEN);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)bufVal, false);
diff --git a/source/dnode/mnode/impl/src/mndFunc.c b/source/dnode/mnode/impl/src/mndFunc.c
index 832f1b8e68b0370d1c8ebaff890956d7f3566b0e..b626c1fb04e230ca86480159ea016f398ccd90aa 100644
--- a/source/dnode/mnode/impl/src/mndFunc.c
+++ b/source/dnode/mnode/impl/src/mndFunc.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndFunc.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndSync.h"
#include "mndTrans.h"
@@ -283,6 +283,9 @@ static int32_t mndProcessCreateFuncReq(SRpcMsg *pReq) {
}
mDebug("func:%s, start to create", createReq.name);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_FUNC) != 0) {
+ goto _OVER;
+ }
pFunc = mndAcquireFunc(pMnode, createReq.name);
if (pFunc != NULL) {
@@ -318,10 +321,6 @@ static int32_t mndProcessCreateFuncReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_FUNC) != 0) {
- goto _OVER;
- }
-
code = mndCreateFunc(pMnode, pReq, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -347,6 +346,9 @@ static int32_t mndProcessDropFuncReq(SRpcMsg *pReq) {
}
mDebug("func:%s, start to drop", dropReq.name);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_FUNC) != 0) {
+ goto _OVER;
+ }
if (dropReq.name[0] == 0) {
terrno = TSDB_CODE_MND_INVALID_FUNC_NAME;
@@ -365,10 +367,6 @@ static int32_t mndProcessDropFuncReq(SRpcMsg *pReq) {
}
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_FUNC) != 0) {
- goto _OVER;
- }
-
code = mndDropFunc(pMnode, pReq, pFunc);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
diff --git a/source/dnode/mnode/impl/src/mndInfoSchema.c b/source/dnode/mnode/impl/src/mndInfoSchema.c
index c9bccaf1d02117dc43a7c631605543243bd6bb3b..45fefaf87008ac8bc27935fc01bef0059265c8be 100644
--- a/source/dnode/mnode/impl/src/mndInfoSchema.c
+++ b/source/dnode/mnode/impl/src/mndInfoSchema.c
@@ -90,6 +90,38 @@ int32_t mndBuildInsTableSchema(SMnode *pMnode, const char *dbFName, const char *
return 0;
}
+int32_t mndBuildInsTableCfg(SMnode *pMnode, const char *dbFName, const char *tbName, STableCfgRsp *pRsp) {
+ if (NULL == pMnode->infosMeta) {
+ terrno = TSDB_CODE_MND_NOT_READY;
+ return -1;
+ }
+
+ STableMetaRsp *pMeta = taosHashGet(pMnode->infosMeta, tbName, strlen(tbName));
+ if (NULL == pMeta) {
+ mError("invalid information schema table name:%s", tbName);
+ terrno = TSDB_CODE_MND_INVALID_SYS_TABLENAME;
+ return -1;
+ }
+
+ strcpy(pRsp->tbName, pMeta->tbName);
+ strcpy(pRsp->stbName, pMeta->stbName);
+ strcpy(pRsp->dbFName, pMeta->dbFName);
+ pRsp->numOfTags = pMeta->numOfTags;
+ pRsp->numOfColumns = pMeta->numOfColumns;
+ pRsp->tableType = pMeta->tableType;
+
+ pRsp->pSchemas = taosMemoryCalloc(pMeta->numOfColumns, sizeof(SSchema));
+ if (pRsp->pSchemas == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ pRsp->pSchemas = NULL;
+ return -1;
+ }
+
+ memcpy(pRsp->pSchemas, pMeta->pSchemas, pMeta->numOfColumns * sizeof(SSchema));
+ return 0;
+}
+
+
int32_t mndInitInfos(SMnode *pMnode) {
pMnode->infosMeta = taosHashInit(20, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
if (pMnode->infosMeta == NULL) {
diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c
index ef82d1131cad05fc67e8bfbdefa174d45d01f25b..df8dc42d176163e5aae58ce69b9027ec26a2b8b3 100644
--- a/source/dnode/mnode/impl/src/mndMain.c
+++ b/source/dnode/mnode/impl/src/mndMain.c
@@ -15,7 +15,6 @@
#define _DEFAULT_SOURCE
#include "mndAcct.h"
-#include "mndAuth.h"
#include "mndBnode.h"
#include "mndCluster.h"
#include "mndConsumer.h"
@@ -27,6 +26,7 @@
#include "mndMnode.h"
#include "mndOffset.h"
#include "mndPerfSchema.h"
+#include "mndPrivilege.h"
#include "mndProfile.h"
#include "mndQnode.h"
#include "mndQuery.h"
@@ -59,55 +59,34 @@ static void *mndBuildTimerMsg(int32_t *pContLen) {
static void mndPullupTrans(SMnode *pMnode) {
int32_t contLen = 0;
void *pReq = mndBuildTimerMsg(&contLen);
- SRpcMsg rpcMsg = {.msgType = TDMT_MND_TRANS_TIMER, .pCont = pReq, .contLen = contLen};
+ if (pReq != NULL) {
+ SRpcMsg rpcMsg = {.msgType = TDMT_MND_TRANS_TIMER, .pCont = pReq, .contLen = contLen};
+ tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
+ }
+}
+
+static void mndTtlTimer(SMnode *pMnode) {
+ int32_t contLen = 0;
+ void *pReq = mndBuildTimerMsg(&contLen);
+ SRpcMsg rpcMsg = {.msgType = TDMT_MND_TTL_TIMER, .pCont = pReq, .contLen = contLen};
tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
}
static void mndCalMqRebalance(SMnode *pMnode) {
int32_t contLen = 0;
void *pReq = mndBuildTimerMsg(&contLen);
- SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pReq, .contLen = contLen};
- tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg);
+ if (pReq != NULL) {
+ SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pReq, .contLen = contLen};
+ tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg);
+ }
}
static void mndPullupTelem(SMnode *pMnode) {
int32_t contLen = 0;
void *pReq = mndBuildTimerMsg(&contLen);
- SRpcMsg rpcMsg = {.msgType = TDMT_MND_TELEM_TIMER, .pCont = pReq, .contLen = contLen};
- tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg);
-}
-
-static void mndPushTtlTime(SMnode *pMnode) {
- SSdb *pSdb = pMnode->pSdb;
- SVgObj *pVgroup = NULL;
- void *pIter = NULL;
-
- while (1) {
- pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
- if (pIter == NULL) break;
-
- int32_t contLen = sizeof(SMsgHead) + sizeof(int32_t);
- SMsgHead *pHead = rpcMallocCont(contLen);
- if (pHead == NULL) {
- mError("ttl time malloc err. contLen:%d", contLen);
- sdbRelease(pSdb, pVgroup);
- continue;
- }
- pHead->contLen = htonl(contLen);
- pHead->vgId = htonl(pVgroup->vgId);
-
- int32_t t = taosGetTimestampSec();
- *(int32_t *)(POINTER_SHIFT(pHead, sizeof(SMsgHead))) = htonl(t);
-
- SRpcMsg rpcMsg = {.msgType = TDMT_VND_DROP_TTL_TABLE, .pCont = pHead, .contLen = contLen};
-
- SEpSet epSet = mndGetVgroupEpset(pMnode, pVgroup);
- int32_t code = tmsgSendReq(&epSet, &rpcMsg);
- if (code != 0) {
- mError("ttl time seed err. code:%d", code);
- }
- mError("ttl time seed succ. time:%d", t);
- sdbRelease(pSdb, pVgroup);
+ if (pReq != NULL) {
+ SRpcMsg rpcMsg = {.msgType = TDMT_MND_TELEM_TIMER, .pCont = pReq, .contLen = contLen};
+ tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg);
}
}
@@ -117,14 +96,14 @@ static void *mndThreadFp(void *param) {
setThreadName("mnode-timer");
while (1) {
- if (lastTime % (864000) == 0) { // sleep 1 day for ttl
- mndPushTtlTime(pMnode);
- }
-
lastTime++;
taosMsleep(100);
if (mndGetStop(pMnode)) break;
+ if (lastTime % (tsTtlPushInterval * 10) == 1) {
+ mndTtlTimer(pMnode);
+ }
+
if (lastTime % (tsTransPullupInterval * 10) == 0) {
mndPullupTrans(pMnode);
}
@@ -260,7 +239,7 @@ static int32_t mndInitSteps(SMnode *pMnode) {
if (mndAllocStep(pMnode, "mnode-dnode", mndInitDnode, mndCleanupDnode) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-user", mndInitUser, mndCleanupUser) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-grant", mndInitGrant, mndCleanupGrant) != 0) return -1;
- if (mndAllocStep(pMnode, "mnode-auth", mndInitAuth, mndCleanupAuth) != 0) return -1;
+ if (mndAllocStep(pMnode, "mnode-privilege", mndInitPrivilege, mndCleanupPrivilege) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-acct", mndInitAcct, mndCleanupAcct) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-stream", mndInitStream, mndCleanupStream) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-topic", mndInitTopic, mndCleanupTopic) != 0) return -1;
@@ -387,6 +366,12 @@ SMnode *mndOpen(const char *path, const SMnodeOpt *pOption) {
return pMnode;
}
+void mndPreClose(SMnode *pMnode) {
+ if (pMnode != NULL) {
+ syncLeaderTransfer(pMnode->syncMgmt.sync);
+ }
+}
+
void mndClose(SMnode *pMnode) {
if (pMnode != NULL) {
mDebug("start to close mnode");
@@ -437,7 +422,7 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
char *syncNodeStr = sync2SimpleStr(pMgmt->sync);
static int64_t mndTick = 0;
if (++mndTick % 10 == 1) {
- mTrace("vgId:%d, sync heartbeat msg:%s, %s", syncGetVgId(pMgmt->sync), TMSG_INFO(pMsg->msgType), syncNodeStr);
+ mTrace("vgId:%d, sync trace msg:%s, %s", syncGetVgId(pMgmt->sync), TMSG_INFO(pMsg->msgType), syncNodeStr);
}
if (gRaftDetailLog) {
char logBuf[512] = {0};
@@ -448,7 +433,7 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
} while (0);
// ToDo: ugly! use function pointer
- if (syncNodeSnapshotEnable(pSyncNode)) {
+ if (syncNodeStrategy(pSyncNode) == SYNC_STRATEGY_STANDARD_SNAPSHOT) {
if (pMsg->msgType == TDMT_SYNC_TIMEOUT) {
SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pMsg);
code = syncNodeOnTimeoutCb(pSyncNode, pSyncMsg);
@@ -463,7 +448,7 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
syncPingReplyDestroy(pSyncMsg);
} else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pMsg);
- code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg);
+ code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg, NULL);
syncClientRequestDestroy(pSyncMsg);
} else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pMsg);
@@ -512,7 +497,7 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
syncPingReplyDestroy(pSyncMsg);
} else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pMsg);
- code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg);
+ code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg, NULL);
syncClientRequestDestroy(pSyncMsg);
} else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pMsg);
@@ -540,6 +525,8 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
}
}
+ syncNodeRelease(pSyncNode);
+
if (code != 0) {
terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
}
@@ -548,17 +535,32 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
static int32_t mndCheckMnodeState(SRpcMsg *pMsg) {
if (!IsReq(pMsg)) return 0;
+ if (pMsg->msgType == TDMT_SCH_QUERY || pMsg->msgType == TDMT_SCH_MERGE_QUERY ||
+ pMsg->msgType == TDMT_SCH_QUERY_CONTINUE || pMsg->msgType == TDMT_SCH_QUERY_HEARTBEAT ||
+ pMsg->msgType == TDMT_SCH_FETCH || pMsg->msgType == TDMT_SCH_MERGE_FETCH || pMsg->msgType == TDMT_SCH_DROP_TASK) {
+ return 0;
+ }
if (mndAcquireRpcRef(pMsg->info.node) == 0) return 0;
+ if (pMsg->msgType == TDMT_MND_MQ_TIMER || pMsg->msgType == TDMT_MND_TELEM_TIMER ||
+ pMsg->msgType == TDMT_MND_TRANS_TIMER || pMsg->msgType == TDMT_MND_TTL_TIMER) {
+ return -1;
+ }
- if (pMsg->msgType != TDMT_MND_MQ_TIMER && pMsg->msgType != TDMT_MND_TELEM_TIMER &&
- pMsg->msgType != TDMT_MND_TRANS_TIMER) {
- mError("msg:%p, failed to check mnode state since %s, type:%s", pMsg, terrstr(), TMSG_INFO(pMsg->msgType));
+ SEpSet epSet = {0};
+ mndGetMnodeEpSet(pMsg->info.node, &epSet);
- SEpSet epSet = {0};
- mndGetMnodeEpSet(pMsg->info.node, &epSet);
+ const STraceId *trace = &pMsg->info.traceId;
+ mError("msg:%p, failed to check mnode state since %s, type:%s, numOfMnodes:%d inUse:%d", pMsg, terrstr(),
+ TMSG_INFO(pMsg->msgType), epSet.numOfEps, epSet.inUse);
+
+ if (epSet.numOfEps > 0) {
+ for (int32_t i = 0; i < epSet.numOfEps; ++i) {
+ mInfo("mnode index:%d, ep:%s:%u", i, epSet.eps[i].fqdn, epSet.eps[i].port);
+ }
int32_t contLen = tSerializeSEpSet(NULL, 0, &epSet);
pMsg->info.rsp = rpcMallocCont(contLen);
+ pMsg->info.hasEpSet = 1;
if (pMsg->info.rsp != NULL) {
tSerializeSEpSet(pMsg->info.rsp, contLen, &epSet);
pMsg->info.rspLen = contLen;
@@ -566,6 +568,8 @@ static int32_t mndCheckMnodeState(SRpcMsg *pMsg) {
} else {
terrno = TSDB_CODE_OUT_OF_MEMORY;
}
+ } else {
+ terrno = TSDB_CODE_APP_NOT_READY;
}
return -1;
@@ -575,17 +579,20 @@ static int32_t mndCheckMsgContent(SRpcMsg *pMsg) {
if (!IsReq(pMsg)) return 0;
if (pMsg->contLen != 0 && pMsg->pCont != NULL) return 0;
- mError("msg:%p, failed to check msg, cont:%p contLen:%d, app:%p type:%s", pMsg, pMsg->pCont, pMsg->contLen,
- pMsg->info.ahandle, TMSG_INFO(pMsg->msgType));
+ const STraceId *trace = &pMsg->info.traceId;
+ mGError("msg:%p, failed to check msg, cont:%p contLen:%d, app:%p type:%s", pMsg, pMsg->pCont, pMsg->contLen,
+ pMsg->info.ahandle, TMSG_INFO(pMsg->msgType));
terrno = TSDB_CODE_INVALID_MSG_LEN;
return -1;
}
int32_t mndProcessRpcMsg(SRpcMsg *pMsg) {
- SMnode *pMnode = pMsg->info.node;
+ SMnode *pMnode = pMsg->info.node;
+ const STraceId *trace = &pMsg->info.traceId;
+
MndMsgFp fp = pMnode->msgFp[TMSG_INDEX(pMsg->msgType)];
if (fp == NULL) {
- mError("msg:%p, failed to get msg handle, app:%p type:%s", pMsg, pMsg->info.ahandle, TMSG_INFO(pMsg->msgType));
+ mGError("msg:%p, failed to get msg handle, app:%p type:%s", pMsg, pMsg->info.ahandle, TMSG_INFO(pMsg->msgType));
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
return -1;
}
@@ -593,18 +600,17 @@ int32_t mndProcessRpcMsg(SRpcMsg *pMsg) {
if (mndCheckMsgContent(pMsg) != 0) return -1;
if (mndCheckMnodeState(pMsg) != 0) return -1;
- STraceId *trace = &pMsg->info.traceId;
mGTrace("msg:%p, start to process in mnode, app:%p type:%s", pMsg, pMsg->info.ahandle, TMSG_INFO(pMsg->msgType));
int32_t code = (*fp)(pMsg);
mndReleaseRpcRef(pMnode);
if (code == TSDB_CODE_ACTION_IN_PROGRESS) {
- mTrace("msg:%p, won't response immediately since in progress", pMsg);
+ mGTrace("msg:%p, won't response immediately since in progress", pMsg);
} else if (code == 0) {
- mTrace("msg:%p, successfully processed", pMsg);
+ mGTrace("msg:%p, successfully processed", pMsg);
} else {
- mError("msg:%p, failed to process since %s, app:%p type:%s", pMsg, terrstr(), pMsg->info.ahandle,
- TMSG_INFO(pMsg->msgType));
+ mGError("msg:%p, failed to process since %s, app:%p type:%s", pMsg, terrstr(), pMsg->info.ahandle,
+ TMSG_INFO(pMsg->msgType));
}
return code;
@@ -620,7 +626,6 @@ void mndSetMsgHandle(SMnode *pMnode, tmsg_t msgType, MndMsgFp fp) {
// Note: uid 0 is reserved
int64_t mndGenerateUid(char *name, int32_t len) {
int32_t hashval = MurmurHash3_32(name, len);
-
do {
int64_t us = taosGetTimestampUs();
int64_t x = (us & 0x000000FFFFFFFFFF) << 24;
@@ -632,7 +637,7 @@ int64_t mndGenerateUid(char *name, int32_t len) {
}
int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgroupInfo *pVgroupInfo,
- SMonGrantInfo *pGrantInfo) {
+ SMonStbInfo *pStbInfo, SMonGrantInfo *pGrantInfo) {
if (mndAcquireRpcRef(pMnode) != 0) return -1;
SSdb *pSdb = pMnode->pSdb;
@@ -641,7 +646,9 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr
pClusterInfo->dnodes = taosArrayInit(sdbGetSize(pSdb, SDB_DNODE), sizeof(SMonDnodeDesc));
pClusterInfo->mnodes = taosArrayInit(sdbGetSize(pSdb, SDB_MNODE), sizeof(SMonMnodeDesc));
pVgroupInfo->vgroups = taosArrayInit(sdbGetSize(pSdb, SDB_VGROUP), sizeof(SMonVgroupDesc));
- if (pClusterInfo->dnodes == NULL || pClusterInfo->mnodes == NULL || pVgroupInfo->vgroups == NULL) {
+ pStbInfo->stbs = taosArrayInit(sdbGetSize(pSdb, SDB_STB), sizeof(SMonStbDesc));
+ if (pClusterInfo->dnodes == NULL || pClusterInfo->mnodes == NULL || pVgroupInfo->vgroups == NULL ||
+ pStbInfo->stbs == NULL) {
mndReleaseRpcRef(pMnode);
return -1;
}
@@ -650,6 +657,8 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr
tstrncpy(pClusterInfo->version, version, sizeof(pClusterInfo->version));
pClusterInfo->monitor_interval = tsMonitorInterval;
pClusterInfo->connections_total = mndGetNumOfConnections(pMnode);
+ pClusterInfo->dbs_total = sdbGetSize(pSdb, SDB_DB);
+ pClusterInfo->stbs_total = sdbGetSize(pSdb, SDB_STB);
void *pIter = NULL;
while (1) {
@@ -699,6 +708,7 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr
if (pIter == NULL) break;
pClusterInfo->vgroups_total++;
+ pClusterInfo->tbs_total += pVgroup->numOfTables;
SMonVgroupDesc desc = {0};
desc.vgroup_id = pVgroup->vgId;
@@ -729,6 +739,27 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr
sdbRelease(pSdb, pVgroup);
}
+ // stb info
+ pIter = NULL;
+ while (1) {
+ SStbObj *pStb = NULL;
+ pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
+ if (pIter == NULL) break;
+
+ SMonStbDesc desc = {0};
+
+ SName name1 = {0};
+ tNameFromString(&name1, pStb->db, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+ tNameGetDbName(&name1, desc.database_name);
+
+ SName name2 = {0};
+ tNameFromString(&name2, pStb->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+ tstrncpy(desc.stb_name, tNameGetTableName(&name2), TSDB_TABLE_NAME_LEN);
+
+ taosArrayPush(pStbInfo->stbs, &desc);
+ sdbRelease(pSdb, pStb);
+ }
+
// grant info
pGrantInfo->expire_time = (pMnode->grant.expireTimeMS - ms) / 86400000.0f;
pGrantInfo->timeseries_total = pMnode->grant.timeseriesAllowed;
diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c
index b40cd713e5b1bc002c9503744055998ef4e9b405..d7eaa722026db935d0369e84b3513bf5603830c7 100644
--- a/source/dnode/mnode/impl/src/mndMnode.c
+++ b/source/dnode/mnode/impl/src/mndMnode.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndMnode.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDnode.h"
#include "mndShow.h"
#include "mndSync.h"
@@ -218,6 +218,7 @@ bool mndIsMnode(SMnode *pMnode, int32_t dnodeId) {
}
void mndGetMnodeEpSet(SMnode *pMnode, SEpSet *pEpSet) {
+#if 0
SSdb *pSdb = pMnode->pSdb;
int32_t totalMnodes = sdbGetSize(pSdb, SDB_MNODE);
void *pIter = NULL;
@@ -237,6 +238,9 @@ void mndGetMnodeEpSet(SMnode *pMnode, SEpSet *pEpSet) {
addEpIntoEpSet(pEpSet, pObj->pDnode->fqdn, pObj->pDnode->port);
sdbRelease(pSdb, pObj);
}
+#else
+ syncGetRetryEpSet(pMnode->syncMgmt.sync, pEpSet);
+#endif
}
static int32_t mndSetCreateMnodeRedoLogs(SMnode *pMnode, STrans *pTrans, SMnodeObj *pObj) {
@@ -389,6 +393,9 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) {
}
mDebug("mnode:%d, start to create", createReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_MNODE) != 0) {
+ goto _OVER;
+ }
pObj = mndAcquireMnode(pMnode, createReq.dnodeId);
if (pObj != NULL) {
@@ -414,10 +421,6 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_MNODE) != 0) {
- goto _OVER;
- }
-
code = mndCreateMnode(pMnode, pReq, pDnode, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -495,7 +498,7 @@ static int32_t mndSetDropMnodeRedoActions(SMnode *pMnode, STrans *pTrans, SDnode
{
int32_t contLen = tSerializeSSetStandbyReq(NULL, 0, &standbyReq) + sizeof(SMsgHead);
void *pReq = taosMemoryMalloc(contLen);
- tSerializeSSetStandbyReq((char*)pReq + sizeof(SMsgHead), contLen, &standbyReq);
+ tSerializeSSetStandbyReq((char *)pReq + sizeof(SMsgHead), contLen, &standbyReq);
SMsgHead *pHead = pReq;
pHead->contLen = htonl(contLen);
pHead->vgId = htonl(MNODE_HANDLE);
@@ -595,6 +598,9 @@ static int32_t mndProcessDropMnodeReq(SRpcMsg *pReq) {
}
mDebug("mnode:%d, start to drop", dropReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_MNODE) != 0) {
+ goto _OVER;
+ }
if (dropReq.dnodeId <= 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -621,10 +627,6 @@ static int32_t mndProcessDropMnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_MNODE) != 0) {
- goto _OVER;
- }
-
code = mndDropMnode(pMnode, pReq, pObj);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
diff --git a/source/dnode/mnode/impl/src/mndOffset.c b/source/dnode/mnode/impl/src/mndOffset.c
index 18f2e993b264d36fbf5e63c5c7783757b4903a4e..00753de0ecf726b90613e46bd0afd5bb20f9d88e 100644
--- a/source/dnode/mnode/impl/src/mndOffset.c
+++ b/source/dnode/mnode/impl/src/mndOffset.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndOffset.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
@@ -36,13 +36,15 @@ static int32_t mndOffsetActionUpdate(SSdb *pSdb, SMqOffsetObj *pOffset, SMqOffse
static int32_t mndProcessCommitOffsetReq(SRpcMsg *pReq);
int32_t mndInitOffset(SMnode *pMnode) {
- SSdbTable table = {.sdbType = SDB_OFFSET,
- .keyType = SDB_KEY_BINARY,
- .encodeFp = (SdbEncodeFp)mndOffsetActionEncode,
- .decodeFp = (SdbDecodeFp)mndOffsetActionDecode,
- .insertFp = (SdbInsertFp)mndOffsetActionInsert,
- .updateFp = (SdbUpdateFp)mndOffsetActionUpdate,
- .deleteFp = (SdbDeleteFp)mndOffsetActionDelete};
+ SSdbTable table = {
+ .sdbType = SDB_OFFSET,
+ .keyType = SDB_KEY_BINARY,
+ .encodeFp = (SdbEncodeFp)mndOffsetActionEncode,
+ .decodeFp = (SdbDecodeFp)mndOffsetActionDecode,
+ .insertFp = (SdbInsertFp)mndOffsetActionInsert,
+ .updateFp = (SdbUpdateFp)mndOffsetActionUpdate,
+ .deleteFp = (SdbDeleteFp)mndOffsetActionDelete,
+ };
mndSetMsgHandle(pMnode, TDMT_MND_MQ_COMMIT_OFFSET, mndProcessCommitOffsetReq);
@@ -183,7 +185,7 @@ static int32_t mndProcessCommitOffsetReq(SRpcMsg *pMsg) {
for (int32_t i = 0; i < commitOffsetReq.num; i++) {
SMqOffset *pOffset = &commitOffsetReq.offsets[i];
- mInfo("commit offset %ld to vg %d of consumer group %s on topic %s", pOffset->offset, pOffset->vgId,
+ mInfo("commit offset %" PRId64 " to vgId:%d of consumer group %s on topic %s", pOffset->offset, pOffset->vgId,
pOffset->cgroup, pOffset->topicName);
if (mndMakePartitionKey(key, pOffset->cgroup, pOffset->topicName, pOffset->vgId) < 0) {
mError("submit offset to topic %s failed", pOffset->topicName);
diff --git a/source/dnode/mnode/impl/src/mndPerfSchema.c b/source/dnode/mnode/impl/src/mndPerfSchema.c
index d7b2e3ec24a89c0a4576753f1e6343cffff9ce02..7056337c8d6d84997f622eac898ffe8e4980898f 100644
--- a/source/dnode/mnode/impl/src/mndPerfSchema.c
+++ b/source/dnode/mnode/impl/src/mndPerfSchema.c
@@ -92,6 +92,37 @@ int32_t mndBuildPerfsTableSchema(SMnode *pMnode, const char *dbFName, const char
return 0;
}
+int32_t mndBuildPerfsTableCfg(SMnode *pMnode, const char *dbFName, const char *tbName, STableCfgRsp *pRsp) {
+ if (NULL == pMnode->perfsMeta) {
+ terrno = TSDB_CODE_MND_NOT_READY;
+ return -1;
+ }
+
+ STableMetaRsp *pMeta = taosHashGet(pMnode->perfsMeta, tbName, strlen(tbName));
+ if (NULL == pMeta) {
+ mError("invalid performance schema table name:%s", tbName);
+ terrno = TSDB_CODE_MND_INVALID_SYS_TABLENAME;
+ return -1;
+ }
+
+ strcpy(pRsp->tbName, pMeta->tbName);
+ strcpy(pRsp->stbName, pMeta->stbName);
+ strcpy(pRsp->dbFName, pMeta->dbFName);
+ pRsp->numOfTags = pMeta->numOfTags;
+ pRsp->numOfColumns = pMeta->numOfColumns;
+ pRsp->tableType = pMeta->tableType;
+
+ pRsp->pSchemas = taosMemoryCalloc(pMeta->numOfColumns, sizeof(SSchema));
+ if (pRsp->pSchemas == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ pRsp->pSchemas = NULL;
+ return -1;
+ }
+
+ memcpy(pRsp->pSchemas, pMeta->pSchemas, pMeta->numOfColumns * sizeof(SSchema));
+ return 0;
+}
+
int32_t mndInitPerfs(SMnode *pMnode) {
pMnode->perfsMeta = taosHashInit(20, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
if (pMnode->perfsMeta == NULL) {
diff --git a/source/dnode/mnode/impl/src/mndAuth.c b/source/dnode/mnode/impl/src/mndPrivilege.c
similarity index 57%
rename from source/dnode/mnode/impl/src/mndAuth.c
rename to source/dnode/mnode/impl/src/mndPrivilege.c
index d47fb9dfb4bfa18b337672ae01adedbe743615f8..e4422c480f5b37874f20d36eb77ae99dbb027d51 100644
--- a/source/dnode/mnode/impl/src/mndAuth.c
+++ b/source/dnode/mnode/impl/src/mndPrivilege.c
@@ -14,66 +14,15 @@
*/
#define _DEFAULT_SOURCE
-#include "mndAuth.h"
+#include "mndPrivilege.h"
+#include "mndDb.h"
#include "mndUser.h"
-static int32_t mndProcessAuthReq(SRpcMsg *pReq);
+int32_t mndInitPrivilege(SMnode *pMnode) { return 0; }
-int32_t mndInitAuth(SMnode *pMnode) {
- mndSetMsgHandle(pMnode, TDMT_MND_AUTH, mndProcessAuthReq);
- return 0;
-}
-
-void mndCleanupAuth(SMnode *pMnode) {}
-
-static int32_t mndRetriveAuth(SMnode *pMnode, SAuthRsp *pRsp) {
- SUserObj *pUser = mndAcquireUser(pMnode, pRsp->user);
- if (pUser == NULL) {
- *pRsp->secret = 0;
- mError("user:%s, failed to auth user since %s", pRsp->user, terrstr());
- return -1;
- }
-
- pRsp->spi = 1;
- pRsp->encrypt = 0;
- *pRsp->ckey = 0;
-
- memcpy(pRsp->secret, pUser->pass, TSDB_PASSWORD_LEN);
- mndReleaseUser(pMnode, pUser);
-
- mDebug("user:%s, auth info is returned", pRsp->user);
- return 0;
-}
-
-static int32_t mndProcessAuthReq(SRpcMsg *pReq) {
- SAuthReq authReq = {0};
- if (tDeserializeSAuthReq(pReq->pCont, pReq->contLen, &authReq) != 0) {
- terrno = TSDB_CODE_INVALID_MSG;
- return -1;
- }
-
- SAuthReq authRsp = {0};
- memcpy(authRsp.user, authReq.user, TSDB_USER_LEN);
-
- int32_t code = mndRetriveAuth(pReq->info.node, &authRsp);
- mTrace("user:%s, auth req received, spi:%d encrypt:%d ruser:%s", pReq->info.conn.user, authRsp.spi, authRsp.encrypt,
- authRsp.user);
-
- int32_t contLen = tSerializeSAuthReq(NULL, 0, &authRsp);
- void *pRsp = rpcMallocCont(contLen);
- if (pRsp == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
-
- tSerializeSAuthReq(pRsp, contLen, &authRsp);
-
- pReq->info.rsp = pRsp;
- pReq->info.rspLen = contLen;
- return code;
-}
+void mndCleanupPrivilege(SMnode *pMnode) {}
-int32_t mndCheckOperAuth(SMnode *pMnode, const char *user, EOperType operType) {
+int32_t mndCheckOperPrivilege(SMnode *pMnode, const char *user, EOperType operType) {
int32_t code = 0;
SUserObj *pUser = mndAcquireUser(pMnode, user);
@@ -93,16 +42,30 @@ int32_t mndCheckOperAuth(SMnode *pMnode, const char *user, EOperType operType) {
goto _OVER;
}
- terrno = TSDB_CODE_MND_NO_RIGHTS;
- code = -1;
+ switch (operType) {
+ case MND_OPER_CONNECT:
+ case MND_OPER_CREATE_FUNC:
+ case MND_OPER_DROP_FUNC:
+ case MND_OPER_SHOW_VARIBALES:
+ break;
+ default:
+ terrno = TSDB_CODE_MND_NO_RIGHTS;
+ code = -1;
+ }
_OVER:
mndReleaseUser(pMnode, pUser);
return code;
}
-int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SAlterUserReq *pAlter) {
+int32_t mndCheckAlterUserPrivilege(SUserObj *pOperUser, SUserObj *pUser, SAlterUserReq *pAlter) {
+ if (pUser->superUser && pAlter->alterType != TSDB_ALTER_USER_PASSWD) {
+ terrno = TSDB_CODE_MND_NO_RIGHTS;
+ return -1;
+ }
+
if (pOperUser->superUser) return 0;
+
if (!pOperUser->enable) {
terrno = TSDB_CODE_MND_USER_DISABLED;
return -1;
@@ -118,7 +81,7 @@ int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SAlterUserRe
return -1;
}
-int32_t mndCheckShowAuth(SMnode *pMnode, const char *user, int32_t showType) {
+int32_t mndCheckShowPrivilege(SMnode *pMnode, const char *user, EShowType showType, const char *dbname) {
int32_t code = 0;
SUserObj *pUser = mndAcquireUser(pMnode, user);
@@ -137,21 +100,41 @@ int32_t mndCheckShowAuth(SMnode *pMnode, const char *user, int32_t showType) {
goto _OVER;
}
- if (!pUser->sysInfo) {
- terrno = TSDB_CODE_MND_NO_RIGHTS;
- code = -1;
+ if (pUser->sysInfo) {
goto _OVER;
}
- terrno = TSDB_CODE_MND_NO_RIGHTS;
- code = -1;
+ switch (showType) {
+ case TSDB_MGMT_TABLE_DB:
+ case TSDB_MGMT_TABLE_STB:
+ case TSDB_MGMT_TABLE_INDEX:
+ case TSDB_MGMT_TABLE_STREAMS:
+ case TSDB_MGMT_TABLE_CONSUMERS:
+ case TSDB_MGMT_TABLE_TOPICS:
+ case TSDB_MGMT_TABLE_SUBSCRIPTIONS:
+ case TSDB_MGMT_TABLE_FUNC:
+ case TSDB_MGMT_TABLE_QUERIES:
+ case TSDB_MGMT_TABLE_CONNS:
+ case TSDB_MGMT_TABLE_APPS:
+ case TSDB_MGMT_TABLE_TRANS:
+ code = 0;
+ break;
+ default:
+ terrno = TSDB_CODE_MND_NO_RIGHTS;
+ code = -1;
+ goto _OVER;
+ }
+
+ if (showType == TSDB_MGMT_TABLE_STB || showType == TSDB_MGMT_TABLE_VGROUP || showType == TSDB_MGMT_TABLE_INDEX) {
+ code = mndCheckDbPrivilegeByName(pMnode, user, MND_OPER_READ_OR_WRITE_DB, dbname);
+ }
_OVER:
mndReleaseUser(pMnode, pUser);
return code;
}
-int32_t mndCheckDbAuth(SMnode *pMnode, const char *user, EOperType operType, SDbObj *pDb) {
+int32_t mndCheckDbPrivilege(SMnode *pMnode, const char *user, EOperType operType, SDbObj *pDb) {
int32_t code = 0;
SUserObj *pUser = mndAcquireUser(pMnode, user);
@@ -172,19 +155,12 @@ int32_t mndCheckDbAuth(SMnode *pMnode, const char *user, EOperType operType, SDb
if (pUser->sysInfo) goto _OVER;
}
- if (operType == MND_OPER_ALTER_DB) {
- if (strcmp(pUser->user, pDb->createUser) == 0 && pUser->sysInfo) goto _OVER;
- }
-
- if (operType == MND_OPER_DROP_DB) {
+ if (operType == MND_OPER_ALTER_DB || operType == MND_OPER_DROP_DB || operType == MND_OPER_COMPACT_DB ||
+ operType == MND_OPER_TRIM_DB) {
if (strcmp(pUser->user, pDb->createUser) == 0 && pUser->sysInfo) goto _OVER;
}
- if (operType == MND_OPER_COMPACT_DB) {
- if (strcmp(pUser->user, pDb->createUser) == 0 && pUser->sysInfo) goto _OVER;
- }
-
- if (operType == MND_OPER_USE_DB) {
+ if (operType == MND_OPER_USE_DB || operType == MND_OPER_READ_OR_WRITE_DB) {
if (strcmp(pUser->user, pDb->createUser) == 0) goto _OVER;
if (taosHashGet(pUser->readDbs, pDb->name, strlen(pDb->name) + 1) != NULL) goto _OVER;
if (taosHashGet(pUser->writeDbs, pDb->name, strlen(pDb->name) + 1) != NULL) goto _OVER;
@@ -207,3 +183,12 @@ _OVER:
mndReleaseUser(pMnode, pUser);
return code;
}
+
+int32_t mndCheckDbPrivilegeByName(SMnode *pMnode, const char *user, EOperType operType, const char *dbname) {
+ SDbObj *pDb = mndAcquireDb(pMnode, dbname);
+ if (pDb == NULL) return -1;
+
+ int32_t code = mndCheckDbPrivilege(pMnode, user, operType, pDb);
+ mndReleaseDb(pMnode, pDb);
+ return code;
+}
\ No newline at end of file
diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c
index fd80679316ad4df7dbcac44e636bb29f42c1800d..38368b4ece860ce1f3220d7de7a7a4d2800cb0ce 100644
--- a/source/dnode/mnode/impl/src/mndProfile.c
+++ b/source/dnode/mnode/impl/src/mndProfile.c
@@ -15,6 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndProfile.h"
+#include "mndPrivilege.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
@@ -70,6 +71,7 @@ static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter);
static void mndFreeApp(SAppObj *pApp);
static int32_t mndRetrieveApps(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
static void mndCancelGetNextApp(SMnode *pMnode, void *pIter);
+static int32_t mndProcessSvrVerReq(SRpcMsg *pReq);
int32_t mndInitProfile(SMnode *pMnode) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
@@ -94,6 +96,7 @@ int32_t mndInitProfile(SMnode *pMnode) {
mndSetMsgHandle(pMnode, TDMT_MND_CONNECT, mndProcessConnectReq);
mndSetMsgHandle(pMnode, TDMT_MND_KILL_QUERY, mndProcessKillQueryReq);
mndSetMsgHandle(pMnode, TDMT_MND_KILL_CONN, mndProcessKillConnReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_SERVER_VERSION, mndProcessSvrVerReq);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndRetrieveConns);
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndCancelGetNextConn);
@@ -122,30 +125,33 @@ static SConnObj *mndCreateConn(SMnode *pMnode, const char *user, int8_t connType
int32_t pid, const char *app, int64_t startTime) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
- char connStr[255] = {0};
- int32_t len = snprintf(connStr, sizeof(connStr), "%s%d%d%d%s", user, ip, port, pid, app);
+ char connStr[255] = {0};
+ int32_t len = snprintf(connStr, sizeof(connStr), "%s%d%d%d%s", user, ip, port, pid, app);
uint32_t connId = mndGenerateUid(connStr, len);
if (startTime == 0) startTime = taosGetTimestampMs();
- SConnObj connObj = {.id = connId,
- .connType = connType,
- .appStartTimeMs = startTime,
- .pid = pid,
- .ip = ip,
- .port = port,
- .killed = 0,
- .loginTimeMs = taosGetTimestampMs(),
- .lastAccessTimeMs = 0,
- .killId = 0,
- .numOfQueries = 0,
- .pQueries = NULL};
+ SConnObj connObj = {
+ .id = connId,
+ .connType = connType,
+ .appStartTimeMs = startTime,
+ .pid = pid,
+ .ip = ip,
+ .port = port,
+ .killed = 0,
+ .loginTimeMs = taosGetTimestampMs(),
+ .lastAccessTimeMs = 0,
+ .killId = 0,
+ .numOfQueries = 0,
+ .pQueries = NULL,
+ };
connObj.lastAccessTimeMs = connObj.loginTimeMs;
tstrncpy(connObj.user, user, TSDB_USER_LEN);
tstrncpy(connObj.app, app, TSDB_APP_NAME_LEN);
int32_t keepTime = tsShellActivityTimer * 3;
- SConnObj *pConn = taosCachePut(pMgmt->connCache, &connId, sizeof(uint32_t), &connObj, sizeof(connObj), keepTime * 1000);
+ SConnObj *pConn =
+ taosCachePut(pMgmt->connCache, &connId, sizeof(uint32_t), &connObj, sizeof(connObj), keepTime * 1000);
if (pConn == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
mError("conn:%d, failed to put into cache since %s, user:%s", connId, user, terrstr());
@@ -174,7 +180,6 @@ static SConnObj *mndAcquireConn(SMnode *pMnode, uint32_t connId) {
}
pConn->lastAccessTimeMs = taosGetTimestampMs();
-
mTrace("conn:%u, acquired from cache, data:%p", pConn->id, pConn);
return pConn;
}
@@ -207,49 +212,59 @@ static void mndCancelGetNextConn(SMnode *pMnode, void *pIter) {
}
static int32_t mndProcessConnectReq(SRpcMsg *pReq) {
- SMnode *pMnode = pReq->info.node;
- SUserObj *pUser = NULL;
- SDbObj *pDb = NULL;
- SConnObj *pConn = NULL;
- int32_t code = -1;
- SConnectReq connReq = {0};
- char ip[30] = {0};
+ SMnode *pMnode = pReq->info.node;
+ SUserObj *pUser = NULL;
+ SDbObj *pDb = NULL;
+ SConnObj *pConn = NULL;
+ int32_t code = -1;
+ SConnectReq connReq = {0};
+ char ip[24] = {0};
+ const STraceId *trace = &pReq->info.traceId;
if (tDeserializeSConnectReq(pReq->pCont, pReq->contLen, &connReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
- goto CONN_OVER;
+ goto _OVER;
}
taosIp2String(pReq->info.conn.clientIp, ip);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CONNECT) != 0) {
+ mGError("user:%s, failed to login from %s since %s", pReq->info.conn.user, ip, terrstr());
+ goto _OVER;
+ }
pUser = mndAcquireUser(pMnode, pReq->info.conn.user);
if (pUser == NULL) {
- mError("user:%s, failed to login while acquire user since %s", pReq->info.conn.user, terrstr());
- goto CONN_OVER;
+ mGError("user:%s, failed to login from %s while acquire user since %s", pReq->info.conn.user, ip, terrstr());
+ goto _OVER;
}
- if (0 != strncmp(connReq.passwd, pUser->pass, TSDB_PASSWORD_LEN - 1)) {
- mError("user:%s, failed to auth while acquire user, input:%s", pReq->info.conn.user, connReq.passwd);
+
+ if (strncmp(connReq.passwd, pUser->pass, TSDB_PASSWORD_LEN - 1) != 0) {
+ mGError("user:%s, failed to login from %s since invalid pass, input:%s", pReq->info.conn.user, ip, connReq.passwd);
code = TSDB_CODE_RPC_AUTH_FAILURE;
- goto CONN_OVER;
+ goto _OVER;
}
if (connReq.db[0]) {
- char db[TSDB_DB_FNAME_LEN];
+ char db[TSDB_DB_FNAME_LEN] = {0};
snprintf(db, TSDB_DB_FNAME_LEN, "%d%s%s", pUser->acctId, TS_PATH_DELIMITER, connReq.db);
pDb = mndAcquireDb(pMnode, db);
if (pDb == NULL) {
terrno = TSDB_CODE_MND_INVALID_DB;
- mError("user:%s, failed to login from %s while use db:%s since %s", pReq->info.conn.user, ip, connReq.db,
- terrstr());
- goto CONN_OVER;
+ mGError("user:%s, failed to login from %s while use db:%s since %s", pReq->info.conn.user, ip, connReq.db,
+ terrstr());
+ goto _OVER;
+ }
+
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_READ_OR_WRITE_DB, pDb) != 0) {
+ goto _OVER;
}
}
pConn = mndCreateConn(pMnode, pReq->info.conn.user, connReq.connType, pReq->info.conn.clientIp,
pReq->info.conn.clientPort, connReq.pid, connReq.app, connReq.startTime);
if (pConn == NULL) {
- mError("user:%s, failed to login from %s while create connection since %s", pReq->info.conn.user, ip, terrstr());
- goto CONN_OVER;
+ mGError("user:%s, failed to login from %s while create connection since %s", pReq->info.conn.user, ip, terrstr());
+ goto _OVER;
}
SConnectRsp connectRsp = {0};
@@ -260,24 +275,25 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) {
connectRsp.connType = connReq.connType;
connectRsp.dnodeNum = mndGetDnodeSize(pMnode);
- snprintf(connectRsp.sVersion, sizeof(connectRsp.sVersion), "ver:%s\nbuild:%s\ngitinfo:%s", version, buildinfo,
+ strcpy(connectRsp.sVer, version);
+ snprintf(connectRsp.sDetailVer, sizeof(connectRsp.sDetailVer), "ver:%s\nbuild:%s\ngitinfo:%s", version, buildinfo,
gitinfo);
mndGetMnodeEpSet(pMnode, &connectRsp.epSet);
int32_t contLen = tSerializeSConnectRsp(NULL, 0, &connectRsp);
- if (contLen < 0) goto CONN_OVER;
+ if (contLen < 0) goto _OVER;
void *pRsp = rpcMallocCont(contLen);
- if (pRsp == NULL) goto CONN_OVER;
+ if (pRsp == NULL) goto _OVER;
tSerializeSConnectRsp(pRsp, contLen, &connectRsp);
pReq->info.rspLen = contLen;
pReq->info.rsp = pRsp;
- mDebug("user:%s, login from %s:%d, conn:%u, app:%s", pReq->info.conn.user, ip, pConn->port, pConn->id, connReq.app);
+ mGDebug("user:%s, login from %s:%d, conn:%u, app:%s", pReq->info.conn.user, ip, pConn->port, pConn->id, connReq.app);
code = 0;
-CONN_OVER:
+_OVER:
mndReleaseUser(pMnode, pUser);
mndReleaseDb(pMnode, pDb);
@@ -302,7 +318,7 @@ static int32_t mndSaveQueryList(SConnObj *pConn, SQueryHbReqBasic *pBasic) {
return TSDB_CODE_SUCCESS;
}
-static SAppObj *mndCreateApp(SMnode *pMnode, uint32_t clientIp, SAppHbReq* pReq) {
+static SAppObj *mndCreateApp(SMnode *pMnode, uint32_t clientIp, SAppHbReq *pReq) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
SAppObj app;
@@ -314,22 +330,19 @@ static SAppObj *mndCreateApp(SMnode *pMnode, uint32_t clientIp, SAppHbReq* pReq)
memcpy(&app.summary, &pReq->summary, sizeof(pReq->summary));
app.lastAccessTimeMs = taosGetTimestampMs();
- int32_t keepTime = tsShellActivityTimer * 3;
+ const int32_t keepTime = tsShellActivityTimer * 3;
SAppObj *pApp = taosCachePut(pMgmt->appCache, &pReq->appId, sizeof(pReq->appId), &app, sizeof(app), keepTime * 1000);
if (pApp == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
mError("failed to app %" PRIx64 " into cache since %s", pReq->appId, terrstr());
return NULL;
}
-
+
mTrace("app %" PRIx64 " is put into cache", pReq->appId);
return pApp;
}
-static void mndFreeApp(SAppObj *pApp) {
- mTrace("app %" PRIx64 " is destroyed", pApp->appId);
-}
-
+static void mndFreeApp(SAppObj *pApp) { mTrace("app %" PRIx64 " is destroyed", pApp->appId); }
static SAppObj *mndAcquireApp(SMnode *pMnode, int64_t appId) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
@@ -356,7 +369,7 @@ static void mndReleaseApp(SMnode *pMnode, SAppObj *pApp) {
void *mndGetNextApp(SMnode *pMnode, SCacheIter *pIter) {
SAppObj *pApp = NULL;
- bool hasNext = taosCacheIterNext(pIter);
+ bool hasNext = taosCacheIterNext(pIter);
if (hasNext) {
size_t dataLen = 0;
pApp = taosCacheIterGetData(pIter, &dataLen);
@@ -439,16 +452,16 @@ static SClientHbRsp *mndMqHbBuildRsp(SMnode *pMnode, SClientHbReq *pReq) {
}
static int32_t mndUpdateAppInfo(SMnode *pMnode, SClientHbReq *pHbReq, SRpcConnInfo *connInfo) {
- SAppHbReq* pReq = &pHbReq->app;
- SAppObj *pApp = mndAcquireApp(pMnode, pReq->appId);
+ SAppHbReq *pReq = &pHbReq->app;
+ SAppObj *pApp = mndAcquireApp(pMnode, pReq->appId);
if (pApp == NULL) {
pApp = mndCreateApp(pMnode, connInfo->clientIp, pReq);
if (pApp == NULL) {
mError("failed to create new app %" PRIx64 " since %s", pReq->appId, terrstr());
return -1;
} else {
- mDebug("a new app %" PRIx64 "created", pReq->appId);
- mndReleaseApp(pMnode, pApp);
+ mDebug("a new app %" PRIx64 " is created", pReq->appId);
+ mndReleaseApp(pMnode, pApp);
return TSDB_CODE_SUCCESS;
}
}
@@ -460,11 +473,32 @@ static int32_t mndUpdateAppInfo(SMnode *pMnode, SClientHbReq *pHbReq, SRpcConnIn
return TSDB_CODE_SUCCESS;
}
+static int32_t mndGetOnlineDnodeNum(SMnode *pMnode, int32_t *num) {
+ SSdb *pSdb = pMnode->pSdb;
+ SDnodeObj *pDnode = NULL;
+ int64_t curMs = taosGetTimestampMs();
+ void *pIter = NULL;
+
+ while (true) {
+ pIter = sdbFetch(pSdb, SDB_DNODE, pIter, (void **)&pDnode);
+ if (pIter == NULL) break;
+
+ bool online = mndIsDnodeOnline(pDnode, curMs);
+ if (online) {
+ (*num)++;
+ }
+
+ sdbRelease(pSdb, pDnode);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t mndProcessQueryHeartBeat(SMnode *pMnode, SRpcMsg *pMsg, SClientHbReq *pHbReq,
SClientHbBatchRsp *pBatchRsp) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
SClientHbRsp hbRsp = {.connKey = pHbReq->connKey, .status = 0, .info = NULL, .query = NULL};
- SRpcConnInfo connInfo = pMsg->info.conn;
+ SRpcConnInfo connInfo = pMsg->info.conn;
mndUpdateAppInfo(pMnode, pHbReq, &connInfo);
@@ -503,7 +537,7 @@ static int32_t mndProcessQueryHeartBeat(SMnode *pMnode, SRpcMsg *pMsg, SClientHb
rspBasic->connId = pConn->id;
rspBasic->totalDnodes = mndGetDnodeSize(pMnode);
- rspBasic->onlineDnodes = 1; // TODO
+ mndGetOnlineDnodeNum(pMnode, &rspBasic->onlineDnodes);
mndGetMnodeEpSet(pMnode, &rspBasic->epSet);
mndCreateQnodeList(pMnode, &rspBasic->pQnodeList, -1);
@@ -621,15 +655,6 @@ static int32_t mndProcessKillQueryReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
- SUserObj *pUser = mndAcquireUser(pMnode, pReq->info.conn.user);
- if (pUser == NULL) return 0;
- if (!pUser->superUser) {
- mndReleaseUser(pMnode, pUser);
- terrno = TSDB_CODE_MND_NO_RIGHTS;
- return -1;
- }
- mndReleaseUser(pMnode, pUser);
-
SKillQueryReq killReq = {0};
if (tDeserializeSKillQueryReq(pReq->pCont, pReq->contLen, &killReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -637,9 +662,13 @@ static int32_t mndProcessKillQueryReq(SRpcMsg *pReq) {
}
mInfo("kill query msg is received, queryId:%s", killReq.queryStrId);
- int32_t connId = 0;
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_KILL_QUERY) != 0) {
+ return -1;
+ }
+
+ int32_t connId = 0;
uint64_t queryId = 0;
- char* p = strchr(killReq.queryStrId, ':');
+ char *p = strchr(killReq.queryStrId, ':');
if (NULL == p) {
mError("invalid query id %s", killReq.queryStrId);
terrno = TSDB_CODE_MND_INVALID_QUERY_ID;
@@ -666,21 +695,16 @@ static int32_t mndProcessKillConnReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
- SUserObj *pUser = mndAcquireUser(pMnode, pReq->info.conn.user);
- if (pUser == NULL) return 0;
- if (!pUser->superUser) {
- mndReleaseUser(pMnode, pUser);
- terrno = TSDB_CODE_MND_NO_RIGHTS;
- return -1;
- }
- mndReleaseUser(pMnode, pUser);
-
SKillConnReq killReq = {0};
if (tDeserializeSKillConnReq(pReq->pCont, pReq->contLen, &killReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
return -1;
}
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_KILL_CONN) != 0) {
+ return -1;
+ }
+
SConnObj *pConn = taosCacheAcquireByKey(pMgmt->connCache, &killReq.connId, sizeof(uint32_t));
if (pConn == NULL) {
mError("connId:%u, failed to kill connection, conn not exist", killReq.connId);
@@ -694,6 +718,27 @@ static int32_t mndProcessKillConnReq(SRpcMsg *pReq) {
}
}
+static int32_t mndProcessSvrVerReq(SRpcMsg *pReq) {
+ int32_t code = -1;
+ SServerVerRsp rsp = {0};
+ strcpy(rsp.ver, version);
+
+ int32_t contLen = tSerializeSServerVerRsp(NULL, 0, &rsp);
+ if (contLen < 0) goto _over;
+ void *pRsp = rpcMallocCont(contLen);
+ if (pRsp == NULL) goto _over;
+ tSerializeSServerVerRsp(pRsp, contLen, &rsp);
+
+ pReq->info.rspLen = contLen;
+ pReq->info.rsp = pRsp;
+
+ code = 0;
+
+_over:
+
+ return code;
+}
+
static int32_t mndRetrieveConns(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
SMnode *pMnode = pReq->info.node;
SSdb *pSdb = pMnode->pSdb;
@@ -853,12 +898,12 @@ static int32_t mndRetrieveQueries(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p
}
static int32_t mndRetrieveApps(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
- SMnode *pMnode = pReq->info.node;
- SSdb *pSdb = pMnode->pSdb;
- int32_t numOfRows = 0;
- int32_t cols = 0;
- SAppObj *pApp = NULL;
-
+ SMnode *pMnode = pReq->info.node;
+ SSdb *pSdb = pMnode->pSdb;
+ int32_t numOfRows = 0;
+ int32_t cols = 0;
+ SAppObj *pApp = NULL;
+
if (pShow->pIter == NULL) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
pShow->pIter = taosCacheCreateIter(pMgmt->appCache);
@@ -931,7 +976,6 @@ static int32_t mndRetrieveApps(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlo
return numOfRows;
}
-
static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter) {
if (pIter != NULL) {
taosCacheDestroyIter(pIter);
diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c
index f5625f32d5a73af783dc0172ba949cc6d4532462..f057f6190defd3c7c8d01e7b8e7d39b37c1f3c6e 100644
--- a/source/dnode/mnode/impl/src/mndQnode.c
+++ b/source/dnode/mnode/impl/src/mndQnode.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndQnode.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDnode.h"
#include "mndShow.h"
#include "mndTrans.h"
@@ -279,6 +279,9 @@ static int32_t mndProcessCreateQnodeReq(SRpcMsg *pReq) {
}
mDebug("qnode:%d, start to create", createReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_QNODE) != 0) {
+ goto _OVER;
+ }
pObj = mndAcquireQnode(pMnode, createReq.dnodeId);
if (pObj != NULL) {
@@ -294,10 +297,6 @@ static int32_t mndProcessCreateQnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_QNODE) != 0) {
- goto _OVER;
- }
-
code = mndCreateQnode(pMnode, pReq, pDnode, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -354,6 +353,14 @@ static int32_t mndSetDropQnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SQn
return 0;
}
+int32_t mndSetDropQnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SQnodeObj *pObj) {
+ if (pObj == NULL) return 0;
+ if (mndSetDropQnodeRedoLogs(pTrans, pObj) != 0) return -1;
+ if (mndSetDropQnodeCommitLogs(pTrans, pObj) != 0) return -1;
+ if (mndSetDropQnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) return -1;
+ return 0;
+}
+
static int32_t mndDropQnode(SMnode *pMnode, SRpcMsg *pReq, SQnodeObj *pObj) {
int32_t code = -1;
@@ -361,9 +368,7 @@ static int32_t mndDropQnode(SMnode *pMnode, SRpcMsg *pReq, SQnodeObj *pObj) {
if (pTrans == NULL) goto _OVER;
mDebug("trans:%d, used to drop qnode:%d", pTrans->id, pObj->id);
- if (mndSetDropQnodeRedoLogs(pTrans, pObj) != 0) goto _OVER;
- if (mndSetDropQnodeCommitLogs(pTrans, pObj) != 0) goto _OVER;
- if (mndSetDropQnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) goto _OVER;
+ if (mndSetDropQnodeInfoToTrans(pMnode, pTrans, pObj) != 0) goto _OVER;
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
code = 0;
@@ -385,6 +390,9 @@ static int32_t mndProcessDropQnodeReq(SRpcMsg *pReq) {
}
mDebug("qnode:%d, start to drop", dropReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_QNODE) != 0) {
+ goto _OVER;
+ }
if (dropReq.dnodeId <= 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -396,10 +404,6 @@ static int32_t mndProcessDropQnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_QNODE) != 0) {
- goto _OVER;
- }
-
code = mndDropQnode(pMnode, pReq, pObj);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -412,19 +416,19 @@ _OVER:
return code;
}
-int32_t mndCreateQnodeList(SMnode *pMnode, SArray** pList, int32_t limit) {
- SSdb *pSdb = pMnode->pSdb;
- void *pIter = NULL;
- SQnodeObj *pObj = NULL;
- int32_t numOfRows = 0;
+int32_t mndCreateQnodeList(SMnode *pMnode, SArray **pList, int32_t limit) {
+ SSdb *pSdb = pMnode->pSdb;
+ void *pIter = NULL;
+ SQnodeObj *pObj = NULL;
+ int32_t numOfRows = 0;
- SArray* qnodeList = taosArrayInit(5, sizeof(SQueryNodeLoad));
+ SArray *qnodeList = taosArrayInit(5, sizeof(SQueryNodeLoad));
if (NULL == qnodeList) {
mError("failed to alloc epSet while process qnode list req");
terrno = TSDB_CODE_OUT_OF_MEMORY;
return terrno;
}
-
+
while (1) {
pIter = sdbFetch(pSdb, SDB_QNODE, pIter, (void **)&pObj);
if (pIter == NULL) break;
@@ -451,7 +455,6 @@ int32_t mndCreateQnodeList(SMnode *pMnode, SArray** pList, int32_t limit)
return TSDB_CODE_SUCCESS;
}
-
static int32_t mndProcessQnodeListReq(SRpcMsg *pReq) {
int32_t code = -1;
SMnode *pMnode = pReq->info.node;
diff --git a/source/dnode/mnode/impl/src/mndQuery.c b/source/dnode/mnode/impl/src/mndQuery.c
index 671152f9c6c4290e472e651aaff4e338798e19f3..5a527b994e2c8eb130fe5c16f294e7a9ef8342f2 100644
--- a/source/dnode/mnode/impl/src/mndQuery.c
+++ b/source/dnode/mnode/impl/src/mndQuery.c
@@ -19,13 +19,13 @@
#include "qworker.h"
int32_t mndPreProcessQueryMsg(SRpcMsg *pMsg) {
- if (TDMT_VND_QUERY != pMsg->msgType) return 0;
+ if (TDMT_SCH_QUERY != pMsg->msgType && TDMT_SCH_MERGE_QUERY != pMsg->msgType) return 0;
SMnode *pMnode = pMsg->info.node;
return qWorkerPreprocessQueryMsg(pMnode->pQuery, pMsg);
}
void mndPostProcessQueryMsg(SRpcMsg *pMsg) {
- if (TDMT_VND_QUERY != pMsg->msgType) return;
+ if (TDMT_SCH_QUERY != pMsg->msgType && TDMT_SCH_MERGE_QUERY != pMsg->msgType) return;
SMnode *pMnode = pMsg->info.node;
qWorkerAbortPreprocessQueryMsg(pMnode->pQuery, pMsg);
}
@@ -37,19 +37,21 @@ int32_t mndProcessQueryMsg(SRpcMsg *pMsg) {
mTrace("msg:%p, in query queue is processing", pMsg);
switch (pMsg->msgType) {
- case TDMT_VND_QUERY:
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY:
code = qWorkerProcessQueryMsg(&handle, pMnode->pQuery, pMsg, 0);
break;
- case TDMT_VND_QUERY_CONTINUE:
+ case TDMT_SCH_QUERY_CONTINUE:
code = qWorkerProcessCQueryMsg(&handle, pMnode->pQuery, pMsg, 0);
break;
- case TDMT_VND_FETCH:
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH:
code = qWorkerProcessFetchMsg(pMnode, pMnode->pQuery, pMsg, 0);
break;
- case TDMT_VND_DROP_TASK:
+ case TDMT_SCH_DROP_TASK:
code = qWorkerProcessDropMsg(pMnode, pMnode->pQuery, pMsg, 0);
break;
- case TDMT_VND_QUERY_HEARTBEAT:
+ case TDMT_SCH_QUERY_HEARTBEAT:
code = qWorkerProcessHbMsg(pMnode, pMnode->pQuery, pMsg, 0);
break;
default:
@@ -67,11 +69,13 @@ int32_t mndInitQuery(SMnode *pMnode) {
return -1;
}
- mndSetMsgHandle(pMnode, TDMT_VND_QUERY, mndProcessQueryMsg);
- mndSetMsgHandle(pMnode, TDMT_VND_QUERY_CONTINUE, mndProcessQueryMsg);
- mndSetMsgHandle(pMnode, TDMT_VND_FETCH, mndProcessQueryMsg);
- mndSetMsgHandle(pMnode, TDMT_VND_DROP_TASK, mndProcessQueryMsg);
- mndSetMsgHandle(pMnode, TDMT_VND_QUERY_HEARTBEAT, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_QUERY, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_MERGE_QUERY, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_QUERY_CONTINUE, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_FETCH, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_MERGE_FETCH, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_DROP_TASK, mndProcessQueryMsg);
+ mndSetMsgHandle(pMnode, TDMT_SCH_QUERY_HEARTBEAT, mndProcessQueryMsg);
return 0;
}
diff --git a/source/dnode/mnode/impl/src/mndScheduler.c b/source/dnode/mnode/impl/src/mndScheduler.c
index 2b6258b10ab76772e69c7a6935c058a526e202f7..aa6e7192fcf923ac88c6f2f84c281bbe8e0ca038 100644
--- a/source/dnode/mnode/impl/src/mndScheduler.c
+++ b/source/dnode/mnode/impl/src/mndScheduler.c
@@ -37,7 +37,7 @@ extern bool tsSchedStreamToSnode;
static int32_t mndAddTaskToTaskSet(SArray* pArray, SStreamTask* pTask) {
int32_t childId = taosArrayGetSize(pArray);
- pTask->childId = childId;
+ pTask->selfChildId = childId;
taosArrayPush(pArray, &pTask);
return 0;
}
@@ -97,37 +97,7 @@ END:
return terrno;
}
-int32_t mndPersistTaskDeployReq(STrans* pTrans, SStreamTask* pTask, const SEpSet* pEpSet, tmsg_t type, int32_t nodeId) {
- SEncoder encoder;
- tEncoderInit(&encoder, NULL, 0);
- tEncodeSStreamTask(&encoder, pTask);
- int32_t size = encoder.pos;
- int32_t tlen = sizeof(SMsgHead) + size;
- tEncoderClear(&encoder);
- void* buf = taosMemoryCalloc(1, tlen);
- if (buf == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
- ((SMsgHead*)buf)->vgId = htonl(nodeId);
- void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
- tEncoderInit(&encoder, abuf, size);
- tEncodeSStreamTask(&encoder, pTask);
- tEncoderClear(&encoder);
-
- STransAction action = {0};
- memcpy(&action.epSet, pEpSet, sizeof(SEpSet));
- action.pCont = buf;
- action.contLen = tlen;
- action.msgType = type;
- if (mndTransAppendRedoAction(pTrans, &action) != 0) {
- taosMemoryFree(buf);
- return -1;
- }
- return 0;
-}
-
-int32_t mndAddSinkToTask(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream, SStreamTask* pTask) {
+int32_t mndAddSinkToTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask) {
pTask->dispatchType = TASK_DISPATCH__NONE;
// sink
if (pStream->smaId != 0) {
@@ -142,7 +112,7 @@ int32_t mndAddSinkToTask(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream, SS
return 0;
}
-int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream, SStreamTask* pTask) {
+int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask) {
pTask->sinkType = TASK_SINK__NONE;
if (pStream->fixedSinkVgId == 0) {
pTask->dispatchType = TASK_DISPATCH__SHUFFLE;
@@ -187,7 +157,7 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, STrans* pTrans, SStreamObj*
return 0;
}
-int32_t mndAssignTaskToVg(SMnode* pMnode, STrans* pTrans, SStreamTask* pTask, SSubplan* plan, const SVgObj* pVgroup) {
+int32_t mndAssignTaskToVg(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, const SVgObj* pVgroup) {
int32_t msgLen;
pTask->nodeId = pVgroup->vgId;
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
@@ -196,11 +166,11 @@ int32_t mndAssignTaskToVg(SMnode* pMnode, STrans* pTrans, SStreamTask* pTask, SS
plan->execNode.epSet = pTask->epSet;
if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) {
+ ASSERT(0);
terrno = TSDB_CODE_QRY_INVALID_INPUT;
return -1;
}
ASSERT(pTask->dispatchType != TASK_DISPATCH__NONE || pTask->sinkType != TASK_SINK__NONE);
- mndPersistTaskDeployReq(pTrans, pTask, &plan->execNode.epSet, TDMT_STREAM_TASK_DEPLOY, pVgroup->vgId);
return 0;
}
@@ -212,8 +182,7 @@ SSnodeObj* mndSchedFetchOneSnode(SMnode* pMnode) {
return pObj;
}
-int32_t mndAssignTaskToSnode(SMnode* pMnode, STrans* pTrans, SStreamTask* pTask, SSubplan* plan,
- const SSnodeObj* pSnode) {
+int32_t mndAssignTaskToSnode(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, const SSnodeObj* pSnode) {
int32_t msgLen;
pTask->nodeId = SNODE_HANDLE;
@@ -223,10 +192,10 @@ int32_t mndAssignTaskToSnode(SMnode* pMnode, STrans* pTrans, SStreamTask* pTask,
plan->execNode.epSet = pTask->epSet;
if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) {
+ ASSERT(0);
terrno = TSDB_CODE_QRY_INVALID_INPUT;
return -1;
}
- mndPersistTaskDeployReq(pTrans, pTask, &plan->execNode.epSet, TDMT_STREAM_TASK_DEPLOY, SNODE_HANDLE);
return 0;
}
@@ -245,7 +214,7 @@ SVgObj* mndSchedFetchOneVg(SMnode* pMnode, int64_t dbUid) {
return pVgroup;
}
-int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
+int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) {
SSdb* pSdb = pMnode->pSdb;
void* pIter = NULL;
SArray* tasks = taosArrayGetP(pStream->tasks, 0);
@@ -256,12 +225,14 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, STrans* pTrans, SStreamOb
SVgObj* pVgroup;
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
if (pIter == NULL) break;
- if (strcmp(pVgroup->dbName, pStream->targetDb) != 0) {
+ if (!mndVgroupInDb(pVgroup, pStream->targetDbUid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
+
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
if (pTask == NULL) {
+ sdbRelease(pSdb, pVgroup);
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
@@ -271,7 +242,7 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, STrans* pTrans, SStreamOb
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
// source
- pTask->inputType = TASK_INPUT_TYPE__DATA_BLOCK;
+ pTask->isDataScan = 0;
// exec
pTask->execType = TASK_EXEC__NONE;
@@ -290,13 +261,11 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, STrans* pTrans, SStreamOb
// dispatch
pTask->dispatchType = TASK_DISPATCH__NONE;
-
- mndPersistTaskDeployReq(pTrans, pTask, &pTask->epSet, TDMT_STREAM_TASK_DEPLOY, pVgroup->vgId);
}
return 0;
}
-int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
+int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, SStreamObj* pStream) {
ASSERT(pStream->fixedSinkVgId != 0);
SArray* tasks = taosArrayGetP(pStream->tasks, 0);
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
@@ -306,6 +275,8 @@ int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, STrans* pTrans, SStreamObj*
}
mndAddTaskToTaskSet(tasks, pTask);
+ ASSERT(pStream->fixedSinkVg.vgId == pStream->fixedSinkVgId);
+
pTask->nodeId = pStream->fixedSinkVgId;
#if 0
SVgObj* pVgroup = mndAcquireVgroup(pMnode, pStream->fixedSinkVgId);
@@ -315,8 +286,9 @@ int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, STrans* pTrans, SStreamObj*
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
#endif
pTask->epSet = mndGetVgroupEpset(pMnode, &pStream->fixedSinkVg);
+
// source
- pTask->inputType = TASK_INPUT_TYPE__DATA_BLOCK;
+ pTask->isDataScan = 0;
// exec
pTask->execType = TASK_EXEC__NONE;
@@ -334,13 +306,10 @@ int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, STrans* pTrans, SStreamObj*
// dispatch
pTask->dispatchType = TASK_DISPATCH__NONE;
-
- mndPersistTaskDeployReq(pTrans, pTask, &pTask->epSet, TDMT_STREAM_TASK_DEPLOY, pStream->fixedSinkVg.vgId);
-
return 0;
}
-int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
+int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
SSdb* pSdb = pMnode->pSdb;
SQueryPlan* pPlan = qStringToQueryPlan(pStream->physicalPlan);
if (pPlan == NULL) {
@@ -365,9 +334,15 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
// add extra sink
hasExtraSink = true;
if (pStream->fixedSinkVgId == 0) {
- mndAddShuffleSinkTasksToStream(pMnode, pTrans, pStream);
+ if (mndAddShuffleSinkTasksToStream(pMnode, pStream) < 0) {
+ // TODO free
+ return -1;
+ }
} else {
- mndAddFixedSinkTaskToStream(pMnode, pTrans, pStream);
+ if (mndAddFixedSinkTaskToStream(pMnode, pStream) < 0) {
+ // TODO free
+ return -1;
+ }
}
}
@@ -383,15 +358,23 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
ASSERT(plan->subplanType == SUBPLAN_TYPE_MERGE);
pInnerTask = tNewSStreamTask(pStream->uid);
+ if (pInnerTask == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ qDestroyQueryPlan(pPlan);
+ return -1;
+ }
mndAddTaskToTaskSet(taskInnerLevel, pInnerTask);
- // input
- pInnerTask->inputType = TASK_INPUT_TYPE__DATA_BLOCK;
+
+ pInnerTask->childEpInfo = taosArrayInit(0, sizeof(void*));
+
+ // source
+ pInnerTask->isDataScan = 0;
// trigger
pInnerTask->triggerParam = pStream->triggerParam;
// dispatch
- if (mndAddDispatcherToInnerTask(pMnode, pTrans, pStream, pInnerTask) < 0) {
+ if (mndAddDispatcherToInnerTask(pMnode, pStream, pInnerTask) < 0) {
qDestroyQueryPlan(pPlan);
return -1;
}
@@ -403,14 +386,13 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
SSnodeObj* pSnode = mndSchedFetchOneSnode(pMnode);
if (pSnode == NULL) {
SVgObj* pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
- if (mndAssignTaskToVg(pMnode, pTrans, pInnerTask, plan, pVgroup) < 0) {
+ if (mndAssignTaskToVg(pMnode, pInnerTask, plan, pVgroup) < 0) {
sdbRelease(pSdb, pVgroup);
qDestroyQueryPlan(pPlan);
return -1;
}
} else {
- if (mndAssignTaskToSnode(pMnode, pTrans, pInnerTask, plan, pSnode) < 0) {
- ASSERT(0);
+ if (mndAssignTaskToSnode(pMnode, pInnerTask, plan, pSnode) < 0) {
sdbRelease(pSdb, pSnode);
qDestroyQueryPlan(pPlan);
return -1;
@@ -418,7 +400,7 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
}
} else {
SVgObj* pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
- if (mndAssignTaskToVg(pMnode, pTrans, pInnerTask, plan, pVgroup) < 0) {
+ if (mndAssignTaskToVg(pMnode, pInnerTask, plan, pVgroup) < 0) {
sdbRelease(pSdb, pVgroup);
qDestroyQueryPlan(pPlan);
return -1;
@@ -439,17 +421,22 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
SVgObj* pVgroup;
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pStream->sourceDbUid) {
+ if (!mndVgroupInDb(pVgroup, pStream->sourceDbUid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
+
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
+ if (pInnerTask == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ sdbRelease(pSdb, pVgroup);
+ qDestroyQueryPlan(pPlan);
+ return -1;
+ }
mndAddTaskToTaskSet(taskSourceLevel, pTask);
- pTask->dataScan = 1;
-
- // input
- pTask->inputType = TASK_INPUT_TYPE__SUMBIT_BLOCK;
+ // source
+ pTask->isDataScan = 1;
// add fixed vg dispatch
pTask->sinkType = TASK_SINK__NONE;
@@ -462,11 +449,25 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
// exec
pTask->execType = TASK_EXEC__PIPE;
- if (mndAssignTaskToVg(pMnode, pTrans, pTask, plan, pVgroup) < 0) {
+ if (mndAssignTaskToVg(pMnode, pTask, plan, pVgroup) < 0) {
+ sdbRelease(pSdb, pVgroup);
+ qDestroyQueryPlan(pPlan);
+ return -1;
+ }
+
+ SStreamChildEpInfo* pEpInfo = taosMemoryMalloc(sizeof(SStreamChildEpInfo));
+ if (pEpInfo == NULL) {
+ ASSERT(0);
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
sdbRelease(pSdb, pVgroup);
qDestroyQueryPlan(pPlan);
return -1;
}
+ pEpInfo->childId = pTask->selfChildId;
+ pEpInfo->epSet = pTask->epSet;
+ pEpInfo->nodeId = pTask->nodeId;
+ pEpInfo->taskId = pTask->taskId;
+ taosArrayPush(pInnerTask->childEpInfo, &pEpInfo);
}
}
@@ -484,31 +485,35 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
SVgObj* pVgroup;
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pStream->sourceDbUid) {
+ if (!mndVgroupInDb(pVgroup, pStream->sourceDbUid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
+
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
+ if (pTask == NULL) {
+ sdbRelease(pSdb, pVgroup);
+ qDestroyQueryPlan(pPlan);
+ return -1;
+ }
mndAddTaskToTaskSet(taskOneLevel, pTask);
- pTask->dataScan = 1;
-
- // input
- pTask->inputType = TASK_INPUT_TYPE__SUMBIT_BLOCK;
+ // source
+ pTask->isDataScan = 1;
// trigger
pTask->triggerParam = pStream->triggerParam;
// sink or dispatch
if (hasExtraSink) {
- mndAddDispatcherToInnerTask(pMnode, pTrans, pStream, pTask);
+ mndAddDispatcherToInnerTask(pMnode, pStream, pTask);
} else {
- mndAddSinkToTask(pMnode, pTrans, pStream, pTask);
+ mndAddSinkToTask(pMnode, pStream, pTask);
}
// exec
pTask->execType = TASK_EXEC__PIPE;
- if (mndAssignTaskToVg(pMnode, pTrans, pTask, plan, pVgroup) < 0) {
+ if (mndAssignTaskToVg(pMnode, pTask, plan, pVgroup) < 0) {
sdbRelease(pSdb, pVgroup);
qDestroyQueryPlan(pPlan);
return -1;
@@ -557,7 +562,7 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib
while (1) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pTopic->dbUid) {
+ if (!mndVgroupInDb(pVgroup, pTopic->dbUid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c
index fed6a5a721088fc39f24712f922ffe13e80e48d7..2a8cbc4425222b5d7be0b1dafd089ec18fd0c391 100644
--- a/source/dnode/mnode/impl/src/mndShow.c
+++ b/source/dnode/mnode/impl/src/mndShow.c
@@ -15,8 +15,8 @@
#define _DEFAULT_SOURCE
#include "mndShow.h"
+#include "mndPrivilege.h"
#include "systable.h"
-#include "mndAuth.h"
#define SHOW_STEP_SIZE 100
@@ -71,7 +71,7 @@ static int32_t convertToRetrieveType(char *name, int32_t len) {
} else if (strncasecmp(name, TSDB_INS_TABLE_USER_FUNCTIONS, len) == 0) {
type = TSDB_MGMT_TABLE_FUNC;
} else if (strncasecmp(name, TSDB_INS_TABLE_USER_INDEXES, len) == 0) {
- // type = TSDB_MGMT_TABLE_INDEX;
+ type = TSDB_MGMT_TABLE_INDEX;
} else if (strncasecmp(name, TSDB_INS_TABLE_USER_STABLES, len) == 0) {
type = TSDB_MGMT_TABLE_STB;
} else if (strncasecmp(name, TSDB_INS_TABLE_USER_TABLES, len) == 0) {
@@ -122,6 +122,7 @@ static SShowObj *mndCreateShowObj(SMnode *pMnode, SRetrieveTableReq *pReq) {
int32_t size = sizeof(SShowObj);
SShowObj showObj = {0};
+
showObj.id = showId;
showObj.pMnode = pMnode;
showObj.type = convertToRetrieveType(pReq->tb, tListLen(pReq->tb));
@@ -230,13 +231,18 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) {
}
mDebug("show:0x%" PRIx64 ", start retrieve data, type:%d", pShow->id, pShow->type);
-
- // if (mndCheckShowAuth(pMnode, pReq->info.conn.user, pShow->type) != 0) return -1;
+ if (retrieveReq.user[0] != 0) {
+ memcpy(pReq->info.conn.user, retrieveReq.user, TSDB_USER_LEN);
+ } else {
+ memcpy(pReq->info.conn.user, TSDB_DEFAULT_USER, strlen(TSDB_DEFAULT_USER) + 1);
+ }
+ if (mndCheckShowPrivilege(pMnode, pReq->info.conn.user, pShow->type, retrieveReq.db) != 0) {
+ return -1;
+ }
int32_t numOfCols = pShow->pMeta->numOfColumns;
SSDataBlock *pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
- pBlock->info.numOfCols = numOfCols;
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData idata = {0};
@@ -271,7 +277,7 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) {
}
size = sizeof(SRetrieveMetaTableRsp) + sizeof(int32_t) + sizeof(SSysTableSchema) * pShow->pMeta->numOfColumns +
- blockDataGetSize(pBlock) + blockDataGetSerialMetaSize(pBlock->info.numOfCols);
+ blockDataGetSize(pBlock) + blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock));
SRetrieveMetaTableRsp *pRsp = rpcMallocCont(size);
if (pRsp == NULL) {
@@ -301,7 +307,7 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) {
}
int32_t len = 0;
- blockCompressEncode(pBlock, pStart, &len, pShow->pMeta->numOfColumns, false);
+ blockEncode(pBlock, pStart, &len, pShow->pMeta->numOfColumns, false);
}
pRsp->numOfRows = htonl(rowsRead);
diff --git a/source/dnode/mnode/impl/src/mndSma.c b/source/dnode/mnode/impl/src/mndSma.c
index c44fb03be23c7740759cf31233b4847756d1af08..c040f0d05b3ca7e7b5602fe62eee2fa245b3b243 100644
--- a/source/dnode/mnode/impl/src/mndSma.c
+++ b/source/dnode/mnode/impl/src/mndSma.c
@@ -15,11 +15,11 @@
#define _DEFAULT_SOURCE
#include "mndSma.h"
-#include "mndAuth.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndInfoSchema.h"
#include "mndMnode.h"
+#include "mndPrivilege.h"
#include "mndScheduler.h"
#include "mndShow.h"
#include "mndStb.h"
@@ -204,6 +204,8 @@ _OVER:
mError("sma:%s, failed to decode from raw:%p since %s", pSma->name, pRaw, terrstr());
taosMemoryFreeClear(pSma->expr);
taosMemoryFreeClear(pSma->tagsFilter);
+ taosMemoryFreeClear(pSma->sql);
+ taosMemoryFreeClear(pSma->ast);
taosMemoryFreeClear(pRow);
return NULL;
}
@@ -221,6 +223,8 @@ static int32_t mndSmaActionDelete(SSdb *pSdb, SSmaObj *pSma) {
mTrace("sma:%s, perform delete action, row:%p", pSma->name, pSma);
taosMemoryFreeClear(pSma->tagsFilter);
taosMemoryFreeClear(pSma->expr);
+ taosMemoryFreeClear(pSma->sql);
+ taosMemoryFreeClear(pSma->ast);
return 0;
}
@@ -396,6 +400,8 @@ static int32_t mndSetUpdateSmaStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStb
stbObj.pColumns = NULL;
stbObj.numOfTags = 0;
stbObj.pTags = NULL;
+ stbObj.numOfFuncs = 0;
+ stbObj.pFuncs = NULL;
stbObj.updateTime = taosGetTimestampMs();
stbObj.lock = 0;
stbObj.smaVer++;
@@ -408,47 +414,6 @@ static int32_t mndSetUpdateSmaStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStb
return 0;
}
-#if 0
-static int32_t mndSetCreateSmaRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SSmaObj *pSma) {
- SSdb *pSdb = pMnode->pSdb;
- SVgObj *pVgroup = NULL;
- void *pIter = NULL;
- int32_t contLen;
-
- while (1) {
- pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
- if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
- sdbRelease(pSdb, pVgroup);
- continue;
- }
-
- void *pReq = mndBuildVCreateSmaReq(pMnode, pVgroup, pSma, &contLen);
- if (pReq == NULL) {
- sdbCancelFetch(pSdb, pIter);
- sdbRelease(pSdb, pVgroup);
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
-
- STransAction action = {0};
- action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
- action.pCont = pReq;
- action.contLen = contLen;
- action.msgType = TDMT_VND_CREATE_SMA;
- if (mndTransAppendRedoAction(pTrans, &action) != 0) {
- taosMemoryFree(pReq);
- sdbCancelFetch(pSdb, pIter);
- sdbRelease(pSdb, pVgroup);
- return -1;
- }
- sdbRelease(pSdb, pVgroup);
- }
-
- return 0;
-}
-#endif
-
static int32_t mndSetCreateSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
SSmaObj *pSma) {
SVnodeGid *pVgid = pVgroup->vnodeGid + 0;
@@ -533,7 +498,7 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
#if 0
smaObj.timezone = pCreate->timezone;
#endif
- smaObj.timezone = tsTimezone; // use timezone of server
+ smaObj.timezone = tsTimezone; // use timezone of server
smaObj.interval = pCreate->interval;
smaObj.offset = pCreate->offset;
smaObj.sliding = pCreate->sliding;
@@ -562,13 +527,24 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
streamObj.updateTime = streamObj.createTime;
streamObj.uid = mndGenerateUid(pCreate->name, strlen(pCreate->name));
streamObj.sourceDbUid = pDb->uid;
+ streamObj.targetDbUid = pDb->uid;
streamObj.version = 1;
streamObj.sql = pCreate->sql;
streamObj.smaId = smaObj.uid;
- streamObj.watermark = 0;
- streamObj.trigger = STREAM_TRIGGER_AT_ONCE;
+ streamObj.watermark = pCreate->watermark;
+ streamObj.trigger = STREAM_TRIGGER_WINDOW_CLOSE;
+ streamObj.triggerParam = pCreate->maxDelay;
streamObj.ast = strdup(smaObj.ast);
+ // check the maxDelay
+ if (streamObj.triggerParam < TSDB_MIN_ROLLUP_MAX_DELAY) {
+ int64_t msInterval = convertTimeFromPrecisionToUnit(pCreate->interval, pDb->cfg.precision, TIME_UNIT_MILLISECOND);
+ streamObj.triggerParam = msInterval > TSDB_MIN_ROLLUP_MAX_DELAY ? msInterval : TSDB_MIN_ROLLUP_MAX_DELAY;
+ }
+ if (streamObj.triggerParam > TSDB_MAX_ROLLUP_MAX_DELAY) {
+ streamObj.triggerParam = TSDB_MAX_ROLLUP_MAX_DELAY;
+ }
+
if (mndAllocSmaVgroup(pMnode, pDb, &streamObj.fixedSinkVg) != 0) {
mError("sma:%s, failed to create since %s", smaObj.name, terrstr());
return -1;
@@ -621,9 +597,8 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
if (mndSetCreateSmaCommitLogs(pMnode, pTrans, &smaObj) != 0) goto _OVER;
if (mndSetCreateSmaVgroupCommitLogs(pMnode, pTrans, &streamObj.fixedSinkVg) != 0) goto _OVER;
if (mndSetUpdateSmaStbCommitLogs(pMnode, pTrans, pStb) != 0) goto _OVER;
- // if (mndSetCreateSmaRedoActions(pMnode, pTrans, pDb, &smaObj) != 0) goto _OVER;
if (mndSetCreateSmaVgroupRedoActions(pMnode, pTrans, pDb, &streamObj.fixedSinkVg, &smaObj) != 0) goto _OVER;
- if (mndScheduleStream(pMnode, pTrans, &streamObj) != 0) goto _OVER;
+ if (mndScheduleStream(pMnode, &streamObj) != 0) goto _OVER;
if (mndPersistStream(pMnode, pTrans, &streamObj) != 0) goto _OVER;
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
@@ -713,7 +688,7 @@ static int32_t mndProcessCreateSmaReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
goto _OVER;
}
@@ -770,49 +745,6 @@ static int32_t mndSetDropSmaVgroupCommitLogs(SMnode *pMnode, STrans *pTrans, SVg
return 0;
}
-#if 0
-static int32_t mndSetDropSmaRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SSmaObj *pSma) {
- SSdb *pSdb = pMnode->pSdb;
- SVgObj *pVgroup = NULL;
- void *pIter = NULL;
- int32_t contLen;
-
- while (1) {
- pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
- if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
- sdbRelease(pSdb, pVgroup);
- continue;
- }
-
- int32_t contLen = 0;
- void *pReq = mndBuildVDropSmaReq(pMnode, pVgroup, pSma, &contLen);
- if (pReq == NULL) {
- sdbCancelFetch(pSdb, pIter);
- sdbRelease(pSdb, pVgroup);
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
-
- STransAction action = {0};
- action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
- action.pCont = pReq;
- action.contLen = contLen;
- action.msgType = TDMT_VND_DROP_SMA;
- action.acceptableCode = TSDB_CODE_VND_SMA_NOT_EXIST;
- if (mndTransAppendRedoAction(pTrans, &action) != 0) {
- taosMemoryFree(pReq);
- sdbCancelFetch(pSdb, pIter);
- sdbRelease(pSdb, pVgroup);
- return -1;
- }
- sdbRelease(pSdb, pVgroup);
- }
-
- return 0;
-}
-#endif
-
static int32_t mndSetDropSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
SVnodeGid *pVgid = pVgroup->vnodeGid + 0;
SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
@@ -857,12 +789,28 @@ static int32_t mndDropSma(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SSmaObj *p
mDebug("trans:%d, used to drop sma:%s", pTrans->id, pSma->name);
mndTransSetDbName(pTrans, pDb->name, NULL);
+ SStreamObj *pStream = mndAcquireStream(pMnode, pSma->name);
+ if (pStream == NULL || pStream->smaId != pSma->uid) {
+ sdbRelease(pMnode->pSdb, pStream);
+ goto _OVER;
+ } else {
+ if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
+ mError("stream:%s, failed to drop task since %s", pStream->name, terrstr());
+ sdbRelease(pMnode->pSdb, pStream);
+ goto _OVER;
+ }
+
+ // drop stream
+ if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
+ sdbRelease(pMnode->pSdb, pStream);
+ goto _OVER;
+ }
+ }
if (mndSetDropSmaRedoLogs(pMnode, pTrans, pSma) != 0) goto _OVER;
if (mndSetDropSmaVgroupRedoLogs(pMnode, pTrans, pVgroup) != 0) goto _OVER;
if (mndSetDropSmaCommitLogs(pMnode, pTrans, pSma) != 0) goto _OVER;
if (mndSetDropSmaVgroupCommitLogs(pMnode, pTrans, pVgroup) != 0) goto _OVER;
if (mndSetUpdateSmaStbCommitLogs(pMnode, pTrans, pStb) != 0) goto _OVER;
- // if (mndSetDropSmaRedoActions(pMnode, pTrans, pDb, pSma) != 0) goto _OVER;
if (mndSetDropSmaVgroupRedoActions(pMnode, pTrans, pDb, pVgroup) != 0) goto _OVER;
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
@@ -889,10 +837,20 @@ int32_t mndDropSmasByStb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *p
if (pSma->stbUid == pStb->uid) {
pVgroup = mndAcquireVgroup(pMnode, pSma->dstVgId);
if (pVgroup == NULL) goto _OVER;
+
+ SStreamObj *pStream = mndAcquireStream(pMnode, pSma->name);
+ if (pStream != NULL && pStream->smaId == pSma->uid) {
+ if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
+ mError("stream:%s, failed to drop task since %s", pStream->name, terrstr());
+ goto _OVER;
+ }
+ if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
+ goto _OVER;
+ }
+ }
if (mndSetDropSmaVgroupCommitLogs(pMnode, pTrans, pVgroup) != 0) goto _OVER;
if (mndSetDropSmaVgroupRedoActions(pMnode, pTrans, pDb, pVgroup) != 0) goto _OVER;
if (mndSetDropSmaCommitLogs(pMnode, pTrans, pSma) != 0) goto _OVER;
- // if (mndSetDropSmaRedoActions(pMnode, pTrans, pDb, pSma) != 0) goto _OVER;
mndReleaseVgroup(pMnode, pVgroup);
pVgroup = NULL;
}
@@ -910,36 +868,26 @@ _OVER:
}
int32_t mndDropSmasByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb) {
- SSdb *pSdb = pMnode->pSdb;
- SSmaObj *pSma = NULL;
- void *pIter = NULL;
- SVgObj *pVgroup = NULL;
- int32_t code = -1;
+ SSdb *pSdb = pMnode->pSdb;
+ void *pIter = NULL;
while (1) {
+ SSmaObj *pSma = NULL;
pIter = sdbFetch(pSdb, SDB_SMA, pIter, (void **)&pSma);
if (pIter == NULL) break;
if (pSma->dbUid == pDb->uid) {
- pVgroup = mndAcquireVgroup(pMnode, pSma->dstVgId);
- if (pVgroup == NULL) goto _OVER;
- if (mndSetDropSmaVgroupCommitLogs(pMnode, pTrans, pVgroup) != 0) goto _OVER;
- if (mndSetDropSmaVgroupRedoActions(pMnode, pTrans, pDb, pVgroup) != 0) goto _OVER;
- if (mndSetDropSmaCommitLogs(pMnode, pTrans, pSma) != 0) goto _OVER;
- mndReleaseVgroup(pMnode, pVgroup);
- pVgroup = NULL;
+ if (mndSetDropSmaCommitLogs(pMnode, pTrans, pSma) != 0) {
+ sdbRelease(pSdb, pSma);
+ sdbCancelFetch(pSdb, pSma);
+ return -1;
+ }
}
sdbRelease(pSdb, pSma);
}
- code = 0;
-
-_OVER:
- sdbCancelFetch(pSdb, pIter);
- sdbRelease(pSdb, pSma);
- mndReleaseVgroup(pMnode, pVgroup);
- return code;
+ return 0;
}
static int32_t mndProcessDropSmaReq(SRpcMsg *pReq) {
@@ -974,7 +922,7 @@ static int32_t mndProcessDropSmaReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
goto _OVER;
}
@@ -1197,14 +1145,17 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
SSmaObj *pSma = NULL;
int32_t cols = 0;
- SDbObj *pDb = mndAcquireDb(pMnode, pShow->db);
- if (pDb == NULL) return 0;
+ SDbObj *pDb = NULL;
+ if (strlen(pShow->db) > 0) {
+ pDb = mndAcquireDb(pMnode, pShow->db);
+ if (pDb == NULL) return 0;
+ }
while (numOfRows < rows) {
pShow->pIter = sdbFetch(pSdb, SDB_SMA, pShow->pIter, (void **)&pSma);
if (pShow->pIter == NULL) break;
- if (pSma->dbUid != pDb->uid) {
+ if (NULL != pDb && pSma->dbUid != pDb->uid) {
sdbRelease(pSdb, pSma);
continue;
}
@@ -1213,29 +1164,32 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
SName smaName = {0};
tNameFromString(&smaName, pSma->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+ char n1[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_TO_VARSTR(n1, (char *)tNameGetTableName(&smaName));
- char n[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
- STR_TO_VARSTR(n, (char *)tNameGetTableName(&smaName));
- cols++;
+ char n2[TSDB_DB_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_TO_VARSTR(n2, (char *)mndGetDbStr(pSma->db));
SName stbName = {0};
tNameFromString(&stbName, pSma->stb, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
-
- char n1[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
- STR_TO_VARSTR(n1, (char *)tNameGetTableName(&stbName));
+ char n3[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_TO_VARSTR(n3, (char *)tNameGetTableName(&stbName));
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, numOfRows, (const char *)n, false);
+ colDataAppend(pColInfo, numOfRows, (const char *)n1, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, numOfRows, (const char *)&pSma->createdTime, false);
+ colDataAppend(pColInfo, numOfRows, (const char *)n2, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
- colDataAppend(pColInfo, numOfRows, (const char *)n1, false);
+ colDataAppend(pColInfo, numOfRows, (const char *)n3, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)&pSma->dstVgId, false);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, numOfRows, (const char *)&pSma->createdTime, false);
+
numOfRows++;
sdbRelease(pSdb, pSma);
}
diff --git a/source/dnode/mnode/impl/src/mndSnode.c b/source/dnode/mnode/impl/src/mndSnode.c
index 12188a3b3a08aee7bdae08b202c3563106ee35d1..d18a233d29eb6f7c0b72a4fbbfc81f2dd2869560 100644
--- a/source/dnode/mnode/impl/src/mndSnode.c
+++ b/source/dnode/mnode/impl/src/mndSnode.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndSnode.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDnode.h"
#include "mndShow.h"
#include "mndTrans.h"
@@ -65,7 +65,7 @@ SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode) {
return epSet;
}
-static SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
+SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
SSnodeObj *pObj = sdbAcquire(pMnode->pSdb, SDB_SNODE, &snodeId);
if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
terrno = TSDB_CODE_MND_SNODE_NOT_EXIST;
@@ -73,7 +73,7 @@ static SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
return pObj;
}
-static void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj) {
+void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj) {
SSdb *pSdb = pMnode->pSdb;
sdbRelease(pSdb, pObj);
}
@@ -273,6 +273,9 @@ _OVER:
}
static int32_t mndProcessCreateSnodeReq(SRpcMsg *pReq) {
+#if 1
+ return TSDB_CODE_OPS_NOT_SUPPORT;
+#else
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
SSnodeObj *pObj = NULL;
@@ -285,6 +288,9 @@ static int32_t mndProcessCreateSnodeReq(SRpcMsg *pReq) {
}
mDebug("snode:%d, start to create", createReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_SNODE) != 0) {
+ goto _OVER;
+ }
pObj = mndAcquireSnode(pMnode, createReq.dnodeId);
if (pObj != NULL) {
@@ -300,10 +306,6 @@ static int32_t mndProcessCreateSnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_SNODE) != 0) {
- goto _OVER;
- }
-
code = mndCreateSnode(pMnode, pReq, pDnode, &createReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -316,6 +318,7 @@ _OVER:
mndReleaseSnode(pMnode, pObj);
mndReleaseDnode(pMnode, pDnode);
return code;
+#endif
}
static int32_t mndSetDropSnodeRedoLogs(STrans *pTrans, SSnodeObj *pObj) {
@@ -361,6 +364,14 @@ static int32_t mndSetDropSnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SSn
return 0;
}
+int32_t mndSetDropSnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SSnodeObj *pObj) {
+ if (pObj == NULL) return 0;
+ if (mndSetDropSnodeRedoLogs(pTrans, pObj) != 0) return -1;
+ if (mndSetDropSnodeCommitLogs(pTrans, pObj) != 0) return -1;
+ if (mndSetDropSnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) return -1;
+ return 0;
+}
+
static int32_t mndDropSnode(SMnode *pMnode, SRpcMsg *pReq, SSnodeObj *pObj) {
int32_t code = -1;
@@ -368,10 +379,7 @@ static int32_t mndDropSnode(SMnode *pMnode, SRpcMsg *pReq, SSnodeObj *pObj) {
if (pTrans == NULL) goto _OVER;
mDebug("trans:%d, used to drop snode:%d", pTrans->id, pObj->id);
-
- if (mndSetDropSnodeRedoLogs(pTrans, pObj) != 0) goto _OVER;
- if (mndSetDropSnodeCommitLogs(pTrans, pObj) != 0) goto _OVER;
- if (mndSetDropSnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) goto _OVER;
+ if (mndSetDropSnodeInfoToTrans(pMnode, pTrans, pObj) != 0) goto _OVER;
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
code = 0;
@@ -382,9 +390,12 @@ _OVER:
}
static int32_t mndProcessDropSnodeReq(SRpcMsg *pReq) {
- SMnode *pMnode = pReq->info.node;
- int32_t code = -1;
- SSnodeObj *pObj = NULL;
+#if 1
+ return TSDB_CODE_OPS_NOT_SUPPORT;
+#else
+ SMnode *pMnode = pReq->info.node;
+ int32_t code = -1;
+ SSnodeObj *pObj = NULL;
SMDropSnodeReq dropReq = {0};
if (tDeserializeSCreateDropMQSBNodeReq(pReq->pCont, pReq->contLen, &dropReq) != 0) {
@@ -393,6 +404,9 @@ static int32_t mndProcessDropSnodeReq(SRpcMsg *pReq) {
}
mDebug("snode:%d, start to drop", dropReq.dnodeId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_SNODE) != 0) {
+ goto _OVER;
+ }
if (dropReq.dnodeId <= 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -404,10 +418,6 @@ static int32_t mndProcessDropSnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_SNODE) != 0) {
- goto _OVER;
- }
-
// check deletable
code = mndDropSnode(pMnode, pReq, pObj);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -419,6 +429,7 @@ _OVER:
mndReleaseSnode(pMnode, pObj);
return code;
+#endif
}
static int32_t mndRetrieveSnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c
index 3e50ea8262045795cc0e8b28c7e5aa967713aacb..bff33af5afb92d7bb41ba810e817fe095d569ec9 100644
--- a/source/dnode/mnode/impl/src/mndStb.c
+++ b/source/dnode/mnode/impl/src/mndStb.c
@@ -15,12 +15,12 @@
#define _DEFAULT_SOURCE
#include "mndStb.h"
-#include "mndAuth.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndInfoSchema.h"
#include "mndMnode.h"
#include "mndPerfSchema.h"
+#include "mndPrivilege.h"
#include "mndScheduler.h"
#include "mndShow.h"
#include "mndSma.h"
@@ -37,12 +37,15 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw);
static int32_t mndStbActionInsert(SSdb *pSdb, SStbObj *pStb);
static int32_t mndStbActionDelete(SSdb *pSdb, SStbObj *pStb);
static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew);
+static int32_t mndProcessTtlTimer(SRpcMsg *pReq);
static int32_t mndProcessCreateStbReq(SRpcMsg *pReq);
static int32_t mndProcessAlterStbReq(SRpcMsg *pReq);
static int32_t mndProcessDropStbReq(SRpcMsg *pReq);
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);
int32_t mndInitStb(SMnode *pMnode) {
SSdbTable table = {
@@ -62,6 +65,8 @@ int32_t mndInitStb(SMnode *pMnode) {
mndSetMsgHandle(pMnode, TDMT_VND_ALTER_STB_RSP, mndTransProcessRsp);
mndSetMsgHandle(pMnode, TDMT_VND_DROP_STB_RSP, mndTransProcessRsp);
mndSetMsgHandle(pMnode, TDMT_MND_TABLE_META, mndProcessTableMetaReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_TTL_TIMER, mndProcessTtlTimer);
+ mndSetMsgHandle(pMnode, TDMT_MND_TABLE_CFG, mndProcessTableCfgReq);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STB, mndRetrieveStb);
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STB, mndCancelGetNextStb);
@@ -74,8 +79,8 @@ void mndCleanupStb(SMnode *pMnode) {}
SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
- int32_t size = sizeof(SStbObj) + (pStb->numOfColumns + pStb->numOfTags) * sizeof(SSchema) + +pStb->commentLen +
- pStb->ast1Len + pStb->ast2Len + STB_RESERVE_SIZE;
+ int32_t size = sizeof(SStbObj) + (pStb->numOfColumns + pStb->numOfTags) * sizeof(SSchema) + pStb->commentLen +
+ pStb->ast1Len + pStb->ast2Len + STB_RESERVE_SIZE + taosArrayGetSize(pStb->pFuncs) * TSDB_FUNC_NAME_LEN;
SSdbRaw *pRaw = sdbAllocRaw(SDB_STB, STB_VER_NUMBER, size);
if (pRaw == NULL) goto _OVER;
@@ -88,6 +93,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
SDB_SET_INT64(pRaw, dataPos, pStb->dbUid, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->tagVer, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->colVer, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pStb->smaVer, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->nextColId, _OVER)
SDB_SET_INT64(pRaw, dataPos, pStb->maxdelay[0], _OVER)
SDB_SET_INT64(pRaw, dataPos, pStb->maxdelay[1], _OVER)
@@ -96,6 +102,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
SDB_SET_INT32(pRaw, dataPos, pStb->ttl, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->numOfColumns, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->numOfTags, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pStb->numOfFuncs, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->commentLen, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->ast1Len, _OVER)
SDB_SET_INT32(pRaw, dataPos, pStb->ast2Len, _OVER)
@@ -118,15 +125,23 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
SDB_SET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER)
}
+ for (int32_t i = 0; i < pStb->numOfFuncs; ++i) {
+ char *func = taosArrayGet(pStb->pFuncs, i);
+ SDB_SET_BINARY(pRaw, dataPos, func, TSDB_FUNC_NAME_LEN, _OVER)
+ }
+
if (pStb->commentLen > 0) {
SDB_SET_BINARY(pRaw, dataPos, pStb->comment, pStb->commentLen + 1, _OVER)
}
+
if (pStb->ast1Len > 0) {
SDB_SET_BINARY(pRaw, dataPos, pStb->pAst1, pStb->ast1Len, _OVER)
}
+
if (pStb->ast2Len > 0) {
SDB_SET_BINARY(pRaw, dataPos, pStb->pAst2, pStb->ast2Len, _OVER)
}
+
SDB_SET_RESERVE(pRaw, dataPos, STB_RESERVE_SIZE, _OVER)
SDB_SET_DATALEN(pRaw, dataPos, _OVER)
@@ -169,6 +184,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT64(pRaw, dataPos, &pStb->dbUid, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->tagVer, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->colVer, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &pStb->smaVer, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->nextColId, _OVER)
SDB_GET_INT64(pRaw, dataPos, &pStb->maxdelay[0], _OVER)
SDB_GET_INT64(pRaw, dataPos, &pStb->maxdelay[1], _OVER)
@@ -177,13 +193,15 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &pStb->ttl, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->numOfColumns, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->numOfTags, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &pStb->numOfFuncs, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->commentLen, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->ast1Len, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pStb->ast2Len, _OVER)
pStb->pColumns = taosMemoryCalloc(pStb->numOfColumns, sizeof(SSchema));
pStb->pTags = taosMemoryCalloc(pStb->numOfTags, sizeof(SSchema));
- if (pStb->pColumns == NULL || pStb->pTags == NULL) {
+ pStb->pFuncs = taosArrayInit(pStb->numOfFuncs, TSDB_FUNC_NAME_LEN);
+ if (pStb->pColumns == NULL || pStb->pTags == NULL || pStb->pFuncs == NULL) {
goto _OVER;
}
@@ -205,16 +223,24 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
SDB_GET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER)
}
+ for (int32_t i = 0; i < pStb->numOfFuncs; ++i) {
+ char funcName[TSDB_FUNC_NAME_LEN] = {0};
+ SDB_GET_BINARY(pRaw, dataPos, funcName, TSDB_FUNC_NAME_LEN, _OVER)
+ taosArrayPush(pStb->pFuncs, funcName);
+ }
+
if (pStb->commentLen > 0) {
pStb->comment = taosMemoryCalloc(pStb->commentLen + 1, 1);
if (pStb->comment == NULL) goto _OVER;
SDB_GET_BINARY(pRaw, dataPos, pStb->comment, pStb->commentLen + 1, _OVER)
}
+
if (pStb->ast1Len > 0) {
pStb->pAst1 = taosMemoryCalloc(pStb->ast1Len, 1);
if (pStb->pAst1 == NULL) goto _OVER;
SDB_GET_BINARY(pRaw, dataPos, pStb->pAst1, pStb->ast1Len, _OVER)
}
+
if (pStb->ast2Len > 0) {
pStb->pAst2 = taosMemoryCalloc(pStb->ast2Len, 1);
if (pStb->pAst2 == NULL) goto _OVER;
@@ -245,6 +271,7 @@ static int32_t mndStbActionInsert(SSdb *pSdb, SStbObj *pStb) {
static int32_t mndStbActionDelete(SSdb *pSdb, SStbObj *pStb) {
mTrace("stb:%s, perform delete action, row:%p", pStb->name, pStb);
+ taosArrayDestroy(pStb->pFuncs);
taosMemoryFreeClear(pStb->pColumns);
taosMemoryFreeClear(pStb->pTags);
taosMemoryFreeClear(pStb->comment);
@@ -296,7 +323,7 @@ static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew) {
pOld->commentLen = pNew->commentLen;
if (pOld->ast1Len < pNew->ast1Len) {
- void *pAst1 = taosMemoryMalloc(pNew->ast1Len);
+ void *pAst1 = taosMemoryMalloc(pNew->ast1Len + 1);
if (pAst1 != NULL) {
taosMemoryFree(pOld->pAst1);
pOld->pAst1 = pAst1;
@@ -308,7 +335,7 @@ static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew) {
}
if (pOld->ast2Len < pNew->ast2Len) {
- void *pAst2 = taosMemoryMalloc(pNew->ast2Len);
+ void *pAst2 = taosMemoryMalloc(pNew->ast2Len + 1);
if (pAst2 != NULL) {
taosMemoryFree(pOld->pAst2);
pOld->pAst2 = pAst2;
@@ -335,12 +362,15 @@ static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew) {
}
if (pNew->commentLen > 0) {
memcpy(pOld->comment, pNew->comment, pNew->commentLen + 1);
+ pOld->commentLen = pNew->commentLen;
}
if (pNew->ast1Len != 0) {
memcpy(pOld->pAst1, pNew->pAst1, pNew->ast1Len);
+ pOld->ast1Len = pNew->ast1Len;
}
if (pNew->ast2Len != 0) {
memcpy(pOld->pAst2, pNew->pAst2, pNew->ast2Len);
+ pOld->ast2Len = pNew->ast2Len;
}
taosWUnLockLatch(&pOld->lock);
return 0;
@@ -379,7 +409,7 @@ 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) {
+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};
@@ -392,6 +422,8 @@ static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pSt
req.name = (char *)tNameGetTableName(&name);
req.suid = pStb->uid;
req.rollup = pStb->ast1Len > 0 ? 1 : 0;
+ req.alterOriData = alterOriData;
+ req.alterOriDataLen = alterOriDataLen;
// todo
req.schemaRow.nCols = pStb->numOfColumns;
req.schemaRow.version = pStb->colVer;
@@ -401,17 +433,17 @@ static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pSt
req.schemaTag.pSchema = pStb->pTags;
if (req.rollup) {
- req.pRSmaParam.maxdelay[0] = pStb->maxdelay[0];
- req.pRSmaParam.maxdelay[1] = pStb->maxdelay[1];
+ req.rsmaParam.maxdelay[0] = pStb->maxdelay[0];
+ req.rsmaParam.maxdelay[1] = pStb->maxdelay[1];
if (pStb->ast1Len > 0) {
- if (mndConvertRsmaTask(&req.pRSmaParam.qmsg[0], &req.pRSmaParam.qmsgLen[0], pStb->pAst1, pStb->uid,
- STREAM_TRIGGER_WINDOW_CLOSE, req.pRSmaParam.watermark[0]) < 0) {
+ if (mndConvertRsmaTask(&req.rsmaParam.qmsg[0], &req.rsmaParam.qmsgLen[0], pStb->pAst1, pStb->uid,
+ STREAM_TRIGGER_WINDOW_CLOSE, req.rsmaParam.watermark[0]) < 0) {
goto _err;
}
}
if (pStb->ast2Len > 0) {
- if (mndConvertRsmaTask(&req.pRSmaParam.qmsg[1], &req.pRSmaParam.qmsgLen[1], pStb->pAst2, pStb->uid,
- STREAM_TRIGGER_WINDOW_CLOSE, req.pRSmaParam.watermark[1]) < 0) {
+ if (mndConvertRsmaTask(&req.rsmaParam.qmsg[1], &req.rsmaParam.qmsgLen[1], pStb->pAst2, pStb->uid,
+ STREAM_TRIGGER_WINDOW_CLOSE, req.rsmaParam.watermark[1]) < 0) {
goto _err;
}
}
@@ -444,12 +476,12 @@ static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pSt
tEncoderClear(&encoder);
*pContLen = contLen;
- taosMemoryFreeClear(req.pRSmaParam.qmsg[0]);
- taosMemoryFreeClear(req.pRSmaParam.qmsg[1]);
+ taosMemoryFreeClear(req.rsmaParam.qmsg[0]);
+ taosMemoryFreeClear(req.rsmaParam.qmsg[1]);
return pHead;
_err:
- taosMemoryFreeClear(req.pRSmaParam.qmsg[0]);
- taosMemoryFreeClear(req.pRSmaParam.qmsg[1]);
+ taosMemoryFreeClear(req.rsmaParam.qmsg[0]);
+ taosMemoryFreeClear(req.rsmaParam.qmsg[1]);
return NULL;
}
@@ -549,7 +581,10 @@ int32_t mndCheckCreateStbReq(SMCreateStbReq *pCreate) {
static int32_t mndSetCreateStbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
SSdbRaw *pRedoRaw = mndStbActionEncode(pStb);
if (pRedoRaw == NULL) return -1;
- if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) return -1;
+ if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
+ sdbFreeRaw(pRedoRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING) != 0) return -1;
return 0;
@@ -558,7 +593,10 @@ static int32_t mndSetCreateStbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *p
static int32_t mndSetCreateStbUndoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
SSdbRaw *pUndoRaw = mndStbActionEncode(pStb);
if (pUndoRaw == NULL) return -1;
- if (mndTransAppendUndolog(pTrans, pUndoRaw) != 0) return -1;
+ if (mndTransAppendUndolog(pTrans, pUndoRaw) != 0) {
+ sdbFreeRaw(pUndoRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED) != 0) return -1;
return 0;
@@ -567,7 +605,10 @@ static int32_t mndSetCreateStbUndoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *p
static int32_t mndSetCreateStbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
SSdbRaw *pCommitRaw = mndStbActionEncode(pStb);
if (pCommitRaw == NULL) return -1;
- if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1;
+ if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
+ sdbFreeRaw(pCommitRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1;
return 0;
@@ -582,12 +623,12 @@ static int32_t mndSetCreateStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj
while (1) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
+ if (!mndVgroupInDb(pVgroup, pDb->uid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
- void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen);
+ void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen, NULL, 0);
if (pReq == NULL) {
sdbCancelFetch(pSdb, pIter);
sdbRelease(pSdb, pVgroup);
@@ -620,7 +661,7 @@ static int32_t mndSetCreateStbUndoActions(SMnode *pMnode, STrans *pTrans, SDbObj
while (1) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
+ if (!mndVgroupInDb(pVgroup, pDb->uid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
@@ -667,10 +708,11 @@ 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 = 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;
+ pDst->smaVer = 1;
pDst->nextColId = 1;
pDst->maxdelay[0] = pCreate->delay1;
pDst->maxdelay[1] = pCreate->delay2;
@@ -679,14 +721,18 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat
pDst->ttl = pCreate->ttl;
pDst->numOfColumns = pCreate->numOfColumns;
pDst->numOfTags = pCreate->numOfTags;
+ pDst->numOfFuncs = pCreate->numOfFuncs;
pDst->commentLen = pCreate->commentLen;
+ pDst->pFuncs = pCreate->pFuncs;
+ pCreate->pFuncs = NULL;
+
if (pDst->commentLen > 0) {
pDst->comment = taosMemoryCalloc(pDst->commentLen + 1, 1);
if (pDst->comment == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
- memcpy(pDst->comment, pCreate->comment, pDst->commentLen + 1);
+ memcpy(pDst->comment, pCreate->pComment, pDst->commentLen + 1);
}
pDst->ast1Len = pCreate->ast1Len;
@@ -741,24 +787,20 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat
static int32_t mndCreateStb(SMnode *pMnode, SRpcMsg *pReq, SMCreateStbReq *pCreate, SDbObj *pDb) {
SStbObj stbObj = {0};
-
int32_t code = -1;
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq);
if (pTrans == NULL) goto _OVER;
mDebug("trans:%d, used to create stb:%s", pTrans->id, pCreate->name);
-
if (mndBuildStbFromReq(pMnode, &stbObj, pCreate, pDb) != 0) goto _OVER;
-
if (mndAddStbToTrans(pMnode, pTrans, pDb, &stbObj) < 0) goto _OVER;
-
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
-
code = 0;
_OVER:
mndTransDrop(pTrans);
+ mndStbActionDelete(pMnode->pSdb, &stbObj);
return code;
}
@@ -772,12 +814,119 @@ int32_t mndAddStbToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *p
return 0;
}
+static int32_t mndProcessTtlTimer(SRpcMsg *pReq) {
+ SMnode *pMnode = pReq->info.node;
+ SSdb *pSdb = pMnode->pSdb;
+ SVgObj *pVgroup = NULL;
+ void *pIter = NULL;
+ SVDropTtlTableReq ttlReq = {.timestamp = taosGetTimestampSec()};
+ int32_t reqLen = tSerializeSVDropTtlTableReq(NULL, 0, &ttlReq);
+ int32_t contLen = reqLen + sizeof(SMsgHead);
+
+ while (1) {
+ pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
+ if (pIter == NULL) break;
+
+ SMsgHead *pHead = rpcMallocCont(contLen);
+ if (pHead == NULL) {
+ sdbCancelFetch(pSdb, pVgroup);
+ sdbRelease(pSdb, pVgroup);
+ continue;
+ }
+ pHead->contLen = htonl(contLen);
+ pHead->vgId = htonl(pVgroup->vgId);
+ tSerializeSVDropTtlTableReq((char *)pHead + sizeof(SMsgHead), contLen, &ttlReq);
+
+ SRpcMsg rpcMsg = {.msgType = TDMT_VND_DROP_TTL_TABLE, .pCont = pHead, .contLen = contLen};
+ SEpSet epSet = mndGetVgroupEpset(pMnode, pVgroup);
+ int32_t code = tmsgSendReq(&epSet, &rpcMsg);
+ if (code != 0) {
+ mError("vgId:%d, failed to send drop ttl table request to vnode since 0x%x", pVgroup->vgId, code);
+ } else {
+ mDebug("vgId:%d, send drop ttl table request to vnode, time:%d", pVgroup->vgId, ttlReq.timestamp);
+ }
+ sdbRelease(pSdb, pVgroup);
+ }
+
+ return 0;
+}
+
+static int32_t mndFindSuperTableTagIndex(const SStbObj *pStb, const char *tagName) {
+ for (int32_t tag = 0; tag < pStb->numOfTags; tag++) {
+ if (strcasecmp(pStb->pTags[tag].name, tagName) == 0) {
+ return tag;
+ }
+ }
+
+ return -1;
+}
+
+static int32_t mndFindSuperTableColumnIndex(const SStbObj *pStb, const char *colName) {
+ for (int32_t col = 0; col < pStb->numOfColumns; col++) {
+ if (strcasecmp(pStb->pColumns[col].name, colName) == 0) {
+ return col;
+ }
+ }
+
+ return -1;
+}
+
+static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq *createReq) {
+ taosRLockLatch(&pStb->lock);
+ memcpy(pDst, pStb, sizeof(SStbObj));
+ taosRUnLockLatch(&pStb->lock);
+
+ pDst->updateTime = taosGetTimestampMs();
+ pDst->numOfColumns = createReq->numOfColumns;
+ pDst->numOfTags = createReq->numOfTags;
+ pDst->pColumns = taosMemoryCalloc(1, pDst->numOfColumns * sizeof(SSchema));
+ pDst->pTags = taosMemoryCalloc(1, pDst->numOfTags * sizeof(SSchema));
+ if (pDst->pColumns == NULL || pDst->pTags == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ for (int32_t i = 0; i < pDst->numOfColumns; ++i) {
+ SField *pField = taosArrayGet(createReq->pColumns, i);
+ SSchema *pSchema = &pDst->pColumns[i];
+ pSchema->type = pField->type;
+ pSchema->bytes = pField->bytes;
+ pSchema->flags = pField->flags;
+ memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN);
+ int32_t cIndex = mndFindSuperTableColumnIndex(pStb, pField->name);
+ if (cIndex >= 0){
+ pSchema->colId = pStb->pColumns[cIndex].colId;
+ }else{
+ pSchema->colId = pDst->nextColId++;
+ }
+ }
+
+ for (int32_t i = 0; i < pDst->numOfTags; ++i) {
+ SField *pField = taosArrayGet(createReq->pTags, i);
+ SSchema *pSchema = &pDst->pTags[i];
+ pSchema->type = pField->type;
+ pSchema->bytes = pField->bytes;
+ memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN);
+ int32_t cIndex = mndFindSuperTableTagIndex(pStb, pField->name);
+ if (cIndex >= 0){
+ pSchema->colId = pStb->pTags[cIndex].colId;
+ }else{
+ pSchema->colId = pDst->nextColId++;
+ }
+
+ }
+ pDst->tagVer = createReq->tagVer;
+ pDst->colVer = createReq->colVer;
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
SStbObj *pStb = NULL;
SDbObj *pDb = NULL;
SMCreateStbReq createReq = {0};
+ bool isAlter = false;
if (tDeserializeSMCreateStbReq(pReq->pCont, pReq->contLen, &createReq) != 0) {
terrno = TSDB_CODE_INVALID_MSG;
@@ -793,15 +942,49 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
pStb = mndAcquireStb(pMnode, createReq.name);
if (pStb != NULL) {
if (createReq.igExists) {
- mDebug("stb:%s, already exist, ignore exist is set", createReq.name);
- code = 0;
- goto _OVER;
+ if (createReq.source == TD_REQ_FROM_APP) {
+ mDebug("stb:%s, already exist, ignore exist is set", createReq.name);
+ code = 0;
+ goto _OVER;
+ } else if (pStb->uid != createReq.suid) {
+ mError("stb:%s, already exist while create, input suid:%" PRId64 " not match with exist suid:%" PRId64,
+ createReq.name, createReq.suid, pStb->uid);
+ terrno = TSDB_CODE_MND_STABLE_UID_NOT_MATCH;
+ goto _OVER;
+ } else if (createReq.tagVer > 0 || createReq.colVer > 0) {
+ int32_t tagDelta = createReq.tagVer - pStb->tagVer;
+ int32_t colDelta = createReq.colVer - pStb->colVer;
+ int32_t verDelta = tagDelta + colDelta;
+ mInfo("stb:%s, already exist while create, input tagVer:%d colVer:%d, exist tagVer:%d colVer:%d",
+ createReq.name, createReq.tagVer, createReq.colVer, pStb->tagVer, pStb->colVer);
+ if (tagDelta <= 0 && colDelta <= 0) {
+ mInfo("stb:%s, schema version is not incremented and nothing needs to be done", createReq.name);
+ code = 0;
+ goto _OVER;
+ } else if ((tagDelta == 1 || colDelta == 1) && (verDelta == 1)) {
+ isAlter = true;
+ mInfo("stb:%s, schema version is only increased by 1 number, do alter operation", createReq.name);
+ } else {
+ mError("stb:%s, schema version increase more than 1 number, error is returned", createReq.name);
+ terrno = TSDB_CODE_MND_INVALID_SCHEMA_VER;
+ goto _OVER;
+ }
+ } else {
+ mError("stb:%s, already exist while create, input tagVer:%d colVer:%d is invalid", createReq.name,
+ createReq.tagVer, createReq.colVer, pStb->tagVer, pStb->colVer);
+ terrno = TSDB_CODE_MND_INVALID_SCHEMA_VER;
+ goto _OVER;
+ }
} else {
terrno = TSDB_CODE_MND_STB_ALREADY_EXIST;
goto _OVER;
}
} 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)){
+ mInfo("stb:%s, alter table does not need to be done, because table is deleted", createReq.name);
+ code = 0;
+ goto _OVER;
}
pDb = mndAcquireDbByStb(pMnode, createReq.name);
@@ -810,7 +993,7 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
goto _OVER;
}
@@ -824,7 +1007,21 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
goto _OVER;
}
- code = mndCreateStb(pMnode, pReq, &createReq, pDb);
+ if (isAlter) {
+ bool needRsp = false;
+ SStbObj pDst = {0};
+ if (mndBuildStbFromAlter(pStb, &pDst, &createReq) != 0) {
+ taosMemoryFreeClear(pDst.pTags);
+ taosMemoryFreeClear(pDst.pColumns);
+ goto _OVER;
+ }
+
+ code = mndAlterStbImp(pMnode, pReq, pDb, &pDst, needRsp, NULL, 0);
+ taosMemoryFreeClear(pDst.pTags);
+ taosMemoryFreeClear(pDst.pColumns);
+ } else {
+ code = mndCreateStb(pMnode, pReq, &createReq, pDb);
+ }
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
_OVER:
@@ -840,7 +1037,8 @@ _OVER:
}
static int32_t mndCheckAlterStbReq(SMAlterStbReq *pAlter) {
- if (pAlter->commentLen >= 0 || pAlter->ttl != 0) return 0;
+ if (pAlter->commentLen >= 0) return 0;
+ if (pAlter->ttl != 0) return 0;
if (pAlter->numOfFields < 1 || pAlter->numOfFields != (int32_t)taosArrayGetSize(pAlter->pFields)) {
terrno = TSDB_CODE_MND_INVALID_STB_OPTION;
@@ -858,26 +1056,6 @@ static int32_t mndCheckAlterStbReq(SMAlterStbReq *pAlter) {
return 0;
}
-static int32_t mndFindSuperTableTagIndex(const SStbObj *pStb, const char *tagName) {
- for (int32_t tag = 0; tag < pStb->numOfTags; tag++) {
- if (strcasecmp(pStb->pTags[tag].name, tagName) == 0) {
- return tag;
- }
- }
-
- return -1;
-}
-
-static int32_t mndFindSuperTableColumnIndex(const SStbObj *pStb, const char *colName) {
- for (int32_t col = 0; col < pStb->numOfColumns; col++) {
- if (strcasecmp(pStb->pColumns[col].name, colName) == 0) {
- return col;
- }
- }
-
- return -1;
-}
-
static int32_t mndAllocStbSchemas(const SStbObj *pOld, SStbObj *pNew) {
pNew->pTags = taosMemoryCalloc(pNew->numOfTags, sizeof(SSchema));
pNew->pColumns = taosMemoryCalloc(pNew->numOfColumns, sizeof(SSchema));
@@ -903,6 +1081,7 @@ static int32_t mndUpdateStbCommentAndTTL(const SStbObj *pOld, SStbObj *pNew, cha
memcpy(pNew->comment, pComment, commentLen + 1);
} else if (commentLen == 0) {
pNew->commentLen = 0;
+ } else {
}
if (ttl >= 0) {
@@ -1179,7 +1358,10 @@ static int32_t mndAlterStbColumnBytes(SMnode *pMnode, const SStbObj *pOld, SStbO
static int32_t mndSetAlterStbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
SSdbRaw *pRedoRaw = mndStbActionEncode(pStb);
if (pRedoRaw == NULL) return -1;
- if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) return -1;
+ if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
+ sdbFreeRaw(pRedoRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY) != 0) return -1;
return 0;
@@ -1188,13 +1370,16 @@ static int32_t mndSetAlterStbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pD
static int32_t mndSetAlterStbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
SSdbRaw *pCommitRaw = mndStbActionEncode(pStb);
if (pCommitRaw == NULL) return -1;
- if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1;
+ if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
+ sdbFreeRaw(pCommitRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1;
return 0;
}
-static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) {
+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;
@@ -1203,12 +1388,12 @@ static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj
while (1) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
+ if (!mndVgroupInDb(pVgroup, pDb->uid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
- void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen);
+ void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen, alterOriData, alterOriDataLen);
if (pReq == NULL) {
sdbCancelFetch(pSdb, pIter);
sdbRelease(pSdb, pVgroup);
@@ -1277,6 +1462,59 @@ static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbNa
return 0;
}
+static int32_t mndBuildStbCfgImp(SDbObj *pDb, SStbObj *pStb, const char *tbName, STableCfgRsp *pRsp) {
+ taosRLockLatch(&pStb->lock);
+
+ int32_t totalCols = pStb->numOfColumns + pStb->numOfTags;
+ pRsp->pSchemas = taosMemoryCalloc(totalCols, sizeof(SSchema));
+ if (pRsp->pSchemas == NULL) {
+ taosRUnLockLatch(&pStb->lock);
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ strcpy(pRsp->dbFName, pStb->db);
+ strcpy(pRsp->tbName, tbName);
+ strcpy(pRsp->stbName, tbName);
+ pRsp->numOfTags = pStb->numOfTags;
+ pRsp->numOfColumns = pStb->numOfColumns;
+ pRsp->tableType = TSDB_SUPER_TABLE;
+ pRsp->delay1 = pStb->maxdelay[0];
+ pRsp->delay2 = pStb->maxdelay[1];
+ pRsp->watermark1 = pStb->watermark[0];
+ pRsp->watermark2 = pStb->watermark[1];
+ pRsp->ttl = pStb->ttl;
+ pRsp->commentLen = pStb->commentLen;
+ if (pStb->commentLen > 0) {
+ pRsp->pComment = strdup(pStb->comment);
+ }
+
+ for (int32_t i = 0; i < pStb->numOfColumns; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i];
+ SSchema *pSrcSchema = &pStb->pColumns[i];
+ memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
+ pSchema->type = pSrcSchema->type;
+ pSchema->colId = pSrcSchema->colId;
+ pSchema->bytes = pSrcSchema->bytes;
+ }
+
+ for (int32_t i = 0; i < pStb->numOfTags; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i + pStb->numOfColumns];
+ SSchema *pSrcSchema = &pStb->pTags[i];
+ memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
+ pSchema->type = pSrcSchema->type;
+ pSchema->colId = pSrcSchema->colId;
+ pSchema->bytes = pSrcSchema->bytes;
+ }
+
+ if (pStb->numOfFuncs > 0) {
+ pRsp->pFuncs = taosArrayDup(pStb->pFuncs);
+ }
+
+ taosRUnLockLatch(&pStb->lock);
+ return 0;
+}
+
static int32_t mndBuildStbSchema(SMnode *pMnode, const char *dbFName, const char *tbName, STableMetaRsp *pRsp,
int32_t *smaVer) {
char tbFName[TSDB_TABLE_FNAME_LEN] = {0};
@@ -1305,14 +1543,37 @@ static int32_t mndBuildStbSchema(SMnode *pMnode, const char *dbFName, const char
return code;
}
-static int32_t mndBuildSMAlterStbRsp(SDbObj *pDb, const SMAlterStbReq *pAlter, SStbObj *pObj, void **pCont,
- int32_t *pLen) {
+static int32_t mndBuildStbCfg(SMnode *pMnode, const char *dbFName, const char *tbName, STableCfgRsp *pRsp) {
+ char tbFName[TSDB_TABLE_FNAME_LEN] = {0};
+ snprintf(tbFName, sizeof(tbFName), "%s.%s", dbFName, tbName);
+
+ SDbObj *pDb = mndAcquireDb(pMnode, dbFName);
+ if (pDb == NULL) {
+ terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
+ return -1;
+ }
+
+ SStbObj *pStb = mndAcquireStb(pMnode, tbFName);
+ if (pStb == NULL) {
+ mndReleaseDb(pMnode, pDb);
+ terrno = TSDB_CODE_PAR_TABLE_NOT_EXIST;
+ return -1;
+ }
+
+ int32_t code = mndBuildStbCfgImp(pDb, pStb, tbName, pRsp);
+
+ mndReleaseDb(pMnode, pDb);
+ mndReleaseStb(pMnode, pStb);
+ return code;
+}
+
+static int32_t mndBuildSMAlterStbRsp(SDbObj *pDb, SStbObj *pObj, void **pCont, int32_t *pLen) {
int32_t ret;
SEncoder ec = {0};
uint32_t contLen = 0;
SMAlterStbRsp alterRsp = {0};
SName name = {0};
- tNameFromString(&name, pAlter->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+ tNameFromString(&name, pObj->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
alterRsp.pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
if (NULL == alterRsp.pMeta) {
@@ -1345,10 +1606,36 @@ static int32_t mndBuildSMAlterStbRsp(SDbObj *pDb, const SMAlterStbReq *pAlter, S
return 0;
}
+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;
+
+ mDebug("trans:%d, used to alter stb:%s", pTrans->id, pStb->name);
+ mndTransSetDbName(pTrans, pDb->name, NULL);
+
+ if (needRsp) {
+ void *pCont = NULL;
+ int32_t contLen = 0;
+ if (mndBuildSMAlterStbRsp(pDb, pStb, &pCont, &contLen) != 0) goto _OVER;
+ mndTransSetRpcRsp(pTrans, pCont, contLen);
+ }
+
+ if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER;
+ if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER;
+ if (mndSetAlterStbRedoActions(pMnode, pTrans, pDb, pStb, alterOriData, alterOriDataLen) != 0) goto _OVER;
+ if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
+
+ code = 0;
+
+_OVER:
+ mndTransDrop(pTrans);
+ return code;
+}
+
static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *pAlter, SDbObj *pDb, SStbObj *pOld) {
bool needRsp = true;
int32_t code = -1;
- STrans *pTrans = NULL;
SField *pField0 = NULL;
SStbObj stbObj = {0};
@@ -1397,30 +1684,9 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
}
if (code != 0) goto _OVER;
-
- code = -1;
- pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq);
- if (pTrans == NULL) goto _OVER;
-
- mDebug("trans:%d, used to alter stb:%s", pTrans->id, pAlter->name);
- mndTransSetDbName(pTrans, pDb->name, NULL);
-
- if (needRsp) {
- void *pCont = NULL;
- int32_t contLen = 0;
- if (mndBuildSMAlterStbRsp(pDb, pAlter, &stbObj, &pCont, &contLen) != 0) goto _OVER;
- mndTransSetRpcRsp(pTrans, pCont, contLen);
- }
-
- if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
- if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
- if (mndSetAlterStbRedoActions(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
- if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
-
- code = 0;
+ code = mndAlterStbImp(pMnode, pReq, pDb, &stbObj, needRsp, pReq->pCont, pReq->contLen);
_OVER:
- mndTransDrop(pTrans);
taosMemoryFreeClear(stbObj.pTags);
taosMemoryFreeClear(stbObj.pColumns);
return code;
@@ -1453,15 +1719,7 @@ static int32_t mndProcessAlterStbReq(SRpcMsg *pReq) {
goto _OVER;
}
- if ((alterReq.tagVer > 0 && alterReq.colVer > 0) &&
- (alterReq.tagVer <= pStb->tagVer || alterReq.colVer <= pStb->colVer)) {
- mDebug("stb:%s, already exist, tagVer:%d colVer:%d smaller than in mnode, tagVer:%d colVer:%d, alter success",
- alterReq.name, alterReq.tagVer, alterReq.colVer, pStb->tagVer, pStb->colVer);
- code = 0;
- goto _OVER;
- }
-
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
goto _OVER;
}
@@ -1483,7 +1741,10 @@ _OVER:
static int32_t mndSetDropStbRedoLogs(SMnode *pMnode, STrans *pTrans, SStbObj *pStb) {
SSdbRaw *pRedoRaw = mndStbActionEncode(pStb);
if (pRedoRaw == NULL) return -1;
- if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) return -1;
+ if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
+ sdbFreeRaw(pRedoRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING) != 0) return -1;
return 0;
@@ -1492,7 +1753,10 @@ static int32_t mndSetDropStbRedoLogs(SMnode *pMnode, STrans *pTrans, SStbObj *pS
static int32_t mndSetDropStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStbObj *pStb) {
SSdbRaw *pCommitRaw = mndStbActionEncode(pStb);
if (pCommitRaw == NULL) return -1;
- if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1;
+ if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
+ sdbFreeRaw(pCommitRaw);
+ return -1;
+ }
if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED) != 0) return -1;
return 0;
@@ -1506,7 +1770,7 @@ static int32_t mndSetDropStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *
while (1) {
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
- if (pVgroup->dbUid != pDb->uid) {
+ if (!mndVgroupInDb(pVgroup, pDb->uid)) {
sdbRelease(pSdb, pVgroup);
continue;
}
@@ -1540,7 +1804,7 @@ static int32_t mndSetDropStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *
static int32_t mndDropStb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb) {
int32_t code = -1;
- STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq);
+ STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq);
if (pTrans == NULL) goto _OVER;
mDebug("trans:%d, used to drop stb:%s", pTrans->id, pStb->name);
@@ -1585,13 +1849,18 @@ static int32_t mndProcessDropStbReq(SRpcMsg *pReq) {
}
}
+ if (dropReq.source == TD_REQ_FROM_TAOX && pStb->uid != dropReq.suid) {
+ code = 0;
+ goto _OVER;
+ }
+
pDb = mndAcquireDbByStb(pMnode, dropReq.name);
if (pDb == NULL) {
terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
goto _OVER;
}
@@ -1664,6 +1933,62 @@ _OVER:
return code;
}
+static int32_t mndProcessTableCfgReq(SRpcMsg *pReq) {
+ SMnode *pMnode = pReq->info.node;
+ int32_t code = -1;
+ STableCfgReq cfgReq = {0};
+ STableCfgRsp cfgRsp = {0};
+
+ if (tDeserializeSTableCfgReq(pReq->pCont, pReq->contLen, &cfgReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ goto _OVER;
+ }
+
+ if (0 == strcmp(cfgReq.dbFName, TSDB_INFORMATION_SCHEMA_DB)) {
+ mDebug("information_schema table:%s.%s, start to retrieve cfg", cfgReq.dbFName, cfgReq.tbName);
+ if (mndBuildInsTableCfg(pMnode, cfgReq.dbFName, cfgReq.tbName, &cfgRsp) != 0) {
+ goto _OVER;
+ }
+ } else if (0 == strcmp(cfgReq.dbFName, TSDB_PERFORMANCE_SCHEMA_DB)) {
+ mDebug("performance_schema table:%s.%s, start to retrieve cfg", cfgReq.dbFName, cfgReq.tbName);
+ if (mndBuildPerfsTableCfg(pMnode, cfgReq.dbFName, cfgReq.tbName, &cfgRsp) != 0) {
+ goto _OVER;
+ }
+ } else {
+ mDebug("stb:%s.%s, start to retrieve cfg", cfgReq.dbFName, cfgReq.tbName);
+ if (mndBuildStbCfg(pMnode, cfgReq.dbFName, cfgReq.tbName, &cfgRsp) != 0) {
+ goto _OVER;
+ }
+ }
+
+ int32_t rspLen = tSerializeSTableCfgRsp(NULL, 0, &cfgRsp);
+ if (rspLen < 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ goto _OVER;
+ }
+
+ void *pRsp = rpcMallocCont(rspLen);
+ if (pRsp == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+
+ tSerializeSTableCfgRsp(pRsp, rspLen, &cfgRsp);
+ pReq->info.rsp = pRsp;
+ pReq->info.rspLen = rspLen;
+ code = 0;
+
+ mTrace("%s.%s, cfg is retrieved", cfgReq.dbFName, cfgReq.tbName);
+
+_OVER:
+ if (code != 0) {
+ mError("stb:%s.%s, failed to retrieve cfg since %s", cfgReq.dbFName, cfgReq.tbName, terrstr());
+ }
+
+ tFreeSTableCfgRsp(&cfgRsp);
+ return code;
+}
+
int32_t mndValidateStbInfo(SMnode *pMnode, SSTableVersion *pStbVersions, int32_t numOfStbs, void **ppRsp,
int32_t *pRspLen) {
SSTbHbRsp hbRsp = {0};
@@ -1848,7 +2173,7 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)&pStb->updateTime, false); // number of tables
- pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
if (pStb->commentLen > 0) {
char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0};
STR_TO_VARSTR(comment, pStb->comment);
@@ -1861,6 +2186,34 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
colDataAppendNULL(pColInfo, numOfRows);
}
+ char watermark[64 + VARSTR_HEADER_SIZE] = {0};
+ sprintf(varDataVal(watermark), "%" PRId64 "a,%" PRId64 "a", pStb->watermark[0], pStb->watermark[1]);
+ varDataSetLen(watermark, strlen(varDataVal(watermark)));
+
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, numOfRows, (const char *)watermark, false);
+
+ char maxDelay[64 + VARSTR_HEADER_SIZE] = {0};
+ sprintf(varDataVal(maxDelay), "%" PRId64 "a,%" PRId64 "a", pStb->maxdelay[0], pStb->maxdelay[1]);
+ varDataSetLen(maxDelay, strlen(varDataVal(maxDelay)));
+
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, numOfRows, (const char *)maxDelay, false);
+
+ 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), funcName);
+ }
+ varDataSetLen(rollup, strlen(varDataVal(rollup)));
+
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, numOfRows, (const char *)rollup, false);
+
numOfRows++;
sdbRelease(pSdb, pStb);
}
diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c
index fb92efecf618d779d63efb613ed5c80baa8188a0..c2125f75f8f81fc2627a4755fbd1cb44277fdfd8 100644
--- a/source/dnode/mnode/impl/src/mndStream.c
+++ b/source/dnode/mnode/impl/src/mndStream.c
@@ -14,10 +14,10 @@
*/
#include "mndStream.h"
-#include "mndAuth.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
+#include "mndPrivilege.h"
#include "mndScheduler.h"
#include "mndShow.h"
#include "mndStb.h"
@@ -54,9 +54,10 @@ int32_t mndInitStream(SMnode *pMnode) {
};
mndSetMsgHandle(pMnode, TDMT_MND_CREATE_STREAM, mndProcessCreateStreamReq);
- mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DEPLOY_RSP, mndTransProcessRsp);
mndSetMsgHandle(pMnode, TDMT_MND_DROP_STREAM, mndProcessDropStreamReq);
- mndSetMsgHandle(pMnode, TDMT_MND_DROP_STREAM_RSP, mndTransProcessRsp);
+
+ mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DEPLOY_RSP, mndTransProcessRsp);
+ mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DROP_RSP, mndTransProcessRsp);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStream);
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndCancelGetNextStream);
@@ -246,8 +247,7 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj,
pObj->uid = mndGenerateUid(pObj->name, strlen(pObj->name));
pObj->status = 0;
- // TODO
- pObj->dropPolicy = 0;
+ pObj->igExpired = pCreate->igExpired;
pObj->trigger = pCreate->triggerType;
pObj->triggerParam = pCreate->maxDelay;
pObj->watermark = pCreate->watermark;
@@ -300,6 +300,7 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj,
.streamQuery = true,
.triggerType = pObj->trigger == STREAM_TRIGGER_MAX_DELAY ? STREAM_TRIGGER_WINDOW_CLOSE : pObj->trigger,
.watermark = pObj->watermark,
+ .igExpired = pObj->igExpired,
};
// using ast and param to build physical plan
@@ -319,70 +320,76 @@ FAIL:
return 0;
}
-int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
- SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
- if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
- mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
- mndTransDrop(pTrans);
+int32_t mndPersistTaskDeployReq(STrans *pTrans, const SStreamTask *pTask) {
+ ASSERT(pTask->isDataScan == 0 || pTask->isDataScan == 1);
+ if (pTask->isDataScan == 0 && pTask->sinkType == TASK_SINK__NONE) {
+ ASSERT(taosArrayGetSize(pTask->childEpInfo) != 0);
+ }
+ SEncoder encoder;
+ tEncoderInit(&encoder, NULL, 0);
+ tEncodeSStreamTask(&encoder, pTask);
+ int32_t size = encoder.pos;
+ int32_t tlen = sizeof(SMsgHead) + size;
+ tEncoderClear(&encoder);
+ void *buf = taosMemoryCalloc(1, tlen);
+ if (buf == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
- sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
- return 0;
-}
+ ((SMsgHead *)buf)->vgId = htonl(pTask->nodeId);
+ void *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
+ tEncoderInit(&encoder, abuf, size);
+ tEncodeSStreamTask(&encoder, pTask);
+ tEncoderClear(&encoder);
-int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
- SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
- if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
- mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
- mndTransDrop(pTrans);
+ STransAction action = {0};
+ memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
+ action.pCont = buf;
+ action.contLen = tlen;
+ action.msgType = TDMT_STREAM_TASK_DEPLOY;
+ if (mndTransAppendRedoAction(pTrans, &action) != 0) {
+ taosMemoryFree(buf);
return -1;
}
- sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
return 0;
}
-int32_t mndAddStreamToTrans(SMnode *pMnode, SStreamObj *pStream, const char *ast, STrans *pTrans) {
- SNode *pAst = NULL;
-
- if (nodesStringToNode(ast, &pAst) < 0) {
- return -1;
- }
-
- if (qExtractResultSchema(pAst, (int32_t *)&pStream->outputSchema.nCols, &pStream->outputSchema.pSchema) != 0) {
- nodesDestroyNode(pAst);
- return -1;
- }
- // free
- nodesDestroyNode(pAst);
-
-#if 0
- printf("|");
- for (int i = 0; i < pStream->outputSchema.nCols; i++) {
- printf(" %15s |", (char *)pStream->outputSchema.pSchema[i].name);
+int32_t mndPersistStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
+ int32_t level = taosArrayGetSize(pStream->tasks);
+ for (int32_t i = 0; i < level; i++) {
+ SArray *pLevel = taosArrayGetP(pStream->tasks, i);
+ int32_t sz = taosArrayGetSize(pLevel);
+ for (int32_t j = 0; j < sz; j++) {
+ SStreamTask *pTask = taosArrayGetP(pLevel, j);
+ if (mndPersistTaskDeployReq(pTrans, pTask) < 0) {
+ return -1;
+ }
+ }
}
- printf("\n=======================================================\n");
-
-#endif
+ return 0;
+}
- if (TSDB_CODE_SUCCESS != mndStreamGetPlanString(ast, pStream->trigger, pStream->watermark, &pStream->physicalPlan)) {
- mError("topic:%s, failed to get plan since %s", pStream->name, terrstr());
+int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
+ if (mndPersistStreamTasks(pMnode, pTrans, pStream) < 0) {
return -1;
}
-
- if (mndScheduleStream(pMnode, pTrans, pStream) < 0) {
- mError("stream:%ld, schedule stream since %s", pStream->uid, terrstr());
+ SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
+ if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
+ mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
return -1;
}
- mDebug("trans:%d, used to create stream:%s", pTrans->id, pStream->name);
+ sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
+ return 0;
+}
+int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
mndTransDrop(pTrans);
return -1;
}
- sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
-
+ sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
return 0;
}
@@ -430,10 +437,6 @@ static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStre
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, user, MND_OPER_WRITE_DB, pDb) != 0) {
- goto _OVER;
- }
-
int32_t numOfStbs = -1;
if (mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs) != 0) {
goto _OVER;
@@ -477,7 +480,7 @@ static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) {
memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
action.pCont = pReq;
action.contLen = sizeof(SVDropStreamTaskReq);
- action.msgType = TDMT_VND_STREAM_TASK_DROP;
+ action.msgType = TDMT_STREAM_TASK_DROP;
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
taosMemoryFree(pReq);
return -1;
@@ -487,7 +490,7 @@ static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) {
return 0;
}
-static int32_t mndDropStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
+int32_t mndDropStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
int32_t lv = taosArrayGetSize(pStream->tasks);
for (int32_t i = 0; i < lv; i++) {
SArray *pTasks = taosArrayGetP(pStream->tasks, i);
@@ -502,64 +505,6 @@ static int32_t mndDropStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pS
return 0;
}
-static int32_t mndCreateStream(SMnode *pMnode, SRpcMsg *pReq, SCMCreateStreamReq *pCreate, SDbObj *pDb) {
- mDebug("stream:%s to create", pCreate->name);
- SStreamObj streamObj = {0};
- tstrncpy(streamObj.name, pCreate->name, TSDB_STREAM_FNAME_LEN);
- tstrncpy(streamObj.sourceDb, pDb->name, TSDB_DB_FNAME_LEN);
- tstrncpy(streamObj.targetSTbName, pCreate->targetStbFullName, TSDB_TABLE_FNAME_LEN);
- streamObj.createTime = taosGetTimestampMs();
- streamObj.updateTime = streamObj.createTime;
- streamObj.uid = mndGenerateUid(pCreate->name, strlen(pCreate->name));
- streamObj.targetStbUid = mndGenerateUid(pCreate->targetStbFullName, TSDB_TABLE_FNAME_LEN);
- streamObj.sourceDbUid = pDb->uid;
- streamObj.version = 1;
- streamObj.sql = pCreate->sql;
- // TODO
- streamObj.fixedSinkVgId = 0;
- streamObj.smaId = 0;
- streamObj.trigger = pCreate->triggerType;
- streamObj.watermark = pCreate->watermark;
- streamObj.triggerParam = pCreate->maxDelay;
-
- if (streamObj.targetSTbName[0]) {
- pDb = mndAcquireDbByStb(pMnode, streamObj.targetSTbName);
- if (pDb == NULL) {
- terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
- return -1;
- }
- tstrncpy(streamObj.targetDb, pDb->name, TSDB_DB_FNAME_LEN);
- }
-
- STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq);
- if (pTrans == NULL) {
- mError("stream:%s, failed to create since %s", pCreate->name, terrstr());
- return -1;
- }
- mDebug("trans:%d, used to create stream:%s", pTrans->id, pCreate->name);
-
- if (mndAddStreamToTrans(pMnode, &streamObj, pCreate->ast, pTrans) != 0) {
- mError("trans:%d, failed to add stream since %s", pTrans->id, terrstr());
- mndTransDrop(pTrans);
- return -1;
- }
-
- if (streamObj.targetSTbName[0] && mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->info.conn.user) < 0) {
- mError("trans:%d, failed to create stb for stream since %s", pTrans->id, terrstr());
- mndTransDrop(pTrans);
- return -1;
- }
-
- if (mndTransPrepare(pMnode, pTrans) != 0) {
- mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
- mndTransDrop(pTrans);
- return -1;
- }
-
- mndTransDrop(pTrans);
- return 0;
-}
-
static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
@@ -593,19 +538,6 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
goto _OVER;
}
- // TODO check read auth for source and write auth for target
-#if 0
- pDb = mndAcquireDb(pMnode, createStreamReq.sourceDB);
- if (pDb == NULL) {
- terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
- goto _OVER;
- }
-
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
- goto _OVER;
- }
-#endif
-
// build stream obj from request
SStreamObj streamObj = {0};
if (mndBuildStreamObjFromCreateReq(pMnode, &streamObj, &createStreamReq) < 0) {
@@ -630,7 +562,7 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
}
// schedule stream task for stream obj
- if (mndScheduleStream(pMnode, pTrans, &streamObj) < 0) {
+ if (mndScheduleStream(pMnode, &streamObj) < 0) {
mError("stream:%s, failed to schedule since %s", createStreamReq.name, terrstr());
mndTransDrop(pTrans);
goto _OVER;
@@ -643,6 +575,16 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
goto _OVER;
}
+ if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_READ_DB, streamObj.sourceDb) != 0) {
+ mndTransDrop(pTrans);
+ goto _OVER;
+ }
+
+ if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, streamObj.targetDb) != 0) {
+ mndTransDrop(pTrans);
+ goto _OVER;
+ }
+
// execute creation
if (mndTransPrepare(pMnode, pTrans) != 0) {
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
@@ -652,8 +594,6 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
mndTransDrop(pTrans);
- /*code = mndCreateStream(pMnode, pReq, &createStreamReq, pDb);*/
- /*if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;*/
code = TSDB_CODE_ACTION_IN_PROGRESS;
_OVER:
@@ -670,45 +610,47 @@ _OVER:
static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
- int32_t code = -1;
SStreamObj *pStream = NULL;
/*SDbObj *pDb = NULL;*/
/*SUserObj *pUser = NULL;*/
- SMDropStreamReq dropReq = *(SMDropStreamReq *)pReq->pCont;
+ SMDropStreamReq dropReq = {0};
+ if (tDeserializeSMDropStreamReq(pReq->pCont, pReq->contLen, &dropReq) < 0) {
+ ASSERT(0);
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
pStream = mndAcquireStream(pMnode, dropReq.name);
if (pStream == NULL) {
if (dropReq.igNotExists) {
mDebug("stream:%s, not exist, ignore not exist is set", dropReq.name);
- code = 0;
- goto DROP_STREAM_OVER;
+ sdbRelease(pMnode->pSdb, pStream);
+ return 0;
} else {
terrno = TSDB_CODE_MND_STREAM_NOT_EXIST;
return -1;
}
}
-#if 0
- // todo check auth
- pUser = mndAcquireUser(pMnode, pReq->info.conn.user);
- if (pUser == NULL) {
- goto DROP_STREAM_OVER;
+ if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
+ return -1;
}
-#endif
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq);
if (pTrans == NULL) {
mError("stream:%s, failed to drop since %s", dropReq.name, terrstr());
- return code;
+ sdbRelease(pMnode->pSdb, pStream);
+ return -1;
}
mDebug("trans:%d, used to drop stream:%s", pTrans->id, dropReq.name);
// drop all tasks
if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
mError("stream:%s, failed to drop task since %s", dropReq.name, terrstr());
- return code;
+ sdbRelease(pMnode->pSdb, pStream);
+ return -1;
}
// drop stream
@@ -717,33 +659,43 @@ static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) {
return -1;
}
-DROP_STREAM_OVER:
- return code;
+ if (mndTransPrepare(pMnode, pTrans) != 0) {
+ mError("trans:%d, failed to prepare drop stream trans since %s", pTrans->id, terrstr());
+ sdbRelease(pMnode->pSdb, pStream);
+ mndTransDrop(pTrans);
+ return -1;
+ }
+
+ sdbRelease(pMnode->pSdb, pStream);
+
+ return TSDB_CODE_ACTION_IN_PROGRESS;
}
int32_t mndDropStreamByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb) {
SSdb *pSdb = pMnode->pSdb;
+ void *pIter = NULL;
- void *pIter = NULL;
- SStreamObj *pStream = NULL;
while (1) {
+ SStreamObj *pStream = NULL;
pIter = sdbFetch(pSdb, SDB_STREAM, pIter, (void **)&pStream);
if (pIter == NULL) break;
if (pStream->sourceDbUid == pDb->uid || pStream->targetDbUid == pDb->uid) {
if (pStream->sourceDbUid != pStream->targetDbUid) {
sdbRelease(pSdb, pStream);
+ sdbCancelFetch(pSdb, pIter);
+ mError("db:%s, failed to drop stream:%s since sourceDbUid:%" PRId64 " not match with targetDbUid:%" PRId64,
+ pDb->name, pStream->name, pStream->sourceDbUid, pStream->targetDbUid);
+ terrno = TSDB_CODE_MND_STREAM_ALREADY_EXIST;
return -1;
} else {
// TODO drop all task on snode
if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
sdbRelease(pSdb, pStream);
+ sdbCancelFetch(pSdb, pIter);
return -1;
}
}
- } else {
- sdbRelease(pSdb, pStream);
- continue;
}
#if 0
diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c
index d2b7a61e83ab5faa8ef412d1e4c9b638facfcf36..d67e4e8783f107a2dc2333e32151380456f22b81 100644
--- a/source/dnode/mnode/impl/src/mndSubscribe.c
+++ b/source/dnode/mnode/impl/src/mndSubscribe.c
@@ -96,6 +96,7 @@ static SMqSubscribeObj *mndCreateSub(SMnode *pMnode, const SMqTopicObj *pTopic,
pSub->dbUid = pTopic->dbUid;
pSub->stbUid = pTopic->stbUid;
pSub->subType = pTopic->subType;
+ pSub->withMeta = pTopic->withMeta;
ASSERT(pSub->unassignedVgs->size == 0);
ASSERT(taosHashGetSize(pSub->consumerHash) == 0);
@@ -120,6 +121,7 @@ static int32_t mndBuildSubChangeReq(void **pBuf, int32_t *pLen, const SMqSubscri
req.vgId = pRebVg->pVgEp->vgId;
req.qmsg = pRebVg->pVgEp->qmsg;
req.subType = pSub->subType;
+ req.withMeta = pSub->withMeta;
req.suid = pSub->stbUid;
strncpy(req.subKey, pSub->key, TSDB_SUBSCRIBE_KEY_LEN);
@@ -233,7 +235,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
.pVgEp = pVgEp,
};
taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg));
- mInfo("mq rebalance: remove vg %d from consumer %ld", pVgEp->vgId, consumerId);
+ mInfo("mq rebalance: remove vgId:%d from consumer:%" PRId64, pVgEp->vgId, consumerId);
}
taosHashRemove(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t));
// put into removed
@@ -253,7 +255,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
.pVgEp = pVgEp,
};
taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &rebOutput, sizeof(SMqRebOutputVg));
- mInfo("mq rebalance: remove vg %d from unassigned", pVgEp->vgId);
+ mInfo("mq rebalance: remove vgId:%d from unassigned", pVgEp->vgId);
}
}
@@ -296,7 +298,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
.pVgEp = pVgEp,
};
taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg));
- mInfo("mq rebalance: remove vg %d from consumer %ld (first scan)", pVgEp->vgId, pConsumerEp->consumerId);
+ mInfo("mq rebalance: remove vgId:%d from consumer:%" PRId64 ",(first scan)", pVgEp->vgId, pConsumerEp->consumerId);
}
imbCnt++;
}
@@ -310,7 +312,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
.pVgEp = pVgEp,
};
taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg));
- mInfo("mq rebalance: remove vg %d from consumer %ld (first scan)", pVgEp->vgId, pConsumerEp->consumerId);
+ mInfo("mq rebalance: remove vgId:%d from consumer:%" PRId64 ",(first scan)", pVgEp->vgId, pConsumerEp->consumerId);
}
}
}
@@ -327,7 +329,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
newConsumerEp.vgs = taosArrayInit(0, sizeof(void *));
taosHashPut(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t), &newConsumerEp, sizeof(SMqConsumerEp));
taosArrayPush(pOutput->newConsumers, &consumerId);
- mInfo("mq rebalance: add new consumer %ld", consumerId);
+ mInfo("mq rebalance: add new consumer:%" PRId64, consumerId);
}
}
@@ -352,7 +354,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp);
pRebVg->newConsumerId = pConsumerEp->consumerId;
taosArrayPush(pOutput->rebVgs, pRebVg);
- mInfo("mq rebalance: add vg %d to consumer %ld (second scan)", pRebVg->pVgEp->vgId, pConsumerEp->consumerId);
+ mInfo("mq rebalance: add vgId:%d to consumer:%" PRId64 ",(second scan)", pRebVg->pVgEp->vgId, pConsumerEp->consumerId);
}
}
@@ -370,7 +372,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp);
pRebVg->newConsumerId = pConsumerEp->consumerId;
taosArrayPush(pOutput->rebVgs, pRebVg);
- mInfo("mq rebalance: add vg %d to consumer %ld (second scan)", pRebVg->pVgEp->vgId, pConsumerEp->consumerId);
+ mInfo("mq rebalance: add vgId:%d to consumer:%" PRId64 ",(second scan)", pRebVg->pVgEp->vgId, pConsumerEp->consumerId);
}
} else {
// if all consumer is removed, put all vg into unassigned
@@ -383,7 +385,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
ASSERT(pRebOutput->newConsumerId == -1);
taosArrayPush(pOutput->pSub->unassignedVgs, &pRebOutput->pVgEp);
taosArrayPush(pOutput->rebVgs, pRebOutput);
- mInfo("mq rebalance: unassign vg %d (second scan)", pRebOutput->pVgEp->vgId);
+ mInfo("mq rebalance: unassign vgId:%d (second scan)", pRebOutput->pVgEp->vgId);
}
}
@@ -391,7 +393,7 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
mInfo("rebalance calculation completed, rebalanced vg:");
for (int32_t i = 0; i < taosArrayGetSize(pOutput->rebVgs); i++) {
SMqRebOutputVg *pOutputRebVg = taosArrayGet(pOutput->rebVgs, i);
- mInfo("vgId:%d, moved from consumer %" PRId64 " to consumer %" PRId64, pOutputRebVg->pVgEp->vgId,
+ mInfo("vgId:%d, moved from consumer:%" PRId64 ", to consumer:%" PRId64, pOutputRebVg->pVgEp->vgId,
pOutputRebVg->oldConsumerId, pOutputRebVg->newConsumerId);
}
@@ -544,7 +546,11 @@ static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg) {
char cgroup[TSDB_CGROUP_LEN];
mndSplitSubscribeKey(pRebInfo->key, topic, cgroup, true);
SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic);
- ASSERT(pTopic);
+ /*ASSERT(pTopic);*/
+ if (pTopic == NULL) {
+ mError("rebalance %s failed since topic %s was dropped, abort", pRebInfo->key, topic);
+ continue;
+ }
taosRLockLatch(&pTopic->lock);
rebOutput.pSub = mndCreateSub(pMnode, pTopic, pRebInfo->key);
diff --git a/source/dnode/mnode/impl/src/mndSync.c b/source/dnode/mnode/impl/src/mndSync.c
index 8666739dab0d4e45cdcb0f5eabe2d4f3804dd4f3..3c3864b620861c36836df917c361f3f979d26077 100644
--- a/source/dnode/mnode/impl/src/mndSync.c
+++ b/source/dnode/mnode/impl/src/mndSync.c
@@ -56,26 +56,28 @@ void mndSyncCommitMsg(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SFsmCbMeta cbM
sdbSetApplyInfo(pMnode->pSdb, cbMeta.index, cbMeta.term, cbMeta.lastConfigIndex);
}
- if (pMgmt->transId == transId) {
+ if (pMgmt->transId == transId && transId != 0) {
if (pMgmt->errCode != 0) {
mError("trans:%d, failed to propose since %s", transId, tstrerror(pMgmt->errCode));
}
pMgmt->transId = 0;
tsem_post(&pMgmt->syncSem);
} else {
+#if 1
+ mError("trans:%d, invalid commit msg since trandId not match with %d", transId, pMgmt->transId);
+#else
STrans *pTrans = mndAcquireTrans(pMnode, transId);
if (pTrans != NULL) {
mndTransExecute(pMnode, pTrans);
mndReleaseTrans(pMnode, pTrans);
}
-#if 0
- sdbWriteFile(pMnode->pSdb, SDB_WRITE_DELTA);
+ // sdbWriteFile(pMnode->pSdb, SDB_WRITE_DELTA);
#endif
}
}
int32_t mndSyncGetSnapshot(struct SSyncFSM *pFsm, SSnapshot *pSnapshot, void *pReaderParam, void **ppReader) {
- mInfo("start to read snapshot from sdb in atomic way");
+ mDebug("start to read snapshot from sdb in atomic way");
SMnode *pMnode = pFsm->data;
return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, &pSnapshot->lastApplyIndex, &pSnapshot->lastApplyTerm,
&pSnapshot->lastConfigIndex);
@@ -96,7 +98,7 @@ void mndRestoreFinish(struct SSyncFSM *pFsm) {
mndTransPullup(pMnode);
mndSetRestore(pMnode, true);
} else {
- mInfo("mnode sync restore finished, and will set ready after first deploy");
+ mInfo("mnode sync restore finished");
}
}
@@ -117,14 +119,14 @@ void mndReConfig(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SReConfigCbMeta cbM
}
}
-int32_t mndSnapshotStartRead(struct SSyncFSM *pFsm, void **ppReader) {
- mInfo("start to read snapshot from sdb");
+int32_t mndSnapshotStartRead(struct SSyncFSM *pFsm, void *pParam, void **ppReader) {
+ mDebug("start to read snapshot from sdb");
SMnode *pMnode = pFsm->data;
return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, NULL, NULL, NULL);
}
int32_t mndSnapshotStopRead(struct SSyncFSM *pFsm, void *pReader) {
- mInfo("stop to read snapshot from sdb");
+ mDebug("stop to read snapshot from sdb");
SMnode *pMnode = pFsm->data;
return sdbStopRead(pMnode->pSdb, pReader);
}
@@ -134,7 +136,7 @@ int32_t mndSnapshotDoRead(struct SSyncFSM *pFsm, void *pReader, void **ppBuf, in
return sdbDoRead(pMnode->pSdb, pReader, ppBuf, len);
}
-int32_t mndSnapshotStartWrite(struct SSyncFSM *pFsm, void **ppWriter) {
+int32_t mndSnapshotStartWrite(struct SSyncFSM *pFsm, void *pParam, void **ppWriter) {
mInfo("start to apply snapshot to sdb");
SMnode *pMnode = pFsm->data;
return sdbStartWrite(pMnode->pSdb, (SSdbIter **)ppWriter);
@@ -178,7 +180,7 @@ int32_t mndInitSync(SMnode *pMnode) {
syncInfo.pWal = pMnode->pWal;
syncInfo.pFsm = mndSyncMakeFsm(pMnode);
syncInfo.isStandBy = pMgmt->standby;
- syncInfo.snapshotEnable = true;
+ syncInfo.snapshotStrategy = SYNC_STRATEGY_STANDARD_SNAPSHOT;
mInfo("start to open mnode sync, standby:%d", pMgmt->standby);
if (pMgmt->standby || pMgmt->replica.id > 0) {
@@ -188,7 +190,7 @@ int32_t mndInitSync(SMnode *pMnode) {
SNodeInfo *pNode = &pCfg->nodeInfo[0];
tstrncpy(pNode->nodeFqdn, pMgmt->replica.fqdn, sizeof(pNode->nodeFqdn));
pNode->nodePort = pMgmt->replica.port;
- mInfo("fqdn:%s port:%u", pNode->nodeFqdn, pNode->nodePort);
+ mInfo("mnode ep:%s:%u", pNode->nodeFqdn, pNode->nodePort);
}
tsem_init(&pMgmt->syncSem, 0, 0);
@@ -198,6 +200,11 @@ int32_t mndInitSync(SMnode *pMnode) {
return -1;
}
+ // decrease election timer
+ setPingTimerMS(pMgmt->sync, 5000);
+ setElectTimerMS(pMgmt->sync, 600);
+ setHeartbeatTimerMS(pMgmt->sync, 300);
+
mDebug("mnode-sync is opened, id:%" PRId64, pMgmt->sync);
return 0;
}
@@ -261,7 +268,8 @@ bool mndIsMaster(SMnode *pMnode) {
SSyncMgmt *pMgmt = &pMnode->syncMgmt;
if (!syncIsReady(pMgmt->sync)) {
- terrno = TSDB_CODE_SYN_NOT_LEADER;
+ // get terrno from syncIsReady
+ // terrno = TSDB_CODE_SYN_NOT_LEADER;
return false;
}
diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c
index 9632c04f4c4166d62ffaad64b8af572e3983aeec..f2a037ab82a9fa2db4674a3a0f1ef852562ac960 100644
--- a/source/dnode/mnode/impl/src/mndTopic.c
+++ b/source/dnode/mnode/impl/src/mndTopic.c
@@ -14,12 +14,12 @@
*/
#include "mndTopic.h"
-#include "mndAuth.h"
#include "mndConsumer.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
#include "mndOffset.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndStb.h"
#include "mndSubscribe.h"
@@ -141,6 +141,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
SDB_SET_INT64(pRaw, dataPos, pTopic->dbUid, TOPIC_ENCODE_OVER);
SDB_SET_INT32(pRaw, dataPos, pTopic->version, TOPIC_ENCODE_OVER);
SDB_SET_INT8(pRaw, dataPos, pTopic->subType, TOPIC_ENCODE_OVER);
+ SDB_SET_INT8(pRaw, dataPos, pTopic->withMeta, TOPIC_ENCODE_OVER);
SDB_SET_INT64(pRaw, dataPos, pTopic->stbUid, TOPIC_ENCODE_OVER);
SDB_SET_INT32(pRaw, dataPos, pTopic->sqlLen, TOPIC_ENCODE_OVER);
@@ -208,6 +209,7 @@ SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT64(pRaw, dataPos, &pTopic->dbUid, TOPIC_DECODE_OVER);
SDB_GET_INT32(pRaw, dataPos, &pTopic->version, TOPIC_DECODE_OVER);
SDB_GET_INT8(pRaw, dataPos, &pTopic->subType, TOPIC_DECODE_OVER);
+ SDB_GET_INT8(pRaw, dataPos, &pTopic->withMeta, TOPIC_DECODE_OVER);
SDB_GET_INT64(pRaw, dataPos, &pTopic->stbUid, TOPIC_DECODE_OVER);
SDB_GET_INT32(pRaw, dataPos, &pTopic->sqlLen, TOPIC_DECODE_OVER);
@@ -357,6 +359,10 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
topicObj.sql = strdup(pCreate->sql);
topicObj.sqlLen = strlen(pCreate->sql) + 1;
topicObj.subType = pCreate->subType;
+ topicObj.withMeta = pCreate->withMeta;
+ if (topicObj.withMeta) {
+ ASSERT(topicObj.subType != TOPIC_SUB_TYPE__COLUMN);
+ }
if (pCreate->subType == TOPIC_SUB_TYPE__COLUMN) {
topicObj.ast = strdup(pCreate->ast);
@@ -395,6 +401,10 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
}
} else if (pCreate->subType == TOPIC_SUB_TYPE__TABLE) {
SStbObj *pStb = mndAcquireStb(pMnode, pCreate->subStbName);
+ if (pStb == NULL) {
+ terrno = TSDB_CODE_MND_STB_NOT_EXIST;
+ return -1;
+ }
topicObj.stbUid = pStb->uid;
}
/*} else if (pCreate->subType == TOPIC_SUB_TYPE__DB) {*/
@@ -474,7 +484,7 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckDbAuth(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) {
+ if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_READ_DB, pDb) != 0) {
goto _OVER;
}
@@ -548,7 +558,7 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) {
mndReleaseConsumer(pMnode, pConsumer);
mndReleaseTopic(pMnode, pTopic);
terrno = TSDB_CODE_MND_TOPIC_SUBSCRIBED;
- mError("topic:%s, failed to drop since subscribed by consumer %ld in consumer group %s", dropReq.name,
+ mError("topic:%s, failed to drop since subscribed by consumer:%" PRId64 ", in consumer group %s", dropReq.name,
pConsumer->consumerId, pConsumer->cgroup);
return -1;
}
@@ -565,6 +575,10 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) {
}
#endif
+ if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_READ_DB, pTopic->db) != 0) {
+ return -1;
+ }
+
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq);
mndTransSetDbName(pTrans, pTopic->db, NULL);
if (pTrans == NULL) {
diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c
index de6a44d456c992defcdbae39d97b260b471e43a6..ea92b2f0e654499327bc88a29154f316cbc21725 100644
--- a/source/dnode/mnode/impl/src/mndTrans.c
+++ b/source/dnode/mnode/impl/src/mndTrans.c
@@ -15,15 +15,15 @@
#define _DEFAULT_SOURCE
#include "mndTrans.h"
-#include "mndAuth.h"
#include "mndConsumer.h"
#include "mndDb.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndSync.h"
#include "mndUser.h"
-#define TRANS_VER_NUMBER 1
-#define TRANS_ARRAY_SIZE 8
+#define TRANS_VER_NUMBER 1
+#define TRANS_ARRAY_SIZE 8
#define TRANS_RESERVE_SIZE 64
static SSdbRaw *mndTransActionEncode(STrans *pTrans);
@@ -55,7 +55,8 @@ static bool mndTransPerfromFinishedStage(SMnode *pMnode, STrans *pTrans);
static bool mndCannotExecuteTransAction(SMnode *pMnode) { return !pMnode->deploy && !mndIsMaster(pMnode); }
static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans);
-static int32_t mndProcessTransReq(SRpcMsg *pReq);
+static int32_t mndProcessTransTimer(SRpcMsg *pReq);
+static int32_t mndProcessTtl(SRpcMsg *pReq);
static int32_t mndProcessKillTransReq(SRpcMsg *pReq);
static int32_t mndRetrieveTrans(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
@@ -72,7 +73,7 @@ int32_t mndInitTrans(SMnode *pMnode) {
.deleteFp = (SdbDeleteFp)mndTransActionDelete,
};
- mndSetMsgHandle(pMnode, TDMT_MND_TRANS_TIMER, mndProcessTransReq);
+ mndSetMsgHandle(pMnode, TDMT_MND_TRANS_TIMER, mndProcessTransTimer);
mndSetMsgHandle(pMnode, TDMT_MND_KILL_TRANS, mndProcessKillTransReq);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_TRANS, mndRetrieveTrans);
@@ -89,7 +90,7 @@ static int32_t mndTransGetActionsSize(SArray *pArray) {
for (int32_t i = 0; i < actionNum; ++i) {
STransAction *pAction = taosArrayGet(pArray, i);
if (pAction->actionType == TRANS_ACTION_RAW) {
- rawDataLen += (sdbGetRawTotalSize(pAction->pRaw) + sizeof(int32_t));
+ rawDataLen += (sizeof(STransAction) + sdbGetRawTotalSize(pAction->pRaw));
} else if (pAction->actionType == TRANS_ACTION_MSG) {
rawDataLen += (sizeof(STransAction) + pAction->contLen);
} else {
@@ -104,7 +105,7 @@ static int32_t mndTransGetActionsSize(SArray *pArray) {
static SSdbRaw *mndTransActionEncode(STrans *pTrans) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
- int32_t rawDataLen = sizeof(STrans) + TRANS_RESERVE_SIZE;
+ int32_t rawDataLen = sizeof(STrans) + TRANS_RESERVE_SIZE + pTrans->paramLen;
rawDataLen += mndTransGetActionsSize(pTrans->redoActions);
rawDataLen += mndTransGetActionsSize(pTrans->undoActions);
rawDataLen += mndTransGetActionsSize(pTrans->commitActions);
@@ -138,8 +139,10 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) {
SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pAction->retryCode, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER)
+ SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER)
if (pAction->actionType == TRANS_ACTION_RAW) {
int32_t len = sdbGetRawTotalSize(pAction->pRaw);
SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER)
@@ -162,8 +165,10 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) {
SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pAction->retryCode, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER)
+ SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER)
if (pAction->actionType == TRANS_ACTION_RAW) {
int32_t len = sdbGetRawTotalSize(pAction->pRaw);
SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER)
@@ -186,8 +191,10 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) {
SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER)
SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pAction->retryCode, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER)
SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER)
+ SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER)
if (pAction->actionType == TRANS_ACTION_RAW) {
int32_t len = sdbGetRawTotalSize(pAction->pRaw);
SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER)
@@ -219,7 +226,8 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) {
_OVER:
if (terrno != 0) {
- mError("trans:%d, failed to encode to raw:%p len:%d since %s", pTrans->id, pRaw, dataPos, terrstr());
+ mError("trans:%d, failed to encode to raw:%p maxlen:%d len:%d since %s", pTrans->id, pRaw, sdbGetRawTotalSize(pRaw),
+ dataPos, terrstr());
sdbFreeRaw(pRaw);
return NULL;
}
@@ -290,10 +298,12 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &action.retryCode, _OVER)
SDB_GET_INT8(pRaw, dataPos, &actionType, _OVER)
action.actionType = actionType;
SDB_GET_INT8(pRaw, dataPos, &stage, _OVER)
action.stage = stage;
+ SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER)
if (action.actionType == TRANS_ACTION_RAW) {
SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER)
SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER)
@@ -323,10 +333,12 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &action.retryCode, _OVER)
SDB_GET_INT8(pRaw, dataPos, &actionType, _OVER)
action.actionType = actionType;
SDB_GET_INT8(pRaw, dataPos, &stage, _OVER)
action.stage = stage;
+ SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER)
if (action.actionType == TRANS_ACTION_RAW) {
SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER)
SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER)
@@ -356,10 +368,12 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER)
SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER)
+ SDB_GET_INT32(pRaw, dataPos, &action.retryCode, _OVER)
SDB_GET_INT8(pRaw, dataPos, &actionType, _OVER)
action.actionType = actionType;
SDB_GET_INT8(pRaw, dataPos, &stage, _OVER)
action.stage = stage;
+ SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER)
if (action.actionType) {
SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER)
SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER)
@@ -432,11 +446,11 @@ static const char *mndTransStr(ETrnStage stage) {
}
static void mndTransTestStartFunc(SMnode *pMnode, void *param, int32_t paramLen) {
- mInfo("test trans start, param:%s, len:%d", (char *)param, paramLen);
+ mDebug("test trans start, param:%s, len:%d", (char *)param, paramLen);
}
static void mndTransTestStopFunc(SMnode *pMnode, void *param, int32_t paramLen) {
- mInfo("test trans stop, param:%s, len:%d", (char *)param, paramLen);
+ mDebug("test trans stop, param:%s, len:%d", (char *)param, paramLen);
}
static TransCbFp mndTransGetCbFp(ETrnFunc ftype) {
@@ -462,15 +476,25 @@ static int32_t mndTransActionInsert(SSdb *pSdb, STrans *pTrans) {
if (fp) {
(*fp)(pSdb->pMnode, pTrans->param, pTrans->paramLen);
}
+ pTrans->startFunc = 0;
}
return 0;
}
static void mndTransDropData(STrans *pTrans) {
- mndTransDropActions(pTrans->redoActions);
- mndTransDropActions(pTrans->undoActions);
- mndTransDropActions(pTrans->commitActions);
+ if (pTrans->redoActions != NULL) {
+ mndTransDropActions(pTrans->redoActions);
+ pTrans->redoActions = NULL;
+ }
+ if (pTrans->undoActions != NULL) {
+ mndTransDropActions(pTrans->undoActions);
+ pTrans->undoActions = NULL;
+ }
+ if (pTrans->commitActions != NULL) {
+ mndTransDropActions(pTrans->commitActions);
+ pTrans->commitActions = NULL;
+ }
if (pTrans->rpcRsp != NULL) {
taosMemoryFree(pTrans->rpcRsp);
pTrans->rpcRsp = NULL;
@@ -491,6 +515,7 @@ static int32_t mndTransActionDelete(SSdb *pSdb, STrans *pTrans, bool callFunc) {
if (fp) {
(*fp)(pSdb->pMnode, pTrans->param, pTrans->paramLen);
}
+ pTrans->stopFunc = 0;
}
mndTransDropData(pTrans);
@@ -804,7 +829,7 @@ static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) {
sendRsp = true;
}
} else {
- if (pTrans->stage == TRN_STAGE_REDO_ACTION && pTrans->failedTimes > 3) {
+ if (pTrans->stage == TRN_STAGE_REDO_ACTION && pTrans->failedTimes > 6) {
if (code == 0) code = TSDB_CODE_MND_TRANS_UNKNOW_ERROR;
sendRsp = true;
}
@@ -874,8 +899,8 @@ int32_t mndTransProcessRsp(SRpcMsg *pRsp) {
pAction->errCode = pRsp->code;
}
- mDebug("trans:%d, %s:%d response is received, code:0x%x, accept:0x%x", transId, mndTransStr(pAction->stage), action,
- pRsp->code, pAction->acceptableCode);
+ mDebug("trans:%d, %s:%d response is received, code:0x%x, accept:0x%x retry:0x%x", transId,
+ mndTransStr(pAction->stage), action, pRsp->code, pAction->acceptableCode, pAction->retryCode);
mndTransExecute(pMnode, pTrans);
_OVER:
@@ -883,6 +908,21 @@ _OVER:
return 0;
}
+static void mndTransResetAction(SMnode *pMnode, STrans *pTrans, STransAction *pAction) {
+ pAction->rawWritten = 0;
+ pAction->msgSent = 0;
+ pAction->msgReceived = 0;
+ if (pAction->errCode == TSDB_CODE_RPC_REDIRECT || pAction->errCode == TSDB_CODE_SYN_NEW_CONFIG_ERROR ||
+ pAction->errCode == TSDB_CODE_SYN_INTERNAL_ERROR || pAction->errCode == TSDB_CODE_SYN_NOT_LEADER) {
+ pAction->epSet.inUse = (pAction->epSet.inUse + 1) % pAction->epSet.numOfEps;
+ mDebug("trans:%d, %s:%d execute status is reset and set epset inuse:%d", pTrans->id, mndTransStr(pAction->stage),
+ pAction->id, pAction->epSet.inUse);
+ } else {
+ mDebug("trans:%d, %s:%d execute status is reset", pTrans->id, mndTransStr(pAction->stage), pAction->id);
+ }
+ pAction->errCode = 0;
+}
+
static void mndTransResetActions(SMnode *pMnode, STrans *pTrans, SArray *pArray) {
int32_t numOfActions = taosArrayGetSize(pArray);
@@ -893,18 +933,7 @@ static void mndTransResetActions(SMnode *pMnode, STrans *pTrans, SArray *pArray)
continue;
if (pAction->rawWritten && (pAction->errCode == 0 || pAction->errCode == pAction->acceptableCode)) continue;
- pAction->rawWritten = 0;
- pAction->msgSent = 0;
- pAction->msgReceived = 0;
- if (pAction->errCode == TSDB_CODE_RPC_REDIRECT || pAction->errCode == TSDB_CODE_SYN_NEW_CONFIG_ERROR ||
- pAction->errCode == TSDB_CODE_SYN_INTERNAL_ERROR || pAction->errCode == TSDB_CODE_SYN_NOT_LEADER) {
- pAction->epSet.inUse = (pAction->epSet.inUse + 1) % pAction->epSet.numOfEps;
- mDebug("trans:%d, %s:%d execute status is reset and set epset inuse:%d", pTrans->id, mndTransStr(pAction->stage),
- action, pAction->epSet.inUse);
- } else {
- mDebug("trans:%d, %s:%d execute status is reset", pTrans->id, mndTransStr(pAction->stage), action);
- }
- pAction->errCode = 0;
+ mndTransResetAction(pMnode, pTrans, pAction);
}
}
@@ -997,7 +1026,7 @@ static int32_t mndTransExecNullMsg(SMnode *pMnode, STrans *pTrans, STransAction
pTrans->lastAction = pAction->id;
pTrans->lastMsgType = pAction->msgType;
pTrans->lastEpset = pAction->epSet;
- pTrans->lastErrorNo == 0;
+ pTrans->lastErrorNo = 0;
return 0;
}
@@ -1111,18 +1140,20 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans)
if (pAction->msgReceived) {
if (pAction->errCode != 0 && pAction->errCode != pAction->acceptableCode) {
code = pAction->errCode;
- pAction->msgSent = 0;
- pAction->msgReceived = 0;
- mDebug("trans:%d, %s:%d execute status is reset", pTrans->id, mndTransStr(pAction->stage), action);
+ mndTransResetAction(pMnode, pTrans, pAction);
+ } else {
+ mDebug("trans:%d, %s:%d execute successfully", pTrans->id, mndTransStr(pAction->stage), action);
}
} else {
code = TSDB_CODE_ACTION_IN_PROGRESS;
}
- }
- if (pAction->rawWritten) {
+ } else if (pAction->rawWritten) {
if (pAction->errCode != 0 && pAction->errCode != pAction->acceptableCode) {
code = pAction->errCode;
+ } else {
+ mDebug("trans:%d, %s:%d write successfully", pTrans->id, mndTransStr(pAction->stage), action);
}
+ } else {
}
}
@@ -1155,9 +1186,16 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans)
} else if (code == TSDB_CODE_ACTION_IN_PROGRESS) {
mDebug("trans:%d, %s:%d is in progress and wait it finish", pTrans->id, mndTransStr(pAction->stage), pAction->id);
break;
+ } else if (code == pAction->retryCode) {
+ mDebug("trans:%d, %s:%d receive code:0x%x and retry", pTrans->id, mndTransStr(pAction->stage), pAction->id, code);
+ taosMsleep(300);
+ action--;
+ continue;
} else {
terrno = code;
pTrans->code = code;
+ mDebug("trans:%d, %s:%d receive code:0x%x and wait another schedule, failedTimes:%d", pTrans->id,
+ mndTransStr(pAction->stage), pAction->id, code, pTrans->failedTimes);
break;
}
}
@@ -1342,7 +1380,7 @@ void mndTransExecute(SMnode *pMnode, STrans *pTrans) {
mndTransSendRpcRsp(pMnode, pTrans);
}
-static int32_t mndProcessTransReq(SRpcMsg *pReq) {
+static int32_t mndProcessTransTimer(SRpcMsg *pReq) {
mndTransPullup(pReq->info.node);
return 0;
}
@@ -1383,8 +1421,7 @@ static int32_t mndProcessKillTransReq(SRpcMsg *pReq) {
}
mInfo("trans:%d, start to kill", killReq.transId);
-
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_KILL_TRANS) != 0) {
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_KILL_TRANS) != 0) {
goto _OVER;
}
diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c
index eb0a818a604da23b995c0493b2e96281d5077e53..921dba422def05d8e4f34a946f925b32464ff4ae 100644
--- a/source/dnode/mnode/impl/src/mndUser.c
+++ b/source/dnode/mnode/impl/src/mndUser.c
@@ -15,7 +15,7 @@
#define _DEFAULT_SOURCE
#include "mndUser.h"
-#include "mndAuth.h"
+#include "mndPrivilege.h"
#include "mndDb.h"
#include "mndShow.h"
#include "mndTrans.h"
@@ -295,7 +295,7 @@ static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate
tstrncpy(userObj.acct, acct, TSDB_USER_LEN);
userObj.createdTime = taosGetTimestampMs();
userObj.updateTime = userObj.createdTime;
- userObj.superUser = pCreate->superUser;
+ userObj.superUser = 0; // pCreate->superUser;
userObj.sysInfo = pCreate->sysInfo;
userObj.enable = pCreate->enable;
@@ -337,6 +337,9 @@ static int32_t mndProcessCreateUserReq(SRpcMsg *pReq) {
}
mDebug("user:%s, start to create", createReq.user);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_USER) != 0) {
+ goto _OVER;
+ }
if (createReq.user[0] == 0) {
terrno = TSDB_CODE_MND_INVALID_USER_FORMAT;
@@ -360,10 +363,6 @@ static int32_t mndProcessCreateUserReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_CREATE_USER) != 0) {
- goto _OVER;
- }
-
code = mndCreateUser(pMnode, pOperUser->acct, &createReq, pReq);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -466,7 +465,7 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckAlterUserAuth(pOperUser, pUser, &alterReq) != 0) {
+ if (mndCheckAlterUserPrivilege(pOperUser, pUser, &alterReq) != 0) {
goto _OVER;
}
@@ -631,6 +630,9 @@ static int32_t mndProcessDropUserReq(SRpcMsg *pReq) {
}
mDebug("user:%s, start to drop", dropReq.user);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_USER) != 0) {
+ goto _OVER;
+ }
if (dropReq.user[0] == 0) {
terrno = TSDB_CODE_MND_INVALID_USER_FORMAT;
@@ -643,10 +645,6 @@ static int32_t mndProcessDropUserReq(SRpcMsg *pReq) {
goto _OVER;
}
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_DROP_USER) != 0) {
- goto _OVER;
- }
-
code = mndDropUser(pMnode, pReq, pUser);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c
index 94ddbcd409c8ef4b1ad6bf8d97bda63edb63ea92..0b24b570a5126dc0385baa5817040464b04c8af2 100644
--- a/source/dnode/mnode/impl/src/mndVgroup.c
+++ b/source/dnode/mnode/impl/src/mndVgroup.c
@@ -15,10 +15,10 @@
#define _DEFAULT_SOURCE
#include "mndVgroup.h"
-#include "mndAuth.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
+#include "mndPrivilege.h"
#include "mndShow.h"
#include "mndTrans.h"
#include "mndUser.h"
@@ -207,6 +207,7 @@ void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVg
createReq.buffer = pDb->cfg.buffer;
createReq.pageSize = pDb->cfg.pageSize;
createReq.pages = pDb->cfg.pages;
+ createReq.cacheLastSize = pDb->cfg.cacheLastSize;
createReq.daysPerFile = pDb->cfg.daysPerFile;
createReq.daysToKeep0 = pDb->cfg.daysToKeep0;
createReq.daysToKeep1 = pDb->cfg.daysToKeep1;
@@ -218,7 +219,7 @@ void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVg
createReq.precision = pDb->cfg.precision;
createReq.compression = pDb->cfg.compression;
createReq.strict = pDb->cfg.strict;
- createReq.cacheLastRow = pDb->cfg.cacheLastRow;
+ createReq.cacheLast = pDb->cfg.cacheLast;
createReq.replica = pVgroup->replica;
createReq.selfIndex = -1;
createReq.hashBegin = pVgroup->hashBegin;
@@ -274,8 +275,9 @@ void *mndBuildAlterVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_
SAlterVnodeReq alterReq = {0};
alterReq.vgVersion = pVgroup->version;
alterReq.buffer = pDb->cfg.buffer;
- alterReq.pages = pDb->cfg.pages;
alterReq.pageSize = pDb->cfg.pageSize;
+ alterReq.pages = pDb->cfg.pages;
+ alterReq.cacheLastSize = pDb->cfg.cacheLastSize;
alterReq.daysPerFile = pDb->cfg.daysPerFile;
alterReq.daysToKeep0 = pDb->cfg.daysToKeep0;
alterReq.daysToKeep1 = pDb->cfg.daysToKeep1;
@@ -283,7 +285,7 @@ void *mndBuildAlterVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_
alterReq.fsyncPeriod = pDb->cfg.fsyncPeriod;
alterReq.walLevel = pDb->cfg.walLevel;
alterReq.strict = pDb->cfg.strict;
- alterReq.cacheLastRow = pDb->cfg.cacheLastRow;
+ alterReq.cacheLast = pDb->cfg.cacheLast;
alterReq.replica = pVgroup->replica;
for (int32_t v = 0; v < pVgroup->replica; ++v) {
@@ -305,7 +307,7 @@ void *mndBuildAlterVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_
terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
- contLen += +sizeof(SMsgHead);
+ contLen += sizeof(SMsgHead);
void *pReq = taosMemoryMalloc(contLen);
if (pReq == NULL) {
@@ -392,9 +394,10 @@ static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2
bool online = mndIsDnodeOnline(pDnode, curMs);
bool isMnode = mndIsMnode(pMnode, pDnode->id);
pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
+ pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
- mDebug("dnode:%d, vnodes:%d support_vnodes:%d is_mnode:%d online:%d", pDnode->id, pDnode->numOfVnodes,
- pDnode->numOfSupportVnodes, isMnode, online);
+ mDebug("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
+ pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
if (isMnode) {
pDnode->numOfVnodes++;
@@ -439,7 +442,7 @@ void mndSortVnodeGid(SVgObj *pVgroup) {
}
}
-static int32_t mndGetAvailableDnode(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray) {
+static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
SSdb *pSdb = pMnode->pSdb;
int32_t allocedVnodes = 0;
void *pIter = NULL;
@@ -462,6 +465,16 @@ static int32_t mndGetAvailableDnode(SMnode *pMnode, SVgObj *pVgroup, SArray *pAr
return -1;
}
+ int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
+ if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
+ mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
+ terrno = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
+ return -1;
+ } else {
+ pDnode->memUsed += vgMem;
+ }
+
pVgid->dnodeId = pDnode->id;
if (pVgroup->replica == 1) {
pVgid->role = TAOS_SYNC_STATE_LEADER;
@@ -469,7 +482,8 @@ static int32_t mndGetAvailableDnode(SMnode *pMnode, SVgObj *pVgroup, SArray *pAr
pVgid->role = TAOS_SYNC_STATE_FOLLOWER;
}
- mInfo("db:%s, vgId:%d, vn:%d dnode:%d is alloced", pVgroup->dbName, pVgroup->vgId, v, pVgid->dnodeId);
+ mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
pDnode->numOfVnodes++;
}
@@ -490,7 +504,7 @@ int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
pVgroup->dbUid = pDb->uid;
pVgroup->replica = 1;
- if (mndGetAvailableDnode(pMnode, pVgroup, pArray) != 0) return -1;
+ if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
return 0;
@@ -538,8 +552,7 @@ int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups) {
pVgroup->dbUid = pDb->uid;
pVgroup->replica = pDb->cfg.replications;
- if (mndGetAvailableDnode(pMnode, pVgroup, pArray) != 0) {
- terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
+ if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) {
goto _OVER;
}
@@ -720,6 +733,46 @@ int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
return numOfVnodes;
}
+int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
+ SDbObj *pDb = pDbInput;
+ if (pDbInput == NULL) {
+ pDb = mndAcquireDb(pMnode, pVgroup->dbName);
+ }
+
+ int64_t vgroupMemroy = 0;
+ if (pDb != NULL) {
+ vgroupMemroy = (int64_t)pDb->cfg.buffer * 1024 * 1024 + (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
+ if (pDb->cfg.cacheLast > 0) {
+ vgroupMemroy += (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
+ }
+ }
+
+ if (pDbInput == NULL) {
+ mndReleaseDb(pMnode, pDb);
+ }
+ return vgroupMemroy;
+}
+
+static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
+ SVgObj *pVgroup = pObj;
+ int32_t dnodeId = *(int32_t *)p1;
+ int64_t *pVnodeMemory = (int64_t *)p2;
+
+ for (int32_t v = 0; v < pVgroup->replica; ++v) {
+ if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
+ *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ }
+ }
+
+ return true;
+}
+
+int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
+ int64_t vnodeMemory = 0;
+ sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
+ return vnodeMemory;
+}
+
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
SMnode *pMnode = pReq->info.node;
SSdb *pSdb = pMnode->pSdb;
@@ -799,9 +852,20 @@ int32_t mndAddVnodeToVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray) {
return -1;
}
+ int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
+ mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
+ terrno = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
+ return -1;
+ } else {
+ pDnode->memUsed += vgMem;
+ }
+
pVgid->dnodeId = pDnode->id;
pVgid->role = TAOS_SYNC_STATE_ERROR;
- mInfo("db:%s, vgId:%d, vn:%d dnode:%d, is added", pVgroup->dbName, pVgroup->vgId, pVgroup->replica, pVgid->dnodeId);
+ mInfo("db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
pVgroup->replica++;
pDnode->numOfVnodes++;
@@ -827,7 +891,10 @@ int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray
for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
if (pVgid->dnodeId == pDnode->id) {
- mInfo("db:%s, vgId:%d, vn:%d dnode:%d, is removed", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
+ int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ pDnode->memUsed -= vgMem;
+ mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
pDnode->numOfVnodes--;
pVgroup->replica--;
*pDelVgid = *pVgid;
@@ -896,6 +963,8 @@ int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pD
action.pCont = pHead;
action.contLen = contLen;
action.msgType = TDMT_VND_ALTER_CONFIRM;
+ // incorrect redirect result will cause this erro
+ action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
taosMemoryFree(pHead);
@@ -942,6 +1011,8 @@ static int32_t mndAddSetVnodeStandByAction(SMnode *pMnode, STrans *pTrans, SDbOb
action.contLen = contLen;
action.msgType = TDMT_SYNC_SET_VNODE_STANDBY;
action.acceptableCode = TSDB_CODE_NODE_NOT_DEPLOYED;
+ // Keep retrying until the target vnode is not the leader
+ action.retryCode = TSDB_CODE_SYN_IS_LEADER;
if (isRedo) {
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
@@ -1003,7 +1074,7 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
mInfo("vgId:%d, will add 1 vnodes", pVgroup->vgId);
if (mndAddVnodeToVgroup(pMnode, &newVg, pArray) != 0) return -1;
- if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[1], true) != 0) return -1;
+ if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1], true) != 0) return -1;
if (mndAddAlterVnodeAction(pMnode, pTrans, pDb, &newVg, TDMT_VND_ALTER_REPLICA) != 0) return -1;
if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
@@ -1017,6 +1088,20 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
+ {
+ SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) return -1;
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
+ pRaw = NULL;
+ }
+
+ {
+ SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) return -1;
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
+ pRaw = NULL;
+ }
+
mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
for (int32_t i = 0; i < newVg.replica; ++i) {
mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
@@ -1025,6 +1110,7 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
}
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId) {
+ int32_t code = 0;
SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId);
if (pArray == NULL) return -1;
@@ -1042,18 +1128,24 @@ int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t del
}
}
+ code = 0;
if (vnIndex != -1) {
mInfo("vgId:%d, vnode:%d will be removed from dnode:%d", pVgroup->vgId, vnIndex, delDnodeId);
SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
- mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray);
+ code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray);
mndReleaseDb(pMnode, pDb);
}
sdbRelease(pMnode->pSdb, pVgroup);
+
+ if (code != 0) {
+ sdbCancelFetch(pMnode->pSdb, pIter);
+ break;
+ }
}
taosArrayDestroy(pArray);
- return 0;
+ return code;
}
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
@@ -1128,6 +1220,17 @@ static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb,
terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
goto _OVER;
}
+
+ int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
+ mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
+ terrno = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
+ return -1;
+ } else {
+ pNew1->memUsed += vgMem;
+ }
+
if (mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id) != 0) goto _OVER;
if (mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id) != 0) goto _OVER;
}
@@ -1140,6 +1243,15 @@ static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb,
terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
goto _OVER;
}
+ int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
+ mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
+ terrno = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
+ return -1;
+ } else {
+ pNew2->memUsed += vgMem;
+ }
if (mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id) != 0) goto _OVER;
if (mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id) != 0) goto _OVER;
}
@@ -1152,14 +1264,32 @@ static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb,
terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
goto _OVER;
}
+ int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
+ if (pNew3->memAvail - vgMem - pNew3->memUsed <= 0) {
+ mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
+ pVgroup->dbName, pVgroup->vgId, vgMem, pNew3->id, pNew3->memAvail, pNew3->memUsed);
+ terrno = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
+ return -1;
+ } else {
+ pNew3->memUsed += vgMem;
+ }
if (mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew3->id) != 0) goto _OVER;
if (mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld3->id) != 0) goto _OVER;
}
- pRaw = mndVgroupActionEncode(&newVg);
- if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER;
- sdbSetRawStatus(pRaw, SDB_STATUS_READY);
- pRaw = NULL;
+ {
+ pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) goto _OVER;
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
+ pRaw = NULL;
+ }
+
+ {
+ pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER;
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
+ pRaw = NULL;
+ }
mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
for (int32_t i = 0; i < newVg.replica; ++i) {
@@ -1177,6 +1307,9 @@ _OVER:
}
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
+#if 1
+ return TSDB_CODE_OPS_NOT_SUPPORT;
+#else
SMnode *pMnode = pReq->info.node;
SDnodeObj *pNew1 = NULL;
SDnodeObj *pNew2 = NULL;
@@ -1200,8 +1333,9 @@ static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
}
mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
-
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP) != 0) goto _OVER;
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP) != 0) {
+ goto _OVER;
+ }
pVgroup = mndAcquireVgroup(pMnode, req.vgId);
if (pVgroup == NULL) goto _OVER;
@@ -1216,7 +1350,8 @@ static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
}
if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
- terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
+ // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
+ code = 0;
goto _OVER;
}
@@ -1338,7 +1473,8 @@ static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
}
if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
- terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
+ // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
+ code = 0;
goto _OVER;
}
@@ -1367,6 +1503,7 @@ _OVER:
mndReleaseDb(pMnode, pDb);
return code;
+#endif
}
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
@@ -1411,13 +1548,25 @@ int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, S
} else {
}
- SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
- if (pVgRaw == NULL) return -1;
- if (mndTransAppendCommitlog(pTrans, pVgRaw) != 0) {
- sdbFreeRaw(pVgRaw);
- return -1;
+ {
+ SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
+ if (pVgRaw == NULL) return -1;
+ if (mndTransAppendRedolog(pTrans, pVgRaw) != 0) {
+ sdbFreeRaw(pVgRaw);
+ return -1;
+ }
+ sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
+ }
+
+ {
+ SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
+ if (pVgRaw == NULL) return -1;
+ if (mndTransAppendCommitlog(pTrans, pVgRaw) != 0) {
+ sdbFreeRaw(pVgRaw);
+ return -1;
+ }
+ sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
}
- sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
}
return 0;
@@ -1494,6 +1643,9 @@ static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) {
SDbObj *pDb = NULL;
mDebug("vgId:%d, start to split", vgId);
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_SPLIT_VGROUP) != 0) {
+ goto _OVER;
+ }
pVgroup = mndAcquireVgroup(pMnode, vgId);
if (pVgroup == NULL) goto _OVER;
@@ -1501,8 +1653,6 @@ static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) {
pDb = mndAcquireDb(pMnode, pVgroup->dbName);
if (pDb == NULL) goto _OVER;
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_SPLIT_VGROUP) != 0) goto _OVER;
-
code = mndSplitVgroup(pMnode, pReq, pDb, pVgroup);
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -1524,12 +1674,23 @@ static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SD
if (mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id) != 0) return -1;
if (mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id) != 0) return -1;
- SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
- if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) {
- sdbFreeRaw(pRaw);
- return -1;
+ {
+ SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) {
+ sdbFreeRaw(pRaw);
+ return -1;
+ }
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
+ }
+
+ {
+ SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
+ if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) {
+ sdbFreeRaw(pRaw);
+ return -1;
+ }
+ sdbSetRawStatus(pRaw, SDB_STATUS_READY);
}
- sdbSetRawStatus(pRaw, SDB_STATUS_READY);
mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
for (int32_t i = 0; i < newVg.replica; ++i) {
@@ -1538,14 +1699,20 @@ static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SD
return 0;
}
-static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst) {
+static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
+ SHashObj *pBalancedVgroups) {
void *pIter = NULL;
int32_t code = -1;
+ SSdb *pSdb = pMnode->pSdb;
while (1) {
SVgObj *pVgroup = NULL;
- pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
+ pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
if (pIter == NULL) break;
+ if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
+ sdbRelease(pSdb, pVgroup);
+ continue;
+ }
bool existInSrc = false;
bool existInDst = false;
@@ -1556,13 +1723,18 @@ static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDno
}
if (!existInSrc || existInDst) {
- sdbRelease(pMnode->pSdb, pVgroup);
+ sdbRelease(pSdb, pVgroup);
+ continue;
}
SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
+ if (code == 0) {
+ code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
+ }
mndReleaseDb(pMnode, pDb);
- sdbRelease(pMnode->pSdb, pVgroup);
+ sdbRelease(pSdb, pVgroup);
+ sdbCancelFetch(pSdb, pIter);
break;
}
@@ -1570,9 +1742,13 @@ static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDno
}
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
- int32_t code = -1;
- int32_t numOfVgroups = 0;
- STrans *pTrans = NULL;
+ int32_t code = -1;
+ int32_t numOfVgroups = 0;
+ STrans *pTrans = NULL;
+ SHashObj *pBalancedVgroups = NULL;
+
+ pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
+ if (pBalancedVgroups == NULL) goto _OVER;
pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq);
if (pTrans == NULL) goto _OVER;
@@ -1581,23 +1757,33 @@ static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
while (1) {
taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
- SDnodeObj *pSrc = taosArrayGet(pArray, 0);
- SDnodeObj *pDst = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
+ for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
+ SDnodeObj *pDnode = taosArrayGet(pArray, i);
+ mDebug("dnode:%d, equivalent vnodes:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
+ pDnode->numOfSupportVnodes, (float)pDnode->numOfVnodes / pDnode->numOfSupportVnodes);
+ }
+
+ SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
+ SDnodeObj *pDst = taosArrayGet(pArray, 0);
float srcScore = (float)(pSrc->numOfVnodes - 1) / pSrc->numOfSupportVnodes;
float dstScore = (float)(pDst->numOfVnodes + 1) / pDst->numOfSupportVnodes;
- if (srcScore + 0.0001 < dstScore) {
- mDebug("trans:%d, balance vgroup from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
- code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst);
+ mDebug("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, srcScore,
+ pDst->id, dstScore);
+
+ if (srcScore > dstScore - 0.000001) {
+ code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
if (code == 0) {
+ pSrc->numOfVnodes--;
+ pDst->numOfVnodes++;
numOfVgroups++;
continue;
} else {
- mError("trans:%d, failed to balance vgroup from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
- return -1;
+ mDebug("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
+ break;
}
} else {
- mDebug("trans:%d, no vgroup need to balance vgroup any more", pTrans->id);
+ mDebug("trans:%d, no vgroup need to balance any more", pTrans->id);
break;
}
}
@@ -1617,15 +1803,25 @@ _OVER:
}
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
+#if 1
+ return TSDB_CODE_OPS_NOT_SUPPORT;
+#else
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
SArray *pArray = NULL;
- void *pIter = NULL;
+ void *pIter = NULL;
int64_t curMs = taosGetTimestampMs();
- mDebug("start to balance vgroup");
+ SBalanceVgroupReq req = {0};
+ if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ goto _OVER;
+ }
- if (mndCheckOperAuth(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP) != 0) goto _OVER;
+ mInfo("start to balance vgroup");
+ if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP) != 0) {
+ goto _OVER;
+ }
while (1) {
SDnodeObj *pDnode = NULL;
@@ -1658,4 +1854,7 @@ _OVER:
taosArrayDestroy(pArray);
return code;
-}
\ No newline at end of file
+#endif
+}
+
+bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
\ No newline at end of file
diff --git a/source/dnode/mnode/impl/test/db/CMakeLists.txt b/source/dnode/mnode/impl/test/db/CMakeLists.txt
index e28cdd4f61824c04f62513868a9010113140fd31..3f6a80835ffa7b2a0a6fcdcff21e1cfd39a02c5f 100644
--- a/source/dnode/mnode/impl/test/db/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/db/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-if(NOT TD_WINDOWS)
- add_test(
- NAME dbTest
- COMMAND dbTest
- )
-endif(NOT TD_WINDOWS)
+add_test(
+ NAME dbTest
+ COMMAND dbTest
+)
diff --git a/source/dnode/mnode/impl/test/db/db.cpp b/source/dnode/mnode/impl/test/db/db.cpp
index a1bab5d1d4786bdcfba5774f657264f46e6f471c..0fb8e9d5305f597d687fbf271a576bebe1a12e06 100644
--- a/source/dnode/mnode/impl/test/db/db.cpp
+++ b/source/dnode/mnode/impl/test/db/db.cpp
@@ -50,7 +50,7 @@ TEST_F(MndTestDb, 02_Create_Alter_Drop_Db) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
createReq.numOfStables = 0;
createReq.numOfRetensions = 0;
@@ -84,7 +84,7 @@ TEST_F(MndTestDb, 02_Create_Alter_Drop_Db) {
alterdbReq.fsyncPeriod = 4000;
alterdbReq.walLevel = 2;
alterdbReq.strict = 1;
- alterdbReq.cacheLastRow = 1;
+ alterdbReq.cacheLast = 1;
alterdbReq.replications = 1;
int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq);
@@ -93,7 +93,7 @@ TEST_F(MndTestDb, 02_Create_Alter_Drop_Db) {
SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_DB, pReq, contLen);
ASSERT_NE(pRsp, nullptr);
- ASSERT_EQ(pRsp->code, 0);
+ ASSERT_EQ(pRsp->code, TSDB_CODE_OPS_NOT_SUPPORT);
}
test.SendShowReq(TSDB_MGMT_TABLE_DB, "user_databases", "");
@@ -146,7 +146,7 @@ TEST_F(MndTestDb, 03_Create_Use_Restart_Use_Db) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
createReq.numOfStables = 0;
createReq.numOfRetensions = 0;
diff --git a/source/dnode/mnode/impl/test/dnode/mdnode.cpp b/source/dnode/mnode/impl/test/dnode/mdnode.cpp
index 0b42b2821988a4fe560d9d4660c8c70a3e9cbb4b..8e4e728416bddef729012bcf1ec6caec8dac6792 100644
--- a/source/dnode/mnode/impl/test/dnode/mdnode.cpp
+++ b/source/dnode/mnode/impl/test/dnode/mdnode.cpp
@@ -288,7 +288,7 @@ TEST_F(MndTestDnode, 05_Create_Drop_Restart_Dnode) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
createReq.numOfStables = 0;
createReq.numOfRetensions = 0;
@@ -319,7 +319,7 @@ TEST_F(MndTestDnode, 05_Create_Drop_Restart_Dnode) {
alterdbReq.fsyncPeriod = 4000;
alterdbReq.walLevel = 2;
alterdbReq.strict = 1;
- alterdbReq.cacheLastRow = 1;
+ alterdbReq.cacheLast = 1;
alterdbReq.replications = 3;
int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq);
@@ -345,7 +345,7 @@ TEST_F(MndTestDnode, 05_Create_Drop_Restart_Dnode) {
alterdbReq.fsyncPeriod = 4000;
alterdbReq.walLevel = 2;
alterdbReq.strict = 1;
- alterdbReq.cacheLastRow = 1;
+ alterdbReq.cacheLast = 1;
alterdbReq.replications = 1;
int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq);
diff --git a/source/dnode/mnode/impl/test/func/CMakeLists.txt b/source/dnode/mnode/impl/test/func/CMakeLists.txt
index 17adfde801c02292a1e26a797541cd3a500e19c4..3b6f2b5782bd75d56ef8420eece43b050dd3dcc9 100644
--- a/source/dnode/mnode/impl/test/func/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/func/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-# if(NOT TD_WINDOWS)
- add_test(
- NAME funcTest
- COMMAND funcTest
- )
-# endif(NOT TD_WINDOWS)
+add_test(
+ NAME funcTest
+ COMMAND funcTest
+)
\ No newline at end of file
diff --git a/source/dnode/mnode/impl/test/profile/CMakeLists.txt b/source/dnode/mnode/impl/test/profile/CMakeLists.txt
index 049a4f3a9f45d6608fdb403e99b95b937e93c483..8b811ebfed3a56ab139ecfc81f3556af2f9bb032 100644
--- a/source/dnode/mnode/impl/test/profile/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/profile/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-# if(NOT TD_WINDOWS)
- add_test(
- NAME profileTest
- COMMAND profileTest
- )
-# endif(NOT TD_WINDOWS)
+add_test(
+ NAME profileTest
+ COMMAND profileTest
+)
diff --git a/source/dnode/mnode/impl/test/show/CMakeLists.txt b/source/dnode/mnode/impl/test/show/CMakeLists.txt
index 33ba0c5697d9188aaa1ec0328afc6f143e49413c..69e93e7086147de77676ea02017a6ce5533acf42 100644
--- a/source/dnode/mnode/impl/test/show/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/show/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-# if(NOT TD_WINDOWS)
- add_test(
- NAME showTest
- COMMAND showTest
- )
-# endif(NOT TD_WINDOWS)
+add_test(
+ NAME showTest
+ COMMAND showTest
+)
diff --git a/source/dnode/mnode/impl/test/sma/CMakeLists.txt b/source/dnode/mnode/impl/test/sma/CMakeLists.txt
index fd596c5021674bb9d4ec185924129b0fd3bbade8..3f9ec123a80e88371a98fa54c99342726831372d 100644
--- a/source/dnode/mnode/impl/test/sma/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/sma/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-if(NOT TD_WINDOWS)
- add_test(
- NAME smaTest
- COMMAND smaTest
- )
-endif(NOT TD_WINDOWS)
+add_test(
+ NAME smaTest
+ COMMAND smaTest
+)
diff --git a/source/dnode/mnode/impl/test/sma/sma.cpp b/source/dnode/mnode/impl/test/sma/sma.cpp
index d795816f57b5e65a7bedaef6c14af6db84680703..ce6954279f8da60e355229f19274f592657da309 100644
--- a/source/dnode/mnode/impl/test/sma/sma.cpp
+++ b/source/dnode/mnode/impl/test/sma/sma.cpp
@@ -55,7 +55,7 @@ void* MndTestSma::BuildCreateDbReq(const char* dbname, int32_t* pContLen) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq);
diff --git a/source/dnode/mnode/impl/test/stb/CMakeLists.txt b/source/dnode/mnode/impl/test/stb/CMakeLists.txt
index 857c404c1c299767685fa1572a7f5a0b6463c939..dcfbe658fcca82f928400b1e9eed2efcfb09a052 100644
--- a/source/dnode/mnode/impl/test/stb/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/stb/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-if(NOT TD_WINDOWS)
- add_test(
- NAME stbTest
- COMMAND stbTest
- )
-endif(NOT TD_WINDOWS)
\ No newline at end of file
+add_test(
+ NAME stbTest
+ COMMAND stbTest
+)
\ No newline at end of file
diff --git a/source/dnode/mnode/impl/test/stb/stb.cpp b/source/dnode/mnode/impl/test/stb/stb.cpp
index 56b8936cf44f5520d1e72dfce8f0877fa4be6684..dfdd8f3a49703ac413418993ce3351d35782ca62 100644
--- a/source/dnode/mnode/impl/test/stb/stb.cpp
+++ b/source/dnode/mnode/impl/test/stb/stb.cpp
@@ -56,7 +56,7 @@ void* MndTestStb::BuildCreateDbReq(const char* dbname, int32_t* pContLen) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq);
@@ -277,8 +277,6 @@ void* MndTestStb::BuildAlterStbUpdateColumnBytesReq(const char* stbname, const c
req.numOfFields = 1;
req.pFields = taosArrayInit(1, sizeof(SField));
req.alterType = TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES;
- req.tagVer = verInBlock;
- req.colVer = verInBlock;
SField field = {0};
field.bytes = bytes;
@@ -818,7 +816,7 @@ TEST_F(MndTestStb, 08_Alter_Stb_AlterTagBytes) {
{
void* pReq = BuildAlterStbUpdateColumnBytesReq(stbname, "col_not_exist", 20, &contLen, 1);
SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_STB, pReq, contLen);
- ASSERT_EQ(pRsp->code, 0);
+ ASSERT_EQ(pRsp->code, TSDB_CODE_MND_COLUMN_NOT_EXIST);
test.SendShowReq(TSDB_MGMT_TABLE_STB, "user_stables", dbname);
EXPECT_EQ(test.GetShowRows(), 1);
diff --git a/source/dnode/mnode/impl/test/topic/topic.cpp b/source/dnode/mnode/impl/test/topic/topic.cpp
index 433a0ab5cc100d0fc96ac575a128f350df5e8bf3..353cedf636bffa57e5ff6e3bc341ed18f2904659 100644
--- a/source/dnode/mnode/impl/test/topic/topic.cpp
+++ b/source/dnode/mnode/impl/test/topic/topic.cpp
@@ -48,7 +48,7 @@ void* MndTestTopic::BuildCreateDbReq(const char* dbname, int32_t* pContLen) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq);
diff --git a/source/dnode/mnode/impl/test/user/CMakeLists.txt b/source/dnode/mnode/impl/test/user/CMakeLists.txt
index ed4d96461742a77fd4a2ba3d0b9cd070c2f00c43..b39ea0e73f728cacc648f6eb0723328e028c05f4 100644
--- a/source/dnode/mnode/impl/test/user/CMakeLists.txt
+++ b/source/dnode/mnode/impl/test/user/CMakeLists.txt
@@ -5,9 +5,7 @@ target_link_libraries(
PUBLIC sut
)
-if(NOT TD_WINDOWS)
- add_test(
- NAME userTest
- COMMAND userTest
- )
-endif(NOT TD_WINDOWS)
+add_test(
+ NAME userTest
+ COMMAND userTest
+)
diff --git a/source/dnode/mnode/impl/test/user/user.cpp b/source/dnode/mnode/impl/test/user/user.cpp
index 6aa28a9007e8bc8e7c45621eb7e29280da964823..d8b6964114f485d5b99ce5484d4d0c0960f0feef 100644
--- a/source/dnode/mnode/impl/test/user/user.cpp
+++ b/source/dnode/mnode/impl/test/user/user.cpp
@@ -33,6 +33,8 @@ TEST_F(MndTestUser, 01_Show_User) {
TEST_F(MndTestUser, 02_Create_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "");
strcpy(createReq.pass, "p1");
@@ -47,6 +49,8 @@ TEST_F(MndTestUser, 02_Create_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u1");
strcpy(createReq.pass, "");
@@ -61,6 +65,8 @@ TEST_F(MndTestUser, 02_Create_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "root");
strcpy(createReq.pass, "1");
@@ -75,6 +81,8 @@ TEST_F(MndTestUser, 02_Create_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u1");
strcpy(createReq.pass, "p1");
@@ -108,9 +116,11 @@ TEST_F(MndTestUser, 02_Create_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u2");
strcpy(createReq.pass, "p1");
- createReq.superUser = 1;
+ createReq.superUser = 0;
int32_t contLen = tSerializeSCreateUserReq(NULL, 0, &createReq);
void* pReq = rpcMallocCont(contLen);
@@ -144,9 +154,11 @@ TEST_F(MndTestUser, 02_Create_User) {
TEST_F(MndTestUser, 03_Alter_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u3");
strcpy(createReq.pass, "p1");
- createReq.superUser = 1;
+ createReq.superUser = 0;
int32_t contLen = tSerializeSCreateUserReq(NULL, 0, &createReq);
void* pReq = rpcMallocCont(contLen);
@@ -225,7 +237,7 @@ TEST_F(MndTestUser, 03_Alter_User) {
alterReq.alterType = TSDB_ALTER_USER_SUPERUSER;
strcpy(alterReq.user, "u3");
strcpy(alterReq.pass, "1");
- alterReq.superUser = 1;
+ alterReq.superUser = 0;
int32_t contLen = tSerializeSAlterUserReq(NULL, 0, &alterReq);
void* pReq = rpcMallocCont(contLen);
@@ -303,7 +315,7 @@ TEST_F(MndTestUser, 03_Alter_User) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq);
@@ -361,7 +373,7 @@ TEST_F(MndTestUser, 03_Alter_User) {
SGetUserAuthRsp authRsp = {0};
tDeserializeSGetUserAuthRsp(pRsp->pCont, pRsp->contLen, &authRsp);
EXPECT_STREQ(authRsp.user, "u3");
- EXPECT_EQ(authRsp.superAuth, 1);
+ EXPECT_EQ(authRsp.superAuth, 0);
int32_t numOfReadDbs = taosHashGetSize(authRsp.readDbs);
int32_t numOfWriteDbs = taosHashGetSize(authRsp.writeDbs);
EXPECT_EQ(numOfReadDbs, 1);
@@ -436,6 +448,8 @@ TEST_F(MndTestUser, 05_Drop_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u1");
strcpy(createReq.pass, "p1");
@@ -468,6 +482,8 @@ TEST_F(MndTestUser, 05_Drop_User) {
TEST_F(MndTestUser, 06_Create_Drop_Alter_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u1");
strcpy(createReq.pass, "p1");
@@ -482,6 +498,8 @@ TEST_F(MndTestUser, 06_Create_Drop_Alter_User) {
{
SCreateUserReq createReq = {0};
+ createReq.enable = 1;
+ createReq.sysInfo = 1;
strcpy(createReq.user, "u2");
strcpy(createReq.pass, "p2");
diff --git a/source/dnode/mnode/sdb/inc/sdb.h b/source/dnode/mnode/sdb/inc/sdb.h
index 1294f0cff3446dca7fb7dcdfc6d293d947d13852..be56d901de35cee34c41fe7c9b902ef43a65e38b 100644
--- a/source/dnode/mnode/sdb/inc/sdb.h
+++ b/source/dnode/mnode/sdb/inc/sdb.h
@@ -163,6 +163,7 @@ typedef struct SSdbRow {
ESdbType type;
ESdbStatus status;
int32_t refCount;
+ int64_t forAlign;
char pObj[];
} SSdbRow;
diff --git a/source/dnode/mnode/sdb/src/sdb.c b/source/dnode/mnode/sdb/src/sdb.c
index fbf66da63277895196555a4185fffb41c2dd2cfb..3db0087334c0eb92be39bc9b97d12356f63062ce 100644
--- a/source/dnode/mnode/sdb/src/sdb.c
+++ b/source/dnode/mnode/sdb/src/sdb.c
@@ -131,7 +131,7 @@ int32_t sdbSetTable(SSdb *pSdb, SSdbTable table) {
hashType = TSDB_DATA_TYPE_BINARY;
}
- SHashObj *hash = taosHashInit(64, taosGetDefaultHashFunction(hashType), true, HASH_NO_LOCK);
+ SHashObj *hash = taosHashInit(64, taosGetDefaultHashFunction(hashType), true, HASH_ENTRY_LOCK);
if (hash == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
diff --git a/source/dnode/mnode/sdb/src/sdbFile.c b/source/dnode/mnode/sdb/src/sdbFile.c
index 47c4a4ed0fe982c64ed8358f66e6d9d0ee6e4f8b..ff4a9e4ead5511b3c876522f2103b429f30da4ed 100644
--- a/source/dnode/mnode/sdb/src/sdbFile.c
+++ b/source/dnode/mnode/sdb/src/sdbFile.c
@@ -519,7 +519,7 @@ static void sdbCloseIter(SSdbIter *pIter) {
pIter->name = NULL;
}
- mInfo("sdbiter:%p, is closed, total:%" PRId64, pIter, pIter->total);
+ mDebug("sdbiter:%p, is closed, total:%" PRId64, pIter, pIter->total);
taosMemoryFree(pIter);
}
@@ -556,7 +556,7 @@ int32_t sdbStartRead(SSdb *pSdb, SSdbIter **ppIter, int64_t *index, int64_t *ter
if (term != NULL) *term = commitTerm;
if (config != NULL) *config = commitConfig;
- mInfo("sdbiter:%p, is created to read snapshot, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64 " file:%s",
+ mDebug("sdbiter:%p, is created to read snapshot, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64 " file:%s",
pIter, commitIndex, commitTerm, commitConfig, pIter->name);
return 0;
}
@@ -583,14 +583,14 @@ int32_t sdbDoRead(SSdb *pSdb, SSdbIter *pIter, void **ppBuf, int32_t *len) {
taosMemoryFree(pBuf);
return -1;
} else if (readlen == 0) {
- mInfo("sdbiter:%p, read snapshot to the end, total:%" PRId64, pIter, pIter->total);
+ mDebug("sdbiter:%p, read snapshot to the end, total:%" PRId64, pIter, pIter->total);
*ppBuf = NULL;
*len = 0;
taosMemoryFree(pBuf);
return 0;
} else { // (readlen <= maxlen)
pIter->total += readlen;
- mInfo("sdbiter:%p, read:%d bytes from snapshot, total:%" PRId64, pIter, readlen, pIter->total);
+ mDebug("sdbiter:%p, read:%d bytes from snapshot, total:%" PRId64, pIter, readlen, pIter->total);
*ppBuf = pBuf;
*len = readlen;
return 0;
@@ -609,7 +609,7 @@ int32_t sdbStartWrite(SSdb *pSdb, SSdbIter **ppIter) {
}
*ppIter = pIter;
- mInfo("sdbiter:%p, is created to write snapshot, file:%s", pIter, pIter->name);
+ mDebug("sdbiter:%p, is created to write snapshot, file:%s", pIter, pIter->name);
return 0;
}
@@ -618,7 +618,7 @@ int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply) {
if (!isApply) {
sdbCloseIter(pIter);
- mInfo("sdbiter:%p, not apply to sdb", pIter);
+ mDebug("sdbiter:%p, not apply to sdb", pIter);
return 0;
}
@@ -641,7 +641,7 @@ int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply) {
return -1;
}
- mInfo("sdbiter:%p, successfully applyed to sdb", pIter);
+ mDebug("sdbiter:%p, successfully applyed to sdb", pIter);
return 0;
}
@@ -654,6 +654,6 @@ int32_t sdbDoWrite(SSdb *pSdb, SSdbIter *pIter, void *pBuf, int32_t len) {
}
pIter->total += writelen;
- mInfo("sdbiter:%p, write:%d bytes to snapshot, total:%" PRId64, pIter, writelen, pIter->total);
+ mDebug("sdbiter:%p, write:%d bytes to snapshot, total:%" PRId64, pIter, writelen, pIter->total);
return 0;
}
\ No newline at end of file
diff --git a/source/dnode/qnode/src/qnode.c b/source/dnode/qnode/src/qnode.c
index ebaf73a952283d0feb4f276b33912dd419becbf7..b65189153ea4f0aa36680586e472eac4007a457f 100644
--- a/source/dnode/qnode/src/qnode.c
+++ b/source/dnode/qnode/src/qnode.c
@@ -65,7 +65,7 @@ int32_t qndGetLoad(SQnode *pQnode, SQnodeLoad *pLoad) {
}
int32_t qndPreprocessQueryMsg(SQnode *pQnode, SRpcMsg * pMsg) {
- if (TDMT_VND_QUERY != pMsg->msgType) {
+ if (TDMT_SCH_QUERY != pMsg->msgType && TDMT_SCH_MERGE_QUERY != pMsg->msgType) {
return 0;
}
@@ -78,28 +78,27 @@ int32_t qndProcessQueryMsg(SQnode *pQnode, int64_t ts, SRpcMsg *pMsg) {
qTrace("message in qnode queue is processing");
switch (pMsg->msgType) {
- case TDMT_VND_QUERY:
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY:
code = qWorkerProcessQueryMsg(&handle, pQnode->pQuery, pMsg, ts);
break;
- case TDMT_VND_QUERY_CONTINUE:
+ case TDMT_SCH_QUERY_CONTINUE:
code = qWorkerProcessCQueryMsg(&handle, pQnode->pQuery, pMsg, ts);
break;
- case TDMT_VND_FETCH:
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH:
code = qWorkerProcessFetchMsg(pQnode, pQnode->pQuery, pMsg, ts);
break;
- case TDMT_VND_FETCH_RSP:
- code = qWorkerProcessFetchRsp(pQnode, pQnode->pQuery, pMsg, ts);
- break;
- case TDMT_VND_CANCEL_TASK:
+ case TDMT_SCH_CANCEL_TASK:
code = qWorkerProcessCancelMsg(pQnode, pQnode->pQuery, pMsg, ts);
break;
- case TDMT_VND_DROP_TASK:
+ case TDMT_SCH_DROP_TASK:
code = qWorkerProcessDropMsg(pQnode, pQnode->pQuery, pMsg, ts);
break;
case TDMT_VND_CONSUME:
// code = tqProcessConsumeReq(pQnode->pTq, pMsg);
// break;
- case TDMT_VND_QUERY_HEARTBEAT:
+ case TDMT_SCH_QUERY_HEARTBEAT:
code = qWorkerProcessHbMsg(pQnode, pQnode->pQuery, pMsg, ts);
break;
default:
diff --git a/source/dnode/snode/src/snode.c b/source/dnode/snode/src/snode.c
index 84a66c680bb9bbd54114a19ed712b24cb8ebe7a9..0a5fe1001cc4f177b071643f5b6070675220a361 100644
--- a/source/dnode/snode/src/snode.c
+++ b/source/dnode/snode/src/snode.c
@@ -92,7 +92,7 @@ static int32_t sndProcessTaskDeployReq(SSnode *pNode, SRpcMsg *pMsg) {
}
tDecoderClear(&decoder);
- pTask->status = TASK_STATUS__IDLE;
+ pTask->execStatus = TASK_EXEC_STATUS__IDLE;
pTask->inputQueue = streamQueueOpen();
pTask->outputQueue = streamQueueOpen();
@@ -105,13 +105,14 @@ static int32_t sndProcessTaskDeployReq(SSnode *pNode, SRpcMsg *pMsg) {
ASSERT(pTask->execType != TASK_EXEC__NONE);
- ASSERT(pTask->dataScan == 0);
+ ASSERT(pTask->isDataScan == 0);
pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, NULL);
ASSERT(pTask->exec.executor);
streamSetupTrigger(pTask);
- qInfo("deploy stream: stream id %ld task id %d child id %d on snode", pTask->streamId, pTask->taskId, pTask->childId);
+ qInfo("deploy stream: stream id %" PRId64 " task id %d child id %d on snode", pTask->streamId, pTask->taskId,
+ pTask->selfChildId);
taosHashPut(pMeta->pHash, &pTask->taskId, sizeof(int32_t), &pTask, sizeof(void *));
@@ -198,6 +199,34 @@ static int32_t sndProcessTaskDropReq(SSnode *pNode, SRpcMsg *pMsg) {
return code;
}
+static int32_t sndProcessTaskRetrieveReq(SSnode *pNode, SRpcMsg *pMsg) {
+ SStreamMeta *pMeta = pNode->pMeta;
+
+ char *msgStr = pMsg->pCont;
+ char *msgBody = POINTER_SHIFT(msgStr, sizeof(SMsgHead));
+ int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
+ SStreamRetrieveReq req;
+ SDecoder decoder;
+ tDecoderInit(&decoder, msgBody, msgLen);
+ tDecodeStreamRetrieveReq(&decoder, &req);
+ int32_t taskId = req.dstTaskId;
+ SStreamTask *pTask = *(SStreamTask **)taosHashGet(pMeta->pHash, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
+ SRpcMsg rsp = {
+ .info = pMsg->info,
+ .code = 0,
+ };
+ streamProcessRetrieveReq(pTask, &req, &rsp);
+ return 0;
+}
+
+static int32_t sndProcessTaskRetrieveRsp(SSnode *pNode, SRpcMsg *pMsg) {
+ //
+ return 0;
+}
+
int32_t sndProcessUMsg(SSnode *pSnode, SRpcMsg *pMsg) {
// stream deploy
// stream stop/resume
@@ -205,7 +234,7 @@ int32_t sndProcessUMsg(SSnode *pSnode, SRpcMsg *pMsg) {
switch (pMsg->msgType) {
case TDMT_STREAM_TASK_DEPLOY:
return sndProcessTaskDeployReq(pSnode, pMsg);
- case TDMT_VND_STREAM_TASK_DROP:
+ case TDMT_STREAM_TASK_DROP:
return sndProcessTaskDropReq(pSnode, pMsg);
default:
ASSERT(0);
@@ -221,10 +250,14 @@ int32_t sndProcessSMsg(SSnode *pSnode, SRpcMsg *pMsg) {
return sndProcessTaskDispatchReq(pSnode, pMsg);
case TDMT_STREAM_TASK_RECOVER:
return sndProcessTaskRecoverReq(pSnode, pMsg);
+ case TDMT_STREAM_RETRIEVE:
+ return sndProcessTaskRecoverReq(pSnode, pMsg);
case TDMT_STREAM_TASK_DISPATCH_RSP:
return sndProcessTaskDispatchRsp(pSnode, pMsg);
case TDMT_STREAM_TASK_RECOVER_RSP:
return sndProcessTaskRecoverRsp(pSnode, pMsg);
+ case TDMT_STREAM_RETRIEVE_RSP:
+ return sndProcessTaskRetrieveRsp(pSnode, pMsg);
default:
ASSERT(0);
}
diff --git a/source/dnode/vnode/CMakeLists.txt b/source/dnode/vnode/CMakeLists.txt
index 15eb35c700f42edeb041b69b48385ab5df6851f6..e9e20912c52666d71af546b53e6a946cb53b6833 100644
--- a/source/dnode/vnode/CMakeLists.txt
+++ b/source/dnode/vnode/CMakeLists.txt
@@ -3,18 +3,17 @@ add_library(vnode STATIC "")
target_sources(
vnode
PRIVATE
+
# vnode
"src/vnd/vnodeOpen.c"
"src/vnd/vnodeBufPool.c"
"src/vnd/vnodeCfg.c"
"src/vnd/vnodeCommit.c"
"src/vnd/vnodeQuery.c"
- "src/vnd/vnodeStateMgr.c"
"src/vnd/vnodeModule.c"
"src/vnd/vnodeSvr.c"
"src/vnd/vnodeSync.c"
"src/vnd/vnodeSnapshot.c"
- "src/vnd/vnodeUtil.c"
# meta
"src/meta/metaOpen.c"
@@ -27,9 +26,10 @@ target_sources(
"src/meta/metaSnapshot.c"
# sma
- "src/sma/sma.c"
"src/sma/smaEnv.c"
+ "src/sma/smaUtil.c"
"src/sma/smaOpen.c"
+ "src/sma/smaCommit.c"
"src/sma/smaRollup.c"
"src/sma/smaTimeRange.c"
@@ -40,9 +40,13 @@ target_sources(
"src/tsdb/tsdbOpen.c"
"src/tsdb/tsdbMemTable.c"
"src/tsdb/tsdbRead.c"
- "src/tsdb/tsdbReadImpl.c"
+ "src/tsdb/tsdbCache.c"
"src/tsdb/tsdbWrite.c"
+ "src/tsdb/tsdbReaderWriter.c"
+ "src/tsdb/tsdbUtil.c"
"src/tsdb/tsdbSnapshot.c"
+ "src/tsdb/tsdbCacheRead.c"
+ "src/tsdb/tsdbRetention.c"
# tq
"src/tq/tq.c"
@@ -59,7 +63,6 @@ target_include_directories(
PUBLIC "inc"
PRIVATE "src/inc"
PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar"
-
)
target_link_libraries(
vnode
@@ -73,18 +76,19 @@ target_link_libraries(
PUBLIC executor
PUBLIC scheduler
PUBLIC tdb
- #PUBLIC bdb
- #PUBLIC scalar
+
+ # PUBLIC bdb
+ # PUBLIC scalar
PUBLIC transport
PUBLIC stream
PUBLIC index
)
target_compile_definitions(vnode PUBLIC -DMETA_REFACT)
-if (${BUILD_WITH_INVERTEDINDEX})
- add_definitions(-DUSE_INVERTED_INDEX)
+
+if(${BUILD_WITH_INVERTEDINDEX})
+ add_definitions(-DUSE_INVERTED_INDEX)
endif(${BUILD_WITH_INVERTEDINDEX})
+
if(${BUILD_TEST})
add_subdirectory(test)
endif(${BUILD_TEST})
-
-
diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h
index 70d89102e67dd933a6228402f647a212d953f63a..f0a6b6505d68cc77b6dedb52c48e87cd06491528 100644
--- a/source/dnode/vnode/inc/vnode.h
+++ b/source/dnode/vnode/inc/vnode.h
@@ -28,7 +28,6 @@
#include "tcommon.h"
#include "tfs.h"
-#include "tmallocator.h"
#include "tmsg.h"
#include "trow.h"
@@ -39,10 +38,11 @@ extern "C" {
#endif
// vnode
-typedef struct SVnode SVnode;
-typedef struct STsdbCfg STsdbCfg; // todo: remove
-typedef struct SVnodeCfg SVnodeCfg;
-typedef struct SVSnapshotReader SVSnapshotReader;
+typedef struct SVnode SVnode;
+typedef struct STsdbCfg STsdbCfg; // todo: remove
+typedef struct SVnodeCfg SVnodeCfg;
+typedef struct SVSnapReader SVSnapReader;
+typedef struct SVSnapWriter SVSnapWriter;
extern const SVnodeCfg vnodeCfgDefault;
@@ -51,28 +51,32 @@ void vnodeCleanup();
int32_t vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs);
void vnodeDestroy(const char *path, STfs *pTfs);
SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb);
+void vnodePreClose(SVnode *pVnode);
void vnodeClose(SVnode *pVnode);
-int32_t vnodePreprocessReq(SVnode *pVnode, SRpcMsg *pMsg);
-int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRpcMsg *pRsp);
-int32_t vnodeProcessCMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp);
-int32_t vnodeProcessSyncReq(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp);
-int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg);
-int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg);
-int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo);
-int32_t vnodeGetLoad(SVnode *pVnode, SVnodeLoad *pLoad);
-int32_t vnodeValidateTableHash(SVnode *pVnode, char *tableFName);
+
int32_t vnodeStart(SVnode *pVnode);
void vnodeStop(SVnode *pVnode);
int64_t vnodeGetSyncHandle(SVnode *pVnode);
void vnodeGetSnapshot(SVnode *pVnode, SSnapshot *pSnapshot);
void vnodeGetInfo(SVnode *pVnode, const char **dbname, int32_t *vgId);
-int32_t vnodeSnapshotReaderOpen(SVnode *pVnode, SVSnapshotReader **ppReader, int64_t sver, int64_t ever);
-int32_t vnodeSnapshotReaderClose(SVSnapshotReader *pReader);
-int32_t vnodeSnapshotRead(SVSnapshotReader *pReader, const void **ppData, uint32_t *nData);
int32_t vnodeProcessCreateTSma(SVnode *pVnode, void *pCont, uint32_t contLen);
+int32_t vnodeGetAllTableList(SVnode *pVnode, uint64_t uid, SArray *list);
+int32_t vnodeGetCtbIdList(SVnode *pVnode, int64_t suid, SArray *list);
+void *vnodeGetIdx(SVnode *pVnode);
+void *vnodeGetIvtIdx(SVnode *pVnode);
-void vnodeProposeMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
-void vnodeApplyMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
+int32_t vnodeGetLoad(SVnode *pVnode, SVnodeLoad *pLoad);
+int32_t vnodeValidateTableHash(SVnode *pVnode, char *tableFName);
+
+int32_t vnodePreProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg);
+int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg);
+
+int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRpcMsg *pRsp);
+int32_t vnodeProcessSyncMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp);
+int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg);
+int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo);
+void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
+void vnodeApplyWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
// meta
typedef struct SMeta SMeta; // todo: remove
@@ -110,52 +114,85 @@ int32_t metaTbCursorNext(SMTbCursor *pTbCur);
// tsdb
// typedef struct STsdb STsdb;
-typedef void *tsdbReaderT;
-
-#define BLOCK_LOAD_OFFSET_SEQ_ORDER 1
-#define BLOCK_LOAD_TABLE_SEQ_ORDER 2
-#define BLOCK_LOAD_TABLE_RR_ORDER 3
-
-tsdbReaderT tsdbReaderOpen(SVnode *pVnode, SQueryTableDataCond *pCond, STableListInfo *tableInfoGroup, uint64_t qId,
- uint64_t taskId);
-tsdbReaderT tsdbQueryCacheLast(SVnode *pVnode, SQueryTableDataCond *pCond, STableListInfo *groupList, uint64_t qId,
- void *pMemRef);
-int32_t tsdbGetFileBlocksDistInfo(tsdbReaderT *pReader, STableBlockDistInfo *pTableBlockInfo);
-bool isTsdbCacheLastRow(tsdbReaderT *pReader);
-int32_t tsdbGetAllTableList(SMeta *pMeta, uint64_t uid, SArray *list);
-int32_t tsdbGetCtbIdList(SMeta *pMeta, int64_t suid, SArray *list);
-void *tsdbGetIdx(SMeta *pMeta);
-void *tsdbGetIvtIdx(SMeta *pMeta);
-int64_t tsdbGetNumOfRowsInMemTable(tsdbReaderT *pHandle);
-
-bool tsdbNextDataBlock(tsdbReaderT pTsdbReadHandle);
-void tsdbRetrieveDataBlockInfo(tsdbReaderT *pTsdbReadHandle, SDataBlockInfo *pBlockInfo);
-int32_t tsdbRetrieveDataBlockStatisInfo(tsdbReaderT *pTsdbReadHandle, SColumnDataAgg ***pBlockStatis, bool *allHave);
-SArray *tsdbRetrieveDataBlock(tsdbReaderT *pTsdbReadHandle, SArray *pColumnIdList);
-void tsdbResetReadHandle(tsdbReaderT queryHandle, SQueryTableDataCond *pCond, int32_t tWinIdx);
-void tsdbCleanupReadHandle(tsdbReaderT queryHandle);
+typedef struct STsdbReader STsdbReader;
+
+#define BLOCK_LOAD_OFFSET_ORDER 1
+#define BLOCK_LOAD_TABLESEQ_ORDER 2
+#define BLOCK_LOAD_EXTERN_ORDER 3
+
+#define LASTROW_RETRIEVE_TYPE_ALL 0x1
+#define LASTROW_RETRIEVE_TYPE_SINGLE 0x2
+
+int32_t tsdbSetTableId(STsdbReader *pReader, int64_t uid);
+int32_t tsdbReaderOpen(SVnode *pVnode, SQueryTableDataCond *pCond, SArray *pTableList, STsdbReader **ppReader,
+ const char *idstr);
+void tsdbReaderClose(STsdbReader *pReader);
+bool tsdbNextDataBlock(STsdbReader *pReader);
+void tsdbRetrieveDataBlockInfo(STsdbReader *pReader, SDataBlockInfo *pDataBlockInfo);
+int32_t tsdbRetrieveDatablockSMA(STsdbReader *pReader, SColumnDataAgg ***pBlockStatis, bool *allHave);
+SArray *tsdbRetrieveDataBlock(STsdbReader *pTsdbReadHandle, SArray *pColumnIdList);
+int32_t tsdbReaderReset(STsdbReader *pReader, SQueryTableDataCond *pCond);
+int32_t tsdbGetFileBlocksDistInfo(STsdbReader *pReader, STableBlockDistInfo *pTableBlockInfo);
+int64_t tsdbGetNumOfRowsInMemTable(STsdbReader *pHandle);
+void *tsdbGetIdx(SMeta *pMeta);
+void *tsdbGetIvtIdx(SMeta *pMeta);
+
+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);
+int32_t tsdbLastrowReaderClose(void *pReader);
+int32_t tsdbGetTableSchema(SVnode *pVnode, int64_t uid, STSchema **pSchema, int64_t *suid);
+
+void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity);
+size_t tsdbCacheGetCapacity(SVnode *pVnode);
// tq
-typedef struct STqReadHandle STqReadHandle;
+typedef struct STqReader {
+ int64_t ver;
+ const SSubmitReq *pMsg;
+ SSubmitBlk *pBlock;
+ SSubmitMsgIter msgIter;
+ SSubmitBlkIter blkIter;
+
+ SWalReader *pWalReader;
+
+ SMeta *pVnodeMeta;
+ SHashObj *tbIdHash;
+ SArray *pColIdList; // SArray
+
+ int32_t cachedSchemaVer;
+ int64_t cachedSchemaSuid;
+ SSchemaWrapper *pSchemaWrapper;
+ STSchema *pSchema;
+} STqReader;
+
+STqReader *tqOpenReader(SVnode *pVnode);
+void tqCloseReader(STqReader *);
-STqReadHandle *tqInitSubmitMsgScanner(SMeta *pMeta);
+void tqReaderSetColIdList(STqReader *pReader, SArray *pColIdList);
+int32_t tqReaderSetTbUidList(STqReader *pReader, const SArray *tbUidList);
+int32_t tqReaderAddTbUidList(STqReader *pReader, const SArray *tbUidList);
+int32_t tqReaderRemoveTbUidList(STqReader *pReader, const SArray *tbUidList);
-void tqReadHandleSetColIdList(STqReadHandle *pReadHandle, SArray *pColIdList);
-int32_t tqReadHandleSetTbUidList(STqReadHandle *pHandle, const SArray *tbUidList);
-int32_t tqReadHandleAddTbUidList(STqReadHandle *pHandle, const SArray *tbUidList);
-int32_t tqReadHandleRemoveTbUidList(STqReadHandle *pHandle, const SArray *tbUidList);
+int32_t tqSeekVer(STqReader *pReader, int64_t ver);
+int32_t tqNextBlock(STqReader *pReader, SFetchRet *ret);
-int32_t tqReadHandleSetMsg(STqReadHandle *pHandle, SSubmitReq *pMsg, int64_t ver);
-bool tqNextDataBlock(STqReadHandle *pHandle);
-bool tqNextDataBlockFilterOut(STqReadHandle *pHandle, SHashObj *filterOutUids);
-int32_t tqRetrieveDataBlock(SArray **ppCols, STqReadHandle *pHandle, uint64_t *pGroupId, uint64_t *pUid,
- int32_t *pNumOfRows, int16_t *pNumOfCols);
+int32_t tqReaderSetDataMsg(STqReader *pReader, SSubmitReq *pMsg, int64_t ver);
+bool tqNextDataBlock(STqReader *pReader);
+bool tqNextDataBlockFilterOut(STqReader *pReader, SHashObj *filterOutUids);
+int32_t tqRetrieveDataBlock(SSDataBlock *pBlock, STqReader *pReader);
// sma
int32_t smaGetTSmaDays(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days);
-// need to reposition
+// SVSnapReader
+int32_t vnodeSnapReaderOpen(SVnode *pVnode, int64_t sver, int64_t ever, SVSnapReader **ppReader);
+int32_t vnodeSnapReaderClose(SVSnapReader *pReader);
+int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData);
+// SVSnapWriter
+int32_t vnodeSnapWriterOpen(SVnode *pVnode, int64_t sver, int64_t ever, SVSnapWriter **ppWriter);
+int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback);
+int32_t vnodeSnapWrite(SVSnapWriter *pWriter, uint8_t *pData, uint32_t nData);
// structs
struct STsdbCfg {
@@ -176,11 +213,13 @@ struct SVnodeCfg {
int32_t vgId;
char dbname[TSDB_DB_FNAME_LEN];
uint64_t dbId;
+ int32_t cacheLastSize;
int32_t szPage;
int32_t szCache;
uint64_t szBuf;
bool isHeap;
bool isWeak;
+ int8_t cacheLast;
int8_t isTsma;
int8_t isRsma;
int8_t hashMethod;
@@ -195,17 +234,23 @@ struct SVnodeCfg {
typedef struct {
TSKEY lastKey;
uint64_t uid;
+ uint64_t groupId;
} STableKeyInfo;
+#define TABLE_ROLLUP_ON ((int8_t)0x1)
+#define TABLE_IS_ROLLUP(FLG) (((FLG) & (TABLE_ROLLUP_ON)) != 0)
+#define TABLE_SET_ROLLUP(FLG) ((FLG) |= TABLE_ROLLUP_ON)
struct SMetaEntry {
int64_t version;
int8_t type;
+ int8_t flags; // TODO: need refactor?
tb_uid_t uid;
char *name;
union {
struct {
SSchemaWrapper schemaRow;
SSchemaWrapper schemaTag;
+ SRSmaParam rsmaParam;
} stbEntry;
struct {
int64_t ctime;
diff --git a/source/dnode/vnode/src/inc/meta.h b/source/dnode/vnode/src/inc/meta.h
index 63a8e7ec6831071fc97b5c17f0cb375bd883cf24..e08925acc398f740c1bc4bcd205e14768cdfcc98 100644
--- a/source/dnode/vnode/src/inc/meta.h
+++ b/source/dnode/vnode/src/inc/meta.h
@@ -57,6 +57,9 @@ int metaRemoveTableFromIdx(SMeta* pMeta, tb_uid_t uid);
// metaCommit ==================
static FORCE_INLINE tb_uid_t metaGenerateUid(SMeta* pMeta) { return tGenIdPI64(); }
+// metaTable ==================
+int metaHandleEntry(SMeta* pMeta, const SMetaEntry* pME);
+
struct SMeta {
TdThreadRwlock lock;
@@ -69,6 +72,7 @@ struct SMeta {
TTB* pUidIdx;
TTB* pNameIdx;
TTB* pCtbIdx;
+ TTB* pSuidIdx;
// ivt idx and idx
void* pTagIvtIdx;
TTB* pTagIdx;
diff --git a/source/dnode/vnode/src/inc/sma.h b/source/dnode/vnode/src/inc/sma.h
index 902e5e1bcc291fbe4826b41d8702f716fd6b6a58..e767d94ebd9eba24f41cd10e2b1908b95dba37ed 100644
--- a/source/dnode/vnode/src/inc/sma.h
+++ b/source/dnode/vnode/src/inc/sma.h
@@ -34,7 +34,8 @@ extern "C" {
typedef struct SSmaEnv SSmaEnv;
typedef struct SSmaStat SSmaStat;
-typedef struct SSmaStatItem SSmaStatItem;
+typedef struct STSmaStat STSmaStat;
+typedef struct SRSmaStat SRSmaStat;
typedef struct SSmaKey SSmaKey;
typedef struct SRSmaInfo SRSmaInfo;
typedef struct SRSmaInfoItem SRSmaInfoItem;
@@ -45,26 +46,53 @@ struct SSmaEnv {
SSmaStat *pStat;
};
-#define SMA_ENV_LOCK(env) ((env)->lock)
-#define SMA_ENV_TYPE(env) ((env)->type)
-#define SMA_ENV_STAT(env) ((env)->pStat)
-#define SMA_ENV_STAT_ITEM(env) ((env)->pStat->tsmaStatItem)
+typedef struct {
+ int8_t inited;
+ int32_t rsetId;
+ void *tmrHandle; // shared by all fetch tasks
+} SSmaMgmt;
-struct SSmaStatItem {
+#define SMA_ENV_LOCK(env) ((env)->lock)
+#define SMA_ENV_TYPE(env) ((env)->type)
+#define SMA_ENV_STAT(env) ((env)->pStat)
+
+struct STSmaStat {
int8_t state; // ETsdbSmaStat
STSma *pTSma; // cache schema
STSchema *pTSchema;
};
+struct SRSmaStat {
+ SSma *pSma;
+ int64_t submitVer;
+ int64_t refId; // shared by fetch tasks
+ int8_t triggerStat; // shared by fetch tasks
+ SHashObj *rsmaInfoHash; // key: stbUid, value: SRSmaInfo;
+};
+
struct SSmaStat {
union {
- SSmaStatItem tsmaStatItem;
- SHashObj *rsmaInfoHash; // key: stbUid, value: SRSmaInfo;
+ STSmaStat tsmaStat; // time-range-wise sma
+ SRSmaStat rsmaStat; // rollup sma
};
T_REF_DECLARE()
};
-#define SMA_STAT_ITEM(s) ((s)->tsmaStatItem)
-#define SMA_STAT_INFO_HASH(s) ((s)->rsmaInfoHash)
+
+#define SMA_TSMA_STAT(s) (&(s)->tsmaStat)
+#define SMA_RSMA_STAT(s) (&(s)->rsmaStat)
+#define RSMA_INFO_HASH(r) ((r)->rsmaInfoHash)
+#define RSMA_TRIGGER_STAT(r) (&(r)->triggerStat)
+#define RSMA_REF_ID(r) ((r)->refId)
+#define RSMA_SUBMIT_VER(r) ((r)->submitVer)
+
+enum {
+ TASK_TRIGGER_STAT_INIT = 0,
+ TASK_TRIGGER_STAT_ACTIVE = 1,
+ TASK_TRIGGER_STAT_INACTIVE = 2,
+ TASK_TRIGGER_STAT_PAUSED = 3,
+ TASK_TRIGGER_STAT_CANCELLED = 4,
+ TASK_TRIGGER_STAT_DROPPED = 5,
+};
void tdDestroySmaEnv(SSmaEnv *pSmaEnv);
void *tdFreeSmaEnv(SSmaEnv *pSmaEnv);
@@ -75,6 +103,10 @@ int32_t tdInsertRSmaData(SSma *pSma, char *msg);
int32_t tdRefSmaStat(SSma *pSma, SSmaStat *pStat);
int32_t tdUnRefSmaStat(SSma *pSma, SSmaStat *pStat);
+
+void *tdAcquireSmaRef(int32_t rsetId, int64_t refId, const char *tags, int32_t ln);
+int32_t tdReleaseSmaRef(int32_t rsetId, int64_t refId, const char *tags, int32_t ln);
+
int32_t tdCheckAndInitSmaEnv(SSma *pSma, int8_t smaType);
int32_t tdLockSma(SSma *pSma);
@@ -107,62 +139,122 @@ static FORCE_INLINE int32_t tdUnLockSmaEnv(SSmaEnv *pEnv) {
return 0;
}
-static FORCE_INLINE int8_t tdSmaStat(SSmaStatItem *pStatItem) {
- if (pStatItem) {
- return atomic_load_8(&pStatItem->state);
+static FORCE_INLINE int8_t tdSmaStat(STSmaStat *pTStat) {
+ if (pTStat) {
+ return atomic_load_8(&pTStat->state);
}
return TSDB_SMA_STAT_UNKNOWN;
}
-static FORCE_INLINE bool tdSmaStatIsOK(SSmaStatItem *pStatItem, int8_t *state) {
- if (!pStatItem) {
+static FORCE_INLINE bool tdSmaStatIsOK(STSmaStat *pTStat, int8_t *state) {
+ if (!pTStat) {
return false;
}
if (state) {
- *state = atomic_load_8(&pStatItem->state);
+ *state = atomic_load_8(&pTStat->state);
return *state == TSDB_SMA_STAT_OK;
}
- return atomic_load_8(&pStatItem->state) == TSDB_SMA_STAT_OK;
+ return atomic_load_8(&pTStat->state) == TSDB_SMA_STAT_OK;
}
-static FORCE_INLINE bool tdSmaStatIsExpired(SSmaStatItem *pStatItem) {
- return pStatItem ? (atomic_load_8(&pStatItem->state) & TSDB_SMA_STAT_EXPIRED) : true;
+static FORCE_INLINE bool tdSmaStatIsExpired(STSmaStat *pTStat) {
+ return pTStat ? (atomic_load_8(&pTStat->state) & TSDB_SMA_STAT_EXPIRED) : true;
}
-static FORCE_INLINE bool tdSmaStatIsDropped(SSmaStatItem *pStatItem) {
- return pStatItem ? (atomic_load_8(&pStatItem->state) & TSDB_SMA_STAT_DROPPED) : true;
+static FORCE_INLINE bool tdSmaStatIsDropped(STSmaStat *pTStat) {
+ return pTStat ? (atomic_load_8(&pTStat->state) & TSDB_SMA_STAT_DROPPED) : true;
}
-static FORCE_INLINE void tdSmaStatSetOK(SSmaStatItem *pStatItem) {
- if (pStatItem) {
- atomic_store_8(&pStatItem->state, TSDB_SMA_STAT_OK);
+static FORCE_INLINE void tdSmaStatSetOK(STSmaStat *pTStat) {
+ if (pTStat) {
+ atomic_store_8(&pTStat->state, TSDB_SMA_STAT_OK);
}
}
-static FORCE_INLINE void tdSmaStatSetExpired(SSmaStatItem *pStatItem) {
- if (pStatItem) {
- atomic_or_fetch_8(&pStatItem->state, TSDB_SMA_STAT_EXPIRED);
+static FORCE_INLINE void tdSmaStatSetExpired(STSmaStat *pTStat) {
+ if (pTStat) {
+ atomic_or_fetch_8(&pTStat->state, TSDB_SMA_STAT_EXPIRED);
}
}
-static FORCE_INLINE void tdSmaStatSetDropped(SSmaStatItem *pStatItem) {
- if (pStatItem) {
- atomic_or_fetch_8(&pStatItem->state, TSDB_SMA_STAT_DROPPED);
+static FORCE_INLINE void tdSmaStatSetDropped(STSmaStat *pTStat) {
+ if (pTStat) {
+ atomic_or_fetch_8(&pTStat->state, TSDB_SMA_STAT_DROPPED);
}
}
-static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType);
-void *tdFreeSmaStatItem(SSmaStatItem *pSmaStatItem);
static int32_t tdDestroySmaState(SSmaStat *pSmaStat, int8_t smaType);
void *tdFreeSmaState(SSmaStat *pSmaStat, int8_t smaType);
+void *tdFreeRSmaInfo(SSma *pSma, SRSmaInfo *pInfo);
+int32_t tdRSmaPersistExecImpl(SRSmaStat *pRSmaStat);
-void *tdFreeRSmaInfo(SRSmaInfo *pInfo);
+int32_t tdProcessRSmaCreateImpl(SSma *pSma, SRSmaParam *param, int64_t suid, const char *tbName);
+int32_t tdProcessRSmaRestoreImpl(SSma *pSma);
int32_t tdProcessTSmaCreateImpl(SSma *pSma, int64_t version, const char *pMsg);
int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg);
int32_t tdProcessTSmaGetDaysImpl(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days);
+// smaFileUtil ================
+
+#define TD_FILE_HEAD_SIZE 512
+
+typedef struct STFInfo STFInfo;
+typedef struct STFile STFile;
+
+struct STFInfo {
+ // common fields
+ uint32_t magic;
+ uint32_t ftype;
+ uint32_t fver;
+ int64_t fsize;
+
+ // specific fields
+ union {
+ struct {
+ int64_t submitVer;
+ } qTaskInfo;
+ };
+};
+
+enum {
+ TD_FTYPE_RSMA_QTASKINFO = 0,
+};
+
+struct STFile {
+ uint8_t state;
+ STFInfo info;
+ char *fname;
+ TdFilePtr pFile;
+};
+
+#define TD_TFILE_PFILE(tf) ((tf)->pFile)
+#define TD_TFILE_OPENED(tf) (TD_TFILE_PFILE(tf) != NULL)
+#define TD_TFILE_FULL_NAME(tf) ((tf)->fname)
+#define TD_TFILE_OPENED(tf) (TD_TFILE_PFILE(tf) != NULL)
+#define TD_TFILE_CLOSED(tf) (!TD_TFILE_OPENED(tf))
+#define TD_TFILE_SET_CLOSED(f) (TD_TFILE_PFILE(f) = NULL)
+#define TD_TFILE_SET_STATE(tf, s) ((tf)->state = (s))
+
+int32_t tdInitTFile(STFile *pTFile, const char *dname, const char *fname);
+int32_t tdCreateTFile(STFile *pTFile, bool updateHeader, int8_t fType);
+int32_t tdOpenTFile(STFile *pTFile, int flags);
+int64_t tdReadTFile(STFile *pTFile, void *buf, int64_t nbyte);
+int64_t tdSeekTFile(STFile *pTFile, int64_t offset, int whence);
+int64_t tdWriteTFile(STFile *pTFile, void *buf, int64_t nbyte);
+int64_t tdAppendTFile(STFile *pTFile, void *buf, int64_t nbyte, int64_t *offset);
+int64_t tdGetTFileSize(STFile *pTFile, int64_t *size);
+int32_t tdRemoveTFile(STFile *pTFile);
+int32_t tdLoadTFileHeader(STFile *pTFile, STFInfo *pInfo);
+int32_t tdUpdateTFileHeader(STFile *pTFile);
+void tdUpdateTFileMagic(STFile *pTFile, void *pCksm);
+void tdCloseTFile(STFile *pTFile);
+void tdDestroyTFile(STFile *pTFile);
+
+void tdGetVndFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t version, char *outputName);
+void tdGetVndDirName(int32_t vgId,const char *pdname, const char *dname, bool endWithSep, char *outputName);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/dnode/vnode/src/inc/tq.h b/source/dnode/vnode/src/inc/tq.h
index 2ee0673ce5f04b34ad07cd4b8edc6cc74ca943ed..c62b7e95bfe4aa0d54401f5bd1b2434476db0cba 100644
--- a/source/dnode/vnode/src/inc/tq.h
+++ b/source/dnode/vnode/src/inc/tq.h
@@ -39,29 +39,11 @@ extern "C" {
#define tqInfo(...) do { if (tqDebugFlag & DEBUG_INFO) { taosPrintLog("TQ ", DEBUG_INFO, 255, __VA_ARGS__); }} while(0)
#define tqDebug(...) do { if (tqDebugFlag & DEBUG_DEBUG) { taosPrintLog("TQ ", DEBUG_DEBUG, tqDebugFlag, __VA_ARGS__); }} while(0)
#define tqTrace(...) do { if (tqDebugFlag & DEBUG_TRACE) { taosPrintLog("TQ ", DEBUG_TRACE, tqDebugFlag, __VA_ARGS__); }} while(0)
+
// clang-format on
typedef struct STqOffsetStore STqOffsetStore;
-// tqRead
-
-struct STqReadHandle {
- int64_t ver;
- const SSubmitReq* pMsg;
- SSubmitBlk* pBlock;
- SSubmitMsgIter msgIter;
- SSubmitBlkIter blkIter;
-
- SMeta* pVnodeMeta;
- SHashObj* tbIdHash;
- SArray* pColIdList; // SArray
-
- int32_t cachedSchemaVer;
- int64_t cachedSchemaSuid;
- SSchemaWrapper* pSchemaWrapper;
- STSchema* pSchema;
-};
-
// tqPush
typedef struct {
@@ -101,12 +83,13 @@ typedef struct {
typedef struct {
int8_t subType;
- STqReadHandle* pExecReader[5];
+ STqReader* pExecReader[5];
union {
STqExecCol execCol;
STqExecTb execTb;
STqExecDb execDb;
};
+
} STqExecHandle;
typedef struct {
@@ -114,9 +97,12 @@ typedef struct {
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
int64_t consumerId;
int32_t epoch;
+ int8_t fetchMeta;
- // reader
- SWalReadHandle* pWalReader;
+ int64_t snapshotVer;
+
+ // TODO remove
+ SWalReader* pWalReader;
// push
STqPushHandle pushHandle;
@@ -145,11 +131,13 @@ typedef struct {
static STqMgmt tqMgmt = {0};
// tqRead
-int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalHead** pHeadWithCkSum);
+int64_t tqScan(STQ* pTq, const STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal* offset);
+int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** pHeadWithCkSum);
// tqExec
-int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkRsp* pRsp, int32_t workerId);
-int32_t tqSendPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataBlkRsp* pRsp);
+int32_t tqLogScanExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataRsp* pRsp, int32_t workerId);
+int32_t tqScanSnapshot(STQ* pTq, const STqExecHandle* pExec, SMqDataRsp* pRsp, STqOffsetVal offset, int32_t workerId);
+int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp);
// tqMeta
int32_t tqMetaOpen(STQ* pTq);
@@ -165,11 +153,23 @@ STqOffsetStore* tqOffsetOpen();
void tqOffsetClose(STqOffsetStore*);
STqOffset* tqOffsetRead(STqOffsetStore* pStore, const char* subscribeKey);
int32_t tqOffsetWrite(STqOffsetStore* pStore, const STqOffset* pOffset);
+int32_t tqOffsetDelete(STqOffsetStore* pStore, const char* subscribeKey);
int32_t tqOffsetSnapshot(STqOffsetStore* pStore);
// tqSink
void tqTableSink(SStreamTask* pTask, void* vnode, int64_t ver, void* data);
+static FORCE_INLINE void tqOffsetResetToData(STqOffsetVal* pOffsetVal, int64_t uid, int64_t ts) {
+ pOffsetVal->type = TMQ_OFFSET__SNAPSHOT_DATA;
+ pOffsetVal->uid = uid;
+ pOffsetVal->ts = ts;
+}
+
+static FORCE_INLINE void tqOffsetResetToLog(STqOffsetVal* pOffsetVal, int64_t ver) {
+ pOffsetVal->type = TMQ_OFFSET__LOG;
+ pOffsetVal->version = ver;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h
index 657b55a0c651a360176cca30acf48ebda4ec1059..4df9f965143b22b0ae50fb7e25bfc904eaa29343 100644
--- a/source/dnode/vnode/src/inc/tsdb.h
+++ b/source/dnode/vnode/src/inc/tsdb.h
@@ -32,99 +32,234 @@ extern "C" {
#define tsdbTrace(...) do { if (tsdbDebugFlag & DEBUG_TRACE) { taosPrintLog("TSDB ", DEBUG_TRACE, tsdbDebugFlag, __VA_ARGS__); }} while(0)
// clang-format on
-typedef struct TSDBROW TSDBROW;
-typedef struct TSDBKEY TSDBKEY;
-typedef struct TABLEID TABLEID;
-typedef struct SDelOp SDelOp;
-
-static int tsdbKeyCmprFn(const void *p1, const void *p2);
-
+typedef struct TSDBROW TSDBROW;
+typedef struct TABLEID TABLEID;
+typedef struct TSDBKEY TSDBKEY;
+typedef struct SDelData SDelData;
+typedef struct SDelIdx SDelIdx;
+typedef struct STbData STbData;
+typedef struct SMemTable SMemTable;
+typedef struct STbDataIter STbDataIter;
+typedef struct STable STable;
+typedef struct SMapData SMapData;
+typedef struct SBlockIdx SBlockIdx;
+typedef struct SBlock SBlock;
+typedef struct SBlockStatis SBlockStatis;
+typedef struct SAggrBlkCol SAggrBlkCol;
+typedef struct SColData SColData;
+typedef struct SBlockDataHdr SBlockDataHdr;
+typedef struct SBlockData SBlockData;
+typedef struct SDelFile SDelFile;
+typedef struct SHeadFile SHeadFile;
+typedef struct SDataFile SDataFile;
+typedef struct SLastFile SLastFile;
+typedef struct SSmaFile SSmaFile;
+typedef struct SDFileSet SDFileSet;
+typedef struct SDataFWriter SDataFWriter;
+typedef struct SDataFReader SDataFReader;
+typedef struct SDelFWriter SDelFWriter;
+typedef struct SDelFReader SDelFReader;
+typedef struct SRowIter SRowIter;
+typedef struct STsdbFS STsdbFS;
+typedef struct SRowMerger SRowMerger;
+typedef struct STsdbFSState STsdbFSState;
+typedef struct STsdbSnapHdr STsdbSnapHdr;
+
+#define TSDB_MAX_SUBBLOCKS 8
+#define TSDB_FHDR_SIZE 512
+
+#define HAS_NONE ((int8_t)0x1)
+#define HAS_NULL ((int8_t)0x2)
+#define HAS_VALUE ((int8_t)0x4)
+
+#define VERSION_MIN 0
+#define VERSION_MAX INT64_MAX
+
+#define TSDBKEY_MIN ((TSDBKEY){.ts = TSKEY_MIN, .version = VERSION_MIN})
+#define TSDBKEY_MAX ((TSDBKEY){.ts = TSKEY_MAX, .version = VERSION_MAX})
+
+// tsdbUtil.c ==============================================================================================
+// TSDBROW
+#define TSDBROW_TS(ROW) (((ROW)->type == 0) ? (ROW)->pTSRow->ts : (ROW)->pBlockData->aTSKEY[(ROW)->iRow])
+#define TSDBROW_VERSION(ROW) (((ROW)->type == 0) ? (ROW)->version : (ROW)->pBlockData->aVersion[(ROW)->iRow])
+#define TSDBROW_SVERSION(ROW) TD_ROW_SVER((ROW)->pTSRow)
+#define TSDBROW_KEY(ROW) ((TSDBKEY){.version = TSDBROW_VERSION(ROW), .ts = TSDBROW_TS(ROW)})
+#define tsdbRowFromTSRow(VERSION, TSROW) ((TSDBROW){.type = 0, .version = (VERSION), .pTSRow = (TSROW)})
+#define tsdbRowFromBlockData(BLOCKDATA, IROW) ((TSDBROW){.type = 1, .pBlockData = (BLOCKDATA), .iRow = (IROW)})
+void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal);
+int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow);
+int32_t tGetTSDBRow(uint8_t *p, TSDBROW *pRow);
+int32_t tsdbRowCmprFn(const void *p1, const void *p2);
+// SRowIter
+void tRowIterInit(SRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema);
+SColVal *tRowIterNext(SRowIter *pIter);
+// SRowMerger
+int32_t tRowMergerInit(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema);
+void tRowMergerClear(SRowMerger *pMerger);
+int32_t tRowMerge(SRowMerger *pMerger, TSDBROW *pRow);
+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
+int32_t tPutBlockCol(uint8_t *p, void *ph);
+int32_t tGetBlockCol(uint8_t *p, void *ph);
+int32_t tBlockColCmprFn(const void *p1, const void *p2);
+// SBlock
+void tBlockReset(SBlock *pBlock);
+int32_t tPutBlock(uint8_t *p, void *ph);
+int32_t tGetBlock(uint8_t *p, void *ph);
+int32_t tBlockCmprFn(const void *p1, const void *p2);
+bool tBlockHasSma(SBlock *pBlock);
+// SBlockIdx
+void tBlockIdxReset(SBlockIdx *pBlockIdx);
+int32_t tPutBlockIdx(uint8_t *p, void *ph);
+int32_t tGetBlockIdx(uint8_t *p, void *ph);
+int32_t tCmprBlockIdx(void const *lhs, void const *rhs);
+// SColdata
+void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn);
+void tColDataReset(SColData *pColData);
+void tColDataClear(void *ph);
+int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal);
+int32_t tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal);
+int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest);
+// SBlockData
+#define tBlockDataFirstRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, 0)
+#define tBlockDataLastRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, (PBLOCKDATA)->nRow - 1)
+#define tBlockDataFirstKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataFirstRow(PBLOCKDATA))
+#define tBlockDataLastKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataLastRow(PBLOCKDATA))
+int32_t tBlockDataInit(SBlockData *pBlockData);
+void tBlockDataReset(SBlockData *pBlockData);
+int32_t tBlockDataSetSchema(SBlockData *pBlockData, STSchema *pTSchema);
+void tBlockDataClearData(SBlockData *pBlockData);
+void tBlockDataClear(SBlockData *pBlockData);
+int32_t tBlockDataAddColData(SBlockData *pBlockData, int32_t iColData, SColData **ppColData);
+int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema);
+int32_t tBlockDataMerge(SBlockData *pBlockData1, SBlockData *pBlockData2, SBlockData *pBlockData);
+int32_t tBlockDataCopy(SBlockData *pBlockDataSrc, SBlockData *pBlockDataDest);
+SColData *tBlockDataGetColDataByIdx(SBlockData *pBlockData, int32_t idx);
+void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColData);
+// SDelIdx
+int32_t tPutDelIdx(uint8_t *p, void *ph);
+int32_t tGetDelIdx(uint8_t *p, void *ph);
+int32_t tCmprDelIdx(void const *lhs, void const *rhs);
+// SDelData
+int32_t tPutDelData(uint8_t *p, void *ph);
+int32_t tGetDelData(uint8_t *p, void *ph);
+// SMapData
+#define tMapDataInit() ((SMapData){0})
+void tMapDataReset(SMapData *pMapData);
+void tMapDataClear(SMapData *pMapData);
+int32_t tMapDataPutItem(SMapData *pMapData, void *pItem, int32_t (*tPutItemFn)(uint8_t *, void *));
+void tMapDataGetItemByIdx(SMapData *pMapData, int32_t idx, void *pItem, int32_t (*tGetItemFn)(uint8_t *, void *));
+int32_t tMapDataSearch(SMapData *pMapData, void *pSearchItem, int32_t (*tGetItemFn)(uint8_t *, void *),
+ int32_t (*tItemCmprFn)(const void *, const void *), void *pItem);
+int32_t tPutMapData(uint8_t *p, SMapData *pMapData);
+int32_t tGetMapData(uint8_t *p, SMapData *pMapData);
+// other
+int32_t tsdbKeyFid(TSKEY key, int32_t minutes, int8_t precision);
+void tsdbFidKeyRange(int32_t fid, int32_t minutes, int8_t precision, TSKEY *minKey, TSKEY *maxKey);
+int32_t tsdbFidLevel(int32_t fid, STsdbKeepCfg *pKeepCfg, int64_t now);
+int32_t tsdbBuildDeleteSkyline(SArray *aDelData, int32_t sidx, int32_t eidx, SArray *aSkyline);
+void tsdbCalcColDataSMA(SColData *pColData, SColumnDataAgg *pColAgg);
// tsdbMemTable ==============================================================================================
-typedef struct STbData STbData;
-typedef struct SMemTable SMemTable;
-typedef struct STbDataIter STbDataIter;
-typedef struct SMergeInfo SMergeInfo;
-typedef struct STable STable;
-
// SMemTable
int32_t tsdbMemTableCreate(STsdb *pTsdb, SMemTable **ppMemTable);
void tsdbMemTableDestroy(SMemTable *pMemTable);
void tsdbGetTbDataFromMemTable(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t uid, STbData **ppTbData);
-
// STbDataIter
-int32_t tsdbTbDataIterCreate(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter **ppIter);
-void *tsdbTbDataIterDestroy(STbDataIter *pIter);
-void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter *pIter);
-bool tsdbTbDataIterNext(STbDataIter *pIter);
-bool tsdbTbDataIterGet(STbDataIter *pIter, TSDBROW *pRow);
-
+int32_t tsdbTbDataIterCreate(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter **ppIter);
+void *tsdbTbDataIterDestroy(STbDataIter *pIter);
+void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter *pIter);
+TSDBROW *tsdbTbDataIterGet(STbDataIter *pIter);
+bool tsdbTbDataIterNext(STbDataIter *pIter);
+// STbData
+int32_t tsdbGetNRowsInTbData(STbData *pTbData);
// tsdbFile.c ==============================================================================================
-typedef int32_t TSDB_FILE_T;
-typedef struct SDFInfo SDFInfo;
-typedef struct SDFile SDFile;
-typedef struct SDFileSet SDFileSet;
-
-// SDFile
-void tsdbInitDFile(STsdb *pRepo, SDFile *pDFile, SDiskID did, int fid, uint32_t ver, TSDB_FILE_T ftype);
-void tsdbInitDFileEx(SDFile *pDFile, SDFile *pODFile);
-int tsdbOpenDFile(SDFile *pDFile, int flags);
-void tsdbCloseDFile(SDFile *pDFile);
-int64_t tsdbSeekDFile(SDFile *pDFile, int64_t offset, int whence);
-int64_t tsdbWriteDFile(SDFile *pDFile, void *buf, int64_t nbyte);
-void tsdbUpdateDFileMagic(SDFile *pDFile, void *pCksm);
-int tsdbAppendDFile(SDFile *pDFile, void *buf, int64_t nbyte, int64_t *offset);
-int tsdbRemoveDFile(SDFile *pDFile);
-int64_t tsdbReadDFile(SDFile *pDFile, void *buf, int64_t nbyte);
-int tsdbCopyDFile(SDFile *pSrc, SDFile *pDest);
-int tsdbEncodeSDFile(void **buf, SDFile *pDFile);
-void *tsdbDecodeSDFile(STsdb *pRepo, void *buf, SDFile *pDFile);
-int tsdbCreateDFile(STsdb *pRepo, SDFile *pDFile, bool updateHeader, TSDB_FILE_T fType);
-int tsdbUpdateDFileHeader(SDFile *pDFile);
-int tsdbLoadDFileHeader(SDFile *pDFile, SDFInfo *pInfo);
-int tsdbParseDFilename(const char *fname, int *vid, int *fid, TSDB_FILE_T *ftype, uint32_t *version);
-
-// SDFileSet
-void tsdbInitDFileSet(STsdb *pRepo, SDFileSet *pSet, SDiskID did, int fid, uint32_t ver);
-void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet);
-int tsdbEncodeDFileSet(void **buf, SDFileSet *pSet);
-void *tsdbDecodeDFileSet(STsdb *pRepo, void *buf, SDFileSet *pSet);
-int tsdbEncodeDFileSetEx(void **buf, SDFileSet *pSet);
-void *tsdbDecodeDFileSetEx(void *buf, SDFileSet *pSet);
-int tsdbApplyDFileSetChange(SDFileSet *from, SDFileSet *to);
-int tsdbCreateDFileSet(STsdb *pRepo, SDFileSet *pSet, bool updateHeader);
-int tsdbUpdateDFileSetHeader(SDFileSet *pSet);
-int tsdbScanAndTryFixDFileSet(STsdb *pRepo, SDFileSet *pSet);
-void tsdbCloseDFileSet(SDFileSet *pSet);
-int tsdbOpenDFileSet(SDFileSet *pSet, int flags);
-void tsdbRemoveDFileSet(SDFileSet *pSet);
-int tsdbCopyDFileSet(SDFileSet *pSrc, SDFileSet *pDest);
-void tsdbGetFidKeyRange(int days, int8_t precision, int fid, TSKEY *minKey, TSKEY *maxKey);
-
+typedef enum { TSDB_HEAD_FILE = 0, TSDB_DATA_FILE, TSDB_LAST_FILE, TSDB_SMA_FILE } EDataFileT;
+void tsdbDataFileName(STsdb *pTsdb, SDFileSet *pDFileSet, EDataFileT ftype, char fname[]);
+bool tsdbFileIsSame(SDFileSet *pDFileSet1, SDFileSet *pDFileSet2, EDataFileT ftype);
+int32_t tsdbUpdateDFileHdr(TdFilePtr pFD, SDFileSet *pSet, EDataFileT ftype);
+int32_t tsdbDFileRollback(STsdb *pTsdb, SDFileSet *pSet, EDataFileT ftype);
+int32_t tPutDataFileHdr(uint8_t *p, SDFileSet *pSet, EDataFileT ftype);
+int32_t tPutDelFile(uint8_t *p, SDelFile *pDelFile);
+int32_t tGetDelFile(uint8_t *p, SDelFile *pDelFile);
+int32_t tPutDFileSet(uint8_t *p, SDFileSet *pSet);
+int32_t tGetDFileSet(uint8_t *p, SDFileSet *pSet);
+// SDelFile
+void tsdbDelFileName(STsdb *pTsdb, SDelFile *pFile, char fname[]);
// tsdbFS.c ==============================================================================================
-typedef struct STsdbFS STsdbFS;
-typedef struct SFSIter SFSIter;
-typedef struct STsdbFSMeta STsdbFSMeta;
-
-STsdbFS *tsdbNewFS(const STsdbKeepCfg *pCfg);
-void *tsdbFreeFS(STsdbFS *pfs);
-int tsdbOpenFS(STsdb *pRepo);
-void tsdbCloseFS(STsdb *pRepo);
-void tsdbStartFSTxn(STsdb *pRepo, int64_t pointsAdd, int64_t storageAdd);
-int tsdbEndFSTxn(STsdb *pRepo);
-int tsdbEndFSTxnWithError(STsdbFS *pfs);
-void tsdbUpdateFSTxnMeta(STsdbFS *pfs, STsdbFSMeta *pMeta);
-// void tsdbUpdateMFile(STsdbFS *pfs, const SMFile *pMFile);
-int tsdbUpdateDFileSet(STsdbFS *pfs, const SDFileSet *pSet);
-
-void tsdbFSIterInit(SFSIter *pIter, STsdbFS *pfs, int direction);
-void tsdbFSIterSeek(SFSIter *pIter, int fid);
-SDFileSet *tsdbFSIterNext(SFSIter *pIter);
-int tsdbLoadMetaCache(STsdb *pRepo, bool recoverMeta);
-int tsdbRLockFS(STsdbFS *pFs);
-int tsdbWLockFS(STsdbFS *pFs);
-int tsdbUnLockFS(STsdbFS *pFs);
-
-// structs
+int32_t tsdbFSOpen(STsdb *pTsdb, STsdbFS **ppFS);
+int32_t tsdbFSClose(STsdbFS *pFS);
+int32_t tsdbFSBegin(STsdbFS *pFS);
+int32_t tsdbFSCommit(STsdbFS *pFS);
+int32_t tsdbFSRollback(STsdbFS *pFS);
+
+int32_t tsdbFSStateUpsertDelFile(STsdbFSState *pState, SDelFile *pDelFile);
+int32_t tsdbFSStateUpsertDFileSet(STsdbFSState *pState, SDFileSet *pSet);
+void tsdbFSStateDeleteDFileSet(STsdbFSState *pState, int32_t fid);
+SDelFile *tsdbFSStateGetDelFile(STsdbFSState *pState);
+SDFileSet *tsdbFSStateGetDFileSet(STsdbFSState *pState, int32_t fid);
+// tsdbReaderWriter.c ==============================================================================================
+// SDataFWriter
+int32_t tsdbDataFWriterOpen(SDataFWriter **ppWriter, STsdb *pTsdb, SDFileSet *pSet);
+int32_t tsdbDataFWriterClose(SDataFWriter **ppWriter, int8_t sync);
+int32_t tsdbUpdateDFileSetHeader(SDataFWriter *pWriter);
+int32_t tsdbWriteBlockIdx(SDataFWriter *pWriter, SArray *aBlockIdx, uint8_t **ppBuf);
+int32_t tsdbWriteBlock(SDataFWriter *pWriter, SMapData *pMapData, uint8_t **ppBuf, SBlockIdx *pBlockIdx);
+int32_t tsdbWriteBlockData(SDataFWriter *pWriter, SBlockData *pBlockData, uint8_t **ppBuf1, uint8_t **ppBuf2,
+ SBlockIdx *pBlockIdx, SBlock *pBlock, int8_t cmprAlg);
+
+SDFileSet *tsdbDataFWriterGetWSet(SDataFWriter *pWriter);
+int32_t tsdbDFileSetCopy(STsdb *pTsdb, SDFileSet *pSetFrom, SDFileSet *pSetTo);
+// SDataFReader
+int32_t tsdbDataFReaderOpen(SDataFReader **ppReader, STsdb *pTsdb, SDFileSet *pSet);
+int32_t tsdbDataFReaderClose(SDataFReader **ppReader);
+int32_t tsdbReadBlockIdx(SDataFReader *pReader, SArray *aBlockIdx, uint8_t **ppBuf);
+int32_t tsdbReadBlock(SDataFReader *pReader, SBlockIdx *pBlockIdx, SMapData *pMapData, uint8_t **ppBuf);
+int32_t tsdbReadColData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, int16_t *aColId, int32_t nCol,
+ SBlockData *pBlockData, uint8_t **ppBuf1, uint8_t **ppBuf2);
+int32_t tsdbReadBlockData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, SBlockData *pBlockData,
+ uint8_t **ppBuf1, uint8_t **ppBuf2);
+int32_t tsdbReadBlockSma(SDataFReader *pReader, SBlock *pBlock, SArray *aColumnDataAgg, uint8_t **ppBuf);
+// SDelFWriter
+int32_t tsdbDelFWriterOpen(SDelFWriter **ppWriter, SDelFile *pFile, STsdb *pTsdb);
+int32_t tsdbDelFWriterClose(SDelFWriter **ppWriter, int8_t sync);
+int32_t tsdbWriteDelData(SDelFWriter *pWriter, SArray *aDelData, uint8_t **ppBuf, SDelIdx *pDelIdx);
+int32_t tsdbWriteDelIdx(SDelFWriter *pWriter, SArray *aDelIdx, uint8_t **ppBuf);
+int32_t tsdbUpdateDelFileHdr(SDelFWriter *pWriter);
+// SDelFReader
+int32_t tsdbDelFReaderOpen(SDelFReader **ppReader, SDelFile *pFile, STsdb *pTsdb, uint8_t **ppBuf);
+int32_t tsdbDelFReaderClose(SDelFReader **ppReader);
+int32_t tsdbReadDelData(SDelFReader *pReader, SDelIdx *pDelIdx, SArray *aDelData, uint8_t **ppBuf);
+int32_t tsdbReadDelIdx(SDelFReader *pReader, SArray *aDelIdx, uint8_t **ppBuf);
+
+#define TSDB_CACHE_NO(c) ((c).cacheLast == 0)
+#define TSDB_CACHE_LAST_ROW(c) (((c).cacheLast & 1) > 0)
+#define TSDB_CACHE_LAST(c) (((c).cacheLast & 2) > 0)
+
+// tsdbCache
+int32_t tsdbOpenCache(STsdb *pTsdb);
+void tsdbCloseCache(SLRUCache *pCache);
+int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb *pTsdb);
+int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, STSRow *row, bool dup);
+int32_t tsdbCacheGetLastH(SLRUCache *pCache, tb_uid_t uid, STsdb *pTsdb, LRUHandle **h);
+int32_t tsdbCacheGetLastrowH(SLRUCache *pCache, tb_uid_t uid, STsdb *pTsdb, LRUHandle **h);
+int32_t tsdbCacheRelease(SLRUCache *pCache, LRUHandle *h);
+
+int32_t tsdbCacheDeleteLastrow(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey);
+int32_t tsdbCacheDeleteLast(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey);
+int32_t tsdbCacheDelete(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey);
+
+void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity);
+size_t tsdbCacheGetCapacity(SVnode *pVnode);
+
+int32_t tsdbCacheLastArray2Row(SArray *pLastArray, STSRow **ppRow, STSchema *pSchema);
+
+// structs =======================
typedef struct {
int minFid;
int midFid;
@@ -132,22 +267,19 @@ typedef struct {
TSKEY minKey;
} SRtn;
-#define TSDB_DATA_DIR_LEN 6 // adapt accordingly
struct STsdb {
char *path;
SVnode *pVnode;
TdThreadMutex mutex;
- char dir[TSDB_DATA_DIR_LEN];
bool repoLocked;
STsdbKeepCfg keepCfg;
SMemTable *mem;
SMemTable *imem;
SRtn rtn;
STsdbFS *fs;
+ SLRUCache *lruCache;
};
-#if 1 // ======================================
-
struct STable {
uint64_t suid;
uint64_t uid;
@@ -155,43 +287,6 @@ struct STable {
STSchema *pCacheSchema; // cached cache
};
-// int tsdbPrepareCommit(STsdb *pTsdb);
-typedef enum {
- TSDB_FILE_HEAD = 0, // .head
- TSDB_FILE_DATA, // .data
- TSDB_FILE_LAST, // .last
- TSDB_FILE_SMAD, // .smad(Block-wise SMA)
- TSDB_FILE_SMAL, // .smal(Block-wise SMA)
- TSDB_FILE_MAX, //
- TSDB_FILE_META, // meta
-} E_TSDB_FILE_T;
-
-struct SDFInfo {
- uint32_t magic;
- uint32_t fver;
- uint32_t len;
- uint32_t totalBlocks;
- uint32_t totalSubBlocks;
- uint32_t offset;
- uint64_t size;
- uint64_t tombSize;
-};
-
-struct SDFile {
- SDFInfo info;
- STfsFile f;
- TdFilePtr pFile;
- uint8_t state;
-};
-
-struct SDFileSet {
- int fid;
- int8_t state; // -128~127
- uint8_t ver; // 0~255, DFileSet version
- uint16_t reserve;
- SDFile files[TSDB_FILE_MAX];
-};
-
struct TSDBKEY {
int64_t version;
TSKEY ts;
@@ -211,13 +306,21 @@ typedef struct SMemSkipList {
SMemSkipListNode *pTail;
} SMemSkipList;
+struct SDelDataInfo {
+ tb_uid_t suid;
+ tb_uid_t uid;
+};
+
struct STbData {
tb_uid_t suid;
tb_uid_t uid;
- TSDBKEY minKey;
- TSDBKEY maxKey;
- SDelOp *pHead;
- SDelOp *pTail;
+ TSKEY minKey;
+ TSKEY maxKey;
+ int64_t minVersion;
+ int64_t maxVersion;
+ int32_t maxSkmVer;
+ SDelData *pHead;
+ SDelData *pTail;
SMemSkipList sl;
};
@@ -225,157 +328,87 @@ struct SMemTable {
SRWLatch latch;
STsdb *pTsdb;
int32_t nRef;
- TSDBKEY minKey;
- TSDBKEY maxKey;
+ TSKEY minKey;
+ TSKEY maxKey;
+ int64_t minVersion;
+ int64_t maxVersion;
int64_t nRow;
- int64_t nDelOp;
- SArray *aTbData; // SArray
-};
-
-struct STsdbFSMeta {
- uint32_t version; // Commit version from 0 to increase
- int64_t totalPoints; // total points
- int64_t totalStorage; // Uncompressed total storage
-};
-
-// ==================
-typedef struct {
- STsdbFSMeta meta; // FS meta
- SDFile cacheFile; // cache file
- SDFile tombstone; // tomestome file
- SArray *df; // data file array
- SArray *sf; // sma data file array v2f1900.index_name_1
-} SFSStatus;
-
-struct STsdbFS {
- TdThreadRwlock lock;
-
- SFSStatus *cstatus; // current status
- bool intxn;
- SFSStatus *nstatus; // new status
+ int64_t nDel;
+ SArray *aTbData; // SArray
};
-#define REPO_ID(r) TD_VID((r)->pVnode)
-#define REPO_CFG(r) (&(r)->pVnode->config.tsdbCfg)
-#define REPO_KEEP_CFG(r) (&(r)->keepCfg)
-#define REPO_FS(r) ((r)->fs)
-#define REPO_META(r) ((r)->pVnode->pMeta)
-#define REPO_TFS(r) ((r)->pVnode->pTfs)
-#define IS_REPO_LOCKED(r) ((r)->repoLocked)
-
int tsdbLockRepo(STsdb *pTsdb);
int tsdbUnlockRepo(STsdb *pTsdb);
-static FORCE_INLINE STSchema *tsdbGetTableSchemaImpl(STsdb *pTsdb, STable *pTable, bool lock, bool copy,
- int32_t version) {
- if ((version < 0) || (schemaVersion(pTable->pSchema) == version)) {
- return pTable->pSchema;
- }
-
- if (!pTable->pCacheSchema || (schemaVersion(pTable->pCacheSchema) != version)) {
- taosMemoryFreeClear(pTable->pCacheSchema);
- pTable->pCacheSchema = metaGetTbTSchema(REPO_META(pTsdb), pTable->uid, version);
- }
- return pTable->pCacheSchema;
-}
-
-// tsdbMemTable.h
-struct SMergeInfo {
- int rowsInserted;
- int rowsUpdated;
- int rowsDeleteSucceed;
- int rowsDeleteFailed;
- int nOperations;
- TSKEY keyFirst;
- TSKEY keyLast;
-};
-
-static void *taosTMalloc(size_t size);
-static void *taosTCalloc(size_t nmemb, size_t size);
-static void *taosTRealloc(void *ptr, size_t size);
-static void *taosTZfree(void *ptr);
-static size_t taosTSizeof(void *ptr);
-static void taosTMemset(void *ptr, int c);
-
struct TSDBROW {
- int64_t version;
- STSRow *pTSRow;
+ int8_t type; // 0 for row from tsRow, 1 for row from block data
+ union {
+ struct {
+ int64_t version;
+ STSRow *pTSRow;
+ };
+ struct {
+ SBlockData *pBlockData;
+ int32_t iRow;
+ };
+ };
};
-static FORCE_INLINE STSRow *tsdbNextIterRow(STbDataIter *pIter) {
- TSDBROW row;
-
- if (pIter == NULL) return NULL;
-
- if (tsdbTbDataIterGet(pIter, &row)) {
- return row.pTSRow;
- }
-
- return NULL;
-}
-
-static FORCE_INLINE TSKEY tsdbNextIterKey(STbDataIter *pIter) {
- STSRow *row = tsdbNextIterRow(pIter);
- if (row == NULL) return TSDB_DATA_TIMESTAMP_NULL;
-
- return TD_ROW_KEY(row);
-}
-
-// tsdbReadImpl
-typedef struct SReadH SReadH;
-
-typedef struct {
- uint64_t suid;
- uint64_t uid;
- uint32_t len;
- uint32_t offset;
- uint32_t hasLast : 2;
- uint32_t numOfBlocks : 30;
- TSDBKEY maxKey;
-} SBlockIdx;
-
-typedef enum {
- TSDB_SBLK_VER_0 = 0,
- TSDB_SBLK_VER_MAX,
-} ESBlockVer;
-
-#define SBlockVerLatest TSDB_SBLK_VER_0
-
-typedef struct {
- uint8_t last : 1;
- uint8_t hasDupKey : 1; // 0: no dup TS key, 1: has dup TS key(since supporting Multi-Version)
- uint8_t blkVer : 6;
- uint8_t numOfSubBlocks;
- col_id_t numOfCols; // not including timestamp column
- uint32_t len; // data block length
- uint32_t keyLen : 20; // key column length, keyOffset = offset+sizeof(SBlockData)+sizeof(SBlockCol)*numOfCols
- uint32_t algorithm : 4;
- uint32_t reserve : 8;
- col_id_t numOfBSma;
- uint16_t numOfRows;
- int64_t offset;
- uint64_t aggrStat : 1;
- uint64_t aggrOffset : 63;
- TSDBKEY minKey;
- TSDBKEY maxKey;
-} SBlock;
+struct SBlockIdx {
+ int64_t suid;
+ int64_t uid;
+ TSKEY minKey;
+ TSKEY maxKey;
+ int64_t minVersion;
+ int64_t maxVersion;
+ int64_t offset;
+ int64_t size;
+};
-typedef struct {
- int32_t delimiter; // For recovery usage
- uint64_t suid;
- uint64_t uid;
- SBlock blocks[];
-} SBlockInfo;
+struct SMapData {
+ int32_t nItem;
+ int32_t *aOffset;
+ int32_t nData;
+ uint8_t *pData;
+};
typedef struct {
- int16_t colId;
- uint16_t type : 6;
- uint16_t blen : 10; // 0 no bitmap if all rows are NORM, > 0 bitmap length
- uint32_t len; // data length + bitmap length
- uint32_t offset;
+ int16_t cid;
+ int8_t type;
+ int8_t smaOn;
+ int8_t flag; // HAS_NONE|HAS_NULL|HAS_VALUE
+ int32_t offset;
+ int32_t szBitmap; // bitmap size
+ int32_t szOffset; // size of offset, only for variant-length data type
+ int32_t szValue; // compressed column value size
+ int32_t szOrigin; // original column value size (only save for variant data type)
} SBlockCol;
typedef struct {
+ int32_t nRow;
+ int8_t cmprAlg;
+ int64_t offset; // block data offset
+ int32_t szBlockCol; // SBlockCol size
+ int32_t szVersion; // VERSION size
+ int32_t szTSKEY; // TSKEY size
+ int32_t szBlock; // total block size
+ int64_t sOffset; // sma offset
+ int32_t nSma; // sma size
+} SSubBlock;
+
+struct SBlock {
+ TSDBKEY minKey;
+ TSDBKEY maxKey;
+ int64_t minVersion;
+ int64_t maxVersion;
+ int32_t nRow;
+ int8_t last;
+ int8_t hasDup;
+ int8_t nSubBlock;
+ SSubBlock aSubBlock[TSDB_MAX_SUBBLOCKS];
+};
+
+struct SAggrBlkCol {
int16_t colId;
int16_t maxIndex;
int16_t minIndex;
@@ -383,330 +416,139 @@ typedef struct {
int64_t sum;
int64_t max;
int64_t min;
-} SAggrBlkCol;
-
-typedef struct {
- int32_t delimiter; // For recovery usage
- int32_t numOfCols; // For recovery usage
- uint64_t uid; // For recovery usage
- SBlockCol cols[];
-} SBlockData;
-
-typedef void SAggrBlkData; // SBlockCol cols[];
-
-struct SReadH {
- STsdb *pRepo;
- SDFileSet rSet; // FSET to read
- SArray *aBlkIdx; // SBlockIdx array
- STable *pTable; // table to read
- SBlockIdx *pBlkIdx; // current reading table SBlockIdx
- int cidx;
- SBlockInfo *pBlkInfo;
- SBlockData *pBlkData; // Block info
- SAggrBlkData *pAggrBlkData; // Aggregate Block info
- SDataCols *pDCols[2];
- void *pBuf; // buffer
- void *pCBuf; // compression buffer
- void *pExBuf; // extra buffer
};
-#define TSDB_READ_REPO(rh) ((rh)->pRepo)
-#define TSDB_READ_REPO_ID(rh) REPO_ID(TSDB_READ_REPO(rh))
-#define TSDB_READ_FSET(rh) (&((rh)->rSet))
-#define TSDB_READ_TABLE(rh) ((rh)->pTable)
-#define TSDB_READ_TABLE_UID(rh) ((rh)->pTable->uid)
-#define TSDB_READ_HEAD_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_HEAD)
-#define TSDB_READ_DATA_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_DATA)
-#define TSDB_READ_LAST_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_LAST)
-#define TSDB_READ_SMAD_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_SMAD)
-#define TSDB_READ_SMAL_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_SMAL)
-#define TSDB_READ_BUF(rh) ((rh)->pBuf)
-#define TSDB_READ_COMP_BUF(rh) ((rh)->pCBuf)
-#define TSDB_READ_EXBUF(rh) ((rh)->pExBuf)
-
-#define TSDB_BLOCK_STATIS_SIZE(ncols, blkVer) (sizeof(SBlockData) + sizeof(SBlockCol) * (ncols) + sizeof(TSCKSUM))
-
-static FORCE_INLINE size_t tsdbBlockStatisSize(int nCols, uint32_t blkVer) {
- switch (blkVer) {
- case TSDB_SBLK_VER_0:
- default:
- return TSDB_BLOCK_STATIS_SIZE(nCols, 0);
- }
-}
-
-#define TSDB_BLOCK_AGGR_SIZE(ncols, blkVer) (sizeof(SAggrBlkCol) * (ncols) + sizeof(TSCKSUM))
-
-static FORCE_INLINE size_t tsdbBlockAggrSize(int nCols, uint32_t blkVer) {
- switch (blkVer) {
- case TSDB_SBLK_VER_0:
- default:
- return TSDB_BLOCK_AGGR_SIZE(nCols, 0);
- }
-}
-
-int tsdbInitReadH(SReadH *pReadh, STsdb *pRepo);
-void tsdbDestroyReadH(SReadH *pReadh);
-int tsdbSetAndOpenReadFSet(SReadH *pReadh, SDFileSet *pSet);
-void tsdbCloseAndUnsetFSet(SReadH *pReadh);
-int tsdbLoadBlockIdx(SReadH *pReadh);
-int tsdbSetReadTable(SReadH *pReadh, STable *pTable);
-int tsdbLoadBlockInfo(SReadH *pReadh, void *pTarget);
-int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlockInfo);
-int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo, const int16_t *colIds, int numOfColsIds,
- bool mergeBitmap);
-int tsdbLoadBlockStatis(SReadH *pReadh, SBlock *pBlock);
-int tsdbEncodeSBlockIdx(void **buf, SBlockIdx *pIdx);
-void *tsdbDecodeSBlockIdx(void *buf, SBlockIdx *pIdx);
-void tsdbGetBlockStatis(SReadH *pReadh, SColumnDataAgg *pStatis, int numOfCols, SBlock *pBlock);
-
-static FORCE_INLINE int tsdbMakeRoom(void **ppBuf, size_t size) {
- void *pBuf = *ppBuf;
- size_t tsize = taosTSizeof(pBuf);
-
- if (tsize < size) {
- if (tsize == 0) tsize = 1024;
-
- while (tsize < size) {
- tsize *= 2;
- }
-
- *ppBuf = taosTRealloc(pBuf, tsize);
- if (*ppBuf == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
- }
-
- return 0;
-}
-
-// tsdbMemory
-static FORCE_INLINE void *taosTMalloc(size_t size) {
- if (size <= 0) return NULL;
-
- void *ret = taosMemoryMalloc(size + sizeof(size_t));
- if (ret == NULL) return NULL;
-
- *(size_t *)ret = size;
-
- return (void *)((char *)ret + sizeof(size_t));
-}
-
-static FORCE_INLINE void *taosTCalloc(size_t nmemb, size_t size) {
- size_t tsize = nmemb * size;
- void *ret = taosTMalloc(tsize);
- if (ret == NULL) return NULL;
-
- taosTMemset(ret, 0);
- return ret;
-}
-
-static FORCE_INLINE size_t taosTSizeof(void *ptr) { return (ptr) ? (*(size_t *)((char *)ptr - sizeof(size_t))) : 0; }
-
-static FORCE_INLINE void taosTMemset(void *ptr, int c) { memset(ptr, c, taosTSizeof(ptr)); }
-
-static FORCE_INLINE void *taosTRealloc(void *ptr, size_t size) {
- if (ptr == NULL) return taosTMalloc(size);
-
- if (size <= taosTSizeof(ptr)) return ptr;
+struct SColData {
+ int16_t cid;
+ int8_t type;
+ int8_t smaOn;
+ int32_t nVal;
+ uint8_t flag;
+ uint8_t *pBitMap;
+ int32_t *aOffset;
+ int32_t nData;
+ uint8_t *pData;
+};
- void *tptr = (void *)((char *)ptr - sizeof(size_t));
- size_t tsize = size + sizeof(size_t);
- void *tptr1 = taosMemoryRealloc(tptr, tsize);
- if (tptr1 == NULL) return NULL;
- tptr = tptr1;
+struct SBlockData {
+ int32_t nRow;
+ int64_t *aVersion;
+ TSKEY *aTSKEY;
+ SArray *aIdx; // SArray
+ SArray *aColData; // SArray
+};
- *(size_t *)tptr = size;
+// ================== TSDB global config
+extern bool tsdbForceKeepFile;
- return (void *)((char *)tptr + sizeof(size_t));
-}
+#define TSDB_FS_ITER_FORWARD TSDB_ORDER_ASC
+#define TSDB_FS_ITER_BACKWARD TSDB_ORDER_DESC
-static FORCE_INLINE void *taosTZfree(void *ptr) {
- if (ptr) {
- taosMemoryFree((void *)((char *)ptr - sizeof(size_t)));
- }
- return NULL;
-}
+struct TABLEID {
+ tb_uid_t suid;
+ tb_uid_t uid;
+};
-// tsdbCommit
+struct STbDataIter {
+ STbData *pTbData;
+ int8_t backward;
+ SMemSkipListNode *pNode;
+ TSDBROW *pRow;
+ TSDBROW row;
+};
-void tsdbGetRtnSnap(STsdb *pRepo, SRtn *pRtn);
+struct SDelData {
+ int64_t version;
+ TSKEY sKey;
+ TSKEY eKey;
+ SDelData *pNext;
+};
-static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t minutes, int8_t precision) {
- if (key < 0) {
- return (int)((key + 1) / tsTickPerMin[precision] / minutes - 1);
- } else {
- return (int)((key / tsTickPerMin[precision] / minutes));
- }
-}
+struct SDelIdx {
+ tb_uid_t suid;
+ tb_uid_t uid;
+ int64_t offset;
+ int64_t size;
+};
-static FORCE_INLINE int tsdbGetFidLevel(int fid, SRtn *pRtn) {
- if (fid >= pRtn->maxFid) {
- return 0;
- } else if (fid >= pRtn->midFid) {
- return 1;
- } else if (fid >= pRtn->minFid) {
- return 2;
- } else {
- return -1;
- }
-}
+struct SDelFile {
+ int64_t commitID;
+ int64_t size;
+ int64_t offset;
+};
-// tsdbFile
-#define TSDB_FILE_HEAD_SIZE 512
-#define TSDB_FILE_DELIMITER 0xF00AFA0F
-#define TSDB_FILE_INIT_MAGIC 0xFFFFFFFF
-#define TSDB_IVLD_FID INT_MIN
-#define TSDB_FILE_STATE_OK 0
-#define TSDB_FILE_STATE_BAD 1
-
-#define TSDB_FILE_F(tf) (&((tf)->f))
-#define TSDB_FILE_PFILE(tf) ((tf)->pFile)
-#define TSDB_FILE_FULL_NAME(tf) (TSDB_FILE_F(tf)->aname)
-#define TSDB_FILE_OPENED(tf) (TSDB_FILE_PFILE(tf) != NULL)
-#define TSDB_FILE_CLOSED(tf) (!TSDB_FILE_OPENED(tf))
-#define TSDB_FILE_SET_CLOSED(f) (TSDB_FILE_PFILE(f) = NULL)
-#define TSDB_FILE_LEVEL(tf) (TSDB_FILE_F(tf)->did.level)
-#define TSDB_FILE_ID(tf) (TSDB_FILE_F(tf)->did.id)
-#define TSDB_FILE_DID(tf) (TSDB_FILE_F(tf)->did)
-#define TSDB_FILE_REL_NAME(tf) (TSDB_FILE_F(tf)->rname)
-#define TSDB_FILE_ABS_NAME(tf) (TSDB_FILE_F(tf)->aname)
-#define TSDB_FILE_FSYNC(tf) taosFsyncFile(TSDB_FILE_PFILE(tf))
-#define TSDB_FILE_STATE(tf) ((tf)->state)
-#define TSDB_FILE_SET_STATE(tf, s) ((tf)->state = (s))
-#define TSDB_FILE_IS_OK(tf) (TSDB_FILE_STATE(tf) == TSDB_FILE_STATE_OK)
-#define TSDB_FILE_IS_BAD(tf) (TSDB_FILE_STATE(tf) == TSDB_FILE_STATE_BAD)
-
-typedef enum {
- TSDB_FS_VER_0 = 0,
- TSDB_FS_VER_MAX,
-} ETsdbFsVer;
-
-#define TSDB_LATEST_FVER TSDB_FS_VER_0 // latest version for DFile
-#define TSDB_LATEST_SFS_VER TSDB_FS_VER_0 // latest version for 'current' file
-
-static FORCE_INLINE uint32_t tsdbGetDFSVersion(TSDB_FILE_T fType) { // latest version for DFile
- switch (fType) {
- case TSDB_FILE_HEAD: // .head
- case TSDB_FILE_DATA: // .data
- case TSDB_FILE_LAST: // .last
- case TSDB_FILE_SMAD: // .smad(Block-wise SMA)
- case TSDB_FILE_SMAL: // .smal(Block-wise SMA)
- default:
- return TSDB_LATEST_FVER;
- }
-}
+#pragma pack(push, 1)
+struct SBlockDataHdr {
+ uint32_t delimiter;
+ int64_t suid;
+ int64_t uid;
+};
+#pragma pack(pop)
-// =============== SDFileSet
-
-#define TSDB_LATEST_FSET_VER 0
-#define TSDB_FSET_FID(s) ((s)->fid)
-#define TSDB_FSET_STATE(s) ((s)->state)
-#define TSDB_FSET_VER(s) ((s)->ver)
-#define TSDB_DFILE_IN_SET(s, t) ((s)->files + (t))
-#define TSDB_FSET_LEVEL(s) TSDB_FILE_LEVEL(TSDB_DFILE_IN_SET(s, 0))
-#define TSDB_FSET_ID(s) TSDB_FILE_ID(TSDB_DFILE_IN_SET(s, 0))
-#define TSDB_FSET_SET_CLOSED(s) \
- do { \
- for (TSDB_FILE_T ftype = TSDB_FILE_HEAD; ftype < TSDB_FILE_MAX; ftype++) { \
- TSDB_FILE_SET_CLOSED(TSDB_DFILE_IN_SET(s, ftype)); \
- } \
- } while (0);
-#define TSDB_FSET_FSYNC(s) \
- do { \
- for (TSDB_FILE_T ftype = TSDB_FILE_HEAD; ftype < TSDB_FILE_MAX; ftype++) { \
- TSDB_FILE_FSYNC(TSDB_DFILE_IN_SET(s, ftype)); \
- } \
- } while (0);
-
-static FORCE_INLINE bool tsdbFSetIsOk(SDFileSet *pSet) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (TSDB_FILE_IS_BAD(TSDB_DFILE_IN_SET(pSet, ftype))) {
- return false;
- }
- }
-
- return true;
-}
+struct SHeadFile {
+ int64_t commitID;
+ int64_t size;
+ int64_t offset;
+};
-// tsdbFS
-// ================== TSDB global config
-extern bool tsdbForceKeepFile;
+struct SDataFile {
+ int64_t commitID;
+ int64_t size;
+};
-// ================== CURRENT file header info
-typedef struct {
- uint32_t version; // Current file system version (relating to code)
- uint32_t len; // Encode content length (including checksum)
-} SFSHeader;
-
-// ================== TSDB File System Meta
-#define FS_CURRENT_STATUS(pfs) ((pfs)->cstatus)
-#define FS_NEW_STATUS(pfs) ((pfs)->nstatus)
-#define FS_IN_TXN(pfs) (pfs)->intxn
-#define FS_VERSION(pfs) ((pfs)->cstatus->meta.version)
-#define FS_TXN_VERSION(pfs) ((pfs)->nstatus->meta.version)
-
-struct SFSIter {
- int direction;
- uint64_t version; // current FS version
- STsdbFS *pfs;
- int index; // used to position next fset when version the same
- int fid; // used to seek when version is changed
- SDFileSet *pSet;
+struct SLastFile {
+ int64_t commitID;
+ int64_t size;
};
-#define TSDB_FS_ITER_FORWARD TSDB_ORDER_ASC
-#define TSDB_FS_ITER_BACKWARD TSDB_ORDER_DESC
+struct SSmaFile {
+ int64_t commitID;
+ int64_t size;
+};
-struct TABLEID {
- tb_uid_t suid;
- tb_uid_t uid;
+struct SDFileSet {
+ SDiskID diskId;
+ int32_t fid;
+ SHeadFile fHead;
+ SDataFile fData;
+ SLastFile fLast;
+ SSmaFile fSma;
};
-struct SDelOp {
- int64_t version;
- TSKEY sKey; // included
- TSKEY eKey; // included
- SDelOp *pNext;
+struct SRowIter {
+ TSDBROW *pRow;
+ STSchema *pTSchema;
+ SColVal colVal;
+ int32_t i;
+};
+struct SRowMerger {
+ STSchema *pTSchema;
+ int64_t version;
+ SArray *pArray; // SArray
};
-typedef struct {
- tb_uid_t suid;
- tb_uid_t uid;
- int64_t version;
- TSKEY sKey;
- TSKEY eKey;
-} SDelInfo;
-
-static FORCE_INLINE int 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;
-}
+struct STsdbFSState {
+ SDelFile *pDelFile;
+ SArray *aDFileSet; // SArray
+ SDelFile delFile;
+};
-struct STbDataIter {
- STbData *pTbData;
- int8_t backward;
- SMemSkipListNode *pNode;
+struct STsdbFS {
+ STsdb *pTsdb;
+ TdThreadRwlock lock;
+ int8_t inTxn;
+ STsdbFSState *cState;
+ STsdbFSState *nState;
};
-#endif
+struct SDelFWriter {
+ STsdb *pTsdb;
+ SDelFile fDel;
+ TdFilePtr pWriteH;
+};
#ifdef __cplusplus
}
#endif
-#endif /*_TD_VNODE_TSDB_H_*/
\ No newline at end of file
+#endif /*_TD_VNODE_TSDB_H_*/
diff --git a/source/dnode/vnode/src/inc/vnd.h b/source/dnode/vnode/src/inc/vnd.h
index 9339402d4300c9271017110f5b0da4a4c672bf05..cb25e93cde52b3ef293ffec568ab3159ad0fd731 100644
--- a/source/dnode/vnode/src/inc/vnd.h
+++ b/source/dnode/vnode/src/inc/vnd.h
@@ -32,7 +32,14 @@ extern "C" {
#define vInfo(...) do { if (vDebugFlag & DEBUG_INFO) { taosPrintLog("VND ", DEBUG_INFO, 255, __VA_ARGS__); }} while(0)
#define vDebug(...) do { if (vDebugFlag & DEBUG_DEBUG) { taosPrintLog("VND ", DEBUG_DEBUG, vDebugFlag, __VA_ARGS__); }} while(0)
#define vTrace(...) do { if (vDebugFlag & DEBUG_TRACE) { taosPrintLog("VND ", DEBUG_TRACE, vDebugFlag, __VA_ARGS__); }} while(0)
-#define vGTrace(param, ...) do { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vTrace(param " GTID: %s", __VA_ARGS__, buf);} while(0)//#define vDye(...) do
+
+#define vGTrace(param, ...) do { if (vDebugFlag & DEBUG_TRACE) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vTrace(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+#define vGFatal(param, ...) do { if (vDebugFlag & DEBUG_FATAL) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vFatal(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+#define vGError(param, ...) do { if (vDebugFlag & DEBUG_ERROR) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vError(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+#define vGWarn(param, ...) do { if (vDebugFlag & DEBUG_WARN) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vWarn(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+#define vGInfo(param, ...) do { if (vDebugFlag & DEBUG_INFO) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vInfo(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+#define vGDebug(param, ...) do { if (vDebugFlag & DEBUG_DEBUG) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vDebug(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
+
// clang-format on
// vnodeCfg.c
@@ -71,6 +78,7 @@ void vnodeBufPoolReset(SVBufPool* pPool);
int32_t vnodeQueryOpen(SVnode* pVnode);
void vnodeQueryClose(SVnode* pVnode);
int32_t vnodeGetTableMeta(SVnode* pVnode, SRpcMsg* pMsg);
+int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg);
// vnodeCommit.c
int32_t vnodeBegin(SVnode* pVnode);
@@ -86,6 +94,8 @@ int32_t vnodeAsyncCommit(SVnode* pVnode);
int32_t vnodeSyncOpen(SVnode* pVnode, char* path);
void vnodeSyncStart(SVnode* pVnode);
void vnodeSyncClose(SVnode* pVnode);
+void vnodeRedirectRpcMsg(SVnode* pVnode, SRpcMsg* pMsg);
+bool vnodeIsLeader(SVnode* pVnode);
#ifdef __cplusplus
}
diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h
index c0dfebb08f566e6a9e28d233c7dc7c8dd1a991ea..7b298ba830a348f280032fc36415cbb7f496bcae 100644
--- a/source/dnode/vnode/src/inc/vnodeInt.h
+++ b/source/dnode/vnode/src/inc/vnodeInt.h
@@ -20,6 +20,7 @@
#include "filter.h"
#include "qworker.h"
#include "sync.h"
+#include "tRealloc.h"
#include "tchecksum.h"
#include "tcoding.h"
#include "tcompare.h"
@@ -33,8 +34,9 @@
#include "tlist.h"
#include "tlockfree.h"
#include "tlosertree.h"
-#include "tmallocator.h"
+#include "tlrucache.h"
#include "tmsgcb.h"
+#include "tref.h"
#include "tskiplist.h"
#include "tstream.h"
#include "ttime.h"
@@ -47,35 +49,38 @@
extern "C" {
#endif
-typedef struct SVnodeInfo SVnodeInfo;
-typedef struct SMeta SMeta;
-typedef struct SSma SSma;
-typedef struct STsdb STsdb;
-typedef struct STQ STQ;
-typedef struct SVState SVState;
-typedef struct SVBufPool SVBufPool;
-typedef struct SQWorker SQHandle;
-typedef struct STsdbKeepCfg STsdbKeepCfg;
-typedef struct SMetaSnapshotReader SMetaSnapshotReader;
-typedef struct STsdbSnapshotReader STsdbSnapshotReader;
+typedef struct SVnodeInfo SVnodeInfo;
+typedef struct SMeta SMeta;
+typedef struct SSma SSma;
+typedef struct STsdb STsdb;
+typedef struct STQ STQ;
+typedef struct SVState SVState;
+typedef struct SVBufPool SVBufPool;
+typedef struct SQWorker SQHandle;
+typedef struct STsdbKeepCfg STsdbKeepCfg;
+typedef struct SMetaSnapReader SMetaSnapReader;
+typedef struct SMetaSnapWriter SMetaSnapWriter;
+typedef struct STsdbSnapReader STsdbSnapReader;
+typedef struct STsdbSnapWriter STsdbSnapWriter;
+typedef struct SSnapDataHdr SSnapDataHdr;
#define VNODE_META_DIR "meta"
#define VNODE_TSDB_DIR "tsdb"
#define VNODE_TQ_DIR "tq"
#define VNODE_WAL_DIR "wal"
#define VNODE_TSMA_DIR "tsma"
+#define VNODE_RSMA_DIR "rsma"
#define VNODE_RSMA0_DIR "tsdb"
#define VNODE_RSMA1_DIR "rsma1"
#define VNODE_RSMA2_DIR "rsma2"
// vnd.h
-void* vnodeBufPoolMalloc(SVBufPool* pPool, int size);
-void vnodeBufPoolFree(SVBufPool* pPool, void* p);
-int32_t vnodeRealloc(void** pp, int32_t size);
-void vnodeFree(void* p);
+void* vnodeBufPoolMalloc(SVBufPool* pPool, int size);
+void vnodeBufPoolFree(SVBufPool* pPool, void* p);
// meta
typedef struct SMCtbCursor SMCtbCursor;
+typedef struct SMStbCursor SMStbCursor;
typedef struct STbUidStore STbUidStore;
int metaOpen(SVnode* pVnode, SMeta** ppMeta);
@@ -91,19 +96,20 @@ int metaTtlDropTable(SMeta* pMeta, int64_t ttl, SArray* tbUids);
int metaAlterTable(SMeta* pMeta, int64_t version, SVAlterTbReq* pReq, STableMetaRsp* pMetaRsp);
SSchemaWrapper* metaGetTableSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver, bool isinline);
STSchema* metaGetTbTSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver);
+int32_t metaGetTbTSchemaEx(SMeta* pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sver, STSchema** ppTSchema);
int metaGetTableEntryByName(SMetaReader* pReader, const char* name);
tb_uid_t metaGetTableEntryUidByName(SMeta* pMeta, const char* name);
int metaGetTbNum(SMeta* pMeta);
SMCtbCursor* metaOpenCtbCursor(SMeta* pMeta, tb_uid_t uid);
void metaCloseCtbCursor(SMCtbCursor* pCtbCur);
tb_uid_t metaCtbCursorNext(SMCtbCursor* pCtbCur);
+SMStbCursor* metaOpenStbCursor(SMeta* pMeta, tb_uid_t uid);
+void metaCloseStbCursor(SMStbCursor* pStbCur);
+tb_uid_t metaStbCursorNext(SMStbCursor* pStbCur);
STSma* metaGetSmaInfoByIndex(SMeta* pMeta, int64_t indexUid);
STSmaWrapper* metaGetSmaInfoByTable(SMeta* pMeta, tb_uid_t uid, bool deepCopy);
SArray* metaGetSmaIdsByTable(SMeta* pMeta, tb_uid_t uid);
SArray* metaGetSmaTbUids(SMeta* pMeta);
-int32_t metaSnapshotReaderOpen(SMeta* pMeta, SMetaSnapshotReader** ppReader, int64_t sver, int64_t ever);
-int32_t metaSnapshotReaderClose(SMetaSnapshotReader* pReader);
-int32_t metaSnapshotRead(SMetaSnapshotReader* pReader, void** ppData, uint32_t* nData);
void* metaGetIdx(SMeta* pMeta);
void* metaGetIvtIdx(SMeta* pMeta);
int metaTtlSmaller(SMeta* pMeta, uint64_t time, SArray* uidList);
@@ -116,18 +122,14 @@ int tsdbOpen(SVnode* pVnode, STsdb** ppTsdb, const char* dir, STsdbKeepC
int tsdbClose(STsdb** pTsdb);
int32_t tsdbBegin(STsdb* pTsdb);
int32_t tsdbCommit(STsdb* pTsdb);
+int32_t tsdbDoRetention(STsdb* pTsdb, int64_t now);
int tsdbScanAndConvertSubmitMsg(STsdb* pTsdb, SSubmitReq* pMsg);
int tsdbInsertData(STsdb* pTsdb, int64_t version, SSubmitReq* pMsg, SSubmitRsp* pRsp);
int32_t tsdbInsertTableData(STsdb* pTsdb, int64_t version, SSubmitMsgIter* pMsgIter, SSubmitBlk* pBlock,
SSubmitBlkRsp* pRsp);
int32_t tsdbDeleteTableData(STsdb* pTsdb, int64_t version, tb_uid_t suid, tb_uid_t uid, TSKEY sKey, TSKEY eKey);
-tsdbReaderT tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, STableListInfo* tableList, uint64_t qId,
- uint64_t taskId);
-tsdbReaderT tsdbQueryCacheLastT(STsdb* tsdb, SQueryTableDataCond* pCond, STableListInfo* tableList, uint64_t qId,
+STsdbReader tsdbQueryCacheLastT(STsdb* tsdb, SQueryTableDataCond* pCond, STableListInfo* tableList, uint64_t qId,
void* pMemRef);
-int32_t tsdbSnapshotReaderOpen(STsdb* pTsdb, STsdbSnapshotReader** ppReader, int64_t sver, int64_t ever);
-int32_t tsdbSnapshotReaderClose(STsdbSnapshotReader* pReader);
-int32_t tsdbSnapshotRead(STsdbSnapshotReader* pReader, void** ppData, uint32_t* nData);
// tq
int tqInit();
@@ -149,24 +151,52 @@ int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskRecoverReq(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskRecoverRsp(STQ* pTq, SRpcMsg* pMsg);
+int32_t tqProcessTaskRetrieveReq(STQ* pTq, SRpcMsg* pMsg);
+int32_t tqProcessTaskRetrieveRsp(STQ* pTq, SRpcMsg* pMsg);
+int32_t tsdbGetStbIdList(SMeta* pMeta, int64_t suid, SArray* list);
SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pSchema, bool createTb, int64_t suid,
const char* stbFullName, int32_t vgId);
// sma
+int32_t smaInit();
+void smaCleanUp();
int32_t smaOpen(SVnode* pVnode);
int32_t smaClose(SSma* pSma);
+int32_t smaBegin(SSma* pSma);
+int32_t smaPreCommit(SSma* pSma);
+int32_t smaCommit(SSma* pSma);
+int32_t smaPostCommit(SSma* pSma);
int32_t tdProcessTSmaCreate(SSma* pSma, int64_t version, const char* msg);
int32_t tdProcessTSmaInsert(SSma* pSma, int64_t indexUid, const char* msg);
+int64_t tdRSmaGetMaxSubmitVer(SSma* pSma, int8_t level);
-int32_t tdProcessRSmaCreate(SVnode* pVnode, SVCreateStbReq* pReq);
+int32_t tdProcessRSmaCreate(SSma* pSma, SVCreateStbReq* pReq);
int32_t tdProcessRSmaSubmit(SSma* pSma, void* pMsg, int32_t inputType);
+int32_t tdProcessRSmaDrop(SSma* pSma, SVDropStbReq* pReq);
int32_t tdFetchTbUidList(SSma* pSma, STbUidStore** ppStore, tb_uid_t suid, tb_uid_t uid);
int32_t tdUpdateTbUidList(SSma* pSma, STbUidStore* pUidStore);
void tdUidStoreDestory(STbUidStore* pStore);
void* tdUidStoreFree(STbUidStore* pStore);
+// SMetaSnapReader ========================================
+int32_t metaSnapReaderOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapReader** ppReader);
+int32_t metaSnapReaderClose(SMetaSnapReader** ppReader);
+int32_t metaSnapRead(SMetaSnapReader* pReader, uint8_t** ppData);
+// SMetaSnapWriter ========================================
+int32_t metaSnapWriterOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapWriter** ppWriter);
+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 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);
+
typedef struct {
int8_t streamType; // sma or other
int8_t dstType;
@@ -184,9 +214,11 @@ typedef struct {
// SVState
struct SVState {
- // int64_t processed;
int64_t committed;
int64_t applied;
+ int64_t applyTerm;
+ int64_t commitID;
+ int64_t commitTerm;
};
struct SVnodeInfo {
@@ -228,8 +260,8 @@ struct SVnode {
SSink* pSink;
tsem_t canCommit;
int64_t sync;
- int32_t syncCount;
- sem_t syncSem;
+ int32_t blockCount;
+ tsem_t syncSem;
SQHandle* pQuery;
};
@@ -245,7 +277,6 @@ struct SVnode {
struct STbUidStore {
tb_uid_t suid;
- tb_uid_t uid; // TODO: just for debugging, remove when uid provided in SSDataBlock
SArray* tbUids;
SHashObj* uidHash;
};
@@ -276,6 +307,12 @@ struct SSma {
// sma
void smaHandleRes(void* pVnode, int64_t smaId, const SArray* data);
+struct SSnapDataHdr {
+ int8_t type;
+ int64_t size;
+ uint8_t data[];
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/source/dnode/vnode/src/meta/metaEntry.c b/source/dnode/vnode/src/meta/metaEntry.c
index acf5b0b61367a07740a9282330bc3881625dfff7..23d7665ba3685d95253a0b844298a2c105ba25c4 100644
--- a/source/dnode/vnode/src/meta/metaEntry.c
+++ b/source/dnode/vnode/src/meta/metaEntry.c
@@ -24,22 +24,25 @@ int metaEncodeEntry(SEncoder *pCoder, const SMetaEntry *pME) {
if (tEncodeCStr(pCoder, pME->name) < 0) return -1;
if (pME->type == TSDB_SUPER_TABLE) {
+ if (tEncodeI8(pCoder, pME->flags) < 0) return -1; // TODO: need refactor?
if (tEncodeSSchemaWrapper(pCoder, &pME->stbEntry.schemaRow) < 0) return -1;
if (tEncodeSSchemaWrapper(pCoder, &pME->stbEntry.schemaTag) < 0) return -1;
+ if (TABLE_IS_ROLLUP(pME->flags)) {
+ if (tEncodeSRSmaParam(pCoder, &pME->stbEntry.rsmaParam) < 0) return -1;
+ }
} else if (pME->type == TSDB_CHILD_TABLE) {
if (tEncodeI64(pCoder, pME->ctbEntry.ctime) < 0) return -1;
if (tEncodeI32(pCoder, pME->ctbEntry.ttlDays) < 0) return -1;
- if (tEncodeI32(pCoder, pME->ctbEntry.commentLen) < 0) return -1;
+ if (tEncodeI32v(pCoder, pME->ctbEntry.commentLen) < 0) return -1;
if (pME->ctbEntry.commentLen > 0){
if (tEncodeCStr(pCoder, pME->ctbEntry.comment) < 0) return -1;
}
if (tEncodeI64(pCoder, pME->ctbEntry.suid) < 0) return -1;
- debugCheckTags((STag*)pME->ctbEntry.pTags); // TODO: remove after debug
if (tEncodeTag(pCoder, (const STag *)pME->ctbEntry.pTags) < 0) return -1;
} else if (pME->type == TSDB_NORMAL_TABLE) {
if (tEncodeI64(pCoder, pME->ntbEntry.ctime) < 0) return -1;
if (tEncodeI32(pCoder, pME->ntbEntry.ttlDays) < 0) return -1;
- if (tEncodeI32(pCoder, pME->ntbEntry.commentLen) < 0) return -1;
+ if (tEncodeI32v(pCoder, pME->ntbEntry.commentLen) < 0) return -1;
if (pME->ntbEntry.commentLen > 0){
if (tEncodeCStr(pCoder, pME->ntbEntry.comment) < 0) return -1;
}
@@ -64,23 +67,26 @@ int metaDecodeEntry(SDecoder *pCoder, SMetaEntry *pME) {
if (tDecodeCStr(pCoder, &pME->name) < 0) return -1;
if (pME->type == TSDB_SUPER_TABLE) {
+ if (tDecodeI8(pCoder, &pME->flags) < 0) return -1; // TODO: need refactor?
if (tDecodeSSchemaWrapperEx(pCoder, &pME->stbEntry.schemaRow) < 0) return -1;
if (tDecodeSSchemaWrapperEx(pCoder, &pME->stbEntry.schemaTag) < 0) return -1;
+ if (TABLE_IS_ROLLUP(pME->flags)) {
+ if (tDecodeSRSmaParam(pCoder, &pME->stbEntry.rsmaParam) < 0) return -1;
+ }
} else if (pME->type == TSDB_CHILD_TABLE) {
if (tDecodeI64(pCoder, &pME->ctbEntry.ctime) < 0) return -1;
if (tDecodeI32(pCoder, &pME->ctbEntry.ttlDays) < 0) return -1;
- if (tDecodeI32(pCoder, &pME->ctbEntry.commentLen) < 0) return -1;
+ if (tDecodeI32v(pCoder, &pME->ctbEntry.commentLen) < 0) return -1;
if (pME->ctbEntry.commentLen > 0){
if (tDecodeCStr(pCoder, &pME->ctbEntry.comment) < 0)
return -1;
}
if (tDecodeI64(pCoder, &pME->ctbEntry.suid) < 0) return -1;
if (tDecodeTag(pCoder, (STag **)&pME->ctbEntry.pTags) < 0) return -1; // (TODO)
- debugCheckTags((STag*)pME->ctbEntry.pTags); // TODO: remove after debug
} else if (pME->type == TSDB_NORMAL_TABLE) {
if (tDecodeI64(pCoder, &pME->ntbEntry.ctime) < 0) return -1;
if (tDecodeI32(pCoder, &pME->ntbEntry.ttlDays) < 0) return -1;
- if (tDecodeI32(pCoder, &pME->ntbEntry.commentLen) < 0) return -1;
+ if (tDecodeI32v(pCoder, &pME->ntbEntry.commentLen) < 0) return -1;
if (pME->ntbEntry.commentLen > 0){
if (tDecodeCStr(pCoder, &pME->ntbEntry.comment) < 0) return -1;
}
diff --git a/source/dnode/vnode/src/meta/metaOpen.c b/source/dnode/vnode/src/meta/metaOpen.c
index 95510c25e57e58d2e739dae0e3b1ec630bc2e596..1022f6796b7ce0be66d618c5ea0cfb4fc7db1af0 100644
--- a/source/dnode/vnode/src/meta/metaOpen.c
+++ b/source/dnode/vnode/src/meta/metaOpen.c
@@ -92,6 +92,13 @@ int metaOpen(SVnode *pVnode, SMeta **ppMeta) {
goto _err;
}
+ // open pSuidIdx
+ ret = tdbTbOpen("suid.idx", sizeof(tb_uid_t), 0, uidIdxKeyCmpr, pMeta->pEnv, &pMeta->pSuidIdx);
+ if (ret < 0) {
+ metaError("vgId:%d, failed to open meta super table index since %s", TD_VID(pVnode), tstrerror(terrno));
+ goto _err;
+ }
+
// open pTagIdx
// TODO(yihaoDeng), refactor later
char indexFullPath[128] = {0};
@@ -141,6 +148,7 @@ _err:
if (pMeta->pTagIvtIdx) indexClose(pMeta->pTagIvtIdx);
if (pMeta->pTagIdx) tdbTbClose(pMeta->pTagIdx);
if (pMeta->pCtbIdx) tdbTbClose(pMeta->pCtbIdx);
+ if (pMeta->pSuidIdx) tdbTbClose(pMeta->pSuidIdx);
if (pMeta->pNameIdx) tdbTbClose(pMeta->pNameIdx);
if (pMeta->pUidIdx) tdbTbClose(pMeta->pUidIdx);
if (pMeta->pSkmDb) tdbTbClose(pMeta->pSkmDb);
@@ -156,12 +164,10 @@ int metaClose(SMeta *pMeta) {
if (pMeta->pIdx) metaCloseIdx(pMeta);
if (pMeta->pSmaIdx) tdbTbClose(pMeta->pSmaIdx);
if (pMeta->pTtlIdx) tdbTbClose(pMeta->pTtlIdx);
-#ifdef USE_INVERTED_INDEX
if (pMeta->pTagIvtIdx) indexClose(pMeta->pTagIvtIdx);
-#else
if (pMeta->pTagIdx) tdbTbClose(pMeta->pTagIdx);
-#endif
if (pMeta->pCtbIdx) tdbTbClose(pMeta->pCtbIdx);
+ if (pMeta->pSuidIdx) tdbTbClose(pMeta->pSuidIdx);
if (pMeta->pNameIdx) tdbTbClose(pMeta->pNameIdx);
if (pMeta->pUidIdx) tdbTbClose(pMeta->pUidIdx);
if (pMeta->pSkmDb) tdbTbClose(pMeta->pSkmDb);
diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c
index a5ca90e55fcba3e20c250e5ffa58d4e71cc5ca07..e1236c2853958f1bb6c364d035b637a410ddb276 100644
--- a/source/dnode/vnode/src/meta/metaQuery.c
+++ b/source/dnode/vnode/src/meta/metaQuery.c
@@ -31,7 +31,7 @@ void metaReaderClear(SMetaReader *pReader) {
}
int metaGetTableEntryByVersion(SMetaReader *pReader, int64_t version, tb_uid_t uid) {
- SMeta * pMeta = pReader->pMeta;
+ SMeta *pMeta = pReader->pMeta;
STbDbKey tbDbKey = {.version = version, .uid = uid};
// query table.db
@@ -54,7 +54,7 @@ _err:
}
int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) {
- SMeta * pMeta = pReader->pMeta;
+ SMeta *pMeta = pReader->pMeta;
int64_t version;
// query uid.idx
@@ -68,7 +68,7 @@ int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) {
}
int metaGetTableEntryByName(SMetaReader *pReader, const char *name) {
- SMeta * pMeta = pReader->pMeta;
+ SMeta *pMeta = pReader->pMeta;
tb_uid_t uid;
// query name.idx
@@ -82,7 +82,7 @@ int metaGetTableEntryByName(SMetaReader *pReader, const char *name) {
}
tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name) {
- void * pData = NULL;
+ void *pData = NULL;
int nData = 0;
tb_uid_t uid = 0;
@@ -138,7 +138,7 @@ void metaCloseTbCursor(SMTbCursor *pTbCur) {
int metaTbCursorNext(SMTbCursor *pTbCur) {
int ret;
- void * pBuf;
+ void *pBuf;
STbCfg tbCfg;
for (;;) {
@@ -147,6 +147,8 @@ int metaTbCursorNext(SMTbCursor *pTbCur) {
return -1;
}
+ tDecoderClear(&pTbCur->mr.coder);
+
metaGetTableEntryByVersion(&pTbCur->mr, *(int64_t *)pTbCur->pVal, *(tb_uid_t *)pTbCur->pKey);
if (pTbCur->mr.me.type == TSDB_SUPER_TABLE) {
continue;
@@ -159,7 +161,7 @@ int metaTbCursorNext(SMTbCursor *pTbCur) {
}
SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, bool isinline) {
- void * pData = NULL;
+ void *pData = NULL;
int nData = 0;
int64_t version;
SSchemaWrapper schema = {0};
@@ -218,12 +220,10 @@ _err:
return NULL;
}
-int metaTtlSmaller(SMeta *pMeta, uint64_t ttl, SArray *uidList){
- metaRLock(pMeta);
- TBC * pCur;
- int ret = tdbTbcOpen(pMeta->pTtlIdx, &pCur, NULL);
+int metaTtlSmaller(SMeta *pMeta, uint64_t ttl, SArray *uidList) {
+ TBC *pCur;
+ int ret = tdbTbcOpen(pMeta->pTtlIdx, &pCur, NULL);
if (ret < 0) {
- metaULock(pMeta);
return ret;
}
@@ -237,27 +237,28 @@ int metaTtlSmaller(SMeta *pMeta, uint64_t ttl, SArray *uidList){
}
void *pKey = NULL;
- int kLen = 0;
- while(1){
+ int kLen = 0;
+ while (1) {
ret = tdbTbcPrev(pCur, &pKey, &kLen, NULL, NULL);
if (ret < 0) {
break;
}
- ttlKey = *(STtlIdxKey*)pKey;
+ ttlKey = *(STtlIdxKey *)pKey;
taosArrayPush(uidList, &ttlKey.uid);
}
tdbTbcClose(pCur);
tdbFree(pKey);
+
return 0;
}
struct SMCtbCursor {
- SMeta * pMeta;
- TBC * pCur;
+ SMeta *pMeta;
+ TBC *pCur;
tb_uid_t suid;
- void * pKey;
- void * pVal;
+ void *pKey;
+ void *pVal;
int kLen;
int vLen;
};
@@ -265,8 +266,8 @@ struct SMCtbCursor {
SMCtbCursor *metaOpenCtbCursor(SMeta *pMeta, tb_uid_t uid) {
SMCtbCursor *pCtbCur = NULL;
SCtbIdxKey ctbIdxKey;
- int ret;
- int c;
+ int ret = 0;
+ int c = 0;
pCtbCur = (SMCtbCursor *)taosMemoryCalloc(1, sizeof(*pCtbCur));
if (pCtbCur == NULL) {
@@ -326,12 +327,78 @@ tb_uid_t metaCtbCursorNext(SMCtbCursor *pCtbCur) {
return pCtbIdxKey->uid;
}
+struct SMStbCursor {
+ SMeta *pMeta;
+ TBC *pCur;
+ tb_uid_t suid;
+ void *pKey;
+ void *pVal;
+ int kLen;
+ int vLen;
+};
+
+SMStbCursor *metaOpenStbCursor(SMeta *pMeta, tb_uid_t suid) {
+ SMStbCursor *pStbCur = NULL;
+ int ret = 0;
+ int c = 0;
+
+ pStbCur = (SMStbCursor *)taosMemoryCalloc(1, sizeof(*pStbCur));
+ if (pStbCur == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ pStbCur->pMeta = pMeta;
+ pStbCur->suid = suid;
+ metaRLock(pMeta);
+
+ ret = tdbTbcOpen(pMeta->pSuidIdx, &pStbCur->pCur, NULL);
+ if (ret < 0) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ metaULock(pMeta);
+ taosMemoryFree(pStbCur);
+ return NULL;
+ }
+
+ // move to the suid
+ tdbTbcMoveTo(pStbCur->pCur, &suid, sizeof(suid), &c);
+ if (c > 0) {
+ tdbTbcMoveToNext(pStbCur->pCur);
+ }
+
+ return pStbCur;
+}
+
+void metaCloseStbCursor(SMStbCursor *pStbCur) {
+ if (pStbCur) {
+ if (pStbCur->pMeta) metaULock(pStbCur->pMeta);
+ if (pStbCur->pCur) {
+ tdbTbcClose(pStbCur->pCur);
+
+ tdbFree(pStbCur->pKey);
+ tdbFree(pStbCur->pVal);
+ }
+
+ taosMemoryFree(pStbCur);
+ }
+}
+
+tb_uid_t metaStbCursorNext(SMStbCursor *pStbCur) {
+ int ret;
+
+ ret = tdbTbcNext(pStbCur->pCur, &pStbCur->pKey, &pStbCur->kLen, &pStbCur->pVal, &pStbCur->vLen);
+ if (ret < 0) {
+ return 0;
+ }
+ return *(tb_uid_t *)pStbCur->pKey;
+}
+
STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver) {
// SMetaReader mr = {0};
- STSchema * pTSchema = NULL;
+ STSchema *pTSchema = NULL;
SSchemaWrapper *pSW = NULL;
STSchemaBuilder sb = {0};
- SSchema * pSchema;
+ SSchema *pSchema;
pSW = metaGetTableSchema(pMeta, uid, sver, 0);
if (!pSW) return NULL;
@@ -350,6 +417,52 @@ STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver) {
return pTSchema;
}
+int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sver, STSchema **ppTSchema) {
+ int32_t code = 0;
+ STSchema *pTSchema = NULL;
+ SSkmDbKey skmDbKey = {.uid = suid ? suid : uid, .sver = sver};
+ void *pData = NULL;
+ int nData = 0;
+
+ // query
+ metaRLock(pMeta);
+ if (tdbTbGet(pMeta->pSkmDb, &skmDbKey, sizeof(skmDbKey), &pData, &nData) < 0) {
+ code = TSDB_CODE_NOT_FOUND;
+ metaULock(pMeta);
+ goto _err;
+ }
+ metaULock(pMeta);
+
+ // decode
+ SDecoder dc = {0};
+ SSchemaWrapper schema;
+ SSchemaWrapper *pSchemaWrapper = &schema;
+
+ tDecoderInit(&dc, pData, nData);
+ tDecodeSSchemaWrapper(&dc, pSchemaWrapper);
+ tDecoderClear(&dc);
+ tdbFree(pData);
+
+ // convert
+ STSchemaBuilder sb = {0};
+
+ tdInitTSchemaBuilder(&sb, pSchemaWrapper->version);
+ for (int i = 0; i < pSchemaWrapper->nCols; i++) {
+ SSchema *pSchema = pSchemaWrapper->pSchema + i;
+ tdAddColToSchema(&sb, pSchema->type, pSchema->flags, pSchema->colId, pSchema->bytes);
+ }
+ pTSchema = tdGetSchemaFromBuilder(&sb);
+ tdDestroyTSchemaBuilder(&sb);
+
+ *ppTSchema = pTSchema;
+ taosMemoryFree(pSchemaWrapper->pSchema);
+ return code;
+
+_err:
+ *ppTSchema = NULL;
+ return code;
+}
+
int metaGetTbNum(SMeta *pMeta) {
// TODO
// ASSERT(0);
@@ -357,11 +470,11 @@ int metaGetTbNum(SMeta *pMeta) {
}
typedef struct {
- SMeta * pMeta;
- TBC * pCur;
+ SMeta *pMeta;
+ TBC *pCur;
tb_uid_t uid;
- void * pKey;
- void * pVal;
+ void *pKey;
+ void *pVal;
int kLen;
int vLen;
} SMSmaCursor;
@@ -433,7 +546,7 @@ tb_uid_t metaSmaCursorNext(SMSmaCursor *pSmaCur) {
STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid, bool deepCopy) {
STSmaWrapper *pSW = NULL;
- SArray * pSmaIds = NULL;
+ SArray *pSmaIds = NULL;
if (!(pSmaIds = metaGetSmaIdsByTable(pMeta, uid))) {
return NULL;
@@ -457,7 +570,7 @@ STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid, bool deepCopy) {
metaReaderInit(&mr, pMeta, 0);
int64_t smaId;
int smaIdx = 0;
- STSma * pTSma = NULL;
+ STSma *pTSma = NULL;
for (int i = 0; i < pSW->number; ++i) {
smaId = *(tb_uid_t *)taosArrayGet(pSmaIds, i);
if (metaGetTableEntryByUid(&mr, smaId) < 0) {
@@ -505,7 +618,7 @@ _err:
}
STSma *metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid) {
- STSma * pTSma = NULL;
+ STSma *pTSma = NULL;
SMetaReader mr = {0};
metaReaderInit(&mr, pMeta, 0);
if (metaGetTableEntryByUid(&mr, indexUid) < 0) {
@@ -527,7 +640,7 @@ STSma *metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid) {
}
SArray *metaGetSmaIdsByTable(SMeta *pMeta, tb_uid_t uid) {
- SArray * pUids = NULL;
+ SArray *pUids = NULL;
SSmaIdxKey *pSmaIdxKey = NULL;
SMSmaCursor *pCur = metaOpenSmaCursor(pMeta, uid);
@@ -565,7 +678,7 @@ SArray *metaGetSmaIdsByTable(SMeta *pMeta, tb_uid_t uid) {
}
SArray *metaGetSmaTbUids(SMeta *pMeta) {
- SArray * pUids = NULL;
+ SArray *pUids = NULL;
SSmaIdxKey *pSmaIdxKey = NULL;
tb_uid_t lastUid = 0;
@@ -613,9 +726,6 @@ const void *metaGetTableTagVal(SMetaEntry *pEntry, int16_t type, STagVal *val) {
ASSERT(pEntry->type == TSDB_CHILD_TABLE);
STag *tag = (STag *)pEntry->ctbEntry.pTags;
if (type == TSDB_DATA_TYPE_JSON) {
- if (tag->nTag == 0) {
- return NULL;
- }
return tag;
}
bool find = tTagGet(tag, val);
@@ -627,20 +737,20 @@ const void *metaGetTableTagVal(SMetaEntry *pEntry, int16_t type, STagVal *val) {
}
typedef struct {
- SMeta * pMeta;
- TBC * pCur;
+ SMeta *pMeta;
+ TBC *pCur;
tb_uid_t suid;
int16_t cid;
int16_t type;
- void * pKey;
- void * pVal;
+ void *pKey;
+ void *pVal;
int32_t kLen;
int32_t vLen;
} SIdxCursor;
int32_t metaFilteTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) {
SIdxCursor *pCursor = NULL;
- char * buf = NULL;
+ char *buf = NULL;
int32_t maxSize = 0;
int32_t ret = 0, valid = 0;
@@ -659,7 +769,7 @@ int32_t metaFilteTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) {
int32_t nKey = 0;
int32_t nTagData = 0;
- void * tagData = NULL;
+ void *tagData = NULL;
if (param->val == NULL) {
metaError("vgId:%d, failed to filter NULL data", TD_VID(pMeta->pVnode));
@@ -695,7 +805,7 @@ int32_t metaFilteTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) {
goto END;
}
- void * entryKey = NULL, *entryVal = NULL;
+ void *entryKey = NULL, *entryVal = NULL;
int32_t nEntryKey, nEntryVal;
bool first = true;
while (1) {
diff --git a/source/dnode/vnode/src/meta/metaSnapshot.c b/source/dnode/vnode/src/meta/metaSnapshot.c
index 5757039d55d410808b4eeb57d2e09286b7939004..ac84842e851f659d7d6b1a1c6373cc3aa3a99f39 100644
--- a/source/dnode/vnode/src/meta/metaSnapshot.c
+++ b/source/dnode/vnode/src/meta/metaSnapshot.c
@@ -15,53 +15,57 @@
#include "meta.h"
-struct SMetaSnapshotReader {
+// SMetaSnapReader ========================================
+struct SMetaSnapReader {
SMeta* pMeta;
- TBC* pTbc;
int64_t sver;
int64_t ever;
+ TBC* pTbc;
};
-int32_t metaSnapshotReaderOpen(SMeta* pMeta, SMetaSnapshotReader** ppReader, int64_t sver, int64_t ever) {
- int32_t code = 0;
- int32_t c = 0;
- SMetaSnapshotReader* pMetaReader = NULL;
+int32_t metaSnapReaderOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapReader** ppReader) {
+ int32_t code = 0;
+ int32_t c = 0;
+ SMetaSnapReader* pMetaSnapReader = NULL;
- pMetaReader = (SMetaSnapshotReader*)taosMemoryCalloc(1, sizeof(*pMetaReader));
- if (pMetaReader == NULL) {
+ // alloc
+ pMetaSnapReader = (SMetaSnapReader*)taosMemoryCalloc(1, sizeof(*pMetaSnapReader));
+ if (pMetaSnapReader == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
- pMetaReader->pMeta = pMeta;
- pMetaReader->sver = sver;
- pMetaReader->ever = ever;
- code = tdbTbcOpen(pMeta->pTbDb, &pMetaReader->pTbc, NULL);
+ pMetaSnapReader->pMeta = pMeta;
+ pMetaSnapReader->sver = sver;
+ pMetaSnapReader->ever = ever;
+
+ // impl
+ code = tdbTbcOpen(pMeta->pTbDb, &pMetaSnapReader->pTbc, NULL);
if (code) {
goto _err;
}
- code = tdbTbcMoveTo(pMetaReader->pTbc, &(STbDbKey){.version = sver, .uid = INT64_MIN}, sizeof(STbDbKey), &c);
+ code = tdbTbcMoveTo(pMetaSnapReader->pTbc, &(STbDbKey){.version = sver, .uid = INT64_MIN}, sizeof(STbDbKey), &c);
if (code) {
goto _err;
}
- *ppReader = pMetaReader;
+ *ppReader = pMetaSnapReader;
return code;
_err:
+ metaError("vgId:%d meta snap reader open failed since %s", TD_VID(pMeta->pVnode), tstrerror(code));
*ppReader = NULL;
return code;
}
-int32_t metaSnapshotReaderClose(SMetaSnapshotReader* pReader) {
- if (pReader) {
- tdbTbcClose(pReader->pTbc);
- taosMemoryFree(pReader);
- }
+int32_t metaSnapReaderClose(SMetaSnapReader** ppReader) {
+ tdbTbcClose((*ppReader)->pTbc);
+ taosMemoryFree(*ppReader);
+ *ppReader = NULL;
return 0;
}
-int32_t metaSnapshotRead(SMetaSnapshotReader* pReader, void** ppData, uint32_t* nDatap) {
+int32_t metaSnapRead(SMetaSnapReader* pReader, uint8_t** ppData) {
const void* pKey = NULL;
const void* pData = NULL;
int32_t nKey = 0;
@@ -71,23 +75,110 @@ int32_t metaSnapshotRead(SMetaSnapshotReader* pReader, void** ppData, uint32_t*
for (;;) {
code = tdbTbcGet(pReader->pTbc, &pKey, &nKey, &pData, &nData);
if (code || ((STbDbKey*)pData)->version > pReader->ever) {
- return TSDB_CODE_VND_READ_END;
+ code = TSDB_CODE_VND_READ_END;
+ goto _exit;
}
if (((STbDbKey*)pData)->version < pReader->sver) {
+ tdbTbcMoveToNext(pReader->pTbc);
continue;
}
+ tdbTbcMoveToNext(pReader->pTbc);
break;
}
// copy the data
- if (vnodeRealloc(ppData, nData) < 0) {
+ if (tRealloc(ppData, sizeof(SSnapDataHdr) + nData) < 0) {
code = TSDB_CODE_OUT_OF_MEMORY;
return code;
}
+ ((SSnapDataHdr*)(*ppData))->type = 0; // TODO: use macro
+ ((SSnapDataHdr*)(*ppData))->size = nData;
+ memcpy(((SSnapDataHdr*)(*ppData))->data, pData, nData);
+
+_exit:
+ return code;
+}
- memcpy(*ppData, pData, nData);
- *nDatap = nData;
+// SMetaSnapWriter ========================================
+struct SMetaSnapWriter {
+ SMeta* pMeta;
+ int64_t sver;
+ int64_t ever;
+};
+
+static int32_t metaSnapRollback(SMetaSnapWriter* pWriter) {
+ int32_t code = 0;
+ // TODO
+ return code;
+}
+
+static int32_t metaSnapCommit(SMetaSnapWriter* pWriter) {
+ int32_t code = 0;
+ // TODO
+ return code;
+}
+
+int32_t metaSnapWriterOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapWriter** ppWriter) {
+ int32_t code = 0;
+ SMetaSnapWriter* pWriter;
+
+ // alloc
+ pWriter = (SMetaSnapWriter*)taosMemoryCalloc(1, sizeof(*pWriter));
+ if (pWriter == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pWriter->pMeta = pMeta;
+ pWriter->sver = sver;
+ pWriter->ever = ever;
+
+ *ppWriter = pWriter;
+ return code;
+
+_err:
+ metaError("vgId:%d meta snapshot writer open failed since %s", TD_VID(pMeta->pVnode), tstrerror(code));
+ *ppWriter = NULL;
+ return code;
+}
+
+int32_t metaSnapWriterClose(SMetaSnapWriter** ppWriter, int8_t rollback) {
+ int32_t code = 0;
+ SMetaSnapWriter* pWriter = *ppWriter;
+
+ if (rollback) {
+ code = metaSnapRollback(pWriter);
+ if (code) goto _err;
+ } else {
+ code = metaSnapCommit(pWriter);
+ if (code) goto _err;
+ }
+ taosMemoryFree(pWriter);
+ *ppWriter = NULL;
+
+ return code;
+
+_err:
+ metaError("vgId:%d meta snapshot writer close failed since %s", TD_VID(pWriter->pMeta->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t metaSnapWrite(SMetaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ SMeta* pMeta = pWriter->pMeta;
+ SMetaEntry metaEntry = {0};
+ SDecoder* pDecoder = &(SDecoder){0};
+
+ tDecoderInit(pDecoder, pData, nData);
+ metaDecodeEntry(pDecoder, &metaEntry);
+
+ code = metaHandleEntry(pMeta, &metaEntry);
+ if (code) goto _err;
+
+ return code;
+
+_err:
+ metaError("vgId:%d meta snapshot write failed since %s", TD_VID(pMeta->pVnode), tstrerror(code));
return code;
}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/meta/metaTable.c b/source/dnode/vnode/src/meta/metaTable.c
index bf5d5912f93df374010043c10ef0cdd48368573c..29c10c40c2b00d8e9006fc4b9fe2505059c3e8a6 100644
--- a/source/dnode/vnode/src/meta/metaTable.c
+++ b/source/dnode/vnode/src/meta/metaTable.c
@@ -16,13 +16,14 @@
#include "meta.h"
static int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
-static int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME);
+static int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
static int metaSaveToTbDb(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateTtlIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME);
+static int metaUpdateSuidIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry);
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type);
@@ -49,7 +50,7 @@ static int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const
if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
return -1;
}
- void * data = pCtbEntry->ctbEntry.pTags;
+ void *data = pCtbEntry->ctbEntry.pTags;
const char *tagName = pSchema->name;
tb_uid_t suid = pCtbEntry->ctbEntry.suid;
@@ -68,32 +69,88 @@ static int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const
STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
char type = pTagVal->type;
- char * key = pTagVal->pKey;
+ char *key = pTagVal->pKey;
int32_t nKey = strlen(key);
SIndexTerm *term = NULL;
if (type == TSDB_DATA_TYPE_NULL) {
- // handle null value
+ term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
} else if (type == TSDB_DATA_TYPE_NCHAR) {
if (pTagVal->nData > 0) {
- char * val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
+ char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE);
memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
type = TSDB_DATA_TYPE_VARCHAR;
term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, val, len);
} else if (pTagVal->nData == 0) {
- char * val = NULL;
- int32_t len = 0;
- // handle NULL key
+ term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
}
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
double val = *(double *)(&pTagVal->i64);
- int len = 0;
+ int len = sizeof(val);
term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, (const char *)&val, len);
} else if (type == TSDB_DATA_TYPE_BOOL) {
int val = *(int *)(&pTagVal->i64);
- int len = 0;
- term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_INT, key, nKey, (const char *)&val, len);
+ int len = sizeof(val);
+ term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
+ }
+ if (term != NULL) {
+ indexMultiTermAdd(terms, term);
+ }
+ }
+ indexJsonPut(pMeta->pTagIvtIdx, terms, tuid);
+ indexMultiTermDestroy(terms);
+#endif
+ return 0;
+}
+int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema) {
+#ifdef USE_INVERTED_INDEX
+ if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
+ return -1;
+ }
+ void *data = pCtbEntry->ctbEntry.pTags;
+ const char *tagName = pSchema->name;
+
+ tb_uid_t suid = pCtbEntry->ctbEntry.suid;
+ tb_uid_t tuid = pCtbEntry->uid;
+ const void *pTagData = pCtbEntry->ctbEntry.pTags;
+ int32_t nTagData = 0;
+
+ SArray *pTagVals = NULL;
+ if (tTagToValArray((const STag *)data, &pTagVals) != 0) {
+ return -1;
+ }
+
+ SIndexMultiTerm *terms = indexMultiTermCreate();
+ int16_t nCols = taosArrayGetSize(pTagVals);
+ for (int i = 0; i < nCols; i++) {
+ STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
+ char type = pTagVal->type;
+
+ char *key = pTagVal->pKey;
+ int32_t nKey = strlen(key);
+
+ SIndexTerm *term = NULL;
+ if (type == TSDB_DATA_TYPE_NULL) {
+ term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
+ } else if (type == TSDB_DATA_TYPE_NCHAR) {
+ if (pTagVal->nData > 0) {
+ char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE);
+ memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
+ type = TSDB_DATA_TYPE_VARCHAR;
+ term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, val, len);
+ } else if (pTagVal->nData == 0) {
+ term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
+ }
+ } else if (type == TSDB_DATA_TYPE_DOUBLE) {
+ double val = *(double *)(&pTagVal->i64);
+ int len = sizeof(val);
+ term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, (const char *)&val, len);
+ } else if (type == TSDB_DATA_TYPE_BOOL) {
+ int val = *(int *)(&pTagVal->i64);
+ int len = sizeof(val);
+ term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
}
if (term != NULL) {
indexMultiTermAdd(terms, term);
@@ -111,9 +168,9 @@ int metaCreateSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
int vLen = 0;
const void *pKey = NULL;
const void *pVal = NULL;
- void * pBuf = NULL;
+ void *pBuf = NULL;
int32_t szBuf = 0;
- void * p = NULL;
+ void *p = NULL;
SMetaReader mr = {0};
// validate req
@@ -138,6 +195,10 @@ int metaCreateSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
me.name = pReq->name;
me.stbEntry.schemaRow = pReq->schemaRow;
me.stbEntry.schemaTag = pReq->schemaTag;
+ if (pReq->rollup) {
+ TABLE_SET_ROLLUP(me.flags);
+ me.stbEntry.rsmaParam = pReq->rsmaParam;
+ }
if (metaHandleEntry(pMeta, &me) < 0) goto _err;
@@ -167,7 +228,7 @@ int metaDropSTable(SMeta *pMeta, int64_t verison, SVDropStbReq *pReq) {
}
// drop all child tables
- TBC * pCtbIdxc = NULL;
+ TBC *pCtbIdxc = NULL;
SArray *pArray = taosArrayInit(8, sizeof(tb_uid_t));
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, &pMeta->txn);
@@ -209,6 +270,7 @@ _drop_super_table:
&pMeta->txn);
tdbTbDelete(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, &pMeta->txn);
tdbTbDelete(pMeta->pUidIdx, &pReq->suid, sizeof(tb_uid_t), &pMeta->txn);
+ tdbTbDelete(pMeta->pSuidIdx, &pReq->suid, sizeof(tb_uid_t), &pMeta->txn);
metaULock(pMeta);
@@ -222,8 +284,8 @@ _exit:
int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
SMetaEntry oStbEntry = {0};
SMetaEntry nStbEntry = {0};
- TBC * pUidIdxc = NULL;
- TBC * pTbDbc = NULL;
+ TBC *pUidIdxc = NULL;
+ TBC *pTbDbc = NULL;
const void *pData;
int nData;
int64_t oversion;
@@ -346,7 +408,7 @@ _err:
}
int metaDropTable(SMeta *pMeta, int64_t version, SVDropTbReq *pReq, SArray *tbUids) {
- void * pData = NULL;
+ void *pData = NULL;
int nData = 0;
int rc = 0;
tb_uid_t uid;
@@ -374,20 +436,22 @@ int metaDropTable(SMeta *pMeta, int64_t version, SVDropTbReq *pReq, SArray *tbUi
int metaTtlDropTable(SMeta *pMeta, int64_t ttl, SArray *tbUids) {
metaWLock(pMeta);
int ret = metaTtlSmaller(pMeta, ttl, tbUids);
- if(ret != 0){
+ if (ret != 0) {
+ metaULock(pMeta);
return ret;
}
for (int i = 0; i < taosArrayGetSize(tbUids); ++i) {
tb_uid_t *uid = (tb_uid_t *)taosArrayGet(tbUids, i);
metaDropTableByUid(pMeta, *uid, NULL);
+ metaDebug("ttl drop table:%" PRId64, *uid);
}
metaULock(pMeta);
return 0;
}
-static void metaBuildTtlIdxKey(STtlIdxKey *ttlKey, const SMetaEntry *pME){
- int32_t ttlDays;
- int64_t ctime;
+static void metaBuildTtlIdxKey(STtlIdxKey *ttlKey, const SMetaEntry *pME) {
+ int64_t ttlDays;
+ int64_t ctime;
if (pME->type == TSDB_CHILD_TABLE) {
ctime = pME->ctbEntry.ctime;
ttlDays = pME->ctbEntry.ttlDays;
@@ -400,21 +464,19 @@ static void metaBuildTtlIdxKey(STtlIdxKey *ttlKey, const SMetaEntry *pME){
if (ttlDays <= 0) return;
- ttlKey->dtime = ctime / 1000 + ttlDays * 24 * 60 * 60;
-// ttlKey->dtime = ctime / 1000 + ttlDays;
+ ttlKey->dtime = ctime / 1000 + ttlDays * tsTtlUnit;
ttlKey->uid = pME->uid;
}
static int metaDeleteTtlIdx(SMeta *pMeta, const SMetaEntry *pME) {
STtlIdxKey ttlKey = {0};
metaBuildTtlIdxKey(&ttlKey, pME);
- if(ttlKey.dtime == 0) return 0;
+ if (ttlKey.dtime == 0) return 0;
return tdbTbDelete(pMeta->pTtlIdx, &ttlKey, sizeof(ttlKey), &pMeta->txn);
}
-
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
- void * pData = NULL;
+ void *pData = NULL;
int nData = 0;
int rc = 0;
SMetaEntry e = {0};
@@ -430,20 +492,44 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
if (type) *type = e.type;
+ if (e.type == TSDB_CHILD_TABLE) {
+ void *tData = NULL;
+ int tLen = 0;
+
+ if (tdbTbGet(pMeta->pUidIdx, &e.ctbEntry.suid, sizeof(tb_uid_t), &tData, &tLen) == 0) {
+ version = *(int64_t *)tData;
+ STbDbKey tbDbKey = {.uid = e.ctbEntry.suid, .version = version};
+ if (tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &tData, &tLen) == 0) {
+ SDecoder tdc = {0};
+ SMetaEntry stbEntry = {0};
+
+ tDecoderInit(&tdc, tData, tLen);
+ metaDecodeEntry(&tdc, &stbEntry);
+ const SSchema *pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0];
+ if (pTagColumn->type == TSDB_DATA_TYPE_JSON) {
+ metaDelJsonVarFromIdx(pMeta, &e, pTagColumn);
+ }
+ tDecoderClear(&tdc);
+ }
+ tdbFree(tData);
+ }
+ }
+
tdbTbDelete(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), &pMeta->txn);
tdbTbDelete(pMeta->pNameIdx, e.name, strlen(e.name) + 1, &pMeta->txn);
tdbTbDelete(pMeta->pUidIdx, &uid, sizeof(uid), &pMeta->txn);
- if(e.type != TSDB_SUPER_TABLE) metaDeleteTtlIdx(pMeta, &e);
+
+ if (e.type != TSDB_SUPER_TABLE) metaDeleteTtlIdx(pMeta, &e);
if (e.type == TSDB_CHILD_TABLE) {
tdbTbDelete(pMeta->pCtbIdx, &(SCtbIdxKey){.suid = e.ctbEntry.suid, .uid = uid}, sizeof(SCtbIdxKey), &pMeta->txn);
} else if (e.type == TSDB_NORMAL_TABLE) {
// drop schema.db (todo)
} else if (e.type == TSDB_SUPER_TABLE) {
+ tdbTbDelete(pMeta->pSuidIdx, &e.uid, sizeof(tb_uid_t), &pMeta->txn);
// drop schema.db (todo)
}
- metaError("ttl drop table:%s", e.name);
tDecoderClear(&dc);
tdbFree(pData);
@@ -451,14 +537,14 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
}
static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq, STableMetaRsp *pMetaRsp) {
- void * pVal = NULL;
+ void *pVal = NULL;
int nVal = 0;
- const void * pData = NULL;
+ const void *pData = NULL;
int nData = 0;
int ret = 0;
tb_uid_t uid;
int64_t oversion;
- SSchema * pColumn = NULL;
+ SSchema *pColumn = NULL;
SMetaEntry entry = {0};
SSchemaWrapper *pSchema;
int c;
@@ -612,7 +698,7 @@ _err:
static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
SMetaEntry ctbEntry = {0};
SMetaEntry stbEntry = {0};
- void * pVal = NULL;
+ void *pVal = NULL;
int nVal = 0;
int ret;
int c;
@@ -643,7 +729,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
oversion = *(int64_t *)pData;
// search table.db
- TBC * pTbDbc = NULL;
+ TBC *pTbDbc = NULL;
SDecoder dc1 = {0};
SDecoder dc2 = {0};
@@ -667,7 +753,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
metaDecodeEntry(&dc2, &stbEntry);
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
- SSchema * pColumn = NULL;
+ SSchema *pColumn = NULL;
int32_t iCol = 0;
for (;;) {
pColumn = NULL;
@@ -697,8 +783,8 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
memcpy((void *)ctbEntry.ctbEntry.pTags, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
} else {
const STag *pOldTag = (const STag *)ctbEntry.ctbEntry.pTags;
- STag * pNewTag = NULL;
- SArray * pTagArray = taosArrayInit(pTagSchema->nCols, sizeof(STagVal));
+ STag *pNewTag = NULL;
+ SArray *pTagArray = taosArrayInit(pTagSchema->nCols, sizeof(STagVal));
if (!pTagArray) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
@@ -757,15 +843,15 @@ _err:
}
static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
- void * pVal = NULL;
- int nVal = 0;
- const void * pData = NULL;
- int nData = 0;
- int ret = 0;
- tb_uid_t uid;
- int64_t oversion;
- SMetaEntry entry = {0};
- int c = 0;
+ void *pVal = NULL;
+ int nVal = 0;
+ const void *pData = NULL;
+ int nData = 0;
+ int ret = 0;
+ tb_uid_t uid;
+ int64_t oversion;
+ SMetaEntry entry = {0};
+ int c = 0;
// search name index
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
@@ -808,22 +894,22 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p
metaWLock(pMeta);
// build SMetaEntry
if (entry.type == TSDB_CHILD_TABLE) {
- if(pAlterTbReq->updateTTL) {
+ if (pAlterTbReq->updateTTL) {
metaDeleteTtlIdx(pMeta, &entry);
entry.ctbEntry.ttlDays = pAlterTbReq->newTTL;
metaUpdateTtlIdx(pMeta, &entry);
}
- if(pAlterTbReq->newCommentLen >= 0) {
+ if (pAlterTbReq->newCommentLen >= 0) {
entry.ctbEntry.commentLen = pAlterTbReq->newCommentLen;
entry.ctbEntry.comment = pAlterTbReq->newComment;
}
} else {
- if(pAlterTbReq->updateTTL) {
+ if (pAlterTbReq->updateTTL) {
metaDeleteTtlIdx(pMeta, &entry);
entry.ntbEntry.ttlDays = pAlterTbReq->newTTL;
metaUpdateTtlIdx(pMeta, &entry);
}
- if(pAlterTbReq->newCommentLen >= 0) {
+ if (pAlterTbReq->newCommentLen >= 0) {
entry.ntbEntry.commentLen = pAlterTbReq->newCommentLen;
entry.ntbEntry.comment = pAlterTbReq->newComment;
}
@@ -861,8 +947,8 @@ int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMeta
static int metaSaveToTbDb(SMeta *pMeta, const SMetaEntry *pME) {
STbDbKey tbDbKey;
- void * pKey = NULL;
- void * pVal = NULL;
+ void *pKey = NULL;
+ void *pVal = NULL;
int kLen = 0;
int vLen = 0;
SEncoder coder = {0};
@@ -911,6 +997,10 @@ static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME) {
return tdbTbInsert(pMeta->pUidIdx, &pME->uid, sizeof(tb_uid_t), &pME->version, sizeof(int64_t), &pMeta->txn);
}
+static int metaUpdateSuidIdx(SMeta *pMeta, const SMetaEntry *pME) {
+ return tdbTbInsert(pMeta->pSuidIdx, &pME->uid, sizeof(tb_uid_t), NULL, 0, &pMeta->txn);
+}
+
static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME) {
return tdbTbInsert(pMeta->pNameIdx, pME->name, strlen(pME->name) + 1, &pME->uid, sizeof(tb_uid_t), &pMeta->txn);
}
@@ -918,7 +1008,7 @@ static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME) {
static int metaUpdateTtlIdx(SMeta *pMeta, const SMetaEntry *pME) {
STtlIdxKey ttlKey = {0};
metaBuildTtlIdxKey(&ttlKey, pME);
- if(ttlKey.dtime == 0) return 0;
+ if (ttlKey.dtime == 0) return 0;
return tdbTbInsert(pMeta->pTtlIdx, &ttlKey, sizeof(ttlKey), NULL, 0, &pMeta->txn);
}
@@ -964,19 +1054,21 @@ static void metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey) {
}
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry) {
- void * pData = NULL;
+ void *pData = NULL;
int nData = 0;
STbDbKey tbDbKey = {0};
SMetaEntry stbEntry = {0};
- STagIdxKey * pTagIdxKey = NULL;
+ STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
const SSchema *pTagColumn; // = &stbEntry.stbEntry.schema.pSchema[0];
- const void * pTagData = NULL; //
+ const void *pTagData = NULL; //
int32_t nTagData = 0;
SDecoder dc = {0};
// get super table
- tdbTbGet(pMeta->pUidIdx, &pCtbEntry->ctbEntry.suid, sizeof(tb_uid_t), &pData, &nData);
+ if (tdbTbGet(pMeta->pUidIdx, &pCtbEntry->ctbEntry.suid, sizeof(tb_uid_t), &pData, &nData) != 0) {
+ return -1;
+ }
tbDbKey.uid = pCtbEntry->ctbEntry.suid;
tbDbKey.version = *(int64_t *)pData;
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData);
@@ -1016,7 +1108,7 @@ static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry) {
static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME) {
SEncoder coder = {0};
- void * pVal = NULL;
+ void *pVal = NULL;
int vLen = 0;
int rcode = 0;
SSkmDbKey skmDbKey = {0};
@@ -1033,6 +1125,11 @@ static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME) {
skmDbKey.uid = pME->uid;
skmDbKey.sver = pSW->version;
+ // if receive tmq meta message is: create stable1 then delete stable1 then create stable1 with multi vgroups
+ if (tdbTbGet(pMeta->pSkmDb, &skmDbKey, sizeof(skmDbKey), NULL, NULL) == 0) {
+ return rcode;
+ }
+
// encode schema
int32_t ret = 0;
tEncodeSize(tEncodeSSchemaWrapper, pSW, vLen, ret);
@@ -1058,7 +1155,7 @@ _exit:
return rcode;
}
-static int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) {
+int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) {
metaWLock(pMeta);
// save to table.db
@@ -1079,6 +1176,10 @@ static int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) {
} else {
// update schema.db
if (metaSaveToSkmDb(pMeta, pME) < 0) goto _err;
+
+ if (pME->type == TSDB_SUPER_TABLE) {
+ if (metaUpdateSuidIdx(pMeta, pME) < 0) goto _err;
+ }
}
if (pME->type != TSDB_SUPER_TABLE) {
diff --git a/source/dnode/vnode/src/sma/sma.c b/source/dnode/vnode/src/sma/sma.c
deleted file mode 100644
index 12f93f9400539958455a8d53df14ce6f4891dda2..0000000000000000000000000000000000000000
--- a/source/dnode/vnode/src/sma/sma.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#include "sma.h"
-
-// functions for external invocation
-
-// TODO: Who is responsible for resource allocate and release?
-int32_t tdProcessTSmaInsert(SSma* pSma, int64_t indexUid, const char* msg) {
- int32_t code = TSDB_CODE_SUCCESS;
-
- if ((code = tdProcessTSmaInsertImpl(pSma, indexUid, msg)) < 0) {
- smaWarn("vgId:%d, insert tsma data failed since %s", SMA_VID(pSma), tstrerror(terrno));
- }
- // TODO: destroy SSDataBlocks(msg)
- return code;
-}
-
-int32_t tdProcessTSmaCreate(SSma* pSma, int64_t version, const char* msg) {
- int32_t code = TSDB_CODE_SUCCESS;
-
- if ((code = tdProcessTSmaCreateImpl(pSma, version, msg)) < 0) {
- smaWarn("vgId:%d, create tsma failed since %s", SMA_VID(pSma), tstrerror(terrno));
- }
- // TODO: destroy SSDataBlocks(msg)
- return code;
-}
-
-int32_t smaGetTSmaDays(SVnodeCfg* pCfg, void* pCont, uint32_t contLen, int32_t* days) {
- int32_t code = TSDB_CODE_SUCCESS;
- if ((code = tdProcessTSmaGetDaysImpl(pCfg, pCont, contLen, days)) < 0) {
- smaWarn("vgId:%d, get tsma days failed since %s", pCfg->vgId, tstrerror(terrno));
- }
- smaDebug("vgId:%d, get tsma days %d", pCfg->vgId, *days);
- return code;
-}
-
-
-// functions for internal invocation
-
-#if 0
-
-/**
- * @brief TODO: Assume that the final generated result it less than 3M
- *
- * @param pReq
- * @param pDataBlocks
- * @param vgId
- * @param suid // TODO: check with Liao whether suid response is reasonable
- *
- * TODO: colId should be set
- */
-int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks, STSchema* pTSchema, int32_t vgId,
- tb_uid_t suid, const char* stbName, bool isCreateCtb) {
- int32_t sz = taosArrayGetSize(pDataBlocks);
- int32_t bufSize = sizeof(SSubmitReq);
- for (int32_t i = 0; i < sz; ++i) {
- SDataBlockInfo* pBlkInfo = &((SSDataBlock*)taosArrayGet(pDataBlocks, i))->info;
- bufSize += pBlkInfo->rows * (TD_ROW_HEAD_LEN + pBlkInfo->rowSize + BitmapLen(pBlkInfo->numOfCols));
- bufSize += sizeof(SSubmitBlk);
- }
-
- *pReq = taosMemoryCalloc(1, bufSize);
- if (!(*pReq)) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return TSDB_CODE_FAILED;
- }
- void* pDataBuf = *pReq;
-
- SArray* pTagArray = NULL;
- int32_t msgLen = sizeof(SSubmitReq);
- int32_t numOfBlks = 0;
- int32_t schemaLen = 0;
- SRowBuilder rb = {0};
- tdSRowInit(&rb, pTSchema->version);
-
- for (int32_t i = 0; i < sz; ++i) {
- SSDataBlock* pDataBlock = taosArrayGet(pDataBlocks, i);
- SDataBlockInfo* pDataBlkInfo = &pDataBlock->info;
- int32_t colNum = pDataBlkInfo->numOfCols;
- int32_t rows = pDataBlkInfo->rows;
- int32_t rowSize = pDataBlkInfo->rowSize;
- int64_t groupId = pDataBlkInfo->groupId;
-
- if (rb.nCols != colNum) {
- tdSRowSetTpInfo(&rb, colNum, pTSchema->flen);
- }
-
- if(isCreateCtb) {
- SMetaReader mr = {0};
- const char* ctbName = buildCtbNameByGroupId(stbName, pDataBlock->info.groupId);
- if (metaGetTableEntryByName(&mr, ctbName) != 0) {
- smaDebug("vgId:%d, no tsma ctb %s exists", vgId, ctbName);
- }
- SVCreateTbReq ctbReq = {0};
- ctbReq.name = ctbName;
- ctbReq.type = TSDB_CHILD_TABLE;
- ctbReq.ctb.suid = suid;
-
- STagVal tagVal = {.cid = colNum + PRIMARYKEY_TIMESTAMP_COL_ID,
- .type = TSDB_DATA_TYPE_BIGINT,
- .i64 = groupId};
- STag* pTag = NULL;
- if(!pTagArray) {
- pTagArray = taosArrayInit(1, sizeof(STagVal));
- if (!pTagArray) goto _err;
- }
- taosArrayClear(pTagArray);
- taosArrayPush(pTagArray, &tagVal);
- tTagNew(pTagArray, 1, false, &pTag);
- if (pTag == NULL) {
- tdDestroySVCreateTbReq(&ctbReq);
- goto _err;
- }
- ctbReq.ctb.pTag = (uint8_t*)pTag;
-
- int32_t code;
- tEncodeSize(tEncodeSVCreateTbReq, &ctbReq, schemaLen, code);
-
- tdDestroySVCreateTbReq(&ctbReq);
- if (code < 0) {
- goto _err;
- }
- }
-
-
-
- SSubmitBlk* pSubmitBlk = POINTER_SHIFT(pDataBuf, msgLen);
- pSubmitBlk->suid = suid;
- pSubmitBlk->uid = groupId;
- pSubmitBlk->numOfRows = rows;
-
- msgLen += sizeof(SSubmitBlk);
- int32_t dataLen = 0;
- for (int32_t j = 0; j < rows; ++j) { // iterate by row
- tdSRowResetBuf(&rb, POINTER_SHIFT(pDataBuf, msgLen)); // set row buf
- bool isStartKey = false;
- int32_t offset = 0;
- for (int32_t k = 0; k < colNum; ++k) { // iterate by column
- SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
- STColumn* pCol = &pTSchema->columns[k];
- void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes);
- switch (pColInfoData->info.type) {
- case TSDB_DATA_TYPE_TIMESTAMP:
- if (!isStartKey) {
- isStartKey = true;
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID, TSDB_DATA_TYPE_TIMESTAMP, TD_VTYPE_NORM, var, true,
- offset, k);
-
- } else {
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, TSDB_DATA_TYPE_TIMESTAMP, TD_VTYPE_NORM, var,
- true, offset, k);
- }
- break;
- case TSDB_DATA_TYPE_NCHAR: {
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, TSDB_DATA_TYPE_NCHAR, TD_VTYPE_NORM, var, true,
- offset, k);
- break;
- }
- case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, TSDB_DATA_TYPE_VARCHAR, TD_VTYPE_NORM, var, true,
- offset, k);
- break;
- }
- case TSDB_DATA_TYPE_VARBINARY:
- case TSDB_DATA_TYPE_DECIMAL:
- case TSDB_DATA_TYPE_BLOB:
- case TSDB_DATA_TYPE_JSON:
- case TSDB_DATA_TYPE_MEDIUMBLOB:
- uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type);
- TASSERT(0);
- break;
- default:
- if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) {
- if (pCol->type == pColInfoData->info.type) {
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pCol->type, TD_VTYPE_NORM, var, true, offset,
- k);
- } else {
- char tv[8] = {0};
- if (pColInfoData->info.type == TSDB_DATA_TYPE_FLOAT) {
- float v = 0;
- GET_TYPED_DATA(v, float, pColInfoData->info.type, var);
- SET_TYPED_DATA(&tv, pCol->type, v);
- } else if (pColInfoData->info.type == TSDB_DATA_TYPE_DOUBLE) {
- double v = 0;
- GET_TYPED_DATA(v, double, pColInfoData->info.type, var);
- SET_TYPED_DATA(&tv, pCol->type, v);
- } else if (IS_SIGNED_NUMERIC_TYPE(pColInfoData->info.type)) {
- int64_t v = 0;
- GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var);
- SET_TYPED_DATA(&tv, pCol->type, v);
- } else {
- uint64_t v = 0;
- GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var);
- SET_TYPED_DATA(&tv, pCol->type, v);
- }
- tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pCol->type, TD_VTYPE_NORM, tv, true, offset,
- k);
- }
- } else {
- uError("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type);
- TASSERT(0);
- }
- break;
- }
- offset += TYPE_BYTES[pCol->type]; // sum/avg would convert to int64_t/uint64_t/double during aggregation
- }
- dataLen += TD_ROW_LEN(rb.pBuf);
-#ifdef TD_DEBUG_PRINT_ROW
- tdSRowPrint(rb.pBuf, pTSchema, __func__);
-#endif
- }
-
- ++numOfBlks;
-
- pSubmitBlk->dataLen = dataLen;
- msgLen += pSubmitBlk->dataLen;
- }
-
- (*pReq)->length = msgLen;
-
- (*pReq)->header.vgId = htonl(vgId);
- (*pReq)->header.contLen = htonl(msgLen);
- (*pReq)->length = (*pReq)->header.contLen;
- (*pReq)->numOfBlocks = htonl(numOfBlks);
- SSubmitBlk* blk = (SSubmitBlk*)((*pReq) + 1);
- while (numOfBlks--) {
- int32_t dataLen = blk->dataLen;
- blk->uid = htobe64(blk->uid);
- blk->suid = htobe64(blk->suid);
- blk->padding = htonl(blk->padding);
- blk->sversion = htonl(blk->sversion);
- blk->dataLen = htonl(blk->dataLen);
- blk->schemaLen = htonl(blk->schemaLen);
- blk->numOfRows = htons(blk->numOfRows);
- blk = (SSubmitBlk*)(blk->data + dataLen);
- }
- return TSDB_CODE_SUCCESS;
-_err:
- taosMemoryFreeClear(*pReq);
- taosArrayDestroy(pTagArray);
-
- return TSDB_CODE_FAILED;
-}
-#endif
diff --git a/source/dnode/vnode/src/sma/smaCommit.c b/source/dnode/vnode/src/sma/smaCommit.c
new file mode 100644
index 0000000000000000000000000000000000000000..e241c14fc79f5b865369fe0d18def99e76c9cfbc
--- /dev/null
+++ b/source/dnode/vnode/src/sma/smaCommit.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "sma.h"
+
+static int32_t tdProcessRSmaPreCommitImpl(SSma *pSma);
+static int32_t tdProcessRSmaCommitImpl(SSma *pSma);
+static int32_t tdProcessRSmaPostCommitImpl(SSma *pSma);
+
+/**
+ * @brief Only applicable to Rollup SMA
+ *
+ * @param pSma
+ * @return int32_t
+ */
+int32_t smaPreCommit(SSma *pSma) { return tdProcessRSmaPreCommitImpl(pSma); }
+
+/**
+ * @brief Only applicable to Rollup SMA
+ *
+ * @param pSma
+ * @return int32_t
+ */
+int32_t smaCommit(SSma *pSma) { return tdProcessRSmaCommitImpl(pSma); }
+
+/**
+ * @brief Only applicable to Rollup SMA
+ *
+ * @param pSma
+ * @return int32_t
+ */
+int32_t smaPostCommit(SSma *pSma) { return tdProcessRSmaPostCommitImpl(pSma); }
+
+/**
+ * @brief set rsma trigger stat active
+ *
+ * @param pSma
+ * @return int32_t
+ */
+int32_t smaBegin(SSma *pSma) {
+ SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma);
+ if (!pSmaEnv) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SSmaStat *pStat = SMA_ENV_STAT(pSmaEnv);
+ SRSmaStat *pRSmaStat = SMA_RSMA_STAT(pStat);
+
+ int8_t rsmaTriggerStat =
+ atomic_val_compare_exchange_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_PAUSED, TASK_TRIGGER_STAT_ACTIVE);
+ switch (rsmaTriggerStat) {
+ case TASK_TRIGGER_STAT_PAUSED: {
+ smaDebug("vgId:%d rsma trigger stat from paused to active", SMA_VID(pSma));
+ break;
+ }
+ case TASK_TRIGGER_STAT_INIT: {
+ atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_ACTIVE);
+ smaDebug("vgId:%d rsma trigger stat from init to active", SMA_VID(pSma));
+ break;
+ }
+ default: {
+ atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_ACTIVE);
+ smaWarn("vgId:%d rsma trigger stat %" PRIi8 " is unexpected", SMA_VID(pSma), rsmaTriggerStat);
+ ASSERT(0);
+ break;
+ }
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief pre-commit for rollup sma.
+ * 1) set trigger stat of rsma timer TASK_TRIGGER_STAT_PAUSED.
+ * 2) wait all triggered fetch tasks finished
+ * 3) perform persist task for qTaskInfo
+ *
+ * @param pSma
+ * @return int32_t
+ */
+static int32_t tdProcessRSmaPreCommitImpl(SSma *pSma) {
+ SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma);
+ if (!pSmaEnv) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SSmaStat *pStat = SMA_ENV_STAT(pSmaEnv);
+ SRSmaStat *pRSmaStat = SMA_RSMA_STAT(pStat);
+
+
+ // step 1: set persistence task paused
+ atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_PAUSED);
+
+ // step 2: wait all triggered fetch tasks finished
+ int32_t nLoops = 0;
+ while (1) {
+ if (T_REF_VAL_GET(pStat) == 0) {
+ smaDebug("vgId:%d, rsma fetch tasks all finished", SMA_VID(pSma));
+ break;
+ } else {
+ smaDebug("vgId:%d, rsma fetch tasks not all finished yet", SMA_VID(pSma));
+ }
+ ++nLoops;
+ if (nLoops > 1000) {
+ sched_yield();
+ nLoops = 0;
+ }
+ }
+
+ // step 3: perform persist task for qTaskInfo
+ tdRSmaPersistExecImpl(pRSmaStat);
+
+ smaDebug("vgId:%d, rsma pre commit success", SMA_VID(pSma));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief commit for rollup sma
+ *
+ * @param pSma
+ * @return int32_t
+ */
+static int32_t tdProcessRSmaCommitImpl(SSma *pSma) {
+ SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma);
+ if (!pSmaEnv) {
+ return TSDB_CODE_SUCCESS;
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief post-commit for rollup sma
+ * 1) clean up the outdated qtaskinfo files
+ *
+ * @param pSma
+ * @return int32_t
+ */
+static int32_t tdProcessRSmaPostCommitImpl(SSma *pSma) {
+ SVnode *pVnode = pSma->pVnode;
+
+ if (!VND_IS_RSMA(pVnode)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int64_t committed = pVnode->state.committed;
+ TdDirPtr pDir = NULL;
+ TdDirEntryPtr pDirEntry = NULL;
+ char dir[TSDB_FILENAME_LEN];
+ const char *pattern = "v[0-9]+qtaskinfo\\.ver([0-9]+)?$";
+ regex_t regex;
+ int code = 0;
+
+ tdGetVndDirName(TD_VID(pVnode), tfsGetPrimaryPath(pVnode->pTfs), VNODE_RSMA_DIR, true, dir);
+
+ // Resource allocation and init
+ if ((code = regcomp(®ex, pattern, REG_EXTENDED)) != 0) {
+ char errbuf[128];
+ regerror(code, ®ex, errbuf, sizeof(errbuf));
+ smaWarn("vgId:%d, rsma post commit, regcomp for %s failed since %s", TD_VID(pVnode), dir, errbuf);
+ return TSDB_CODE_FAILED;
+ }
+
+ if ((pDir = taosOpenDir(dir)) == NULL) {
+ regfree(®ex);
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ smaWarn("vgId:%d, rsma post commit, open dir %s failed since %s", TD_VID(pVnode), dir, terrstr());
+ return TSDB_CODE_FAILED;
+ }
+
+ int32_t dirLen = strlen(dir);
+ char *dirEnd = POINTER_SHIFT(dir, dirLen);
+ regmatch_t regMatch[2];
+ while ((pDirEntry = taosReadDir(pDir)) != NULL) {
+ char *entryName = taosGetDirEntryName(pDirEntry);
+ if (!entryName) {
+ continue;
+ }
+
+ code = regexec(®ex, entryName, 2, regMatch, 0);
+
+ if (code == 0) {
+ // match
+ int64_t version = -1;
+ sscanf((const char *)POINTER_SHIFT(entryName, regMatch[1].rm_so), "%" PRIi64, &version);
+ if ((version < committed) && (version > -1)) {
+ strncpy(dirEnd, entryName, TSDB_FILENAME_LEN - dirLen);
+ if (taosRemoveFile(dir) != 0) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ smaWarn("vgId:%d, committed version:%" PRIi64 ", failed to remove %s since %s", TD_VID(pVnode), committed,
+ dir, terrstr());
+ } else {
+ smaDebug("vgId:%d, committed version:%" PRIi64 ", success to remove %s", TD_VID(pVnode), committed, dir);
+ }
+ }
+ } else if (code == REG_NOMATCH) {
+ // not match
+ smaTrace("vgId:%d, rsma post commit, not match %s", TD_VID(pVnode), entryName);
+ continue;
+ } else {
+ // has other error
+ char errbuf[128];
+ regerror(code, ®ex, errbuf, sizeof(errbuf));
+ smaWarn("vgId:%d, rsma post commit, regexec failed since %s", TD_VID(pVnode), errbuf);
+
+ taosCloseDir(&pDir);
+ regfree(®ex);
+ return TSDB_CODE_FAILED;
+ }
+ }
+
+ taosCloseDir(&pDir);
+ regfree(®ex);
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/dnode/vnode/src/sma/smaEnv.c b/source/dnode/vnode/src/sma/smaEnv.c
index a80af2b20255fa51d114d9568afadac9318765cf..2cf4fd51a96130966f5f0d0957247bb67d3aff64 100644
--- a/source/dnode/vnode/src/sma/smaEnv.c
+++ b/source/dnode/vnode/src/sma/smaEnv.c
@@ -18,14 +18,85 @@
typedef struct SSmaStat SSmaStat;
#define RSMA_TASK_INFO_HASH_SLOT 8
+#define SMA_MGMT_REF_NUM 10240
+
+extern SSmaMgmt smaMgmt;
// declaration of static functions
-static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType);
+static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pSma);
static SSmaEnv *tdNewSmaEnv(const SSma *pSma, int8_t smaType, const char *path);
static int32_t tdInitSmaEnv(SSma *pSma, int8_t smaType, const char *path, SSmaEnv **pEnv);
+static void *tdFreeTSmaStat(STSmaStat *pStat);
+static void tdDestroyRSmaStat(void *pRSmaStat);
+/**
+ * @brief rsma init
+ *
+ * @return int32_t
+ */
// implementation
+int32_t smaInit() {
+ int8_t old;
+ int32_t nLoops = 0;
+ while (1) {
+ old = atomic_val_compare_exchange_8(&smaMgmt.inited, 0, 2);
+ if (old != 2) break;
+ if (++nLoops > 1000) {
+ sched_yield();
+ nLoops = 0;
+ }
+ }
+
+ if (old == 0) {
+ // init tref rset
+ smaMgmt.rsetId = taosOpenRef(SMA_MGMT_REF_NUM, tdDestroyRSmaStat);
+
+ if (smaMgmt.rsetId < 0) {
+ atomic_store_8(&smaMgmt.inited, 0);
+ smaError("failed to init sma rset since %s", terrstr());
+ return TSDB_CODE_FAILED;
+ }
+
+ // init fetch timer handle
+ smaMgmt.tmrHandle = taosTmrInit(10000, 100, 10000, "RSMA");
+ if (!smaMgmt.tmrHandle) {
+ taosCloseRef(smaMgmt.rsetId);
+ atomic_store_8(&smaMgmt.inited, 0);
+ smaError("failed to init sma tmr hanle since %s", terrstr());
+ return TSDB_CODE_FAILED;
+ }
+
+ atomic_store_8(&smaMgmt.inited, 1);
+ smaInfo("sma mgmt env is initialized, rsetId:%d, tmrHandle:%p", smaMgmt.rsetId, smaMgmt.tmrHandle);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief rsma cleanup
+ *
+ */
+void smaCleanUp() {
+ int8_t old;
+ int32_t nLoops = 0;
+ while (1) {
+ old = atomic_val_compare_exchange_8(&smaMgmt.inited, 1, 2);
+ if (old != 2) break;
+ if (++nLoops > 1000) {
+ sched_yield();
+ nLoops = 0;
+ }
+ }
+
+ if (old == 1) {
+ taosCloseRef(smaMgmt.rsetId);
+ taosTmrCleanUp(smaMgmt.tmrHandle);
+ smaInfo("sma mgmt env is cleaned up, rsetId:%d, tmrHandle:%p", smaMgmt.rsetId, smaMgmt.tmrHandle);
+ atomic_store_8(&smaMgmt.inited, 0);
+ }
+}
static SSmaEnv *tdNewSmaEnv(const SSma *pSma, int8_t smaType, const char *path) {
SSmaEnv *pEnv = NULL;
@@ -45,7 +116,7 @@ static SSmaEnv *tdNewSmaEnv(const SSma *pSma, int8_t smaType, const char *path)
return NULL;
}
- if (tdInitSmaStat(&SMA_ENV_STAT(pEnv), smaType) != TSDB_CODE_SUCCESS) {
+ if (tdInitSmaStat(&SMA_ENV_STAT(pEnv), smaType, pSma) != TSDB_CODE_SUCCESS) {
tdFreeSmaEnv(pEnv);
return NULL;
}
@@ -105,7 +176,7 @@ int32_t tdUnRefSmaStat(SSma *pSma, SSmaStat *pStat) {
return 0;
}
-static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType) {
+static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pSma) {
ASSERT(pSmaStat != NULL);
if (*pSmaStat) { // no lock
@@ -125,10 +196,29 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType) {
}
if (smaType == TSDB_SMA_TYPE_ROLLUP) {
- SMA_STAT_INFO_HASH(*pSmaStat) = taosHashInit(
- RSMA_TASK_INFO_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK);
+ SRSmaStat *pRSmaStat = (SRSmaStat *)(*pSmaStat);
+ pRSmaStat->pSma = (SSma *)pSma;
+ atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_INIT);
+
+ // init smaMgmt
+ smaInit();
+
+ int64_t refId = taosAddRef(smaMgmt.rsetId, pRSmaStat);
+ if (refId < 0) {
+ smaError("vgId:%d, taosAddRef refId:%" PRIi64 " to rsetId rsetId:%d max:%d failed since:%s", SMA_VID(pSma),
+ refId, smaMgmt.rsetId, SMA_MGMT_REF_NUM, tstrerror(terrno));
+ return TSDB_CODE_FAILED;
+ } else {
+ smaDebug("vgId:%d, taosAddRef refId:%" PRIi64 " to rsetId rsetId:%d max:%d succeed", SMA_VID(pSma), refId,
+ smaMgmt.rsetId, SMA_MGMT_REF_NUM);
+ }
+ pRSmaStat->refId = refId;
+
- if (!SMA_STAT_INFO_HASH(*pSmaStat)) {
+ // init hash
+ RSMA_INFO_HASH(pRSmaStat) = taosHashInit(
+ RSMA_TASK_INFO_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK);
+ if (!RSMA_INFO_HASH(pRSmaStat)) {
taosMemoryFreeClear(*pSmaStat);
return TSDB_CODE_FAILED;
}
@@ -141,18 +231,66 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType) {
return TSDB_CODE_SUCCESS;
}
-void *tdFreeSmaStatItem(SSmaStatItem *pSmaStatItem) {
- if (pSmaStatItem) {
- tDestroyTSma(pSmaStatItem->pTSma);
- taosMemoryFreeClear(pSmaStatItem->pTSma);
- taosMemoryFreeClear(pSmaStatItem);
+static void tdDestroyTSmaStat(STSmaStat *pStat) {
+ if (pStat) {
+ smaDebug("destroy tsma stat");
+ tDestroyTSma(pStat->pTSma);
+ taosMemoryFreeClear(pStat->pTSma);
+ taosMemoryFreeClear(pStat->pTSchema);
}
+}
+
+static void *tdFreeTSmaStat(STSmaStat *pStat) {
+ tdDestroyTSmaStat(pStat);
+ taosMemoryFreeClear(pStat);
return NULL;
}
-void* tdFreeSmaState(SSmaStat *pSmaStat, int8_t smaType) {
+static void tdDestroyRSmaStat(void *pRSmaStat) {
+ if (pRSmaStat) {
+ SRSmaStat *pStat = (SRSmaStat *)pRSmaStat;
+ SSma *pSma = pStat->pSma;
+ smaDebug("vgId:%d, destroy rsma stat %p", SMA_VID(pSma), pRSmaStat);
+ // step 1: set rsma trigger stat cancelled
+ atomic_store_8(RSMA_TRIGGER_STAT(pStat), TASK_TRIGGER_STAT_CANCELLED);
+
+ // step 2: destroy the rsma info and associated fetch tasks
+ // TODO: use taosHashSetFreeFp when taosHashSetFreeFp is ready.
+ if (taosHashGetSize(RSMA_INFO_HASH(pStat)) > 0) {
+ void *infoHash = taosHashIterate(RSMA_INFO_HASH(pStat), NULL);
+ while (infoHash) {
+ SRSmaInfo *pSmaInfo = *(SRSmaInfo **)infoHash;
+ tdFreeRSmaInfo(pSma, pSmaInfo);
+ infoHash = taosHashIterate(RSMA_INFO_HASH(pStat), infoHash);
+ }
+ }
+ taosHashCleanup(RSMA_INFO_HASH(pStat));
+
+ // step 3: wait all triggered fetch tasks finished
+ int32_t nLoops = 0;
+ while (1) {
+ if (T_REF_VAL_GET((SSmaStat *)pStat) == 0) {
+ smaDebug("vgId:%d, rsma fetch tasks all finished", SMA_VID(pSma));
+ break;
+ } else {
+ smaDebug("vgId:%d, rsma fetch tasks not all finished yet", SMA_VID(pSma));
+ }
+ ++nLoops;
+ if (nLoops > 1000) {
+ sched_yield();
+ nLoops = 0;
+ }
+ }
+ }
+}
+
+void *tdFreeSmaState(SSmaStat *pSmaStat, int8_t smaType) {
tdDestroySmaState(pSmaStat, smaType);
- taosMemoryFreeClear(pSmaStat);
+ if (smaType == TSDB_SMA_TYPE_TIME_RANGE) {
+ taosMemoryFreeClear(pSmaStat);
+ }
+ // tref used to free rsma stat
+
return NULL;
}
@@ -162,24 +300,26 @@ void* tdFreeSmaState(SSmaStat *pSmaStat, int8_t smaType) {
* @param pSmaStat
* @return int32_t
*/
+
int32_t tdDestroySmaState(SSmaStat *pSmaStat, int8_t smaType) {
if (pSmaStat) {
if (smaType == TSDB_SMA_TYPE_TIME_RANGE) {
- tdFreeSmaStatItem(&pSmaStat->tsmaStatItem);
+ tdDestroyTSmaStat(SMA_TSMA_STAT(pSmaStat));
} else if (smaType == TSDB_SMA_TYPE_ROLLUP) {
- // TODO: use taosHashSetFreeFp when taosHashSetFreeFp is ready.
- void *infoHash = taosHashIterate(SMA_STAT_INFO_HASH(pSmaStat), NULL);
- while (infoHash) {
- SRSmaInfo *pInfoHash = *(SRSmaInfo **)infoHash;
- tdFreeRSmaInfo(pInfoHash);
- infoHash = taosHashIterate(SMA_STAT_INFO_HASH(pSmaStat), infoHash);
+ SRSmaStat *pRSmaStat = SMA_RSMA_STAT(pSmaStat);
+ if (taosRemoveRef(smaMgmt.rsetId, RSMA_REF_ID(pRSmaStat)) < 0) {
+ smaError("vgId:%d, remove refId:%" PRIi64 " from rsmaRef:%" PRIi32 " failed since %s", SMA_VID(pRSmaStat->pSma),
+ RSMA_REF_ID(pRSmaStat), smaMgmt.rsetId, terrstr());
+ ASSERT(0);
+ } else {
+ smaDebug("vgId:%d, remove refId:%" PRIi64 " from rsmaRef:%" PRIi32 " succeed", SMA_VID(pRSmaStat->pSma),
+ RSMA_REF_ID(pRSmaStat), smaMgmt.rsetId);
}
- taosHashCleanup(SMA_STAT_INFO_HASH(pSmaStat));
} else {
ASSERT(0);
}
}
- return TSDB_CODE_SUCCESS;
+ return 0;
}
int32_t tdLockSma(SSma *pSma) {
@@ -220,7 +360,7 @@ int32_t tdCheckAndInitSmaEnv(SSma *pSma, int8_t smaType) {
}
break;
default:
- TASSERT(0);
+ smaError("vgId:%d undefined smaType:%", SMA_VID(pSma), smaType);
return TSDB_CODE_FAILED;
}
@@ -242,35 +382,4 @@ int32_t tdCheckAndInitSmaEnv(SSma *pSma, int8_t smaType) {
tdUnLockSma(pSma);
return TSDB_CODE_SUCCESS;
-};
-
-int32_t smaTimerInit(void **timer, int8_t *initFlag, const char *label) {
- int8_t old;
- while (1) {
- old = atomic_val_compare_exchange_8(initFlag, 0, 2);
- if (old != 2) break;
- }
-
- if (old == 0) {
- *timer = taosTmrInit(10000, 100, 10000, label);
- if (!(*timer)) {
- atomic_store_8(initFlag, 0);
- return -1;
- }
- atomic_store_8(initFlag, 1);
- }
- return 0;
-}
-
-void smaTimerCleanUp(void *timer, int8_t *initFlag) {
- int8_t old;
- while (1) {
- old = atomic_val_compare_exchange_8(initFlag, 1, 2);
- if (old != 2) break;
- }
-
- if (old == 1) {
- taosTmrCleanUp(timer);
- atomic_store_8(initFlag, 0);
- }
-}
+};
\ No newline at end of file
diff --git a/source/dnode/vnode/src/sma/smaOpen.c b/source/dnode/vnode/src/sma/smaOpen.c
index a1c47a96c0d2d12a6652dc66019a109fc698a5af..d73b03f4a2e9690c36693d29860a5e2ad09f720e 100644
--- a/source/dnode/vnode/src/sma/smaOpen.c
+++ b/source/dnode/vnode/src/sma/smaOpen.c
@@ -18,6 +18,7 @@
static int32_t smaEvalDays(SRetention *r, int8_t precision);
static int32_t smaSetKeepCfg(STsdbKeepCfg *pKeepCfg, STsdbCfg *pCfg, int type);
+static int32_t rsmaRestore(SSma *pSma);
#define SMA_SET_KEEP_CFG(l) \
do { \
@@ -100,6 +101,9 @@ int32_t smaOpen(SVnode *pVnode) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
+
+ pVnode->pSma = pSma;
+
pSma->pVnode = pVnode;
taosThreadMutexInit(&pSma->mutex, NULL);
pSma->locked = false;
@@ -117,24 +121,41 @@ int32_t smaOpen(SVnode *pVnode) {
ASSERT(0);
}
}
+
+ // restore the rsma
+#if 1
+ if (rsmaRestore(pSma) < 0) {
+ goto _err;
+ }
+#endif
}
- pVnode->pSma = pSma;
return 0;
_err:
- taosMemoryFreeClear(pSma);
return -1;
}
int32_t smaClose(SSma *pSma) {
if (pSma) {
taosThreadMutexDestroy(&pSma->mutex);
+ SMA_TSMA_ENV(pSma) = tdFreeSmaEnv(SMA_TSMA_ENV(pSma));
+ SMA_RSMA_ENV(pSma) = tdFreeSmaEnv(SMA_RSMA_ENV(pSma));
if SMA_RSMA_TSDB0 (pSma) tsdbClose(&SMA_RSMA_TSDB0(pSma));
if SMA_RSMA_TSDB1 (pSma) tsdbClose(&SMA_RSMA_TSDB1(pSma));
if SMA_RSMA_TSDB2 (pSma) tsdbClose(&SMA_RSMA_TSDB2(pSma));
- // SMA_TSMA_ENV(pSma) = tdFreeSmaEnv(SMA_TSMA_ENV(pSma));
- // SMA_RSMA_ENV(pSma) = tdFreeSmaEnv(SMA_RSMA_ENV(pSma));
taosMemoryFreeClear(pSma);
}
return 0;
+}
+
+/**
+ * @brief rsma env restore
+ *
+ * @param pSma
+ * @return int32_t
+ */
+static int32_t rsmaRestore(SSma *pSma) {
+ ASSERT(VND_IS_RSMA(pSma->pVnode));
+
+ return tdProcessRSmaRestoreImpl(pSma);
}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/sma/smaRollup.c b/source/dnode/vnode/src/sma/smaRollup.c
index 1f18f6cb8777452dde659bbdec8a22d9f84e30de..06ffb639de057ec773e8962fc44898aaa8e10817 100644
--- a/source/dnode/vnode/src/sma/smaRollup.c
+++ b/source/dnode/vnode/src/sma/smaRollup.c
@@ -14,80 +14,119 @@
*/
#include "sma.h"
-#include "tstream.h"
-
-static FORCE_INLINE int32_t tdUidStorePut(STbUidStore *pStore, tb_uid_t suid, tb_uid_t *uid);
-static FORCE_INLINE int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids);
-static FORCE_INLINE int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t inputType, SRSmaInfoItem *rsmaItem,
- tb_uid_t suid, int8_t level);
-
-#define SET_RSMA_INFO_ITEM_PARAMS(__idx, __level) \
- if (param->qmsg[__idx]) { \
- pRSmaInfo->items[__idx].pRsmaInfo = pRSmaInfo; \
- pRSmaInfo->items[__idx].taskInfo = qCreateStreamExecTaskInfo(param->qmsg[0], &handle); \
- if (!pRSmaInfo->items[__idx].taskInfo) { \
- goto _err; \
- } \
- pRSmaInfo->items[__idx].triggerStatus = TASK_TRIGGER_STATUS__IN_ACTIVE; \
- if (param->maxdelay[__idx] < 1) { \
- int64_t msInterval = \
- convertTimeFromPrecisionToUnit(pRetention[__level].freq, pTsdbCfg->precision, TIME_UNIT_MILLISECOND); \
- pRSmaInfo->items[__idx].maxDelay = msInterval; \
- } else { \
- pRSmaInfo->items[__idx].maxDelay = param->maxdelay[__idx]; \
- } \
- if (pRSmaInfo->items[__idx].maxDelay > TSDB_MAX_ROLLUP_MAX_DELAY) { \
- pRSmaInfo->items[__idx].maxDelay = TSDB_MAX_ROLLUP_MAX_DELAY; \
- } \
- pRSmaInfo->items[__idx].level = TSDB_RETENTION_L##__level; \
- pRSmaInfo->items[__idx].tmrHandle = taosTmrInit(10000, 100, 10000, "RSMA"); \
- if (!pRSmaInfo->items[__idx].tmrHandle) { \
- goto _err; \
- } \
- }
-struct SRSmaInfoItem {
- SRSmaInfo *pRsmaInfo;
- void *taskInfo; // qTaskInfo_t
- void *tmrHandle;
- tmr_h tmrId;
- int8_t level;
- int8_t tmrInitFlag;
- int8_t triggerStatus; // TASK_TRIGGER_STATUS__IN_ACTIVE/TASK_TRIGGER_STATUS__ACTIVE
- int32_t maxDelay;
+#define RSMA_QTASKINFO_BUFSIZE 32768
+#define RSMA_QTASKINFO_HEAD_LEN (sizeof(int32_t) + sizeof(int8_t) + sizeof(int64_t)) // len + type + suid
+
+SSmaMgmt smaMgmt = {
+ .inited = 0,
+ .rsetId = -1,
};
-typedef struct {
- int64_t suid;
- SRSmaInfoItem *pItem;
- SSma *pSma;
- STSchema *pTSchema;
-} SRSmaTriggerParam;
+#define TD_QTASKINFO_FNAME_PREFIX "qtaskinfo.ver"
+typedef struct SRSmaQTaskInfoItem SRSmaQTaskInfoItem;
+typedef struct SRSmaQTaskInfoIter SRSmaQTaskInfoIter;
+
+static int32_t tdUidStorePut(STbUidStore *pStore, tb_uid_t suid, tb_uid_t *uid);
+static int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids);
+static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat *pStat, SRSmaInfo *pRSmaInfo,
+ SReadHandle *handle, int8_t idx);
+static int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t inputType, SRSmaInfoItem *rsmaItem,
+ STSchema *pTSchema, tb_uid_t suid, int8_t level);
+static SRSmaInfo *tdGetRSmaInfoBySuid(SSma *pSma, int64_t suid);
+static int32_t tdRSmaFetchAndSubmitResult(SRSmaInfoItem *pItem, STSchema *pTSchema, int64_t suid, SRSmaStat *pStat,
+ int8_t blkType);
+static void tdRSmaFetchTrigger(void *param, void *tmrId);
+static void tdRSmaQTaskInfoGetFName(int32_t vid, int64_t version, char *outputName);
+
+static int32_t tdRSmaQTaskInfoIterInit(SRSmaQTaskInfoIter *pIter, STFile *pTFile);
+static int32_t tdRSmaQTaskInfoIterNextBlock(SRSmaQTaskInfoIter *pIter, bool *isFinish);
+static int32_t tdRSmaQTaskInfoRestore(SSma *pSma, SRSmaQTaskInfoIter *pIter);
+static int32_t tdRSmaQTaskInfoItemRestore(SSma *pSma, const SRSmaQTaskInfoItem *infoItem);
+
+static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables);
+static int32_t tdRSmaRestoreQTaskInfoReload(SSma *pSma, int64_t *committed);
+static int32_t tdRSmaRestoreTSDataReload(SSma *pSma, int64_t committed);
+
+struct SRSmaInfoItem {
+ void *taskInfo; // qTaskInfo_t
+ int64_t refId;
+ tmr_h tmrId;
+ int32_t maxDelay;
+ int8_t level;
+ int8_t triggerStat;
+};
struct SRSmaInfo {
STSchema *pTSchema;
- SSma *pSma;
int64_t suid;
SRSmaInfoItem items[TSDB_RETENTION_L2];
};
-static FORCE_INLINE void tdFreeTaskHandle(qTaskInfo_t *taskHandle) {
+static SRSmaInfo *tdGetRSmaInfoByItem(SRSmaInfoItem *pItem) {
+ // adapt accordingly if definition of SRSmaInfo update
+ SRSmaInfo *pResult = NULL;
+ int32_t rsmaInfoHeadLen = sizeof(int64_t) + sizeof(STSchema *);
+ ASSERT(pItem->level == TSDB_RETENTION_L1 || pItem->level == TSDB_RETENTION_L2);
+ pResult = (SRSmaInfo *)POINTER_SHIFT(pItem, -(sizeof(SRSmaInfoItem) * (pItem->level - 1) + rsmaInfoHeadLen));
+ ASSERT(pResult->pTSchema->numOfCols > 1);
+ return pResult;
+}
+
+struct SRSmaQTaskInfoItem {
+ int32_t len;
+ int8_t type;
+ int64_t suid;
+ void *qTaskInfo;
+};
+
+struct SRSmaQTaskInfoIter {
+ STFile *pTFile;
+ int64_t offset;
+ int64_t fsize;
+ int32_t nBytes;
+ int32_t nAlloc;
+ char *pBuf;
+ // ------------
+ char *qBuf; // for iterator
+ int32_t nBufPos;
+};
+
+static void tdRSmaQTaskInfoGetFName(int32_t vgId, int64_t version, char *outputName) {
+ tdGetVndFileName(vgId, NULL, VNODE_RSMA_DIR, TD_QTASKINFO_FNAME_PREFIX, version, outputName);
+}
+
+static FORCE_INLINE int32_t tdRSmaQTaskInfoContLen(int32_t lenWithHead) {
+ return lenWithHead - RSMA_QTASKINFO_HEAD_LEN;
+}
+
+static FORCE_INLINE void tdRSmaQTaskInfoIterDestroy(SRSmaQTaskInfoIter *pIter) { taosMemoryFreeClear(pIter->pBuf); }
+
+static FORCE_INLINE void tdFreeTaskHandle(qTaskInfo_t *taskHandle, int32_t vgId, int32_t level) {
// Note: free/kill may in RC
qTaskInfo_t otaskHandle = atomic_load_ptr(taskHandle);
if (otaskHandle && atomic_val_compare_exchange_ptr(taskHandle, otaskHandle, NULL)) {
+ smaDebug("vgId:%d, free qTaskInfo_t %p of level %d", vgId, otaskHandle, level);
qDestroyTask(otaskHandle);
+ } else {
+ smaDebug("vgId:%d, not free qTaskInfo_t %p of level %d", vgId, otaskHandle, level);
}
}
-void *tdFreeRSmaInfo(SRSmaInfo *pInfo) {
+void *tdFreeRSmaInfo(SSma *pSma, SRSmaInfo *pInfo) {
if (pInfo) {
- for (int32_t i = 0; i < TSDB_RETENTION_MAX; ++i) {
+ for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) {
SRSmaInfoItem *pItem = &pInfo->items[i];
if (pItem->taskInfo) {
- tdFreeTaskHandle(pItem->taskInfo);
- }
- if (pItem->tmrHandle) {
- taosTmrCleanUp(pItem->tmrHandle);
+ if (pItem->tmrId) {
+ smaDebug("vgId:%d, table %" PRIi64 " stop fetch timer %p level %d", SMA_VID(pSma), pInfo->suid, pItem->tmrId,
+ i + 1);
+ taosTmrStopA(&pItem->tmrId);
+ }
+ tdFreeTaskHandle(&pItem->taskInfo, SMA_VID(pSma), i + 1);
+ } else {
+ smaDebug("vgId:%d, table %" PRIi64 " no need to destroy rsma info level %d since empty taskInfo", SMA_VID(pSma),
+ pInfo->suid, i + 1);
}
}
taosMemoryFree(pInfo->pTSchema);
@@ -107,9 +146,7 @@ static FORCE_INLINE int32_t tdUidStoreInit(STbUidStore **pStore) {
return TSDB_CODE_SUCCESS;
}
-static FORCE_INLINE int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids) {
- SSmaEnv *pEnv = SMA_RSMA_ENV(pSma);
- SSmaStat *pStat = SMA_ENV_STAT(pEnv);
+static int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids) {
SRSmaInfo *pRSmaInfo = NULL;
if (!suid || !tbUids) {
@@ -118,27 +155,32 @@ static FORCE_INLINE int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SA
return TSDB_CODE_FAILED;
}
- pRSmaInfo = taosHashGet(SMA_STAT_INFO_HASH(pStat), suid, sizeof(tb_uid_t));
- if (!pRSmaInfo || !(pRSmaInfo = *(SRSmaInfo **)pRSmaInfo)) {
+ pRSmaInfo = tdGetRSmaInfoBySuid(pSma, *suid);
+
+ if (!pRSmaInfo) {
smaError("vgId:%d, failed to get rsma info for uid:%" PRIi64, SMA_VID(pSma), *suid);
terrno = TSDB_CODE_RSMA_INVALID_STAT;
return TSDB_CODE_FAILED;
}
- if (pRSmaInfo->items[0].taskInfo && (qUpdateQualifiedTableId(pRSmaInfo->items[0].taskInfo, tbUids, true) < 0)) {
- smaError("vgId:%d, update tbUidList failed for uid:%" PRIi64 " since %s", SMA_VID(pSma), *suid, terrstr(terrno));
- return TSDB_CODE_FAILED;
- } else {
- smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 ", uid:%" PRIi64, SMA_VID(pSma),
- pRSmaInfo->items[0].taskInfo, *suid, *(int64_t *)taosArrayGet(tbUids, 0));
+ if (pRSmaInfo->items[0].taskInfo) {
+ if ((qUpdateQualifiedTableId(pRSmaInfo->items[0].taskInfo, tbUids, true) < 0)) {
+ smaError("vgId:%d, update tbUidList failed for uid:%" PRIi64 " since %s", SMA_VID(pSma), *suid, terrstr(terrno));
+ return TSDB_CODE_FAILED;
+ } else {
+ smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 ", uid:%" PRIi64, SMA_VID(pSma),
+ pRSmaInfo->items[0].taskInfo, *suid, *(int64_t *)taosArrayGet(tbUids, 0));
+ }
}
- if (pRSmaInfo->items[1].taskInfo && (qUpdateQualifiedTableId(pRSmaInfo->items[1].taskInfo, tbUids, true) < 0)) {
- smaError("vgId:%d, update tbUidList failed for uid:%" PRIi64 " since %s", SMA_VID(pSma), *suid, terrstr(terrno));
- return TSDB_CODE_FAILED;
- } else {
- smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 ", uid:%" PRIi64, SMA_VID(pSma),
- pRSmaInfo->items[1].taskInfo, *suid, *(int64_t *)taosArrayGet(tbUids, 0));
+ if (pRSmaInfo->items[1].taskInfo) {
+ if ((qUpdateQualifiedTableId(pRSmaInfo->items[1].taskInfo, tbUids, true) < 0)) {
+ smaError("vgId:%d, update tbUidList failed for uid:%" PRIi64 " since %s", SMA_VID(pSma), *suid, terrstr(terrno));
+ return TSDB_CODE_FAILED;
+ } else {
+ smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 ", uid:%" PRIi64, SMA_VID(pSma),
+ pRSmaInfo->items[1].taskInfo, *suid, *(int64_t *)taosArrayGet(tbUids, 0));
+ }
}
return TSDB_CODE_SUCCESS;
@@ -185,9 +227,9 @@ int32_t tdFetchTbUidList(SSma *pSma, STbUidStore **ppStore, tb_uid_t suid, tb_ui
return TSDB_CODE_SUCCESS;
}
- SSmaStat *pStat = SMA_ENV_STAT(pEnv);
- SHashObj *infoHash = NULL;
- if (!pStat || !(infoHash = SMA_STAT_INFO_HASH(pStat))) {
+ SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv);
+ SHashObj *infoHash = NULL;
+ if (!pStat || !(infoHash = RSMA_INFO_HASH(pStat))) {
terrno = TSDB_CODE_RSMA_INVALID_STAT;
return TSDB_CODE_FAILED;
}
@@ -213,27 +255,56 @@ int32_t tdFetchTbUidList(SSma *pSma, STbUidStore **ppStore, tb_uid_t suid, tb_ui
return TSDB_CODE_SUCCESS;
}
+static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat *pStat, SRSmaInfo *pRSmaInfo,
+ SReadHandle *pReadHandle, int8_t idx) {
+ SRetention *pRetention = SMA_RETENTION(pSma);
+ STsdbCfg *pTsdbCfg = SMA_TSDB_CFG(pSma);
+
+ if (param->qmsg[idx]) {
+ SRSmaInfoItem *pItem = &(pRSmaInfo->items[idx]);
+ pItem->refId = RSMA_REF_ID(pStat);
+ pItem->taskInfo = qCreateStreamExecTaskInfo(param->qmsg[idx], pReadHandle);
+ if (!pItem->taskInfo) {
+ terrno = TSDB_CODE_RSMA_QTASKINFO_CREATE;
+ goto _err;
+ }
+ pItem->triggerStat = TASK_TRIGGER_STAT_INACTIVE;
+ if (param->maxdelay[idx] < TSDB_MIN_ROLLUP_MAX_DELAY) {
+ int64_t msInterval =
+ convertTimeFromPrecisionToUnit(pRetention[idx + 1].freq, pTsdbCfg->precision, TIME_UNIT_MILLISECOND);
+ pItem->maxDelay = (int32_t)msInterval;
+ } else {
+ pItem->maxDelay = (int32_t)param->maxdelay[idx];
+ }
+ if (pItem->maxDelay > TSDB_MAX_ROLLUP_MAX_DELAY) {
+ pItem->maxDelay = TSDB_MAX_ROLLUP_MAX_DELAY;
+ }
+ pItem->level = idx == 0 ? TSDB_RETENTION_L1 : TSDB_RETENTION_L2;
+ smaInfo("vgId:%d table:%" PRIi64 " level:%" PRIi8 " maxdelay:%" PRIi64 " watermark:%" PRIi64
+ ", finally maxdelay:%" PRIi32,
+ SMA_VID(pSma), pRSmaInfo->suid, idx + 1, param->maxdelay[idx], param->watermark[idx], pItem->maxDelay);
+ }
+ return TSDB_CODE_SUCCESS;
+_err:
+ return TSDB_CODE_FAILED;
+}
+
/**
- * @brief Check and init qTaskInfo_t, only applicable to stable with SRSmaParam.
+ * @brief for rsam create or restore
*
- * @param pTsdb
- * @param pMeta
- * @param pReq
+ * @param pSma
+ * @param param
+ * @param suid
+ * @param tbName
* @return int32_t
*/
-int32_t tdProcessRSmaCreate(SVnode *pVnode, SVCreateStbReq *pReq) {
- SSma *pSma = pVnode->pSma;
- if (!pReq->rollup) {
- smaTrace("vgId:%d, return directly since no rollup for stable %s %" PRIi64, SMA_VID(pSma), pReq->name, pReq->suid);
- return TSDB_CODE_SUCCESS;
- }
-
- SMeta *pMeta = pVnode->pMeta;
- SMsgCb *pMsgCb = &pVnode->msgCb;
- SRSmaParam *param = &pReq->pRSmaParam;
+int32_t tdProcessRSmaCreateImpl(SSma *pSma, SRSmaParam *param, int64_t suid, const char *tbName) {
+ SVnode *pVnode = pSma->pVnode;
+ SMeta *pMeta = pVnode->pMeta;
+ SMsgCb *pMsgCb = &pVnode->msgCb;
if ((param->qmsgLen[0] == 0) && (param->qmsgLen[1] == 0)) {
- smaWarn("vgId:%d, no qmsg1/qmsg2 for rollup stable %s %" PRIi64, SMA_VID(pSma), pReq->name, pReq->suid);
+ smaDebug("vgId:%d, no qmsg1/qmsg2 for rollup table %s %" PRIi64, SMA_VID(pSma), tbName, suid);
return TSDB_CODE_SUCCESS;
}
@@ -243,13 +314,13 @@ int32_t tdProcessRSmaCreate(SVnode *pVnode, SVCreateStbReq *pReq) {
}
SSmaEnv *pEnv = SMA_RSMA_ENV(pSma);
- SSmaStat *pStat = SMA_ENV_STAT(pEnv);
+ SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv);
SRSmaInfo *pRSmaInfo = NULL;
- pRSmaInfo = taosHashGet(SMA_STAT_INFO_HASH(pStat), &pReq->suid, sizeof(tb_uid_t));
+ pRSmaInfo = taosHashGet(RSMA_INFO_HASH(pStat), &suid, sizeof(tb_uid_t));
if (pRSmaInfo) {
- ASSERT(0); // TODO: free original pRSmaInfo is exists abnormally
- smaWarn("vgId:%d, rsma info already exists for stb: %s, %" PRIi64, SMA_VID(pSma), pReq->name, pReq->suid);
+ ASSERT(0); // TODO: free original pRSmaInfo if exists abnormally
+ smaDebug("vgId:%d, rsma info already exists for table %s, %" PRIi64, SMA_VID(pSma), tbName, suid);
return TSDB_CODE_SUCCESS;
}
@@ -260,48 +331,93 @@ int32_t tdProcessRSmaCreate(SVnode *pVnode, SVCreateStbReq *pReq) {
return TSDB_CODE_FAILED;
}
- STqReadHandle *pReadHandle = tqInitSubmitMsgScanner(pMeta);
- if (!pReadHandle) {
+ STqReader *pReader = tqOpenReader(pVnode);
+ if (!pReader) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
SReadHandle handle = {
- .reader = pReadHandle,
+ .tqReader = pReader,
.meta = pMeta,
.pMsgCb = pMsgCb,
.vnode = pVnode,
};
- STSchema *pTSchema = metaGetTbTSchema(SMA_META(pSma), pReq->suid, -1);
+ STSchema *pTSchema = metaGetTbTSchema(SMA_META(pSma), suid, -1);
if (!pTSchema) {
terrno = TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION;
goto _err;
}
pRSmaInfo->pTSchema = pTSchema;
- pRSmaInfo->pSma = pSma;
- pRSmaInfo->suid = pReq->suid;
+ pRSmaInfo->suid = suid;
- SRetention *pRetention = SMA_RETENTION(pSma);
- STsdbCfg *pTsdbCfg = SMA_TSDB_CFG(pSma);
+ if (tdSetRSmaInfoItemParams(pSma, param, pStat, pRSmaInfo, &handle, 0) < 0) {
+ goto _err;
+ }
- SET_RSMA_INFO_ITEM_PARAMS(0, 1);
- SET_RSMA_INFO_ITEM_PARAMS(1, 2);
+ if (tdSetRSmaInfoItemParams(pSma, param, pStat, pRSmaInfo, &handle, 1) < 0) {
+ goto _err;
+ }
- if (taosHashPut(SMA_STAT_INFO_HASH(pStat), &pReq->suid, sizeof(tb_uid_t), &pRSmaInfo, sizeof(pRSmaInfo)) !=
- TSDB_CODE_SUCCESS) {
+ if (taosHashPut(RSMA_INFO_HASH(pStat), &suid, sizeof(tb_uid_t), &pRSmaInfo, sizeof(pRSmaInfo)) < 0) {
goto _err;
- } else {
- smaDebug("vgId:%d, register rsma info succeed for suid:%" PRIi64, SMA_VID(pSma), pReq->suid);
}
+ smaDebug("vgId:%d, register rsma info succeed for table %" PRIi64, SMA_VID(pSma), suid);
+
return TSDB_CODE_SUCCESS;
_err:
- tdFreeRSmaInfo(pRSmaInfo);
- taosMemoryFree(pReadHandle);
+ tdFreeRSmaInfo(pSma, pRSmaInfo);
+ taosMemoryFree(pReader);
return TSDB_CODE_FAILED;
}
+/**
+ * @brief Check and init qTaskInfo_t, only applicable to stable with SRSmaParam currently
+ *
+ * @param pSma
+ * @param pReq
+ * @return int32_t
+ */
+int32_t tdProcessRSmaCreate(SSma *pSma, SVCreateStbReq *pReq) {
+ SVnode *pVnode = pSma->pVnode;
+ if (!pReq->rollup) {
+ smaTrace("vgId:%d, not create rsma for stable %s %" PRIi64 " since no rollup in req", TD_VID(pVnode), pReq->name,
+ pReq->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (!VND_IS_RSMA(pVnode)) {
+ smaTrace("vgId:%d, not create rsma for stable %s %" PRIi64 " since vnd is not rsma", TD_VID(pVnode), pReq->name,
+ pReq->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return tdProcessRSmaCreateImpl(pSma, &pReq->rsmaParam, pReq->suid, pReq->name);
+}
+
+/**
+ * @brief drop cache for stb
+ *
+ * @param pSma
+ * @param pReq
+ * @return int32_t
+ */
+int32_t tdProcessRSmaDrop(SSma *pSma, SVDropStbReq *pReq) {
+ SVnode *pVnode = pSma->pVnode;
+ if (!VND_IS_RSMA(pVnode)) {
+ smaTrace("vgId:%d, not create rsma for stable %s %" PRIi64 " since vnd is not rsma", TD_VID(pVnode), pReq->name,
+ pReq->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
+
+
+ smaDebug("vgId:%d, drop rsma for table %" PRIi64 " succeed", TD_VID(pVnode), pReq->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
/**
* @brief store suid/[uids], prefer to use array and then hash
*
@@ -404,7 +520,6 @@ static int32_t tdProcessSubmitReq(STsdb *pTsdb, int64_t version, void *pReq) {
}
static int32_t tdFetchSubmitReqSuids(SSubmitReq *pMsg, STbUidStore *pStore) {
- ASSERT(pMsg != NULL);
SSubmitMsgIter msgIter = {0};
SSubmitBlk *pBlock = NULL;
SSubmitBlkIter blkIter = {0};
@@ -412,23 +527,50 @@ static int32_t tdFetchSubmitReqSuids(SSubmitReq *pMsg, STbUidStore *pStore) {
terrno = TSDB_CODE_SUCCESS;
- if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) return -1;
+ if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) {
+ return -1;
+ }
while (true) {
- if (tGetSubmitMsgNext(&msgIter, &pBlock) < 0) return -1;
+ if (tGetSubmitMsgNext(&msgIter, &pBlock) < 0) {
+ return -1;
+ }
if (!pBlock) break;
tdUidStorePut(pStore, msgIter.suid, NULL);
- pStore->uid = msgIter.uid; // TODO: remove, just for debugging
}
- if (terrno != TSDB_CODE_SUCCESS) return -1;
+ if (terrno != TSDB_CODE_SUCCESS) {
+ return -1;
+ }
return 0;
}
-static int32_t tdFetchAndSubmitRSmaResult(SRSmaInfoItem *pItem, int8_t blkType) {
- SArray *pResult = NULL;
- SRSmaInfo *pRSmaInfo = pItem->pRsmaInfo;
- SSma *pSma = pRSmaInfo->pSma;
+static void tdDestroySDataBlockArray(SArray *pArray) {
+ // TODO
+#if 0
+ for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
+ SSDataBlock *pDataBlock = taosArrayGet(pArray, i);
+ blockDestroyInner(pDataBlock);
+ }
+#endif
+ taosArrayDestroy(pArray);
+}
+
+int64_t tdRSmaGetMaxSubmitVer(SSma *pSma, int8_t level) {
+ if (level == TSDB_RETENTION_L0) {
+ return pSma->pVnode->state.applied;
+ }
+
+ SSmaEnv *pRSmaEnv = SMA_RSMA_ENV(pSma);
+ SRSmaStat *pRSmaStat = (SRSmaStat *)(SMA_ENV_STAT(pRSmaEnv));
+
+ return atomic_load_64(&pRSmaStat->submitVer);
+}
+
+static int32_t tdRSmaFetchAndSubmitResult(SRSmaInfoItem *pItem, STSchema *pTSchema, int64_t suid, SRSmaStat *pStat,
+ int8_t blkType) {
+ SArray *pResult = NULL;
+ SSma *pSma = pStat->pSma;
while (1) {
SSDataBlock *output = NULL;
@@ -439,8 +581,9 @@ static int32_t tdFetchAndSubmitRSmaResult(SRSmaInfoItem *pItem, int8_t blkType)
if (!output) {
break;
}
+
if (!pResult) {
- pResult = taosArrayInit(0, sizeof(SSDataBlock));
+ pResult = taosArrayInit(1, sizeof(SSDataBlock));
if (!pResult) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return TSDB_CODE_FAILED;
@@ -451,100 +594,98 @@ static int32_t tdFetchAndSubmitRSmaResult(SRSmaInfoItem *pItem, int8_t blkType)
}
if (taosArrayGetSize(pResult) > 0) {
-#if 0
+#if 1
char flag[10] = {0};
snprintf(flag, 10, "level %" PRIi8, pItem->level);
- blockDebugShowData(pResult, flag);
+ blockDebugShowDataBlocks(pResult, flag);
#endif
STsdb *sinkTsdb = (pItem->level == TSDB_RETENTION_L1 ? pSma->pRSmaTsdb1 : pSma->pRSmaTsdb2);
SSubmitReq *pReq = NULL;
- if (buildSubmitReqFromDataBlock(&pReq, pResult, pRSmaInfo->pTSchema, SMA_VID(pSma), pRSmaInfo->suid) < 0) {
- taosArrayDestroy(pResult);
- return TSDB_CODE_FAILED;
+ // TODO: the schema update should be handled
+ if (buildSubmitReqFromDataBlock(&pReq, pResult, pTSchema, SMA_VID(pSma), suid) < 0) {
+ smaError("vgId:%d, build submit req for rsma table %" PRIi64 "l evel %" PRIi8 " failed since %s", SMA_VID(pSma),
+ suid, pItem->level, terrstr());
+ goto _err;
}
- if (pReq && tdProcessSubmitReq(sinkTsdb, INT64_MAX, pReq) < 0) {
- taosArrayDestroy(pResult);
+ if (pReq && tdProcessSubmitReq(sinkTsdb, atomic_add_fetch_64(&pStat->submitVer, 1), pReq) < 0) {
taosMemoryFreeClear(pReq);
- return TSDB_CODE_FAILED;
+ smaError("vgId:%d, process submit req for rsma table %" PRIi64 " level %" PRIi8 " failed since %s", SMA_VID(pSma),
+ suid, pItem->level, terrstr());
+ goto _err;
}
taosMemoryFreeClear(pReq);
+ } else if (terrno == 0) {
+ smaDebug("vgId:%d, no rsma %" PRIi8 " data fetched yet", SMA_VID(pSma), pItem->level);
} else {
- smaDebug("vgId:%d, no rsma % " PRIi8 " data generated since %s", SMA_VID(pSma), pItem->level, tstrerror(terrno));
+ smaDebug("vgId:%d, no rsma %" PRIi8 " data fetched since %s", SMA_VID(pSma), pItem->level, tstrerror(terrno));
}
- if (blkType == STREAM_DATA_TYPE_SUBMIT_BLOCK) {
- atomic_store_8(&pItem->triggerStatus, TASK_TRIGGER_STATUS__ACTIVE);
- }
-
- taosArrayDestroy(pResult);
- return 0;
-}
-
-/**
- * @brief trigger to get rsma result
- *
- * @param param
- * @param tmrId
- */
-static void rsmaTriggerByTimer(void *param, void *tmrId) {
- // SRSmaTriggerParam *pParam = (SRSmaTriggerParam *)param;
- // SRSmaInfoItem *pItem = pParam->pItem;
- SRSmaInfoItem *pItem = param;
-
- if (atomic_load_8(&pItem->triggerStatus) == TASK_TRIGGER_STATUS__ACTIVE) {
- smaTrace("level %" PRIi8 " status is active for tb suid:%" PRIi64, pItem->level, pItem->pRsmaInfo->suid);
- SSDataBlock dataBlock = {.info.type = STREAM_GET_ALL};
-
- atomic_store_8(&pItem->triggerStatus, TASK_TRIGGER_STATUS__IN_ACTIVE);
- qSetStreamInput(pItem->taskInfo, &dataBlock, STREAM_DATA_TYPE_SSDATA_BLOCK, false);
-
- tdFetchAndSubmitRSmaResult(pItem, STREAM_DATA_TYPE_SSDATA_BLOCK);
- } else {
- smaTrace("level %" PRIi8 " status is inactive for tb suid:%" PRIi64, pItem->level, pItem->pRsmaInfo->suid);
- }
-
- // taosTmrReset(rsmaTriggerByTimer, pItem->maxDelay, pItem, pItem->tmrHandle, &pItem->tmrId);
+ tdDestroySDataBlockArray(pResult);
+ return TSDB_CODE_SUCCESS;
+_err:
+ tdDestroySDataBlockArray(pResult);
+ return TSDB_CODE_FAILED;
}
-static FORCE_INLINE int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t inputType, SRSmaInfoItem *pItem,
- tb_uid_t suid, int8_t level) {
+static int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t inputType, SRSmaInfoItem *pItem,
+ STSchema *pTSchema, tb_uid_t suid, int8_t level) {
if (!pItem || !pItem->taskInfo) {
smaDebug("vgId:%d, no qTaskInfo to execute rsma %" PRIi8 " task for suid:%" PRIu64, SMA_VID(pSma), level, suid);
return TSDB_CODE_SUCCESS;
}
+ if (!pTSchema) {
+ smaWarn("vgId:%d, no schema to execute rsma %" PRIi8 " task for suid:%" PRIu64, SMA_VID(pSma), level, suid);
+ return TSDB_CODE_FAILED;
+ }
smaDebug("vgId:%d, execute rsma %" PRIi8 " task for qTaskInfo:%p suid:%" PRIu64, SMA_VID(pSma), level,
pItem->taskInfo, suid);
- // inputType = STREAM_DATA_TYPE_SUBMIT_BLOCK(1)
- if (qSetStreamInput(pItem->taskInfo, pMsg, inputType, true) < 0) {
+ if (qSetStreamInput(pItem->taskInfo, pMsg, inputType, true) < 0) { // INPUT__DATA_SUBMIT
smaError("vgId:%d, rsma % " PRIi8 " qSetStreamInput failed since %s", SMA_VID(pSma), level, tstrerror(terrno));
return TSDB_CODE_FAILED;
}
- // SRSmaTriggerParam triggerParam = {.suid = suid, .pItem = pItem, .pSma = pSma, .pTSchema = pTSchema};
- tdFetchAndSubmitRSmaResult(pItem, STREAM_DATA_TYPE_SUBMIT_BLOCK);
- atomic_store_8(&pItem->triggerStatus, TASK_TRIGGER_STATUS__ACTIVE);
- taosTmrReset(rsmaTriggerByTimer, pItem->maxDelay, pItem, pItem->tmrHandle, &pItem->tmrId);
+ SSmaEnv *pEnv = SMA_RSMA_ENV(pSma);
+ SRSmaStat *pStat = SMA_RSMA_STAT(pEnv->pStat);
+
+ tdRSmaFetchAndSubmitResult(pItem, pTSchema, suid, pStat, STREAM_INPUT__DATA_SUBMIT);
+ atomic_store_8(&pItem->triggerStat, TASK_TRIGGER_STAT_ACTIVE);
+
+ if (smaMgmt.tmrHandle) {
+ taosTmrReset(tdRSmaFetchTrigger, pItem->maxDelay, pItem, smaMgmt.tmrHandle, &pItem->tmrId);
+ } else {
+ ASSERT(0);
+ }
return TSDB_CODE_SUCCESS;
}
-static int32_t tdExecuteRSma(SSma *pSma, const void *pMsg, int32_t inputType, tb_uid_t suid) {
- SSmaEnv *pEnv = SMA_RSMA_ENV(pSma);
+static SRSmaInfo *tdGetRSmaInfoBySuid(SSma *pSma, int64_t suid) {
+ SSmaEnv *pEnv = SMA_RSMA_ENV(pSma);
+ SRSmaStat *pStat = NULL;
if (!pEnv) {
// only applicable when rsma env exists
- return TSDB_CODE_SUCCESS;
+ return NULL;
}
- SSmaStat *pStat = SMA_ENV_STAT(pEnv);
- SRSmaInfo *pRSmaInfo = NULL;
-
- pRSmaInfo = taosHashGet(SMA_STAT_INFO_HASH(pStat), &suid, sizeof(tb_uid_t));
+ pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv);
+ if (!pStat || !RSMA_INFO_HASH(pStat)) {
+ return NULL;
+ }
+ SRSmaInfo *pRSmaInfo = taosHashGet(RSMA_INFO_HASH(pStat), &suid, sizeof(tb_uid_t));
if (!pRSmaInfo || !(pRSmaInfo = *(SRSmaInfo **)pRSmaInfo)) {
+ return NULL;
+ }
+ return pRSmaInfo;
+}
+
+static int32_t tdExecuteRSma(SSma *pSma, const void *pMsg, int32_t inputType, tb_uid_t suid) {
+ SRSmaInfo *pRSmaInfo = tdGetRSmaInfoBySuid(pSma, suid);
+ if (!pRSmaInfo) {
smaDebug("vgId:%d, return as no rsma info for suid:%" PRIu64, SMA_VID(pSma), suid);
return TSDB_CODE_SUCCESS;
}
@@ -554,9 +695,9 @@ static int32_t tdExecuteRSma(SSma *pSma, const void *pMsg, int32_t inputType, tb
return TSDB_CODE_SUCCESS;
}
- if (inputType == STREAM_DATA_TYPE_SUBMIT_BLOCK) {
- tdExecuteRSmaImpl(pSma, pMsg, inputType, &pRSmaInfo->items[0], suid, TSDB_RETENTION_L1);
- tdExecuteRSmaImpl(pSma, pMsg, inputType, &pRSmaInfo->items[1], suid, TSDB_RETENTION_L2);
+ if (inputType == STREAM_INPUT__DATA_SUBMIT) {
+ tdExecuteRSmaImpl(pSma, pMsg, inputType, &pRSmaInfo->items[0], pRSmaInfo->pTSchema, suid, TSDB_RETENTION_L1);
+ tdExecuteRSmaImpl(pSma, pMsg, inputType, &pRSmaInfo->items[1], pRSmaInfo->pTSchema, suid, TSDB_RETENTION_L2);
}
return TSDB_CODE_SUCCESS;
@@ -575,7 +716,7 @@ int32_t tdProcessRSmaSubmit(SSma *pSma, void *pMsg, int32_t inputType) {
return TSDB_CODE_SUCCESS;
}
- if (inputType == STREAM_DATA_TYPE_SUBMIT_BLOCK) {
+ if (inputType == STREAM_INPUT__DATA_SUBMIT) {
STbUidStore uidStore = {0};
tdFetchSubmitReqSuids(pMsg, &uidStore);
@@ -594,3 +735,543 @@ int32_t tdProcessRSmaSubmit(SSma *pSma, void *pMsg, int32_t inputType) {
}
return TSDB_CODE_SUCCESS;
}
+
+static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) {
+ SVnode *pVnode = pSma->pVnode;
+
+ SArray *suidList = taosArrayInit(1, sizeof(tb_uid_t));
+ if (tsdbGetStbIdList(SMA_META(pSma), 0, suidList) < 0) {
+ taosArrayDestroy(suidList);
+ smaError("vgId:%d, failed to restore rsma env since get stb id list error: %s", TD_VID(pVnode), terrstr());
+ return TSDB_CODE_FAILED;
+ }
+
+ int64_t arrSize = taosArrayGetSize(suidList);
+
+ if (nTables) {
+ *nTables = arrSize;
+ }
+
+ if (arrSize == 0) {
+ taosArrayDestroy(suidList);
+ smaDebug("vgId:%d, no need to restore rsma env since empty stb id list", TD_VID(pVnode));
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SMetaReader mr = {0};
+ metaReaderInit(&mr, SMA_META(pSma), 0);
+ for (int64_t i = 0; i < arrSize; ++i) {
+ tb_uid_t suid = *(tb_uid_t *)taosArrayGet(suidList, i);
+ smaDebug("vgId:%d, rsma restore, suid is %" PRIi64, TD_VID(pVnode), suid);
+ if (metaGetTableEntryByUid(&mr, suid) < 0) {
+ smaError("vgId:%d, rsma restore, failed to get table meta for %" PRIi64 " since %s", TD_VID(pVnode), suid,
+ terrstr());
+ goto _err;
+ }
+ ASSERT(mr.me.type == TSDB_SUPER_TABLE);
+ ASSERT(mr.me.uid == suid);
+ if (TABLE_IS_ROLLUP(mr.me.flags)) {
+ SRSmaParam *param = &mr.me.stbEntry.rsmaParam;
+ for (int i = 0; i < TSDB_RETENTION_L2; ++i) {
+ smaDebug("vgId:%d, rsma restore, table:%" PRIi64 " level:%d, maxdelay:%" PRIi64 " watermark:%" PRIi64
+ " qmsgLen:%" PRIi32,
+ TD_VID(pVnode), suid, i, param->maxdelay[i], param->watermark[i], param->qmsgLen[i]);
+ }
+ if (tdProcessRSmaCreateImpl(pSma, &mr.me.stbEntry.rsmaParam, suid, mr.me.name) < 0) {
+ smaError("vgId:%d, rsma restore env failed for %" PRIi64 " since %s", TD_VID(pVnode), suid, terrstr());
+ goto _err;
+ }
+ smaDebug("vgId:%d, rsma restore env success for %" PRIi64, TD_VID(pVnode), suid);
+ }
+ }
+
+ metaReaderClear(&mr);
+ taosArrayDestroy(suidList);
+
+ return TSDB_CODE_SUCCESS;
+_err:
+ metaReaderClear(&mr);
+ taosArrayDestroy(suidList);
+
+ return TSDB_CODE_FAILED;
+}
+
+static int32_t tdRSmaRestoreQTaskInfoReload(SSma *pSma, int64_t *committed) {
+ SVnode *pVnode = pSma->pVnode;
+ STFile tFile = {0};
+ char qTaskInfoFName[TSDB_FILENAME_LEN] = {0};
+
+ tdRSmaQTaskInfoGetFName(TD_VID(pVnode), pVnode->state.committed, qTaskInfoFName);
+ if (tdInitTFile(&tFile, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFName) < 0) {
+ goto _err;
+ }
+
+ if (!taosCheckExistFile(TD_TFILE_FULL_NAME(&tFile))) {
+ *committed = 0;
+ if (pVnode->state.committed > 0) {
+ smaWarn("vgId:%d, rsma restore for version %" PRIi64 ", not start as %s not exist", TD_VID(pVnode),
+ pVnode->state.committed, TD_TFILE_FULL_NAME(&tFile));
+ } else {
+ smaDebug("vgId:%d, rsma restore for version %" PRIi64 ", no need as %s not exist", TD_VID(pVnode),
+ pVnode->state.committed, TD_TFILE_FULL_NAME(&tFile));
+ }
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (tdOpenTFile(&tFile, TD_FILE_READ) < 0) {
+ goto _err;
+ }
+
+ STFInfo tFileInfo = {0};
+ if (tdLoadTFileHeader(&tFile, &tFileInfo) < 0) {
+ goto _err;
+ }
+
+ ASSERT(tFileInfo.qTaskInfo.submitVer > 0);
+
+ SSmaEnv *pRSmaEnv = pSma->pRSmaEnv;
+ SRSmaStat *pRSmaStat = (SRSmaStat *)SMA_ENV_STAT(pRSmaEnv);
+ atomic_store_64(&pRSmaStat->submitVer, tFileInfo.qTaskInfo.submitVer);
+ smaDebug("%s:%d tFileInfo.qTaskInfo.submitVer = %" PRIi64, __func__, __LINE__, tFileInfo.qTaskInfo.submitVer);
+
+ SRSmaQTaskInfoIter fIter = {0};
+ if (tdRSmaQTaskInfoIterInit(&fIter, &tFile) < 0) {
+ tdRSmaQTaskInfoIterDestroy(&fIter);
+ tdCloseTFile(&tFile);
+ tdDestroyTFile(&tFile);
+ goto _err;
+ }
+
+ if (tdRSmaQTaskInfoRestore(pSma, &fIter) < 0) {
+ tdRSmaQTaskInfoIterDestroy(&fIter);
+ tdCloseTFile(&tFile);
+ tdDestroyTFile(&tFile);
+ goto _err;
+ }
+
+ tdRSmaQTaskInfoIterDestroy(&fIter);
+ tdCloseTFile(&tFile);
+ tdDestroyTFile(&tFile);
+
+ // restored successfully from committed
+ *committed = pVnode->state.committed;
+
+ return TSDB_CODE_SUCCESS;
+_err:
+ smaError("vgId:%d, rsma restore for version %" PRIi64 ", qtaskinfo reload failed since %s", TD_VID(pVnode),
+ pVnode->state.committed, terrstr());
+ return TSDB_CODE_FAILED;
+}
+
+/**
+ * @brief reload ts data from checkpoint
+ *
+ * @param pSma
+ * @param committed restore from committed version
+ * @return int32_t
+ */
+static int32_t tdRSmaRestoreTSDataReload(SSma *pSma, int64_t committed) {
+ // TODO
+ smaDebug("vgId:%d, rsma restore from %" PRIi64 ", ts data reload success", SMA_VID(pSma), committed);
+ return TSDB_CODE_SUCCESS;
+_err:
+ smaError("vgId:%d, rsma restore from %" PRIi64 ", ts data reload failed since %s", SMA_VID(pSma), committed,
+ terrstr());
+ return TSDB_CODE_FAILED;
+}
+
+int32_t tdProcessRSmaRestoreImpl(SSma *pSma) {
+ // step 1: iterate all stables to restore the rsma env
+ int64_t nTables = 0;
+ if (tdRSmaRestoreQTaskInfoInit(pSma, &nTables) < 0) {
+ goto _err;
+ }
+
+ if (nTables <= 0) {
+ smaDebug("vgId:%d, no need to restore rsma task since no tables", SMA_VID(pSma));
+ return TSDB_CODE_SUCCESS;
+ }
+
+ // step 2: retrieve qtaskinfo items from the persistence file(rsma/qtaskinfo) and restore
+ int64_t committed = -1;
+ if (tdRSmaRestoreQTaskInfoReload(pSma, &committed) < 0) {
+ goto _err;
+ }
+
+ // step 3: reload ts data from checkpoint
+ if (tdRSmaRestoreTSDataReload(pSma, committed) < 0) {
+ goto _err;
+ }
+
+ return TSDB_CODE_SUCCESS;
+_err:
+ smaError("vgId:%d failed to restore rsma task since %s", SMA_VID(pSma), terrstr());
+ return TSDB_CODE_FAILED;
+}
+
+static int32_t tdRSmaQTaskInfoItemRestore(SSma *pSma, const SRSmaQTaskInfoItem *pItem) {
+ SRSmaInfo *pRSmaInfo = NULL;
+ void *qTaskInfo = NULL;
+
+ pRSmaInfo = tdGetRSmaInfoBySuid(pSma, pItem->suid);
+ if (!pRSmaInfo) {
+ smaDebug("vgId:%d, no restore as no rsma info for table:%" PRIu64, SMA_VID(pSma), pItem->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (pItem->type == TSDB_RETENTION_L1) {
+ qTaskInfo = pRSmaInfo->items[0].taskInfo;
+ } else if (pItem->type == TSDB_RETENTION_L2) {
+ qTaskInfo = pRSmaInfo->items[1].taskInfo;
+ } else {
+ ASSERT(0);
+ }
+
+ if (!qTaskInfo) {
+ smaDebug("vgId:%d, no restore as NULL rsma qTaskInfo for table:%" PRIu64, SMA_VID(pSma), pItem->suid);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (qDeserializeTaskStatus(qTaskInfo, pItem->qTaskInfo, pItem->len) < 0) {
+ smaError("vgId:%d, restore rsma task failed for table:%" PRIi64 " level %d since %s", SMA_VID(pSma), pItem->suid,
+ pItem->type, terrstr(terrno));
+ return TSDB_CODE_FAILED;
+ }
+ smaDebug("vgId:%d, restore rsma task success for table:%" PRIi64 " level %d", SMA_VID(pSma), pItem->suid,
+ pItem->type);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t tdRSmaQTaskInfoIterInit(SRSmaQTaskInfoIter *pIter, STFile *pTFile) {
+ memset(pIter, 0, sizeof(*pIter));
+ pIter->pTFile = pTFile;
+ pIter->offset = TD_FILE_HEAD_SIZE;
+
+ if (tdGetTFileSize(pTFile, &pIter->fsize) < 0) {
+ return TSDB_CODE_FAILED;
+ }
+
+ if ((pIter->fsize - TD_FILE_HEAD_SIZE) < RSMA_QTASKINFO_BUFSIZE) {
+ pIter->nAlloc = pIter->fsize - TD_FILE_HEAD_SIZE;
+ } else {
+ pIter->nAlloc = RSMA_QTASKINFO_BUFSIZE;
+ }
+
+ if (pIter->nAlloc < TD_FILE_HEAD_SIZE) {
+ pIter->nAlloc = TD_FILE_HEAD_SIZE;
+ }
+
+ pIter->pBuf = taosMemoryMalloc(pIter->nAlloc);
+ if (!pIter->pBuf) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return TSDB_CODE_FAILED;
+ }
+ pIter->qBuf = pIter->pBuf;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t tdRSmaQTaskInfoIterNextBlock(SRSmaQTaskInfoIter *pIter, bool *isFinish) {
+ STFile *pTFile = pIter->pTFile;
+ int64_t nBytes = RSMA_QTASKINFO_BUFSIZE;
+
+ if (pIter->offset >= pIter->fsize) {
+ *isFinish = true;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if ((pIter->fsize - pIter->offset) < RSMA_QTASKINFO_BUFSIZE) {
+ nBytes = pIter->fsize - pIter->offset;
+ }
+
+ if (tdSeekTFile(pTFile, pIter->offset, SEEK_SET) < 0) {
+ return TSDB_CODE_FAILED;
+ }
+
+ if (tdReadTFile(pTFile, pIter->qBuf, nBytes) != nBytes) {
+ return TSDB_CODE_FAILED;
+ }
+
+ int32_t infoLen = 0;
+ taosDecodeFixedI32(pIter->qBuf, &infoLen);
+ if (infoLen > nBytes) {
+ if (infoLen <= RSMA_QTASKINFO_BUFSIZE) {
+ terrno = TSDB_CODE_RSMA_FILE_CORRUPTED;
+ smaError("iterate rsma qtaskinfo file %s failed since %s", TD_TFILE_FULL_NAME(pIter->pTFile), terrstr());
+ return TSDB_CODE_FAILED;
+ }
+ pIter->nAlloc = infoLen;
+ void *pBuf = taosMemoryRealloc(pIter->pBuf, infoLen);
+ if (!pBuf) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return TSDB_CODE_FAILED;
+ }
+ pIter->pBuf = pBuf;
+ pIter->qBuf = pIter->pBuf;
+ nBytes = infoLen;
+
+ if (tdSeekTFile(pTFile, pIter->offset, SEEK_SET)) {
+ return TSDB_CODE_FAILED;
+ }
+
+ if (tdReadTFile(pTFile, pIter->pBuf, nBytes) != nBytes) {
+ return TSDB_CODE_FAILED;
+ }
+ }
+
+ pIter->offset += nBytes;
+ pIter->nBytes = nBytes;
+ pIter->nBufPos = 0;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t tdRSmaQTaskInfoRestore(SSma *pSma, SRSmaQTaskInfoIter *pIter) {
+ while (1) {
+ // block iter
+ bool isFinish = false;
+ if (tdRSmaQTaskInfoIterNextBlock(pIter, &isFinish) < 0) {
+ return TSDB_CODE_FAILED;
+ }
+ if (isFinish) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ // consume the block
+ int32_t qTaskInfoLenWithHead = 0;
+ pIter->qBuf = taosDecodeFixedI32(pIter->qBuf, &qTaskInfoLenWithHead);
+ if (qTaskInfoLenWithHead < RSMA_QTASKINFO_HEAD_LEN) {
+ terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
+ smaError("vgId:%d, restore rsma qtaskinfo file %s failed since %s", SMA_VID(pSma),
+ TD_TFILE_FULL_NAME(pIter->pTFile), terrstr());
+ return TSDB_CODE_FAILED;
+ }
+
+ while (1) {
+ if ((pIter->nBufPos + qTaskInfoLenWithHead) <= pIter->nBytes) {
+ SRSmaQTaskInfoItem infoItem = {0};
+ pIter->qBuf = taosDecodeFixedI8(pIter->qBuf, &infoItem.type);
+ pIter->qBuf = taosDecodeFixedI64(pIter->qBuf, &infoItem.suid);
+ infoItem.qTaskInfo = pIter->qBuf;
+ infoItem.len = tdRSmaQTaskInfoContLen(qTaskInfoLenWithHead);
+ // do the restore job
+ smaDebug("vgId:%d, restore the qtask info %s offset:%" PRIi64 "\n", SMA_VID(pSma),
+ TD_TFILE_FULL_NAME(pIter->pTFile), pIter->offset - pIter->nBytes + pIter->nBufPos);
+ tdRSmaQTaskInfoItemRestore(pSma, &infoItem);
+
+ pIter->qBuf = POINTER_SHIFT(pIter->qBuf, infoItem.len);
+ pIter->nBufPos += qTaskInfoLenWithHead;
+
+ if ((pIter->nBufPos + RSMA_QTASKINFO_HEAD_LEN) >= pIter->nBytes) {
+ // prepare and load next block in the file
+ pIter->offset -= (pIter->nBytes - pIter->nBufPos);
+ break;
+ }
+
+ pIter->qBuf = taosDecodeFixedI32(pIter->qBuf, &qTaskInfoLenWithHead);
+ continue;
+ }
+ // prepare and load next block in the file
+ pIter->offset -= (pIter->nBytes - pIter->nBufPos);
+ break;
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t tdRSmaPersistExecImpl(SRSmaStat *pRSmaStat) {
+ SSma *pSma = pRSmaStat->pSma;
+ SVnode *pVnode = pSma->pVnode;
+ int32_t vid = SMA_VID(pSma);
+ int64_t toffset = 0;
+ bool isFileCreated = false;
+
+ if (taosHashGetSize(RSMA_INFO_HASH(pRSmaStat)) <= 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ void *infoHash = taosHashIterate(RSMA_INFO_HASH(pRSmaStat), NULL);
+ if (!infoHash) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ STFile tFile = {0};
+ if (RSMA_SUBMIT_VER(pRSmaStat) > 0) {
+ char qTaskInfoFName[TSDB_FILENAME_LEN];
+ tdRSmaQTaskInfoGetFName(vid, pSma->pVnode->state.applied, qTaskInfoFName);
+ if (tdInitTFile(&tFile, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFName) < 0) {
+ smaError("vgId:%d, rsma persit, init %s failed since %s", vid, qTaskInfoFName, terrstr());
+ goto _err;
+ }
+ if (tdCreateTFile(&tFile, true, TD_FTYPE_RSMA_QTASKINFO) < 0) {
+ smaError("vgId:%d, rsma persit, create %s failed since %s", vid, TD_TFILE_FULL_NAME(&tFile), terrstr());
+ goto _err;
+ }
+ smaDebug("vgId:%d, rsma, serialize qTaskInfo, file %s created", vid, TD_TFILE_FULL_NAME(&tFile));
+
+ isFileCreated = true;
+ }
+
+ while (infoHash) {
+ SRSmaInfo *pRSmaInfo = *(SRSmaInfo **)infoHash;
+ for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) {
+ qTaskInfo_t taskInfo = pRSmaInfo->items[i].taskInfo;
+ if (!taskInfo) {
+ smaDebug("vgId:%d, rsma, table %" PRIi64 " level %d qTaskInfo is NULL", vid, pRSmaInfo->suid, i + 1);
+ continue;
+ }
+
+ char *pOutput = NULL;
+ int32_t len = 0;
+ int8_t type = (int8_t)(i + 1);
+ if (qSerializeTaskStatus(taskInfo, &pOutput, &len) < 0) {
+ smaError("vgId:%d, rsma, table %" PRIi64 " level %d serialize qTaskInfo failed since %s", vid, pRSmaInfo->suid,
+ i + 1, terrstr(terrno));
+ goto _err;
+ }
+ if (!pOutput || len <= 0) {
+ smaDebug("vgId:%d, rsma, table %" PRIi64
+ " level %d serialize qTaskInfo success but no output(len %d), not persist",
+ vid, pRSmaInfo->suid, i + 1, len);
+ taosMemoryFreeClear(pOutput);
+ continue;
+ }
+
+ smaDebug("vgId:%d, rsma, table %" PRIi64 " level %d serialize qTaskInfo success with len %d, need persist", vid,
+ pRSmaInfo->suid, i + 1, len);
+
+ if (!isFileCreated) {
+ char qTaskInfoFName[TSDB_FILENAME_LEN];
+ tdRSmaQTaskInfoGetFName(vid, pSma->pVnode->state.applied, qTaskInfoFName);
+ if (tdInitTFile(&tFile, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFName) < 0) {
+ smaError("vgId:%d, rsma persit, init %s failed since %s", vid, qTaskInfoFName, terrstr());
+ goto _err;
+ }
+ if (tdCreateTFile(&tFile, true, TD_FTYPE_RSMA_QTASKINFO) < 0) {
+ smaError("vgId:%d, rsma persit, create %s failed since %s", vid, TD_TFILE_FULL_NAME(&tFile), terrstr());
+ goto _err;
+ }
+ smaDebug("vgId:%d, rsma, table %" PRIi64 " serialize qTaskInfo, file %s created", vid, pRSmaInfo->suid,
+ TD_TFILE_FULL_NAME(&tFile));
+
+ isFileCreated = true;
+ }
+
+ char tmpBuf[RSMA_QTASKINFO_HEAD_LEN] = {0};
+ void *pTmpBuf = &tmpBuf;
+ int32_t headLen = 0;
+ headLen += taosEncodeFixedI32(&pTmpBuf, len + RSMA_QTASKINFO_HEAD_LEN);
+ headLen += taosEncodeFixedI8(&pTmpBuf, type);
+ headLen += taosEncodeFixedI64(&pTmpBuf, pRSmaInfo->suid);
+
+ ASSERT(headLen <= RSMA_QTASKINFO_HEAD_LEN);
+ tdAppendTFile(&tFile, (void *)&tmpBuf, headLen, &toffset);
+ smaDebug("vgId:%d, rsma, table %" PRIi64 " level %d head part(len:%d) appended to offset:%" PRIi64, vid,
+ pRSmaInfo->suid, i + 1, headLen, toffset);
+ tdAppendTFile(&tFile, pOutput, len, &toffset);
+ smaDebug("vgId:%d, rsma, table %" PRIi64 " level %d body part len:%d appended to offset:%" PRIi64, vid,
+ pRSmaInfo->suid, i + 1, len, toffset);
+
+ taosMemoryFree(pOutput);
+ }
+
+ infoHash = taosHashIterate(RSMA_INFO_HASH(pRSmaStat), infoHash);
+ }
+
+ if (isFileCreated) {
+ tFile.info.qTaskInfo.submitVer = atomic_load_64(&pRSmaStat->submitVer);
+ if (tdUpdateTFileHeader(&tFile) < 0) {
+ smaError("vgId:%d, rsma, failed to update tfile %s header since %s", vid, TD_TFILE_FULL_NAME(&tFile),
+ tstrerror(terrno));
+ goto _err;
+ } else {
+ smaDebug("vgId:%d, rsma, succeed to update tfile %s header", vid, TD_TFILE_FULL_NAME(&tFile));
+ }
+
+ tdCloseTFile(&tFile);
+ tdDestroyTFile(&tFile);
+ }
+ return TSDB_CODE_SUCCESS;
+_err:
+ smaError("vgId:%d, rsma persit failed since %s", vid, terrstr());
+ if (isFileCreated) {
+ tdRemoveTFile(&tFile);
+ tdDestroyTFile(&tFile);
+ }
+ return TSDB_CODE_FAILED;
+}
+
+/**
+ * @brief trigger to get rsma result
+ *
+ * @param param
+ * @param tmrId
+ */
+static void tdRSmaFetchTrigger(void *param, void *tmrId) {
+ SRSmaInfoItem *pItem = param;
+ SSma *pSma = NULL;
+ SRSmaStat *pStat = (SRSmaStat *)tdAcquireSmaRef(smaMgmt.rsetId, pItem->refId, __func__, __LINE__);
+
+ if (!pStat) {
+ smaDebug("rsma fetch task not start since already destroyed, rsetId rsetId:%" PRIi64 " refId:%d)", smaMgmt.rsetId,
+ pItem->refId);
+ return;
+ }
+
+ pSma = pStat->pSma;
+
+ // if rsma trigger stat in paused, cancelled or finished, not start fetch task
+ int8_t rsmaTriggerStat = atomic_load_8(RSMA_TRIGGER_STAT(pStat));
+ switch (rsmaTriggerStat) {
+ case TASK_TRIGGER_STAT_PAUSED:
+ case TASK_TRIGGER_STAT_CANCELLED: {
+ tdReleaseSmaRef(smaMgmt.rsetId, pItem->refId, __func__, __LINE__);
+ smaDebug("vgId:%d, not fetch rsma level %" PRIi8 " data since stat is %" PRIi8 ", rsetId rsetId:%" PRIi64
+ " refId:%d",
+ SMA_VID(pSma), pItem->level, rsmaTriggerStat, smaMgmt.rsetId, pItem->refId);
+ return;
+ }
+ default:
+ break;
+ }
+
+ SRSmaInfo *pRSmaInfo = tdGetRSmaInfoByItem(pItem);
+
+ int8_t fetchTriggerStat =
+ atomic_val_compare_exchange_8(&pItem->triggerStat, TASK_TRIGGER_STAT_ACTIVE, TASK_TRIGGER_STAT_INACTIVE);
+ switch (fetchTriggerStat) {
+ case TASK_TRIGGER_STAT_ACTIVE: {
+ smaDebug("vgId:%d, fetch rsma level %" PRIi8 " data for table:%" PRIi64 " since stat is active", SMA_VID(pSma),
+ pItem->level, pRSmaInfo->suid);
+
+ tdRefSmaStat(pSma, (SSmaStat *)pStat);
+
+ SSDataBlock dataBlock = {.info.type = STREAM_GET_ALL};
+ qSetStreamInput(pItem->taskInfo, &dataBlock, STREAM_INPUT__DATA_BLOCK, false);
+ tdRSmaFetchAndSubmitResult(pItem, pRSmaInfo->pTSchema, pRSmaInfo->suid, pStat, STREAM_INPUT__DATA_BLOCK);
+
+ tdUnRefSmaStat(pSma, (SSmaStat *)pStat);
+ } break;
+ case TASK_TRIGGER_STAT_PAUSED: {
+ smaDebug("vgId:%d, not fetch rsma level %" PRIi8 " data for table:%" PRIi64 " since stat is paused",
+ SMA_VID(pSma), pItem->level, pRSmaInfo->suid);
+ } break;
+ case TASK_TRIGGER_STAT_INACTIVE: {
+ smaDebug("vgId:%d, not fetch rsma level %" PRIi8 " data for table:%" PRIi64 " since stat is inactive",
+ SMA_VID(pSma), pItem->level, pRSmaInfo->suid);
+ } break;
+ case TASK_TRIGGER_STAT_INIT: {
+ smaDebug("vgId:%d, not fetch rsma level %" PRIi8 " data for table:%" PRIi64 " since stat is init", SMA_VID(pSma),
+ pItem->level, pRSmaInfo->suid);
+ } break;
+ default: {
+ smaWarn("vgId:%d, not fetch rsma level %" PRIi8 " data for table:%" PRIi64 " since stat is unknown",
+ SMA_VID(pSma), pItem->level, pRSmaInfo->suid);
+ } break;
+ }
+
+_end:
+ tdReleaseSmaRef(smaMgmt.rsetId, pItem->refId, __func__, __LINE__);
+}
diff --git a/source/dnode/vnode/src/sma/smaTimeRange.c b/source/dnode/vnode/src/sma/smaTimeRange.c
index 4352c466c5526cc4a00f10c629e2e99b1015cf7d..6d71f3a250f4b02ae9d1acc2c5b11e5cf8721c56 100644
--- a/source/dnode/vnode/src/sma/smaTimeRange.c
+++ b/source/dnode/vnode/src/sma/smaTimeRange.c
@@ -20,6 +20,36 @@
#define SMA_STORAGE_MINUTES_DAY 1440
#define SMA_STORAGE_SPLIT_FACTOR 14400 // least records in tsma file
+// TODO: Who is responsible for resource allocate and release?
+int32_t tdProcessTSmaInsert(SSma *pSma, int64_t indexUid, const char *msg) {
+ int32_t code = TSDB_CODE_SUCCESS;
+
+ if ((code = tdProcessTSmaInsertImpl(pSma, indexUid, msg)) < 0) {
+ smaWarn("vgId:%d, insert tsma data failed since %s", SMA_VID(pSma), tstrerror(terrno));
+ }
+ // TODO: destroy SSDataBlocks(msg)
+ return code;
+}
+
+int32_t tdProcessTSmaCreate(SSma *pSma, int64_t version, const char *msg) {
+ int32_t code = TSDB_CODE_SUCCESS;
+
+ if ((code = tdProcessTSmaCreateImpl(pSma, version, msg)) < 0) {
+ smaWarn("vgId:%d, create tsma failed since %s", SMA_VID(pSma), tstrerror(terrno));
+ }
+ // TODO: destroy SSDataBlocks(msg)
+ return code;
+}
+
+int32_t smaGetTSmaDays(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if ((code = tdProcessTSmaGetDaysImpl(pCfg, pCont, contLen, days)) < 0) {
+ smaWarn("vgId:%d, get tsma days failed since %s", pCfg->vgId, tstrerror(terrno));
+ }
+ smaDebug("vgId:%d, get tsma days %d", pCfg->vgId, *days);
+ return code;
+}
+
/**
* @brief Judge the tsma file split days
*
@@ -113,7 +143,7 @@ int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
if (!pDataBlocks) {
terrno = TSDB_CODE_TSMA_INVALID_PTR;
smaWarn("vgId:%d, insert tsma data failed since pDataBlocks is NULL", SMA_VID(pSma));
- return terrno;
+ return TSDB_CODE_FAILED;
}
if (taosArrayGetSize(pDataBlocks) <= 0) {
@@ -127,9 +157,9 @@ int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
return TSDB_CODE_FAILED;
}
- SSmaEnv *pEnv = SMA_TSMA_ENV(pSma);
- SSmaStat *pStat = NULL;
- SSmaStatItem *pItem = NULL;
+ SSmaEnv *pEnv = SMA_TSMA_ENV(pSma);
+ SSmaStat *pStat = NULL;
+ STSmaStat *pTsmaStat = NULL;
if (!pEnv || !(pStat = SMA_ENV_STAT(pEnv))) {
terrno = TSDB_CODE_TSMA_INVALID_STAT;
@@ -137,32 +167,43 @@ int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
}
tdRefSmaStat(pSma, pStat);
- pItem = &pStat->tsmaStatItem;
-
- ASSERT(pItem);
+ pTsmaStat = SMA_TSMA_STAT(pStat);
- if (!pItem->pTSma) {
+ if (!pTsmaStat->pTSma) {
STSma *pTSma = metaGetSmaInfoByIndex(SMA_META(pSma), indexUid);
if (!pTSma) {
- terrno = TSDB_CODE_TSMA_NO_INDEX_IN_META;
- smaWarn("vgId:%d, tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma), indexUid, tstrerror(terrno));
- return TSDB_CODE_FAILED;
+ smaError("vgId:%d, failed to get STSma while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma),
+ indexUid, tstrerror(terrno));
+ goto _err;
+ }
+ pTsmaStat->pTSma = pTSma;
+ pTsmaStat->pTSchema = metaGetTbTSchema(SMA_META(pSma), pTSma->dstTbUid, -1);
+ if (!pTsmaStat->pTSchema) {
+ smaError("vgId:%d, failed to get STSchema while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma),
+ indexUid, tstrerror(terrno));
+ goto _err;
}
- pItem->pTSma = pTSma;
- pItem->pTSchema = metaGetTbTSchema(SMA_META(pSma), pTSma->dstTbUid, -1);
- ASSERT(pItem->pTSchema); // TODO
}
- ASSERT(pItem->pTSma->indexUid == indexUid);
-
- SSubmitReq *pSubmitReq = NULL;
+ if (pTsmaStat->pTSma->indexUid != indexUid) {
+ terrno = TSDB_CODE_VND_APP_ERROR;
+ smaError("vgId:%d, tsma insert for smaIndex %" PRIi64 "(!=%" PRIi64 ") failed since %s", SMA_VID(pSma), indexUid,
+ pTsmaStat->pTSma->indexUid, tstrerror(terrno));
+ goto _err;
+ }
- pSubmitReq = tdBlockToSubmit((const SArray *)msg, pItem->pTSchema, true, pItem->pTSma->dstTbUid,
- pItem->pTSma->dstTbName, pItem->pTSma->dstVgId);
+ SSubmitReq *pSubmitReq = tdBlockToSubmit((const SArray *)msg, pTsmaStat->pTSchema, true, pTsmaStat->pTSma->dstTbUid,
+ pTsmaStat->pTSma->dstTbName, pTsmaStat->pTSma->dstVgId);
- ASSERT(pSubmitReq); // TODO
+ if (!pSubmitReq) {
+ smaError("vgId:%d, failed to gen submit blk while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma),
+ indexUid, tstrerror(terrno));
+ goto _err;
+ }
- ASSERT(!strncasecmp("td.tsma.rst.tb", pItem->pTSma->dstTbName, 14));
+#if 0
+ ASSERT(!strncasecmp("td.tsma.rst.tb", pTsmaStat->pTSma->dstTbName, 14));
+#endif
SRpcMsg submitReqMsg = {
.msgType = TDMT_VND_SUBMIT,
@@ -170,9 +211,15 @@ int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
.contLen = ntohl(pSubmitReq->length),
};
- ASSERT(tmsgPutToQueue(&pSma->pVnode->msgCb, WRITE_QUEUE, &submitReqMsg) == 0);
+ if (tmsgPutToQueue(&pSma->pVnode->msgCb, WRITE_QUEUE, &submitReqMsg) < 0) {
+ smaError("vgId:%d, failed to put SubmitReq msg while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma),
+ indexUid, tstrerror(terrno));
+ goto _err;
+ }
tdUnRefSmaStat(pSma, pStat);
-
return TSDB_CODE_SUCCESS;
+_err:
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/sma/smaUtil.c b/source/dnode/vnode/src/sma/smaUtil.c
new file mode 100644
index 0000000000000000000000000000000000000000..22d82e8df0805bebcfd7730bfa3133d48d4f9f32
--- /dev/null
+++ b/source/dnode/vnode/src/sma/smaUtil.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "sma.h"
+
+// smaFileUtil ================
+
+#define TD_FILE_STATE_OK 0
+#define TD_FILE_STATE_BAD 1
+
+#define TD_FILE_INIT_MAGIC 0xFFFFFFFF
+
+static int32_t tdEncodeTFInfo(void **buf, STFInfo *pInfo);
+static void *tdDecodeTFInfo(void *buf, STFInfo *pInfo);
+
+static int32_t tdEncodeTFInfo(void **buf, STFInfo *pInfo) {
+ int32_t tlen = 0;
+
+ tlen += taosEncodeFixedU32(buf, pInfo->magic);
+ tlen += taosEncodeFixedU32(buf, pInfo->ftype);
+ tlen += taosEncodeFixedU32(buf, pInfo->fver);
+ tlen += taosEncodeFixedI64(buf, pInfo->fsize);
+ if (pInfo->ftype == TD_FTYPE_RSMA_QTASKINFO) {
+ tlen += taosEncodeFixedI64(buf, pInfo->qTaskInfo.submitVer);
+ }
+
+ return tlen;
+}
+
+static void *tdDecodeTFInfo(void *buf, STFInfo *pInfo) {
+ buf = taosDecodeFixedU32(buf, &(pInfo->magic));
+ buf = taosDecodeFixedU32(buf, &(pInfo->ftype));
+ buf = taosDecodeFixedU32(buf, &(pInfo->fver));
+ buf = taosDecodeFixedI64(buf, &(pInfo->fsize));
+ // specific
+ if (pInfo->ftype == TD_FTYPE_RSMA_QTASKINFO) {
+ buf = taosDecodeFixedI64(buf, &(pInfo->qTaskInfo.submitVer));
+ }
+
+ return buf;
+}
+
+int64_t tdWriteTFile(STFile *pTFile, void *buf, int64_t nbyte) {
+ ASSERT(TD_TFILE_OPENED(pTFile));
+
+ int64_t nwrite = taosWriteFile(pTFile->pFile, buf, nbyte);
+ if (nwrite < nbyte) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ }
+
+ return nwrite;
+}
+
+int64_t tdSeekTFile(STFile *pTFile, int64_t offset, int whence) {
+ ASSERT(TD_TFILE_OPENED(pTFile));
+
+ int64_t loffset = taosLSeekFile(TD_TFILE_PFILE(pTFile), offset, whence);
+ if (loffset < 0) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ }
+
+ return loffset;
+}
+
+int64_t tdGetTFileSize(STFile *pTFile, int64_t *size) {
+ ASSERT(TD_TFILE_OPENED(pTFile));
+ return taosFStatFile(pTFile->pFile, size, NULL);
+}
+
+int64_t tdReadTFile(STFile *pTFile, void *buf, int64_t nbyte) {
+ ASSERT(TD_TFILE_OPENED(pTFile));
+
+ int64_t nread = taosReadFile(pTFile->pFile, buf, nbyte);
+ if (nread < 0) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ }
+
+ return nread;
+}
+
+int32_t tdUpdateTFileHeader(STFile *pTFile) {
+ char buf[TD_FILE_HEAD_SIZE] = "\0";
+
+ if (tdSeekTFile(pTFile, 0, SEEK_SET) < 0) {
+ return -1;
+ }
+
+ void *ptr = buf;
+ tdEncodeTFInfo(&ptr, &(pTFile->info));
+
+ taosCalcChecksumAppend(0, (uint8_t *)buf, TD_FILE_HEAD_SIZE);
+ if (tdWriteTFile(pTFile, buf, TD_FILE_HEAD_SIZE) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t tdLoadTFileHeader(STFile *pTFile, STFInfo *pInfo) {
+ char buf[TD_FILE_HEAD_SIZE] = "\0";
+ uint32_t _version;
+
+ ASSERT(TD_TFILE_OPENED(pTFile));
+
+ if (tdSeekTFile(pTFile, 0, SEEK_SET) < 0) {
+ return -1;
+ }
+
+ if (tdReadTFile(pTFile, buf, TD_FILE_HEAD_SIZE) < 0) {
+ return -1;
+ }
+
+ if (!taosCheckChecksumWhole((uint8_t *)buf, TD_FILE_HEAD_SIZE)) {
+ terrno = TSDB_CODE_FILE_CORRUPTED;
+ return -1;
+ }
+
+ void *pBuf = buf;
+ pBuf = tdDecodeTFInfo(pBuf, pInfo);
+ return 0;
+}
+
+void tdUpdateTFileMagic(STFile *pTFile, void *pCksm) {
+ pTFile->info.magic = taosCalcChecksum(pTFile->info.magic, (uint8_t *)(pCksm), sizeof(TSCKSUM));
+}
+
+int64_t tdAppendTFile(STFile *pTFile, void *buf, int64_t nbyte, int64_t *offset) {
+ ASSERT(TD_TFILE_OPENED(pTFile));
+
+ int64_t toffset;
+
+ if ((toffset = tdSeekTFile(pTFile, 0, SEEK_END)) < 0) {
+ return -1;
+ }
+
+#if 0
+ smaDebug("append to file %s, offset:%" PRIi64 " nbyte:%" PRIi64 " fsize:%" PRIi64, TD_TFILE_FULL_NAME(pTFile),
+ toffset, nbyte, toffset + nbyte);
+#endif
+
+ ASSERT(pTFile->info.fsize == toffset);
+
+ if (offset) {
+ *offset = toffset;
+ }
+
+ if (tdWriteTFile(pTFile, buf, nbyte) < 0) {
+ return -1;
+ }
+
+ pTFile->info.fsize += nbyte;
+
+ return nbyte;
+}
+
+int32_t tdOpenTFile(STFile *pTFile, int flags) {
+ ASSERT(!TD_TFILE_OPENED(pTFile));
+
+ pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), flags);
+ if (pTFile->pFile == NULL) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+void tdCloseTFile(STFile *pTFile) {
+ if (TD_TFILE_OPENED(pTFile)) {
+ taosCloseFile(&pTFile->pFile);
+ TD_TFILE_SET_CLOSED(pTFile);
+ }
+}
+
+void tdDestroyTFile(STFile *pTFile) { taosMemoryFreeClear(TD_TFILE_FULL_NAME(pTFile)); }
+
+void tdGetVndFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t version,
+ char *outputName) {
+ if (version < 0) {
+ if (pdname) {
+ snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId,
+ TD_DIRSEP, dname, TD_DIRSEP, vgId, fname);
+ } else {
+ snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s", TD_DIRSEP, vgId, TD_DIRSEP, dname, TD_DIRSEP,
+ vgId, fname);
+ }
+ } else {
+ if (pdname) {
+ snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s%" PRIi64, pdname, TD_DIRSEP, TD_DIRSEP,
+ vgId, TD_DIRSEP, dname, TD_DIRSEP, vgId, fname, version);
+ } else {
+ snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s%" PRIi64, TD_DIRSEP, vgId, TD_DIRSEP, dname,
+ TD_DIRSEP, vgId, fname, version);
+ }
+ }
+}
+
+void tdGetVndDirName(int32_t vgId, const char *pdname, const char *dname, bool endWithSep, char *outputName) {
+ if (pdname) {
+ if (endWithSep) {
+ snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId, TD_DIRSEP,
+ dname, TD_DIRSEP);
+ } else {
+ snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId, TD_DIRSEP,
+ dname);
+ }
+ } else {
+ if (endWithSep) {
+ snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%s", TD_DIRSEP, vgId, TD_DIRSEP, dname, TD_DIRSEP);
+ } else {
+ snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s", TD_DIRSEP, vgId, TD_DIRSEP, dname);
+ }
+ }
+}
+
+int32_t tdInitTFile(STFile *pTFile, const char *dname, const char *fname) {
+ TD_TFILE_SET_STATE(pTFile, TD_FILE_STATE_OK);
+ TD_TFILE_SET_CLOSED(pTFile);
+
+ memset(&(pTFile->info), 0, sizeof(pTFile->info));
+ pTFile->info.magic = TD_FILE_INIT_MAGIC;
+
+ char tmpName[TSDB_FILENAME_LEN * 2 + 32] = {0};
+ snprintf(tmpName, TSDB_FILENAME_LEN * 2 + 32, "%s%s%s", dname, TD_DIRSEP, fname);
+ int32_t tmpNameLen = strlen(tmpName) + 1;
+ pTFile->fname = taosMemoryMalloc(tmpNameLen);
+ if (!pTFile->fname) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+ tstrncpy(pTFile->fname, tmpName, tmpNameLen);
+
+ return 0;
+}
+
+int32_t tdCreateTFile(STFile *pTFile, bool updateHeader, int8_t fType) {
+ ASSERT(pTFile->info.fsize == 0 && pTFile->info.magic == TD_FILE_INIT_MAGIC);
+ pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
+ if (pTFile->pFile == NULL) {
+ if (errno == ENOENT) {
+ // Try to create directory recursively
+ char *s = strdup(TD_TFILE_FULL_NAME(pTFile));
+ if (taosMulMkDir(taosDirName(s)) != 0) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ taosMemoryFree(s);
+ return -1;
+ }
+ taosMemoryFree(s);
+ pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
+ if (pTFile->pFile == NULL) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ }
+ }
+ }
+
+ if (!updateHeader) {
+ return 0;
+ }
+
+ pTFile->info.fsize += TD_FILE_HEAD_SIZE;
+ pTFile->info.fver = 0;
+
+ if (tdUpdateTFileHeader(pTFile) < 0) {
+ tdCloseTFile(pTFile);
+ tdRemoveTFile(pTFile);
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t tdRemoveTFile(STFile *pTFile) {
+ if (taosRemoveFile(TD_TFILE_FULL_NAME(pTFile)) != 0) {
+ terrno = TAOS_SYSTEM_ERROR(errno);
+ return -1;
+ };
+ return 0;
+}
+
+// smaXXXUtil ================
+void *tdAcquireSmaRef(int32_t rsetId, int64_t refId, const char *tags, int32_t ln) {
+ void *pResult = taosAcquireRef(rsetId, refId);
+ if (!pResult) {
+ smaWarn("%s:%d taosAcquireRef for rsetId:%" PRIi64 " refId:%d failed since %s", tags, ln, rsetId, refId, terrstr());
+ } else {
+ smaDebug("%s:%d taosAcquireRef for rsetId:%" PRIi64 " refId:%d success", tags, ln, rsetId, refId);
+ }
+ return pResult;
+}
+
+int32_t tdReleaseSmaRef(int32_t rsetId, int64_t refId, const char *tags, int32_t ln) {
+ if (taosReleaseRef(rsetId, refId) < 0) {
+ smaWarn("%s:%d taosReleaseRef for rsetId:%" PRIi64 " refId:%d failed since %s", tags, ln, rsetId, refId, terrstr());
+ return TSDB_CODE_FAILED;
+ }
+ smaDebug("%s:%d taosReleaseRef for rsetId:%" PRIi64 " refId:%d success", tags, ln, rsetId, refId);
+
+ return TSDB_CODE_SUCCESS;
+}
+// ...
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c
index ece4b7e2a45685bf1106d10e5fe00350d7183c55..6f4a04ee09d6a6b7f4afb96374fe0ab62dc5abfc 100644
--- a/source/dnode/vnode/src/tq/tq.c
+++ b/source/dnode/vnode/src/tq/tq.c
@@ -28,8 +28,12 @@ int32_t tqInit() {
atomic_store_8(&tqMgmt.inited, 0);
return -1;
}
+ if (streamInit() < 0) {
+ return -1;
+ }
atomic_store_8(&tqMgmt.inited, 1);
}
+
return 0;
}
@@ -42,6 +46,7 @@ void tqCleanUp() {
if (old == 1) {
taosTmrCleanUp(tqMgmt.timer);
+ streamCleanUp();
atomic_store_8(&tqMgmt.inited, 0);
}
}
@@ -85,19 +90,19 @@ void tqClose(STQ* pTq) {
}
}
-int32_t tqSendPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataBlkRsp* pRsp) {
- int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqDataBlkRsp(NULL, pRsp);
+int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp) {
+ int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqMetaRsp(NULL, pRsp);
void* buf = rpcMallocCont(tlen);
if (buf == NULL) {
return -1;
}
- ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP;
+ ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_META_RSP;
((SMqRspHead*)buf)->epoch = pReq->epoch;
((SMqRspHead*)buf)->consumerId = pReq->consumerId;
void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
- tEncodeSMqDataBlkRsp(&abuf, pRsp);
+ tEncodeSMqMetaRsp(&abuf, pRsp);
SRpcMsg resp = {
.info = pMsg->info,
@@ -107,8 +112,59 @@ int32_t tqSendPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, con
};
tmsgSendRsp(&resp);
- tqDebug("vg %d from consumer %ld (epoch %d) send rsp, block num: %d, reqOffset: %ld, rspOffset: %ld",
- TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, pRsp->reqOffset, pRsp->rspOffset);
+ tqDebug("vgId:%d from consumer:%" PRId64 ", (epoch %d) send rsp, res msg type %d, reqOffset:%" PRId64
+ ", rspOffset:%" PRId64,
+ TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->resMsgType, pRsp->reqOffset, pRsp->rspOffset);
+
+ return 0;
+}
+
+int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp) {
+ ASSERT(taosArrayGetSize(pRsp->blockData) == pRsp->blockNum);
+ ASSERT(taosArrayGetSize(pRsp->blockDataLen) == pRsp->blockNum);
+
+ if (pRsp->withSchema) {
+ ASSERT(taosArrayGetSize(pRsp->blockSchema) == pRsp->blockNum);
+ } else {
+ ASSERT(taosArrayGetSize(pRsp->blockSchema) == 0);
+ }
+
+ int32_t len;
+ int32_t code;
+ tEncodeSize(tEncodeSMqDataRsp, pRsp, len, code);
+ if (code < 0) {
+ return -1;
+ }
+ int32_t tlen = sizeof(SMqRspHead) + len;
+ void* buf = rpcMallocCont(tlen);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP;
+ ((SMqRspHead*)buf)->epoch = pReq->epoch;
+ ((SMqRspHead*)buf)->consumerId = pReq->consumerId;
+
+ void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
+
+ SEncoder encoder;
+ tEncoderInit(&encoder, abuf, len);
+ tEncodeSMqDataRsp(&encoder, pRsp);
+
+ SRpcMsg rsp = {
+ .info = pMsg->info,
+ .pCont = buf,
+ .contLen = tlen,
+ .code = 0,
+ };
+ tmsgSendRsp(&rsp);
+
+ char buf1[80];
+ char buf2[80];
+ tFormatOffset(buf1, 80, &pRsp->reqOffset);
+ tFormatOffset(buf2, 80, &pRsp->rspOffset);
+ tqDebug("vgId:%d from consumer:%" PRId64 ", (epoch %d) send rsp, block num: %d, reqOffset:%s, rspOffset:%s",
+ TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2);
return 0;
}
@@ -123,170 +179,272 @@ int32_t tqProcessOffsetCommitReq(STQ* pTq, char* msg, int32_t msgLen) {
}
tDecoderClear(&decoder);
- if (offset.type == TMQ_OFFSET__SNAPSHOT) {
- tqDebug("receive offset commit msg to %s on vg %d, offset(type:snapshot) uid: %ld, ts: %ld", offset.subKey,
- TD_VID(pTq->pVnode), offset.uid, offset.ts);
- } else if (offset.type == TMQ_OFFSET__LOG) {
- tqDebug("receive offset commit msg to %s on vg %d, offset(type:log) version: %ld", offset.subKey,
- TD_VID(pTq->pVnode), offset.version);
+ if (offset.val.type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:snapshot) uid:%" PRId64 ", ts:%" PRId64,
+ offset.subKey, TD_VID(pTq->pVnode), offset.val.uid, offset.val.ts);
+ } else if (offset.val.type == TMQ_OFFSET__LOG) {
+ tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:log) version:%" PRId64, offset.subKey,
+ TD_VID(pTq->pVnode), offset.val.version);
} else {
ASSERT(0);
}
- STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, offset.subKey);
- if (pOffset == NULL || pOffset->version < offset.version) {
- if (tqOffsetWrite(pTq->pOffsetStore, &offset) < 0) {
- ASSERT(0);
- return -1;
- }
+ /*STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, offset.subKey);*/
+ /*if (pOffset != NULL) {*/
+ /*if (pOffset->val.type == TMQ_OFFSET__LOG && pOffset->val.version < offset.val.version) {*/
+ if (tqOffsetWrite(pTq->pOffsetStore, &offset) < 0) {
+ ASSERT(0);
+ return -1;
}
+ /*}*/
+ /*}*/
return 0;
}
-int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
- SMqPollReq* pReq = pMsg->pCont;
- int64_t consumerId = pReq->consumerId;
- int64_t timeout = pReq->timeout;
- int32_t reqEpoch = pReq->epoch;
- int64_t fetchOffset;
- int32_t code = 0;
-
- // get offset to fetch message
- if (pReq->currentOffset >= 0) {
- fetchOffset = pReq->currentOffset + 1;
+static int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq, int8_t subType) {
+ pRsp->reqOffset = pReq->reqOffset;
+
+ pRsp->blockData = taosArrayInit(0, sizeof(void*));
+ pRsp->blockDataLen = taosArrayInit(0, sizeof(int32_t));
+
+ if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL) {
+ return -1;
+ }
+
+ pRsp->withTbName = pReq->withTbName;
+ if (pRsp->withTbName) {
+ pRsp->blockTbName = taosArrayInit(0, sizeof(void*));
+ if (pRsp->blockTbName == NULL) {
+ // TODO free
+ return -1;
+ }
+ }
+
+ if (subType == TOPIC_SUB_TYPE__COLUMN) {
+ pRsp->withSchema = false;
} else {
- STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, pReq->subKey);
- if (pOffset != NULL) {
- ASSERT(pOffset->type == TMQ_OFFSET__LOG);
- tqDebug("consumer %ld, restore offset of %s on vg %d, offset(type:log) version: %ld", consumerId, pReq->subKey,
- TD_VID(pTq->pVnode), pOffset->version);
- fetchOffset = pOffset->version + 1;
- } else {
- if (pReq->currentOffset == TMQ_CONF__RESET_OFFSET__EARLIEAST) {
- fetchOffset = walGetFirstVer(pTq->pWal);
- } else if (pReq->currentOffset == TMQ_CONF__RESET_OFFSET__LATEST) {
- fetchOffset = walGetCommittedVer(pTq->pWal);
- } else if (pReq->currentOffset == TMQ_CONF__RESET_OFFSET__NONE) {
- tqError("tmq poll: no offset committed for consumer %ld in vg %d, subkey %s", consumerId, TD_VID(pTq->pVnode),
- pReq->subKey);
- terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET;
- return -1;
- }
- tqDebug("consumer %ld, restore offset of %s on vg %d failed, config is %ld, set to %ld", consumerId, pReq->subKey,
- TD_VID(pTq->pVnode), pReq->currentOffset, fetchOffset);
+ pRsp->withSchema = true;
+ pRsp->blockSchema = taosArrayInit(0, sizeof(void*));
+ if (pRsp->blockSchema == NULL) {
+ // TODO free
+ return -1;
}
}
+ return 0;
+}
- tqDebug("tmq poll: consumer %ld (epoch %d) recv poll req in vg %d, req offset %ld fetch offset %ld", consumerId,
- pReq->epoch, TD_VID(pTq->pVnode), pReq->currentOffset, fetchOffset);
+static int32_t tqInitMetaRsp(SMqMetaRsp* pRsp, const SMqPollReq* pReq) { return 0; }
+int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
+ SMqPollReq* pReq = pMsg->pCont;
+ int64_t consumerId = pReq->consumerId;
+ int64_t timeout = pReq->timeout;
+ int32_t reqEpoch = pReq->epoch;
+ int32_t code = 0;
+ STqOffsetVal reqOffset = pReq->reqOffset;
+ STqOffsetVal fetchOffsetNew;
+
+ // todo
+ workerId = 0;
+
+ // 1.find handle
STqHandle* pHandle = taosHashGet(pTq->handles, pReq->subKey, strlen(pReq->subKey));
/*ASSERT(pHandle);*/
if (pHandle == NULL) {
- tqError("tmq poll: no consumer handle for consumer %ld in vg %d, subkey %s", consumerId, TD_VID(pTq->pVnode),
- pReq->subKey);
+ tqError("tmq poll: no consumer handle for consumer:%" PRId64 ", in vgId:%d, subkey %s", consumerId,
+ TD_VID(pTq->pVnode), pReq->subKey);
return -1;
}
+ // check rebalance
if (pHandle->consumerId != consumerId) {
- tqError("tmq poll: consumer handle mismatch for consumer %ld in vg %d, subkey %s, handle consumer id %ld",
+ tqError("tmq poll: consumer handle mismatch for consumer:%" PRId64
+ ", in vgId:%d, subkey %s, handle consumer id %" PRId64,
consumerId, TD_VID(pTq->pVnode), pReq->subKey, pHandle->consumerId);
return -1;
}
+ // update epoch if need
int32_t consumerEpoch = atomic_load_32(&pHandle->epoch);
while (consumerEpoch < reqEpoch) {
consumerEpoch = atomic_val_compare_exchange_32(&pHandle->epoch, consumerEpoch, reqEpoch);
}
- SWalHead* pHeadWithCkSum = taosMemoryMalloc(sizeof(SWalHead) + 2048);
- if (pHeadWithCkSum == NULL) {
- return -1;
- }
-
- walSetReaderCapacity(pHandle->pWalReader, 2048);
+ char buf[80];
+ tFormatOffset(buf, 80, &reqOffset);
+ tqDebug("tmq poll: consumer %ld (epoch %d), subkey %s, recv poll req in vg %d, req offset %s", consumerId,
+ pReq->epoch, pHandle->subKey, TD_VID(pTq->pVnode), buf);
- SMqDataBlkRsp rsp = {0};
- rsp.reqOffset = pReq->currentOffset;
+ SMqDataRsp dataRsp = {0};
+ tqInitDataRsp(&dataRsp, pReq, pHandle->execHandle.subType);
- rsp.blockData = taosArrayInit(0, sizeof(void*));
- rsp.blockDataLen = taosArrayInit(0, sizeof(int32_t));
-
- rsp.withTbName = pReq->withTbName;
- if (rsp.withTbName) {
- rsp.blockTbName = taosArrayInit(0, sizeof(void*));
- }
- if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
- rsp.withSchema = false;
- rsp.withTag = false;
+ // 2.reset offset if needed
+ if (reqOffset.type > 0) {
+ fetchOffsetNew = reqOffset;
} else {
- rsp.withSchema = true;
- rsp.withTag = false;
- rsp.blockSchema = taosArrayInit(0, sizeof(void*));
+ STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, pReq->subKey);
+ if (pOffset != NULL) {
+ fetchOffsetNew = pOffset->val;
+ char formatBuf[80];
+ tFormatOffset(formatBuf, 80, &fetchOffsetNew);
+ tqDebug("tmq poll: consumer %" PRId64 ", subkey %s, vg %d, offset reset to %s", consumerId, pHandle->subKey,
+ TD_VID(pTq->pVnode), formatBuf);
+ } else {
+ if (reqOffset.type == TMQ_OFFSET__RESET_EARLIEAST) {
+ if (pReq->useSnapshot && pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
+ if (!pHandle->fetchMeta) {
+ tqOffsetResetToData(&fetchOffsetNew, 0, 0);
+ } else {
+ // reset to meta
+ ASSERT(0);
+ }
+ } else {
+ tqOffsetResetToLog(&fetchOffsetNew, walGetFirstVer(pTq->pVnode->pWal));
+ }
+ } else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) {
+ tqOffsetResetToLog(&dataRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal));
+ tqDebug("tmq poll: consumer %ld, subkey %s, vg %d, offset reset to %ld", consumerId, pHandle->subKey,
+ TD_VID(pTq->pVnode), dataRsp.rspOffset.version);
+ if (tqSendDataRsp(pTq, pMsg, pReq, &dataRsp) < 0) {
+ code = -1;
+ }
+ goto OVER;
+ } else if (reqOffset.type == TMQ_OFFSET__RESET_NONE) {
+ tqError("tmq poll: subkey %s, no offset committed for consumer %" PRId64
+ " in vg %d, subkey %s, reset none failed",
+ pHandle->subKey, consumerId, TD_VID(pTq->pVnode), pReq->subKey);
+ terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET;
+ code = -1;
+ goto OVER;
+ }
+ }
}
- while (1) {
- consumerEpoch = atomic_load_32(&pHandle->epoch);
- if (consumerEpoch > reqEpoch) {
- tqWarn("tmq poll: consumer %ld (epoch %d) vg %d offset %ld, found new consumer epoch %d, discard req epoch %d",
- consumerId, pReq->epoch, TD_VID(pTq->pVnode), fetchOffset, consumerEpoch, reqEpoch);
- break;
+ // 3.query
+ if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
+ /*if (fetchOffsetNew.type == TMQ_OFFSET__LOG) {*/
+ /*fetchOffsetNew.version++;*/
+ /*}*/
+ if (tqScan(pTq, pHandle, &dataRsp, &fetchOffsetNew) < 0) {
+ ASSERT(0);
+ code = -1;
+ goto OVER;
+ }
+ if (dataRsp.blockNum == 0) {
+ // TODO add to async task pool
+ /*dataRsp.rspOffset.version--;*/
}
+ if (tqSendDataRsp(pTq, pMsg, pReq, &dataRsp) < 0) {
+ code = -1;
+ }
+ goto OVER;
+ }
- if (tqFetchLog(pTq, pHandle, &fetchOffset, &pHeadWithCkSum) < 0) {
- // TODO add push mgr
- break;
+ if (pHandle->execHandle.subType != TOPIC_SUB_TYPE__COLUMN) {
+ int64_t fetchVer = fetchOffsetNew.version + 1;
+ SWalCkHead* pCkHead = taosMemoryMalloc(sizeof(SWalCkHead) + 2048);
+ if (pCkHead == NULL) {
+ code = -1;
+ goto OVER;
}
- SWalReadHead* pHead = &pHeadWithCkSum->head;
+ walSetReaderCapacity(pHandle->pWalReader, 2048);
- tqDebug("tmq poll: consumer %ld (epoch %d) iter log, vg %d offset %ld msgType %d", consumerId, pReq->epoch,
- TD_VID(pTq->pVnode), fetchOffset, pHead->msgType);
+ while (1) {
+ consumerEpoch = atomic_load_32(&pHandle->epoch);
+ if (consumerEpoch > reqEpoch) {
+ tqWarn("tmq poll: consumer %ld (epoch %d), subkey %s, vg %d offset %" PRId64
+ ", found new consumer epoch %d, discard req epoch %d",
+ consumerId, pReq->epoch, pHandle->subKey, TD_VID(pTq->pVnode), fetchVer, consumerEpoch, reqEpoch);
+ break;
+ }
- if (pHead->msgType == TDMT_VND_SUBMIT) {
- SSubmitReq* pCont = (SSubmitReq*)&pHead->body;
+ if (tqFetchLog(pTq, pHandle, &fetchVer, &pCkHead) < 0) {
+ // TODO add push mgr
- if (tqDataExec(pTq, &pHandle->execHandle, pCont, &rsp, workerId) < 0) {
- /*ASSERT(0);*/
+ tqOffsetResetToLog(&dataRsp.rspOffset, fetchVer);
+ ASSERT(dataRsp.rspOffset.version >= dataRsp.reqOffset.version);
+ if (tqSendDataRsp(pTq, pMsg, pReq, &dataRsp) < 0) {
+ code = -1;
+ }
+ goto OVER;
}
- } else {
- // TODO
- ASSERT(0);
- }
- // TODO batch optimization:
- // TODO continue scan until meeting batch requirement
- if (rsp.blockNum > 0 /* threshold */) {
- break;
- } else {
- fetchOffset++;
+ SWalCont* pHead = &pCkHead->head;
+
+ tqDebug("tmq poll: consumer:%" PRId64 ", (epoch %d) iter log, vgId:%d offset %" PRId64 " msgType %d", consumerId,
+ pReq->epoch, TD_VID(pTq->pVnode), fetchVer, pHead->msgType);
+
+ if (pHead->msgType == TDMT_VND_SUBMIT) {
+ SSubmitReq* pCont = (SSubmitReq*)&pHead->body;
+
+ if (tqLogScanExec(pTq, &pHandle->execHandle, pCont, &dataRsp, workerId) < 0) {
+ /*ASSERT(0);*/
+ }
+ // TODO batch optimization:
+ // TODO continue scan until meeting batch requirement
+ if (dataRsp.blockNum > 0 /* threshold */) {
+ tqOffsetResetToLog(&dataRsp.rspOffset, fetchVer);
+ ASSERT(dataRsp.rspOffset.version >= dataRsp.reqOffset.version);
+
+ if (tqSendDataRsp(pTq, pMsg, pReq, &dataRsp) < 0) {
+ code = -1;
+ }
+ goto OVER;
+ } else {
+ fetchVer++;
+ }
+
+ } else {
+ ASSERT(pHandle->fetchMeta);
+ ASSERT(IS_META_MSG(pHead->msgType));
+ tqDebug("fetch meta msg, ver:%" PRId64 ", type:%d", pHead->version, pHead->msgType);
+ SMqMetaRsp metaRsp = {0};
+ /*metaRsp.reqOffset = pReq->reqOffset.version;*/
+ metaRsp.rspOffset = fetchVer;
+ /*metaRsp.rspOffsetNew.version = fetchVer;*/
+ tqOffsetResetToLog(&metaRsp.reqOffsetNew, pReq->reqOffset.version);
+ tqOffsetResetToLog(&metaRsp.rspOffsetNew, fetchVer);
+ metaRsp.resMsgType = pHead->msgType;
+ metaRsp.metaRspLen = pHead->bodyLen;
+ metaRsp.metaRsp = pHead->body;
+ if (tqSendMetaPollRsp(pTq, pMsg, pReq, &metaRsp) < 0) {
+ code = -1;
+ goto OVER;
+ }
+ code = 0;
+ goto OVER;
+ }
}
- }
- taosMemoryFree(pHeadWithCkSum);
-
- ASSERT(taosArrayGetSize(rsp.blockData) == rsp.blockNum);
- ASSERT(taosArrayGetSize(rsp.blockDataLen) == rsp.blockNum);
- if (rsp.withSchema) {
- ASSERT(taosArrayGetSize(rsp.blockSchema) == rsp.blockNum);
- }
-
- rsp.rspOffset = fetchOffset;
+ taosMemoryFree(pCkHead);
+#if 0
+ } else if (fetchOffsetNew.type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ tqInfo("retrieve using snapshot actual offset: uid %" PRId64 " ts %" PRId64, fetchOffsetNew.uid, fetchOffsetNew.ts);
+ if (tqScanSnapshot(pTq, &pHandle->execHandle, &dataRsp, fetchOffsetNew, workerId) < 0) {
+ ASSERT(0);
+ }
- if (tqSendPollRsp(pTq, pMsg, pReq, &rsp) < 0) {
- code = -1;
+ // 4. send rsp
+ if (tqSendDataRsp(pTq, pMsg, pReq, &dataRsp) < 0) {
+ code = -1;
+ }
+#endif
+ } else if (fetchOffsetNew.type == TMQ_OFFSET__SNAPSHOT_META) {
+ ASSERT(0);
}
+OVER:
// TODO wrap in destroy func
- taosArrayDestroy(rsp.blockDataLen);
- taosArrayDestroyP(rsp.blockData, (FDelete)taosMemoryFree);
+ taosArrayDestroy(dataRsp.blockDataLen);
+ taosArrayDestroyP(dataRsp.blockData, (FDelete)taosMemoryFree);
- if (rsp.withSchema) {
- taosArrayDestroyP(rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper);
+ if (dataRsp.withSchema) {
+ taosArrayDestroyP(dataRsp.blockSchema, (FDelete)tDeleteSSchemaWrapper);
}
- if (rsp.withTbName) {
- taosArrayDestroyP(rsp.blockTbName, (FDelete)taosMemoryFree);
+ if (dataRsp.withTbName) {
+ taosArrayDestroyP(dataRsp.blockTbName, (FDelete)taosMemoryFree);
}
return code;
@@ -298,6 +456,8 @@ int32_t tqProcessVgDeleteReq(STQ* pTq, char* msg, int32_t msgLen) {
int32_t code = taosHashRemove(pTq->handles, pReq->subKey, strlen(pReq->subKey));
ASSERT(code == 0);
+ tqOffsetDelete(pTq->pOffsetStore, pReq->subKey);
+
if (tqMetaDeleteHandle(pTq, pReq->subKey) < 0) {
ASSERT(0);
}
@@ -321,36 +481,50 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
pHandle->epoch = -1;
pHandle->execHandle.subType = req.subType;
+ pHandle->fetchMeta = req.withMeta;
- pHandle->pWalReader = walOpenReadHandle(pTq->pVnode->pWal);
- for (int32_t i = 0; i < 5; i++) {
- pHandle->execHandle.pExecReader[i] = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
- }
+ pHandle->pWalReader = walOpenReader(pTq->pVnode->pWal, NULL);
+
+ // TODO version should be assigned in preprocess
+ int64_t ver = walGetCommittedVer(pTq->pVnode->pWal);
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
pHandle->execHandle.execCol.qmsg = req.qmsg;
+ pHandle->snapshotVer = ver;
req.qmsg = NULL;
for (int32_t i = 0; i < 5; i++) {
SReadHandle handle = {
- .reader = pHandle->execHandle.pExecReader[i],
.meta = pTq->pVnode->pMeta,
+ .vnode = pTq->pVnode,
+ .initTableReader = true,
+ .initTqReader = true,
+ .version = ver,
};
- pHandle->execHandle.execCol.task[i] = qCreateStreamExecTaskInfo(pHandle->execHandle.execCol.qmsg, &handle);
+ pHandle->execHandle.execCol.task[i] = qCreateQueueExecTaskInfo(pHandle->execHandle.execCol.qmsg, &handle);
ASSERT(pHandle->execHandle.execCol.task[i]);
+ void* scanner = NULL;
+ qExtractStreamScanner(pHandle->execHandle.execCol.task[i], &scanner);
+ ASSERT(scanner);
+ pHandle->execHandle.pExecReader[i] = qExtractReaderFromStreamScanner(scanner);
+ ASSERT(pHandle->execHandle.pExecReader[i]);
}
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) {
+ for (int32_t i = 0; i < 5; i++) {
+ pHandle->execHandle.pExecReader[i] = tqOpenReader(pTq->pVnode);
+ }
pHandle->execHandle.execDb.pFilterOutTbUid =
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) {
pHandle->execHandle.execTb.suid = req.suid;
SArray* tbUidList = taosArrayInit(0, sizeof(int64_t));
- tsdbGetCtbIdList(pTq->pVnode->pMeta, req.suid, tbUidList);
- tqDebug("vg %d, tq try get suid: %ld", TD_VID(pTq->pVnode), req.suid);
+ vnodeGetCtbIdList(pTq->pVnode, req.suid, tbUidList);
+ tqDebug("vgId:%d, tq try get suid:%" PRId64, pTq->pVnode->config.vgId, req.suid);
for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) {
int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i);
- tqDebug("vg %d, idx %d, uid: %ld", TD_VID(pTq->pVnode), i, tbUid);
+ tqDebug("vgId:%d, idx %d, uid:%" PRId64, TD_VID(pTq->pVnode), i, tbUid);
}
for (int32_t i = 0; i < 5; i++) {
- tqReadHandleSetTbUidList(pHandle->execHandle.pExecReader[i], tbUidList);
+ pHandle->execHandle.pExecReader[i] = tqOpenReader(pTq->pVnode);
+ tqReaderSetTbUidList(pHandle->execHandle.pExecReader[i], tbUidList);
}
taosArrayDestroy(tbUidList);
}
@@ -383,8 +557,12 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, char* msg, int32_t msgLen) {
ASSERT(0);
}
tDecoderClear(&decoder);
+ ASSERT(pTask->isDataScan == 0 || pTask->isDataScan == 1);
+ if (pTask->isDataScan == 0 && pTask->sinkType == TASK_SINK__NONE) {
+ ASSERT(taosArrayGetSize(pTask->childEpInfo) != 0);
+ }
- pTask->status = TASK_STATUS__IDLE;
+ pTask->execStatus = TASK_EXEC_STATUS__IDLE;
pTask->inputQueue = streamQueueOpen();
pTask->outputQueue = streamQueueOpen();
@@ -398,20 +576,17 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, char* msg, int32_t msgLen) {
// exec
if (pTask->execType != TASK_EXEC__NONE) {
// expand runners
- if (pTask->dataScan) {
- STqReadHandle* pStreamReader = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
- SReadHandle handle = {
- .reader = pStreamReader,
- .meta = pTq->pVnode->pMeta,
- .vnode = pTq->pVnode,
+ if (pTask->isDataScan) {
+ SReadHandle handle = {
+ .meta = pTq->pVnode->pMeta,
+ .vnode = pTq->pVnode,
+ .initTqReader = 1,
};
- /*pTask->exec.inputHandle = pStreamReader;*/
pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle);
- ASSERT(pTask->exec.executor);
} else {
pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, NULL);
- ASSERT(pTask->exec.executor);
}
+ ASSERT(pTask->exec.executor);
}
// sink
@@ -433,7 +608,7 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, char* msg, int32_t msgLen) {
streamSetupTrigger(pTask);
- tqInfo("deploy stream task id %d child id %d on vg %d", pTask->taskId, pTask->childId, TD_VID(pTq->pVnode));
+ tqInfo("deploy stream task id %d child id %d on vgId:%d", pTask->taskId, pTask->selfChildId, TD_VID(pTq->pVnode));
taosHashPut(pTq->pStreamTasks, &pTask->taskId, sizeof(int32_t), &pTask, sizeof(void*));
@@ -459,7 +634,10 @@ int32_t tqProcessStreamTrigger(STQ* pTq, SSubmitReq* pReq) {
pIter = taosHashIterate(pTq->pStreamTasks, pIter);
if (pIter == NULL) break;
SStreamTask* pTask = *(SStreamTask**)pIter;
- if (pTask->inputType != STREAM_INPUT__DATA_SUBMIT) continue;
+ if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) {
+ continue;
+ }
+ if (!pTask->isDataScan) continue;
if (!failed) {
if (streamTaskInput(pTask, (SStreamQueueItem*)pSubmit) < 0) {
@@ -487,6 +665,9 @@ int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg) {
SStreamTaskRunReq* pReq = pMsg->pCont;
int32_t taskId = pReq->taskId;
SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
streamProcessRunReq(pTask);
return 0;
}
@@ -501,9 +682,12 @@ int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg) {
tDecodeStreamDispatchReq(&decoder, &req);
int32_t taskId = req.taskId;
SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
- SRpcMsg rsp = {
- .info = pMsg->info,
- .code = 0,
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
+ SRpcMsg rsp = {
+ .info = pMsg->info,
+ .code = 0,
};
streamProcessDispatchReq(pTask, &req, &rsp);
return 0;
@@ -513,6 +697,9 @@ int32_t tqProcessTaskRecoverReq(STQ* pTq, SRpcMsg* pMsg) {
SStreamTaskRecoverReq* pReq = pMsg->pCont;
int32_t taskId = pReq->taskId;
SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
streamProcessRecoverReq(pTask, pReq, pMsg);
return 0;
}
@@ -521,6 +708,9 @@ int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg) {
SStreamDispatchRsp* pRsp = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
int32_t taskId = pRsp->taskId;
SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
streamProcessDispatchRsp(pTask, pRsp);
return 0;
}
@@ -529,16 +719,58 @@ int32_t tqProcessTaskRecoverRsp(STQ* pTq, SRpcMsg* pMsg) {
SStreamTaskRecoverRsp* pRsp = pMsg->pCont;
int32_t taskId = pRsp->taskId;
SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
streamProcessRecoverRsp(pTask, pRsp);
return 0;
}
int32_t tqProcessTaskDropReq(STQ* pTq, char* msg, int32_t msgLen) {
SVDropStreamTaskReq* pReq = (SVDropStreamTaskReq*)msg;
+
+ SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &pReq->taskId, sizeof(int32_t));
+ atomic_store_8(&pTask->taskStatus, TASK_STATUS__DROPPING);
+ // todo
+ // clear queue
+ // push drop req into queue
+ // launch exec to free memory
+ // remove from hash
+ return 0;
+
+#if 0
int32_t code = taosHashRemove(pTq->pStreamTasks, &pReq->taskId, sizeof(int32_t));
+ // set status dropping
ASSERT(code == 0);
if (code == 0) {
// sendrsp
}
return code;
+#endif
+}
+
+int32_t tqProcessTaskRetrieveReq(STQ* pTq, SRpcMsg* pMsg) {
+ char* msgStr = pMsg->pCont;
+ char* msgBody = POINTER_SHIFT(msgStr, sizeof(SMsgHead));
+ int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
+ SStreamRetrieveReq req;
+ SDecoder decoder;
+ tDecoderInit(&decoder, msgBody, msgLen);
+ tDecodeStreamRetrieveReq(&decoder, &req);
+ int32_t taskId = req.dstTaskId;
+ SStreamTask* pTask = *(SStreamTask**)taosHashGet(pTq->pStreamTasks, &taskId, sizeof(int32_t));
+ if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__NORMAL) {
+ return 0;
+ }
+ SRpcMsg rsp = {
+ .info = pMsg->info,
+ .code = 0,
+ };
+ streamProcessRetrieveReq(pTask, &req, &rsp);
+ return 0;
+}
+
+int32_t tqProcessTaskRetrieveRsp(STQ* pTq, SRpcMsg* pMsg) {
+ //
+ return 0;
}
diff --git a/source/dnode/vnode/src/tq/tqExec.c b/source/dnode/vnode/src/tq/tqExec.c
index 7c75d88a83d5813ceb5c34eb6f1e0cb779335d5f..0bdbe82b772e807e6e05798ecb836b3b089d1bb0 100644
--- a/source/dnode/vnode/src/tq/tqExec.c
+++ b/source/dnode/vnode/src/tq/tqExec.c
@@ -15,7 +15,7 @@
#include "tq.h"
-static int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataBlkRsp* pRsp) {
+static int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataRsp* pRsp) {
int32_t dataStrLen = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
void* buf = taosMemoryCalloc(1, dataStrLen);
if (buf == NULL) return -1;
@@ -29,7 +29,7 @@ static int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataBlkRsp* pRs
// TODO enable compress
int32_t actualLen = 0;
- blockCompressEncode(pBlock, pRetrieve->data, &actualLen, pBlock->info.numOfCols, false);
+ blockEncode(pBlock, pRetrieve->data, &actualLen, taosArrayGetSize(pBlock->pDataBlock), false);
actualLen += sizeof(SRetrieveTableRsp);
ASSERT(actualLen <= dataStrLen);
taosArrayPush(pRsp->blockDataLen, &actualLen);
@@ -37,7 +37,7 @@ static int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataBlkRsp* pRs
return 0;
}
-static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, int32_t workerId, SMqDataBlkRsp* pRsp) {
+static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, int32_t workerId, SMqDataRsp* pRsp) {
SSchemaWrapper* pSW = tCloneSSchemaWrapper(pExec->pExecReader[workerId]->pSchemaWrapper);
if (pSW == NULL) {
return -1;
@@ -46,10 +46,9 @@ static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, int32_t workerI
return 0;
}
-static int32_t tqAddTbNameToRsp(const STQ* pTq, const STqExecHandle* pExec, SMqDataBlkRsp* pRsp, int32_t workerId) {
+static int32_t tqAddTbNameToRsp(const STQ* pTq, int64_t uid, SMqDataRsp* pRsp) {
SMetaReader mr = {0};
metaReaderInit(&mr, pTq->pVnode->pMeta, 0);
- int64_t uid = pExec->pExecReader[workerId]->msgIter.uid;
if (metaGetTableEntryByUid(&mr, uid) < 0) {
ASSERT(0);
return -1;
@@ -60,68 +59,167 @@ static int32_t tqAddTbNameToRsp(const STQ* pTq, const STqExecHandle* pExec, SMqD
return 0;
}
-int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkRsp* pRsp, int32_t workerId) {
- if (pExec->subType == TOPIC_SUB_TYPE__COLUMN) {
- qTaskInfo_t task = pExec->execCol.task[workerId];
- ASSERT(task);
- qSetStreamInput(task, pReq, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
- while (1) {
- SSDataBlock* pDataBlock = NULL;
- uint64_t ts = 0;
- if (qExecTask(task, &pDataBlock, &ts) < 0) {
- ASSERT(0);
- }
- if (pDataBlock == NULL) break;
+int64_t tqScan(STQ* pTq, const STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal* pOffset) {
+ const STqExecHandle* pExec = &pHandle->execHandle;
+ qTaskInfo_t task = pExec->execCol.task[0];
+
+ if (qStreamPrepareScan(task, pOffset) < 0) {
+ ASSERT(pOffset->type == TMQ_OFFSET__LOG);
+ pRsp->rspOffset = *pOffset;
+ return 0;
+ }
- ASSERT(pDataBlock->info.rows != 0);
- ASSERT(pDataBlock->info.numOfCols != 0);
+ int32_t rowCnt = 0;
+ while (1) {
+ SSDataBlock* pDataBlock = NULL;
+ uint64_t ts = 0;
+ tqDebug("task start to execute");
+ if (qExecTask(task, &pDataBlock, &ts) < 0) {
+ ASSERT(0);
+ }
+ tqDebug("task execute end, get %p", pDataBlock);
+ if (pDataBlock != NULL) {
tqAddBlockDataToRsp(pDataBlock, pRsp);
+ pRsp->blockNum++;
if (pRsp->withTbName) {
- tqAddTbNameToRsp(pTq, pExec, pRsp, workerId);
+ if (pOffset->type == TMQ_OFFSET__LOG) {
+ int64_t uid = pExec->pExecReader[0]->msgIter.uid;
+ tqAddTbNameToRsp(pTq, uid, pRsp);
+ } else {
+ pRsp->withTbName = 0;
+ }
}
- pRsp->blockNum++;
+ if (pOffset->type == TMQ_OFFSET__LOG) {
+ continue;
+ } else {
+ rowCnt += pDataBlock->info.rows;
+ if (rowCnt <= 4096) continue;
+ }
+ }
+
+ if (pRsp->blockNum == 0 && pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ tqOffsetResetToLog(pOffset, pHandle->snapshotVer + 1);
+ qStreamPrepareScan(task, pOffset);
+ continue;
+ }
+
+ void* meta = qStreamExtractMetaMsg(task);
+ if (meta != NULL) {
+ // tq add meta to rsp
+ }
+
+ if (qStreamExtractOffset(task, &pRsp->rspOffset) < 0) {
+ ASSERT(0);
+ }
+
+ ASSERT(pRsp->rspOffset.type != 0);
+
+ if (pRsp->reqOffset.type == TMQ_OFFSET__LOG) {
+ ASSERT(pRsp->rspOffset.version + 1 >= pRsp->reqOffset.version);
+ }
+ tqDebug("task exec exited");
+ break;
+ }
+
+ return 0;
+}
+
+#if 0
+int32_t tqScanSnapshot(STQ* pTq, const STqExecHandle* pExec, SMqDataRsp* pRsp, STqOffsetVal offset, int32_t workerId) {
+ ASSERT(pExec->subType == TOPIC_SUB_TYPE__COLUMN);
+ qTaskInfo_t task = pExec->execCol.task[workerId];
+
+ if (qStreamPrepareTsdbScan(task, offset.uid, offset.ts) < 0) {
+ ASSERT(0);
+ }
+
+ int32_t rowCnt = 0;
+ while (1) {
+ SSDataBlock* pDataBlock = NULL;
+ uint64_t ts = 0;
+ if (qExecTask(task, &pDataBlock, &ts) < 0) {
+ ASSERT(0);
+ }
+ if (pDataBlock == NULL) break;
+
+ ASSERT(pDataBlock->info.rows != 0);
+ ASSERT(taosArrayGetSize(pDataBlock->pDataBlock) != 0);
+
+ tqAddBlockDataToRsp(pDataBlock, pRsp);
+
+ if (pRsp->withTbName) {
+ pRsp->withTbName = 0;
+#if 0
+ int64_t uid;
+ int64_t ts;
+ if (qGetStreamScanStatus(task, &uid, &ts) < 0) {
+ ASSERT(0);
+ }
+ tqAddTbNameToRsp(pTq, uid, pRsp);
+#endif
}
- } else if (pExec->subType == TOPIC_SUB_TYPE__TABLE) {
+ pRsp->blockNum++;
+
+ rowCnt += pDataBlock->info.rows;
+ if (rowCnt >= 4096) break;
+ }
+ int64_t uid;
+ int64_t ts;
+ if (qGetStreamScanStatus(task, &uid, &ts) < 0) {
+ ASSERT(0);
+ }
+ tqOffsetResetToData(&pRsp->rspOffset, uid, ts);
+
+ return 0;
+}
+#endif
+
+int32_t tqLogScanExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataRsp* pRsp, int32_t workerId) {
+ ASSERT(pExec->subType != TOPIC_SUB_TYPE__COLUMN);
+
+ if (pExec->subType == TOPIC_SUB_TYPE__TABLE) {
pRsp->withSchema = 1;
- STqReadHandle* pReader = pExec->pExecReader[workerId];
- tqReadHandleSetMsg(pReader, pReq, 0);
+ STqReader* pReader = pExec->pExecReader[workerId];
+ tqReaderSetDataMsg(pReader, pReq, 0);
while (tqNextDataBlock(pReader)) {
SSDataBlock block = {0};
- if (tqRetrieveDataBlock(&block.pDataBlock, pReader, &block.info.groupId, &block.info.uid, &block.info.rows,
- &block.info.numOfCols) < 0) {
+ if (tqRetrieveDataBlock(&block, pReader) < 0) {
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;
ASSERT(0);
}
tqAddBlockDataToRsp(&block, pRsp);
if (pRsp->withTbName) {
- tqAddTbNameToRsp(pTq, pExec, pRsp, workerId);
+ int64_t uid = pExec->pExecReader[workerId]->msgIter.uid;
+ tqAddTbNameToRsp(pTq, uid, pRsp);
}
tqAddBlockSchemaToRsp(pExec, workerId, pRsp);
pRsp->blockNum++;
}
} else if (pExec->subType == TOPIC_SUB_TYPE__DB) {
pRsp->withSchema = 1;
- STqReadHandle* pReader = pExec->pExecReader[workerId];
- tqReadHandleSetMsg(pReader, pReq, 0);
+ STqReader* pReader = pExec->pExecReader[workerId];
+ tqReaderSetDataMsg(pReader, pReq, 0);
while (tqNextDataBlockFilterOut(pReader, pExec->execDb.pFilterOutTbUid)) {
SSDataBlock block = {0};
- if (tqRetrieveDataBlock(&block.pDataBlock, pReader, &block.info.groupId, &block.info.uid, &block.info.rows,
- &block.info.numOfCols) < 0) {
+ if (tqRetrieveDataBlock(&block, pReader) < 0) {
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;
ASSERT(0);
}
tqAddBlockDataToRsp(&block, pRsp);
if (pRsp->withTbName) {
- tqAddTbNameToRsp(pTq, pExec, pRsp, workerId);
+ int64_t uid = pExec->pExecReader[workerId]->msgIter.uid;
+ tqAddTbNameToRsp(pTq, uid, pRsp);
}
tqAddBlockSchemaToRsp(pExec, workerId, pRsp);
pRsp->blockNum++;
}
}
+
if (pRsp->blockNum == 0) {
pRsp->skipLogNum++;
return -1;
}
+
return 0;
}
diff --git a/source/dnode/vnode/src/tq/tqMeta.c b/source/dnode/vnode/src/tq/tqMeta.c
index 398a09ecbc33dbd81efc344539159fc001c9b308..e6df58696d6421295f1a7e5551f4b1f05b75747e 100644
--- a/source/dnode/vnode/src/tq/tqMeta.c
+++ b/source/dnode/vnode/src/tq/tqMeta.c
@@ -19,6 +19,7 @@ static int32_t tEncodeSTqHandle(SEncoder* pEncoder, const STqHandle* pHandle) {
if (tStartEncode(pEncoder) < 0) return -1;
if (tEncodeCStr(pEncoder, pHandle->subKey) < 0) return -1;
if (tEncodeI64(pEncoder, pHandle->consumerId) < 0) return -1;
+ if (tEncodeI64(pEncoder, pHandle->snapshotVer) < 0) return -1;
if (tEncodeI32(pEncoder, pHandle->epoch) < 0) return -1;
if (tEncodeI8(pEncoder, pHandle->execHandle.subType) < 0) return -1;
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
@@ -32,6 +33,7 @@ static int32_t tDecodeSTqHandle(SDecoder* pDecoder, STqHandle* pHandle) {
if (tStartDecode(pDecoder) < 0) return -1;
if (tDecodeCStrTo(pDecoder, pHandle->subKey) < 0) return -1;
if (tDecodeI64(pDecoder, &pHandle->consumerId) < 0) return -1;
+ if (tDecodeI64(pDecoder, &pHandle->snapshotVer) < 0) return -1;
if (tDecodeI32(pDecoder, &pHandle->epoch) < 0) return -1;
if (tDecodeI8(pDecoder, &pHandle->execHandle.subType) < 0) return -1;
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
@@ -77,19 +79,26 @@ int32_t tqMetaOpen(STQ* pTq) {
STqHandle handle;
tDecoderInit(&decoder, (uint8_t*)pVal, vLen);
tDecodeSTqHandle(&decoder, &handle);
- handle.pWalReader = walOpenReadHandle(pTq->pVnode->pWal);
- for (int32_t i = 0; i < 5; i++) {
- handle.execHandle.pExecReader[i] = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
- }
+ handle.pWalReader = walOpenReader(pTq->pVnode->pWal, NULL);
+ /*for (int32_t i = 0; i < 5; i++) {*/
+ /*handle.execHandle.pExecReader[i] = tqOpenReader(pTq->pVnode);*/
+ /*}*/
if (handle.execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
for (int32_t i = 0; i < 5; i++) {
SReadHandle reader = {
- .reader = handle.execHandle.pExecReader[i],
.meta = pTq->pVnode->pMeta,
- .pMsgCb = &pTq->pVnode->msgCb,
+ .vnode = pTq->pVnode,
+ .initTableReader = true,
+ .initTqReader = true,
+ .version = handle.snapshotVer,
};
- handle.execHandle.execCol.task[i] = qCreateStreamExecTaskInfo(handle.execHandle.execCol.qmsg, &reader);
+ handle.execHandle.execCol.task[i] = qCreateQueueExecTaskInfo(handle.execHandle.execCol.qmsg, &reader);
ASSERT(handle.execHandle.execCol.task[i]);
+ void* scanner = NULL;
+ qExtractStreamScanner(handle.execHandle.execCol.task[i], &scanner);
+ ASSERT(scanner);
+ handle.execHandle.pExecReader[i] = qExtractReaderFromStreamScanner(scanner);
+ ASSERT(handle.execHandle.pExecReader[i]);
}
} else {
handle.execHandle.execDb.pFilterOutTbUid =
@@ -98,6 +107,7 @@ int32_t tqMetaOpen(STQ* pTq) {
taosHashPut(pTq->handles, pKey, kLen, &handle, sizeof(STqHandle));
}
+ tdbTbcClose(pCur);
if (tdbTxnClose(&txn) < 0) {
ASSERT(0);
}
@@ -105,6 +115,9 @@ int32_t tqMetaOpen(STQ* pTq) {
}
int32_t tqMetaClose(STQ* pTq) {
+ if (pTq->pExecStore) {
+ tdbTbClose(pTq->pExecStore);
+ }
tdbClose(pTq->pMetaStore);
return 0;
}
diff --git a/source/dnode/vnode/src/tq/tqOffset.c b/source/dnode/vnode/src/tq/tqOffset.c
index e5475d7c300531b7b3e0d8cce369fa9eb0415930..ec9674d637af8c1456f20769f36e1ec57acc2193 100644
--- a/source/dnode/vnode/src/tq/tqOffset.c
+++ b/source/dnode/vnode/src/tq/tqOffset.c
@@ -44,6 +44,7 @@ STqOffsetStore* tqOffsetOpen(STQ* pTq) {
}
char* fname = buildFileName(pStore->pTq->path);
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_READ);
+ taosMemoryFree(fname);
if (pFile != NULL) {
STqOffsetHead head = {0};
int64_t code;
@@ -77,7 +78,6 @@ STqOffsetStore* tqOffsetOpen(STQ* pTq) {
}
taosCloseFile(&pFile);
- taosMemoryFree(fname);
}
return pStore;
}
@@ -85,6 +85,7 @@ STqOffsetStore* tqOffsetOpen(STQ* pTq) {
void tqOffsetClose(STqOffsetStore* pStore) {
tqOffsetSnapshot(pStore);
taosHashCleanup(pStore->pHash);
+ taosMemoryFree(pStore);
}
STqOffset* tqOffsetRead(STqOffsetStore* pStore, const char* subscribeKey) {
@@ -92,16 +93,21 @@ STqOffset* tqOffsetRead(STqOffsetStore* pStore, const char* subscribeKey) {
}
int32_t tqOffsetWrite(STqOffsetStore* pStore, const STqOffset* pOffset) {
- ASSERT(pOffset->type == TMQ_OFFSET__LOG);
- ASSERT(pOffset->version >= 0);
+ /*ASSERT(pOffset->val.type == TMQ_OFFSET__LOG);*/
+ /*ASSERT(pOffset->val.version >= 0);*/
return taosHashPut(pStore->pHash, pOffset->subKey, strlen(pOffset->subKey), pOffset, sizeof(STqOffset));
}
+int32_t tqOffsetDelete(STqOffsetStore* pStore, const char* subscribeKey) {
+ return taosHashRemove(pStore->pHash, subscribeKey, strlen(subscribeKey));
+}
+
int32_t tqOffsetSnapshot(STqOffsetStore* pStore) {
// open file
// TODO file name should be with a version
char* fname = buildFileName(pStore->pTq->path);
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
+ taosMemoryFree(fname);
if (pFile == NULL) {
ASSERT(0);
return -1;
@@ -133,13 +139,12 @@ int32_t tqOffsetSnapshot(STqOffsetStore* pStore) {
int64_t writeLen;
if ((writeLen = taosWriteFile(pFile, buf, totLen)) != totLen) {
ASSERT(0);
- tqError("write offset incomplete, len %d, write len %ld", bodyLen, writeLen);
+ tqError("write offset incomplete, len %d, write len %" PRId64, bodyLen, writeLen);
taosHashCancelIterate(pStore->pHash, pIter);
return -1;
}
}
// close and rename file
taosCloseFile(&pFile);
- taosMemoryFree(fname);
return 0;
}
diff --git a/source/dnode/vnode/src/tq/tqPush.c b/source/dnode/vnode/src/tq/tqPush.c
index 3af8901b2b20f97f66ea78209ddb3d9936fc93c1..e9e5f6cd8bc353c643546ba823f438ea9984b9e3 100644
--- a/source/dnode/vnode/src/tq/tqPush.c
+++ b/source/dnode/vnode/src/tq/tqPush.c
@@ -15,16 +15,17 @@
#include "tq.h"
+#if 0
void tqTmrRspFunc(void* param, void* tmrId) {
STqHandle* pHandle = (STqHandle*)param;
atomic_store_8(&pHandle->pushHandle.tmrStopped, 1);
}
-static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubmit** ppSubmit, SMqDataBlkRsp* pRsp) {
+static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubmit** ppSubmit, SMqDataRsp* pRsp) {
SStreamDataSubmit* pSubmit = *ppSubmit;
while (pSubmit != NULL) {
ASSERT(pSubmit->ver == pHandle->pushHandle.processedVer + 1);
- if (tqDataExec(pTq, &pHandle->execHandle, pSubmit->data, pRsp, 0) < 0) {
+ if (tqLogScanExec(pTq, &pHandle->execHandle, pSubmit->data, pRsp, 0) < 0) {
/*ASSERT(0);*/
}
// update processed
@@ -43,11 +44,11 @@ static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubm
}
int32_t tqExecFromInputQ(STQ* pTq, STqHandle* pHandle) {
- SMqDataBlkRsp rsp = {0};
+ SMqDataRsp rsp = {0};
// 1. guard and set status executing
- int8_t execStatus =
- atomic_val_compare_exchange_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE, TASK_STATUS__EXECUTING);
- if (execStatus == TASK_STATUS__IDLE) {
+ int8_t execStatus = atomic_val_compare_exchange_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE,
+ TASK_EXEC_STATUS__EXECUTING);
+ if (execStatus == TASK_EXEC_STATUS__IDLE) {
SStreamDataSubmit* pSubmit = NULL;
// 2. check processedVer
// 2.1. if not missed, get msg from queue
@@ -68,18 +69,18 @@ int32_t tqExecFromInputQ(STQ* pTq, STqHandle* pHandle) {
goto SEND_RSP;
}
// set exec status closing
- atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__CLOSING);
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__CLOSING);
// second run
if (tqLoopExecFromQueue(pTq, pHandle, &pSubmit, &rsp) == 0) {
goto SEND_RSP;
}
// set exec status idle
- atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE);
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE);
}
SEND_RSP:
// 4. if get result
// 4.1 set exec input status blocked and exec status idle
- atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE);
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE);
// 4.2 rpc send
rsp.rspOffset = pHandle->pushHandle.processedVer;
/*if (tqSendPollRsp(pTq, pMsg, pReq, &rsp) < 0) {*/
@@ -150,7 +151,7 @@ int32_t tqEnqueueAll(STQ* pTq, SSubmitReq* pReq) {
continue;
}
int8_t execStatus = atomic_load_8(&pHandle->pushHandle.execStatus);
- if (execStatus == TASK_STATUS__IDLE || execStatus == TASK_STATUS__CLOSING) {
+ if (execStatus == TASK_EXEC_STATUS__IDLE || execStatus == TASK_EXEC_STATUS__CLOSING) {
tqSendExecReq(pTq, pHandle);
}
}
@@ -175,13 +176,13 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_
taosWLockLatch(&pHandle->pushHandle.lock);
- SMqDataBlkRsp rsp = {0};
+ SMqDataRsp rsp = {0};
rsp.reqOffset = pHandle->pushHandle.reqOffset;
rsp.blockData = taosArrayInit(0, sizeof(void*));
rsp.blockDataLen = taosArrayInit(0, sizeof(int32_t));
if (msgType == TDMT_VND_SUBMIT) {
- tqDataExec(pTq, &pHandle->execHandle, pReq, &rsp, workerId);
+ tqLogScanExec(pTq, &pHandle->execHandle, pReq, &rsp, workerId);
} else {
// TODO
ASSERT(0);
@@ -222,7 +223,7 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_
memset(&pHandle->pushHandle.rpcInfo, 0, sizeof(SRpcHandleInfo));
taosWUnLockLatch(&pHandle->pushHandle.lock);
- tqDebug("vg %d offset %ld from consumer %ld (epoch %d) send rsp, block num: %d, reqOffset: %ld, rspOffset: %ld",
+ tqDebug("vgId:%d offset %" PRId64 " from consumer:%" PRId64 ", (epoch %d) send rsp, block num: %d, reqOffset:%" PRId64 ", rspOffset:%" PRId64,
TD_VID(pTq->pVnode), fetchOffset, pHandle->pushHandle.consumerId, pHandle->pushHandle.epoch, rsp.blockNum,
rsp.reqOffset, rsp.rspOffset);
@@ -233,6 +234,7 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_
return 0;
}
+#endif
int tqPushMsg(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver) {
if (msgType == TDMT_VND_SUBMIT) {
diff --git a/source/dnode/vnode/src/tq/tqRead.c b/source/dnode/vnode/src/tq/tqRead.c
index 0c38d6442b623ff56b0d67c771c800b83b570bb8..a7ad935caa12c5ee794784c48bfc09bcd3a59dbc 100644
--- a/source/dnode/vnode/src/tq/tqRead.c
+++ b/source/dnode/vnode/src/tq/tqRead.c
@@ -15,22 +15,22 @@
#include "tq.h"
-int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalHead** ppHeadWithCkSum) {
+int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** ppCkHead) {
int32_t code = 0;
taosThreadMutexLock(&pHandle->pWalReader->mutex);
int64_t offset = *fetchOffset;
while (1) {
- if (walFetchHead(pHandle->pWalReader, offset, *ppHeadWithCkSum) < 0) {
- tqDebug("tmq poll: consumer %ld (epoch %d) vg %d offset %ld, no more log to return", pHandle->consumerId,
- pHandle->epoch, TD_VID(pTq->pVnode), offset);
+ if (walFetchHead(pHandle->pWalReader, offset, *ppCkHead) < 0) {
+ tqDebug("tmq poll: consumer:%" PRId64 ", (epoch %d) vgId:%d offset %" PRId64 ", no more log to return",
+ pHandle->consumerId, pHandle->epoch, TD_VID(pTq->pVnode), offset);
*fetchOffset = offset - 1;
code = -1;
goto END;
}
- if ((*ppHeadWithCkSum)->head.msgType == TDMT_VND_SUBMIT) {
- code = walFetchBody(pHandle->pWalReader, ppHeadWithCkSum);
+ if ((*ppCkHead)->head.msgType == TDMT_VND_SUBMIT) {
+ code = walFetchBody(pHandle->pWalReader, ppCkHead);
if (code < 0) {
ASSERT(0);
@@ -42,7 +42,23 @@ int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalHead*
code = 0;
goto END;
} else {
- code = walSkipFetchBody(pHandle->pWalReader, *ppHeadWithCkSum);
+ if (pHandle->fetchMeta) {
+ SWalCont* pHead = &((*ppCkHead)->head);
+ if (IS_META_MSG(pHead->msgType)) {
+ code = walFetchBody(pHandle->pWalReader, ppCkHead);
+
+ if (code < 0) {
+ ASSERT(0);
+ *fetchOffset = offset;
+ code = -1;
+ goto END;
+ }
+ *fetchOffset = offset;
+ code = 0;
+ goto END;
+ }
+ }
+ code = walSkipFetchBody(pHandle->pWalReader, *ppCkHead);
if (code < 0) {
ASSERT(0);
*fetchOffset = offset;
@@ -57,57 +73,132 @@ END:
return code;
}
-STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta) {
- STqReadHandle* pReadHandle = taosMemoryMalloc(sizeof(STqReadHandle));
- if (pReadHandle == NULL) {
+STqReader* tqOpenReader(SVnode* pVnode) {
+ STqReader* pReader = taosMemoryMalloc(sizeof(STqReader));
+ if (pReader == NULL) {
+ return NULL;
+ }
+
+ pReader->pWalReader = walOpenReader(pVnode->pWal, NULL);
+ if (pReader->pWalReader == NULL) {
return NULL;
}
- pReadHandle->pVnodeMeta = pMeta;
- pReadHandle->pMsg = NULL;
- pReadHandle->ver = -1;
- pReadHandle->pColIdList = NULL;
- pReadHandle->cachedSchemaVer = -1;
- pReadHandle->cachedSchemaSuid = -1;
- pReadHandle->pSchema = NULL;
- pReadHandle->pSchemaWrapper = NULL;
- pReadHandle->tbIdHash = NULL;
- return pReadHandle;
+
+ pReader->pVnodeMeta = pVnode->pMeta;
+ pReader->pMsg = NULL;
+ pReader->ver = -1;
+ pReader->pColIdList = NULL;
+ pReader->cachedSchemaVer = 0;
+ pReader->cachedSchemaSuid = 0;
+ pReader->pSchema = NULL;
+ pReader->pSchemaWrapper = NULL;
+ pReader->tbIdHash = NULL;
+ return pReader;
+}
+
+void tqCloseReader(STqReader* pReader) {
+ // close wal reader
+ // free cached schema
+ // free hash
+ taosMemoryFree(pReader);
+}
+
+int32_t tqSeekVer(STqReader* pReader, int64_t ver) {
+ if (walReadSeekVer(pReader->pWalReader, ver) < 0) {
+ ASSERT(pReader->pWalReader->curInvalid);
+ ASSERT(pReader->pWalReader->curVersion == ver);
+ return -1;
+ }
+ ASSERT(pReader->pWalReader->curVersion == ver);
+ return 0;
+}
+
+int32_t tqNextBlock(STqReader* pReader, SFetchRet* ret) {
+ bool fromProcessedMsg = pReader->pMsg != NULL;
+
+ while (1) {
+ if (!fromProcessedMsg) {
+ if (walNextValidMsg(pReader->pWalReader) < 0) {
+ pReader->ver = pReader->pWalReader->curVersion - pReader->pWalReader->curInvalid;
+ ret->offset.type = TMQ_OFFSET__LOG;
+ ret->offset.version = pReader->ver;
+ ret->fetchType = FETCH_TYPE__NONE;
+ ASSERT(ret->offset.version >= 0);
+ return -1;
+ }
+ void* body = pReader->pWalReader->pHead->head.body;
+ if (pReader->pWalReader->pHead->head.msgType != TDMT_VND_SUBMIT) {
+ // TODO do filter
+ ret->fetchType = FETCH_TYPE__META;
+ ret->meta = pReader->pWalReader->pHead->head.body;
+ return 0;
+ } else {
+ tqReaderSetDataMsg(pReader, body, pReader->pWalReader->pHead->head.version);
+ }
+ }
+
+ while (tqNextDataBlock(pReader)) {
+ // TODO mem free
+ memset(&ret->data, 0, sizeof(SSDataBlock));
+ int32_t code = tqRetrieveDataBlock(&ret->data, pReader);
+ if (code != 0 || ret->data.info.rows == 0) {
+ ASSERT(0);
+ continue;
+ }
+ ret->fetchType = FETCH_TYPE__DATA;
+ return 0;
+ }
+
+ if (fromProcessedMsg) {
+ ret->offset.type = TMQ_OFFSET__LOG;
+ ret->offset.version = pReader->ver;
+ ASSERT(pReader->ver >= 0);
+ ret->fetchType = FETCH_TYPE__NONE;
+ return 0;
+ }
+ }
}
-int32_t tqReadHandleSetMsg(STqReadHandle* pReadHandle, SSubmitReq* pMsg, int64_t ver) {
- pReadHandle->pMsg = pMsg;
+int32_t tqReaderSetDataMsg(STqReader* pReader, SSubmitReq* pMsg, int64_t ver) {
+ pReader->pMsg = pMsg;
- if (tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter) < 0) return -1;
+ if (tInitSubmitMsgIter(pMsg, &pReader->msgIter) < 0) return -1;
while (true) {
- if (tGetSubmitMsgNext(&pReadHandle->msgIter, &pReadHandle->pBlock) < 0) return -1;
- if (pReadHandle->pBlock == NULL) break;
+ if (tGetSubmitMsgNext(&pReader->msgIter, &pReader->pBlock) < 0) return -1;
+ if (pReader->pBlock == NULL) break;
}
- if (tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter) < 0) return -1;
- pReadHandle->ver = ver;
- memset(&pReadHandle->blkIter, 0, sizeof(SSubmitBlkIter));
+ if (tInitSubmitMsgIter(pMsg, &pReader->msgIter) < 0) return -1;
+ pReader->ver = ver;
+ memset(&pReader->blkIter, 0, sizeof(SSubmitBlkIter));
return 0;
}
-bool tqNextDataBlock(STqReadHandle* pHandle) {
+bool tqNextDataBlock(STqReader* pReader) {
+ if (pReader->pMsg == NULL) return false;
while (1) {
- if (tGetSubmitMsgNext(&pHandle->msgIter, &pHandle->pBlock) < 0) {
+ if (tGetSubmitMsgNext(&pReader->msgIter, &pReader->pBlock) < 0) {
+ return false;
+ }
+ if (pReader->pBlock == NULL) {
+ pReader->pMsg = NULL;
return false;
}
- if (pHandle->pBlock == NULL) return false;
- if (pHandle->tbIdHash == NULL) {
+ if (pReader->tbIdHash == NULL) {
return true;
}
- void* ret = taosHashGet(pHandle->tbIdHash, &pHandle->msgIter.uid, sizeof(int64_t));
+ void* ret = taosHashGet(pReader->tbIdHash, &pReader->msgIter.uid, sizeof(int64_t));
+ /*tqDebug("search uid %" PRId64, pHandle->msgIter.uid);*/
if (ret != NULL) {
+ /*tqDebug("find uid %" PRId64, pHandle->msgIter.uid);*/
return true;
}
}
return false;
}
-bool tqNextDataBlockFilterOut(STqReadHandle* pHandle, SHashObj* filterOutUids) {
+bool tqNextDataBlockFilterOut(STqReader* pHandle, SHashObj* filterOutUids) {
while (1) {
if (tGetSubmitMsgNext(&pHandle->msgIter, &pHandle->pBlock) < 0) {
return false;
@@ -123,61 +214,48 @@ bool tqNextDataBlockFilterOut(STqReadHandle* pHandle, SHashObj* filterOutUids) {
return false;
}
-int32_t tqRetrieveDataBlock(SArray** ppCols, STqReadHandle* pHandle, uint64_t* pGroupId, uint64_t* pUid,
- int32_t* pNumOfRows, int16_t* pNumOfCols) {
- *pUid = 0;
-
- // TODO set to real sversion
- /*int32_t sversion = 1;*/
- int32_t sversion = htonl(pHandle->pBlock->sversion);
- if (pHandle->cachedSchemaSuid == 0 || pHandle->cachedSchemaVer != sversion ||
- pHandle->cachedSchemaSuid != pHandle->msgIter.suid) {
- pHandle->pSchema = metaGetTbTSchema(pHandle->pVnodeMeta, pHandle->msgIter.uid, sversion);
- if (pHandle->pSchema == NULL) {
- tqWarn("cannot found tsschema for table: uid: %ld (suid: %ld), version %d, possibly dropped table",
- pHandle->msgIter.uid, pHandle->msgIter.suid, pHandle->cachedSchemaVer);
+int32_t tqRetrieveDataBlock(SSDataBlock* pBlock, STqReader* pReader) {
+ // TODO: cache multiple schema
+ int32_t sversion = htonl(pReader->pBlock->sversion);
+ if (pReader->cachedSchemaSuid == 0 || pReader->cachedSchemaVer != sversion ||
+ pReader->cachedSchemaSuid != pReader->msgIter.suid) {
+ if (pReader->pSchema) taosMemoryFree(pReader->pSchema);
+ pReader->pSchema = metaGetTbTSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion);
+ if (pReader->pSchema == NULL) {
+ tqWarn("cannot found tsschema for table: uid:%" PRId64 " (suid:%" PRId64 "), version %d, possibly dropped table",
+ pReader->msgIter.uid, pReader->msgIter.suid, pReader->cachedSchemaVer);
/*ASSERT(0);*/
terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND;
return -1;
}
- // this interface use suid instead of uid
- pHandle->pSchemaWrapper = metaGetTableSchema(pHandle->pVnodeMeta, pHandle->msgIter.uid, sversion, true);
- if (pHandle->pSchemaWrapper == NULL) {
- tqWarn("cannot found schema wrapper for table: suid: %ld, version %d, possibly dropped table",
- pHandle->msgIter.uid, pHandle->cachedSchemaVer);
+ if (pReader->pSchemaWrapper) tDeleteSSchemaWrapper(pReader->pSchemaWrapper);
+ pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion, true);
+ if (pReader->pSchemaWrapper == NULL) {
+ tqWarn("cannot found schema wrapper for table: suid:%" PRId64 ", version %d, possibly dropped table",
+ pReader->msgIter.uid, pReader->cachedSchemaVer);
/*ASSERT(0);*/
terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND;
return -1;
}
- pHandle->cachedSchemaVer = sversion;
- pHandle->cachedSchemaSuid = pHandle->msgIter.suid;
+ pReader->cachedSchemaVer = sversion;
+ pReader->cachedSchemaSuid = pReader->msgIter.suid;
}
- STSchema* pTschema = pHandle->pSchema;
- SSchemaWrapper* pSchemaWrapper = pHandle->pSchemaWrapper;
+ STSchema* pTschema = pReader->pSchema;
+ SSchemaWrapper* pSchemaWrapper = pReader->pSchemaWrapper;
- *pNumOfRows = pHandle->msgIter.numOfRows;
- int32_t colNumNeed = taosArrayGetSize(pHandle->pColIdList);
+ int32_t colNumNeed = taosArrayGetSize(pReader->pColIdList);
if (colNumNeed == 0) {
- *ppCols = taosArrayInit(pSchemaWrapper->nCols, sizeof(SColumnInfoData));
- if (*ppCols == NULL) {
- return -1;
- }
-
int32_t colMeta = 0;
while (colMeta < pSchemaWrapper->nCols) {
SSchema* pColSchema = &pSchemaWrapper->pSchema[colMeta];
- SColumnInfoData colInfo = {0};
- colInfo.info.bytes = pColSchema->bytes;
- colInfo.info.colId = pColSchema->colId;
- colInfo.info.type = pColSchema->type;
-
- if (colInfoDataEnsureCapacity(&colInfo, 0, *pNumOfRows) < 0) {
+ SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId);
+ int32_t code = blockDataAppendColInfo(pBlock, &colInfo);
+ if (code != TSDB_CODE_SUCCESS) {
goto FAIL;
}
- taosArrayPush(*ppCols, &colInfo);
colMeta++;
}
} else {
@@ -185,75 +263,69 @@ int32_t tqRetrieveDataBlock(SArray** ppCols, STqReadHandle* pHandle, uint64_t* p
colNumNeed = pSchemaWrapper->nCols;
}
- *ppCols = taosArrayInit(colNumNeed, sizeof(SColumnInfoData));
- if (*ppCols == NULL) {
- return -1;
- }
-
int32_t colMeta = 0;
int32_t colNeed = 0;
while (colMeta < pSchemaWrapper->nCols && colNeed < colNumNeed) {
SSchema* pColSchema = &pSchemaWrapper->pSchema[colMeta];
col_id_t colIdSchema = pColSchema->colId;
- col_id_t colIdNeed = *(col_id_t*)taosArrayGet(pHandle->pColIdList, colNeed);
+ col_id_t colIdNeed = *(col_id_t*)taosArrayGet(pReader->pColIdList, colNeed);
if (colIdSchema < colIdNeed) {
colMeta++;
} else if (colIdSchema > colIdNeed) {
colNeed++;
} else {
- SColumnInfoData colInfo = {0};
- colInfo.info.bytes = pColSchema->bytes;
- colInfo.info.colId = pColSchema->colId;
- colInfo.info.type = pColSchema->type;
-
- if (colInfoDataEnsureCapacity(&colInfo, 0, *pNumOfRows) < 0) {
+ SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId);
+ int32_t code = blockDataAppendColInfo(pBlock, &colInfo);
+ if (code != TSDB_CODE_SUCCESS) {
goto FAIL;
}
- taosArrayPush(*ppCols, &colInfo);
colMeta++;
colNeed++;
}
}
}
- int32_t colActual = taosArrayGetSize(*ppCols);
- *pNumOfCols = colActual;
+ if (blockDataEnsureCapacity(pBlock, pReader->msgIter.numOfRows) < 0) {
+ goto FAIL;
+ }
- // TODO in stream shuffle case, fetch groupId
- *pGroupId = 0;
+ int32_t colActual = blockDataGetNumOfCols(pBlock);
STSRowIter iter = {0};
tdSTSRowIterInit(&iter, pTschema);
STSRow* row;
int32_t curRow = 0;
- tInitSubmitBlkIter(&pHandle->msgIter, pHandle->pBlock, &pHandle->blkIter);
- *pUid = pHandle->msgIter.uid; // set the uid of table for submit block
+ tInitSubmitBlkIter(&pReader->msgIter, pReader->pBlock, &pReader->blkIter);
- while ((row = tGetSubmitBlkNext(&pHandle->blkIter)) != NULL) {
+ pBlock->info.uid = pReader->msgIter.uid;
+ pBlock->info.rows = pReader->msgIter.numOfRows;
+
+ while ((row = tGetSubmitBlkNext(&pReader->blkIter)) != NULL) {
tdSTSRowIterReset(&iter, row);
// get all wanted col of that block
for (int32_t i = 0; i < colActual; i++) {
- SColumnInfoData* pColData = taosArrayGet(*ppCols, i);
+ SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
SCellVal sVal = {0};
if (!tdSTSRowIterNext(&iter, pColData->info.colId, pColData->info.type, &sVal)) {
break;
}
- if (colDataAppend(pColData, curRow, sVal.val, sVal.valType == TD_VTYPE_NULL) < 0) {
+ if (colDataAppend(pColData, curRow, sVal.val, sVal.valType != TD_VTYPE_NORM) < 0) {
goto FAIL;
}
}
curRow++;
}
return 0;
+
FAIL:
- if (*ppCols) taosArrayDestroy(*ppCols);
+ blockDataFreeRes(pBlock);
return -1;
}
-void tqReadHandleSetColIdList(STqReadHandle* pReadHandle, SArray* pColIdList) { pReadHandle->pColIdList = pColIdList; }
+void tqReaderSetColIdList(STqReader* pReadHandle, SArray* pColIdList) { pReadHandle->pColIdList = pColIdList; }
-int tqReadHandleSetTbUidList(STqReadHandle* pHandle, const SArray* tbUidList) {
+int tqReaderSetTbUidList(STqReader* pHandle, const SArray* tbUidList) {
if (pHandle->tbIdHash) {
taosHashClear(pHandle->tbIdHash);
}
@@ -272,7 +344,7 @@ int tqReadHandleSetTbUidList(STqReadHandle* pHandle, const SArray* tbUidList) {
return 0;
}
-int tqReadHandleAddTbUidList(STqReadHandle* pHandle, const SArray* tbUidList) {
+int tqReaderAddTbUidList(STqReader* pHandle, const SArray* tbUidList) {
if (pHandle->tbIdHash == NULL) {
pHandle->tbIdHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
if (pHandle->tbIdHash == NULL) {
@@ -289,7 +361,7 @@ int tqReadHandleAddTbUidList(STqReadHandle* pHandle, const SArray* tbUidList) {
return 0;
}
-int tqReadHandleRemoveTbUidList(STqReadHandle* pHandle, const SArray* tbUidList) {
+int tqReaderRemoveTbUidList(STqReader* pHandle, const SArray* tbUidList) {
ASSERT(pHandle->tbIdHash != NULL);
for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) {
@@ -326,8 +398,8 @@ int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) {
while (1) {
pIter = taosHashIterate(pTq->pStreamTasks, pIter);
if (pIter == NULL) break;
- SStreamTask* pTask = (SStreamTask*)pIter;
- if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
+ SStreamTask* pTask = *(SStreamTask**)pIter;
+ if (pTask->isDataScan) {
int32_t code = qUpdateQualifiedTableId(pTask->exec.executor, tbUidList, isAdd);
ASSERT(code == 0);
}
diff --git a/source/dnode/vnode/src/tq/tqSink.c b/source/dnode/vnode/src/tq/tqSink.c
index b628f0dde5347b2a482bb618c77017c1753a60bf..25615f8d5cc93e962fb8e61798f748cb75d9e0fd 100644
--- a/source/dnode/vnode/src/tq/tqSink.c
+++ b/source/dnode/vnode/src/tq/tqSink.c
@@ -16,59 +16,90 @@
#include "tq.h"
SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, bool createTb, int64_t suid,
- const char* stbFullName, int32_t vgId) {
+ const char* stbFullName, int32_t vgId) {
SSubmitReq* ret = NULL;
+ SArray* schemaReqs = NULL;
+ SArray* schemaReqSz = NULL;
SArray* tagArray = taosArrayInit(1, sizeof(STagVal));
if (!tagArray) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
- // cal size
- int32_t cap = sizeof(SSubmitReq);
int32_t sz = taosArrayGetSize(pBlocks);
- for (int32_t i = 0; i < sz; i++) {
- SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i);
- int32_t rows = pDataBlock->info.rows;
- // TODO min
- int32_t rowSize = pDataBlock->info.rowSize;
- int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema);
- int32_t schemaLen = 0;
-
- if (createTb) {
- SVCreateTbReq createTbReq = {0};
- char* cname = buildCtbNameByGroupId(stbFullName, pDataBlock->info.groupId);
- createTbReq.name = cname;
- createTbReq.flags = 0;
- createTbReq.type = TSDB_CHILD_TABLE;
- createTbReq.ctb.suid = suid;
- STagVal tagVal = {
- .cid = pDataBlock->info.numOfCols + 1,
- .type = TSDB_DATA_TYPE_UBIGINT,
- .i64 = (int64_t)pDataBlock->info.groupId,
+ if (createTb) {
+ schemaReqs = taosArrayInit(sz, sizeof(void*));
+ schemaReqSz = taosArrayInit(sz, sizeof(int32_t));
+ for (int32_t i = 0; i < sz; i++) {
+ SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i);
+ STagVal tagVal = {
+ .cid = taosArrayGetSize(pDataBlock->pDataBlock) + 1,
+ .type = TSDB_DATA_TYPE_UBIGINT,
+ .i64 = (int64_t)pDataBlock->info.groupId,
};
STag* pTag = NULL;
taosArrayClear(tagArray);
taosArrayPush(tagArray, &tagVal);
tTagNew(tagArray, 1, false, &pTag);
if (pTag == NULL) {
- tdDestroySVCreateTbReq(&createTbReq);
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
taosArrayDestroy(tagArray);
return NULL;
}
+
+ SVCreateTbReq createTbReq = {0};
+ createTbReq.name = buildCtbNameByGroupId(stbFullName, pDataBlock->info.groupId);
+ createTbReq.ctb.name = strdup(stbFullName);
+ createTbReq.flags = 0;
+ createTbReq.type = TSDB_CHILD_TABLE;
+ createTbReq.ctb.suid = suid;
createTbReq.ctb.pTag = (uint8_t*)pTag;
int32_t code;
+ int32_t schemaLen;
tEncodeSize(tEncodeSVCreateTbReq, &createTbReq, schemaLen, code);
-
- tdDestroySVCreateTbReq(&createTbReq);
if (code < 0) {
+ tdDestroySVCreateTbReq(&createTbReq);
taosArrayDestroy(tagArray);
+ taosMemoryFreeClear(ret);
+ return NULL;
+ }
+
+ void* schemaStr = taosMemoryMalloc(schemaLen);
+ if (schemaStr == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return NULL;
+ }
+ taosArrayPush(schemaReqs, &schemaStr);
+ taosArrayPush(schemaReqSz, &schemaLen);
+
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, schemaStr, schemaLen);
+ code = tEncodeSVCreateTbReq(&encoder, &createTbReq);
+ if (code < 0) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
+ tEncoderClear(&encoder);
+ tdDestroySVCreateTbReq(&createTbReq);
}
+ }
+ taosArrayDestroy(tagArray);
+
+ // cal size
+ int32_t cap = sizeof(SSubmitReq);
+ for (int32_t i = 0; i < sz; i++) {
+ SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i);
+ int32_t rows = pDataBlock->info.rows;
+ // TODO min
+ int32_t rowSize = pDataBlock->info.rowSize;
+ int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema);
+ int32_t schemaLen = 0;
+ if (createTb) {
+ schemaLen = *(int32_t*)taosArrayGet(schemaReqSz, i);
+ }
cap += sizeof(SSubmitBlk) + schemaLen + rows * maxLen;
}
@@ -80,11 +111,10 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
ret->length = sizeof(SSubmitReq);
ret->numOfBlocks = htonl(sz);
- void* submitBlk = POINTER_SHIFT(ret, sizeof(SSubmitReq));
+ SSubmitBlk* blkHead = POINTER_SHIFT(ret, sizeof(SSubmitReq));
for (int32_t i = 0; i < sz; i++) {
SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i);
- SSubmitBlk* blkHead = submitBlk;
blkHead->numOfRows = htons(pDataBlock->info.rows);
blkHead->sversion = htonl(pTSchema->version);
// TODO
@@ -93,63 +123,20 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
blkHead->uid = 0;
int32_t rows = pDataBlock->info.rows;
- /*int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema);*/
- /*blkHead->dataLen = htonl(rows * maxLen);*/
- blkHead->dataLen = 0;
- void* blockData = POINTER_SHIFT(submitBlk, sizeof(SSubmitBlk));
+ int32_t dataLen = 0;
+
+ void* blkSchema = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk));
int32_t schemaLen = 0;
if (createTb) {
- SVCreateTbReq createTbReq = {0};
- char* cname = buildCtbNameByGroupId(stbFullName, pDataBlock->info.groupId);
- createTbReq.name = cname;
- createTbReq.flags = 0;
- createTbReq.type = TSDB_CHILD_TABLE;
- createTbReq.ctb.suid = suid;
-
- STagVal tagVal = {
- .cid = pDataBlock->info.numOfCols + 1,
- .type = TSDB_DATA_TYPE_UBIGINT,
- .i64 = (int64_t)pDataBlock->info.groupId,
- };
- taosArrayClear(tagArray);
- taosArrayPush(tagArray, &tagVal);
- STag* pTag = NULL;
- tTagNew(tagArray, 1, false, &pTag);
- if (pTag == NULL) {
- tdDestroySVCreateTbReq(&createTbReq);
- taosArrayDestroy(tagArray);
- taosMemoryFreeClear(ret);
- return NULL;
- }
- createTbReq.ctb.pTag = (uint8_t*)pTag;
-
- int32_t code;
- tEncodeSize(tEncodeSVCreateTbReq, &createTbReq, schemaLen, code);
- if (code < 0) {
- tdDestroySVCreateTbReq(&createTbReq);
- taosArrayDestroy(tagArray);
- taosMemoryFreeClear(ret);
- return NULL;
- }
-
- SEncoder encoder = {0};
- tEncoderInit(&encoder, blockData, schemaLen);
- code = tEncodeSVCreateTbReq(&encoder, &createTbReq);
- tEncoderClear(&encoder);
- tdDestroySVCreateTbReq(&createTbReq);
-
- if (code < 0) {
- taosArrayDestroy(tagArray);
- taosMemoryFreeClear(ret);
- return NULL;
- }
+ schemaLen = *(int32_t*)taosArrayGet(schemaReqSz, i);
+ void* schemaStr = taosArrayGetP(schemaReqs, i);
+ memcpy(blkSchema, schemaStr, schemaLen);
}
blkHead->schemaLen = htonl(schemaLen);
- STSRow* rowData = POINTER_SHIFT(blockData, schemaLen);
-
+ STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen);
for (int32_t j = 0; j < rows; j++) {
SRowBuilder rb = {0};
tdSRowInit(&rb, pTSchema->version);
@@ -168,18 +155,19 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
}
int32_t rowLen = TD_ROW_LEN(rowData);
rowData = POINTER_SHIFT(rowData, rowLen);
- blkHead->dataLen += rowLen;
+ dataLen += rowLen;
}
- int32_t dataLen = blkHead->dataLen;
blkHead->dataLen = htonl(dataLen);
ret->length += sizeof(SSubmitBlk) + schemaLen + dataLen;
- blkHead = POINTER_SHIFT(blkHead, schemaLen + dataLen);
- /*submitBlk = blkHead;*/
+ blkHead = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk) + schemaLen + dataLen);
}
ret->length = htonl(ret->length);
- taosArrayDestroy(tagArray);
+
+ if (schemaReqs) taosArrayDestroyP(schemaReqs, taosMemoryFree);
+ taosArrayDestroy(schemaReqSz);
+
return ret;
}
@@ -198,5 +186,7 @@ void tqTableSink(SStreamTask* pTask, void* vnode, int64_t ver, void* data) {
.contLen = ntohl(pReq->length),
};
- ASSERT(tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) == 0);
+ if (tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) != 0) {
+ tqDebug("failed to put into write-queue since %s", terrstr());
+ }
}
diff --git a/source/dnode/vnode/src/tsdb/tsdbCache.c b/source/dnode/vnode/src/tsdb/tsdbCache.c
new file mode 100644
index 0000000000000000000000000000000000000000..605f4bf3d59bef465b523ecccf6114ad11f24fef
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbCache.c
@@ -0,0 +1,1760 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdb.h"
+
+typedef struct {
+ TSKEY ts;
+ SColVal colVal;
+} SLastCol;
+
+int32_t tsdbOpenCache(STsdb *pTsdb) {
+ int32_t code = 0;
+ SLRUCache *pCache = NULL;
+ size_t cfgCapacity = pTsdb->pVnode->config.cacheLastSize * 1024 * 1024;
+
+ pCache = taosLRUCacheInit(cfgCapacity, -1, .5);
+ if (pCache == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ taosLRUCacheSetStrictCapacity(pCache, true);
+
+_err:
+ pTsdb->lruCache = pCache;
+ return code;
+}
+
+void tsdbCloseCache(SLRUCache *pCache) {
+ if (pCache) {
+ taosLRUCacheEraseUnrefEntries(pCache);
+
+ taosLRUCacheCleanup(pCache);
+ }
+}
+
+static void getTableCacheKeyS(tb_uid_t uid, const char *cacheType, char *key, int *len) {
+ snprintf(key, 30, "%" PRIi64 "%s", uid, cacheType);
+ *len = strlen(key);
+}
+
+static void getTableCacheKey(tb_uid_t uid, int cacheType, char *key, int *len) {
+ if (cacheType == 0) { // last_row
+ *(uint64_t *)key = (uint64_t)uid;
+ } else { // last
+ *(uint64_t *)key = ((uint64_t)uid) | 0x8000000000000000;
+ }
+
+ *len = sizeof(uint64_t);
+}
+
+static void deleteTableCacheLastrow(const void *key, size_t keyLen, void *value) { taosMemoryFree(value); }
+
+static void deleteTableCacheLast(const void *key, size_t keyLen, void *value) { taosArrayDestroy(value); }
+
+int32_t tsdbCacheDeleteLastrow(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) {
+ int32_t code = 0;
+
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "lr", key, &keyLen);
+ getTableCacheKey(uid, 0, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ STSRow *pRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ if (pRow->ts <= eKey) {
+ taosLRUCacheRelease(pCache, h, true);
+ } else {
+ taosLRUCacheRelease(pCache, h, false);
+ }
+
+ // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen);
+ }
+
+ return code;
+}
+
+int32_t tsdbCacheDeleteLast(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) {
+ int32_t code = 0;
+
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "l", key, &keyLen);
+ getTableCacheKey(uid, 1, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ SArray *pLast = (SArray *)taosLRUCacheValue(pCache, h);
+ bool invalidate = false;
+ int16_t nCol = taosArrayGetSize(pLast);
+
+ for (int16_t iCol = 0; iCol < nCol; ++iCol) {
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pLast, iCol);
+ if (eKey >= tTsVal->ts) {
+ invalidate = true;
+ break;
+ }
+ }
+
+ if (invalidate) {
+ taosLRUCacheRelease(pCache, h, true);
+ } else {
+ taosLRUCacheRelease(pCache, h, false);
+ }
+ // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen);
+ }
+
+ return code;
+}
+
+int32_t tsdbCacheDelete(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) {
+ int32_t code = 0;
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "lr", key, &keyLen);
+ getTableCacheKey(uid, 0, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ STSRow *pRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ if (pRow->ts <= eKey) {
+ taosLRUCacheRelease(pCache, h, true);
+ } else {
+ taosLRUCacheRelease(pCache, h, false);
+ }
+
+ // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen);
+ }
+
+ // getTableCacheKey(uid, "l", key, &keyLen);
+ getTableCacheKey(uid, 1, key, &keyLen);
+ h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ SArray *pLast = (SArray *)taosLRUCacheValue(pCache, h);
+ bool invalidate = false;
+ int16_t nCol = taosArrayGetSize(pLast);
+
+ for (int16_t iCol = 0; iCol < nCol; ++iCol) {
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pLast, iCol);
+ if (eKey >= tTsVal->ts) {
+ invalidate = true;
+ break;
+ }
+ }
+
+ if (invalidate) {
+ taosLRUCacheRelease(pCache, h, true);
+ } else {
+ taosLRUCacheRelease(pCache, h, false);
+ }
+ // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen);
+ }
+
+ return code;
+}
+
+int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, STSRow *row, bool dup) {
+ int32_t code = 0;
+ STSRow *cacheRow = NULL;
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "lr", key, &keyLen);
+ getTableCacheKey(uid, 0, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ cacheRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ if (row->ts >= cacheRow->ts) {
+ if (row->ts == cacheRow->ts) {
+ STSRow *mergedRow;
+ SRowMerger merger = {0};
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+
+ tRowMergerInit(&merger, &tsdbRowFromTSRow(0, cacheRow), pTSchema);
+
+ tRowMerge(&merger, &tsdbRowFromTSRow(1, row));
+
+ tRowMergerGetRow(&merger, &mergedRow);
+ tRowMergerClear(&merger);
+
+ taosMemoryFreeClear(pTSchema);
+
+ row = mergedRow;
+ dup = false;
+ }
+
+ if (TD_ROW_LEN(row) <= TD_ROW_LEN(cacheRow)) {
+ tdRowCpy(cacheRow, row);
+ if (!dup) {
+ taosMemoryFree(row);
+ }
+
+ taosLRUCacheRelease(pCache, h, false);
+ } else {
+ taosLRUCacheRelease(pCache, h, true);
+ // tsdbCacheDeleteLastrow(pCache, uid, TSKEY_MAX);
+ if (dup) {
+ cacheRow = tdRowDup(row);
+ } else {
+ cacheRow = row;
+ }
+ _taos_lru_deleter_t deleter = deleteTableCacheLastrow;
+ LRUStatus status = taosLRUCacheInsert(pCache, key, keyLen, cacheRow, TD_ROW_LEN(cacheRow), deleter, NULL,
+ TAOS_LRU_PRIORITY_LOW);
+ if (status != TAOS_LRU_STATUS_OK) {
+ code = -1;
+ }
+ /* tsdbCacheInsertLastrow(pCache, uid, row, dup); */
+ }
+ }
+ } /*else {
+ if (dup) {
+ cacheRow = tdRowDup(row);
+ } else {
+ cacheRow = row;
+ }
+
+ _taos_lru_deleter_t deleter = deleteTableCacheLastrow;
+ LRUStatus status =
+ taosLRUCacheInsert(pCache, key, keyLen, cacheRow, TD_ROW_LEN(cacheRow), deleter, NULL, TAOS_LRU_PRIORITY_LOW);
+ if (status != TAOS_LRU_STATUS_OK) {
+ code = -1;
+ }
+ }*/
+
+ return code;
+}
+
+int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb *pTsdb) {
+ int32_t code = 0;
+ STSRow *cacheRow = NULL;
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // ((void)(row));
+
+ // getTableCacheKey(uid, "l", key, &keyLen);
+ getTableCacheKey(uid, 1, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+ TSKEY keyTs = row->ts;
+ bool invalidate = false;
+
+ SArray *pLast = (SArray *)taosLRUCacheValue(pCache, h);
+ int16_t nCol = taosArrayGetSize(pLast);
+ int16_t iCol = 0;
+
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pLast, iCol);
+ if (keyTs > tTsVal->ts) {
+ STColumn *pTColumn = &pTSchema->columns[0];
+ SColVal tColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = keyTs});
+
+ taosArraySet(pLast, iCol, &(SLastCol){.ts = keyTs, .colVal = tColVal});
+ }
+
+ for (++iCol; iCol < nCol; ++iCol) {
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pLast, iCol);
+ if (keyTs >= tTsVal->ts) {
+ SColVal *tColVal = &tTsVal->colVal;
+
+ SColVal colVal = {0};
+ tTSRowGetVal(row, pTSchema, iCol, &colVal);
+ if (colVal.isNone || colVal.isNull) {
+ if (keyTs == tTsVal->ts && !tColVal->isNone && !tColVal->isNull) {
+ invalidate = true;
+
+ break;
+ }
+ } else {
+ taosArraySet(pLast, iCol, &(SLastCol){.ts = keyTs, .colVal = colVal});
+ }
+ }
+ }
+
+ taosMemoryFreeClear(pTSchema);
+
+ taosLRUCacheRelease(pCache, h, invalidate);
+
+ // clear last cache anyway, lazy load when get last lookup
+ // taosLRUCacheRelease(pCache, h, true);
+ }
+
+ return code;
+}
+
+static tb_uid_t getTableSuidByUid(tb_uid_t uid, STsdb *pTsdb) {
+ tb_uid_t suid = 0;
+
+ SMetaReader mr = {0};
+ metaReaderInit(&mr, pTsdb->pVnode->pMeta, 0);
+ if (metaGetTableEntryByUid(&mr, uid) < 0) {
+ metaReaderClear(&mr); // table not esist
+ return 0;
+ }
+
+ if (mr.me.type == TSDB_CHILD_TABLE) {
+ suid = mr.me.ctbEntry.suid;
+ } else if (mr.me.type == TSDB_NORMAL_TABLE) {
+ suid = 0;
+ } else {
+ suid = 0;
+ }
+
+ metaReaderClear(&mr);
+
+ return suid;
+}
+
+static int32_t getTableDelDataFromDelIdx(SDelFReader *pDelReader, SDelIdx *pDelIdx, SArray *aDelData) {
+ int32_t code = 0;
+
+ // SMapData delDataMap;
+ // SDelData delData;
+
+ if (pDelIdx) {
+ // tMapDataReset(&delDataMap);
+
+ // code = tsdbReadDelData(pDelReader, pDelIdx, &delDataMap, NULL);
+ code = tsdbReadDelData(pDelReader, pDelIdx, aDelData, NULL);
+ if (code) goto _err;
+ /*
+ for (int32_t iDelData = 0; iDelData < delDataMap.nItem; ++iDelData) {
+ code = tMapDataGetItemByIdx(&delDataMap, iDelData, &delData, tGetDelData);
+ if (code) goto _err;
+
+ taosArrayPush(aDelData, &delData);
+ }
+ */
+ }
+
+_err:
+ return code;
+}
+
+static int32_t getTableDelDataFromTbData(STbData *pTbData, SArray *aDelData) {
+ int32_t code = 0;
+ SDelData *pDelData = pTbData ? pTbData->pHead : NULL;
+
+ for (; pDelData; pDelData = pDelData->pNext) {
+ taosArrayPush(aDelData, pDelData);
+ }
+
+ return code;
+}
+
+static int32_t getTableDelData(STbData *pMem, STbData *pIMem, SDelFReader *pDelReader, SDelIdx *pDelIdx,
+ SArray *aDelData) {
+ int32_t code = 0;
+
+ if (pMem) {
+ code = getTableDelDataFromTbData(pMem, aDelData);
+ if (code) goto _err;
+ }
+
+ if (pIMem) {
+ code = getTableDelDataFromTbData(pIMem, aDelData);
+ if (code) goto _err;
+ }
+
+ if (pDelIdx) {
+ code = getTableDelDataFromDelIdx(pDelReader, pDelIdx, aDelData);
+ if (code) goto _err;
+ }
+
+_err:
+ return code;
+}
+
+static int32_t getTableDelSkyline(STbData *pMem, STbData *pIMem, SDelFReader *pDelReader, SDelIdx *pDelIdx,
+ SArray *aSkyline) {
+ int32_t code = 0;
+ SArray *aDelData = NULL;
+
+ aDelData = taosArrayInit(32, sizeof(SDelData));
+ code = getTableDelData(pMem, pIMem, pDelReader, pDelIdx, aDelData);
+ if (code) goto _err;
+
+ size_t nDelData = taosArrayGetSize(aDelData);
+ if (nDelData > 0) {
+ code = tsdbBuildDeleteSkyline(aDelData, 0, (int32_t)(nDelData - 1), aSkyline);
+ if (code) goto _err;
+ }
+
+ if (aDelData) {
+ taosArrayDestroy(aDelData);
+ }
+_err:
+ return code;
+}
+
+static int32_t getTableDelIdx(SDelFReader *pDelFReader, tb_uid_t suid, tb_uid_t uid, SDelIdx *pDelIdx) {
+ int32_t code = 0;
+ SArray *pDelIdxArray = NULL;
+
+ // SMapData delIdxMap;
+ pDelIdxArray = taosArrayInit(32, sizeof(SDelIdx));
+ SDelIdx idx = {.suid = suid, .uid = uid};
+
+ // tMapDataReset(&delIdxMap);
+ // code = tsdbReadDelIdx(pDelFReader, &delIdxMap, NULL);
+ code = tsdbReadDelIdx(pDelFReader, pDelIdxArray, NULL);
+ if (code) goto _err;
+
+ // code = tMapDataSearch(&delIdxMap, &idx, tGetDelIdx, tCmprDelIdx, pDelIdx);
+ SDelIdx *pIdx = taosArraySearch(pDelIdxArray, &idx, tCmprDelIdx, TD_EQ);
+ if (code) goto _err;
+
+ *pDelIdx = *pIdx;
+
+ if (pDelIdxArray) {
+ taosArrayDestroy(pDelIdxArray);
+ }
+_err:
+ return code;
+}
+
+typedef enum SFSNEXTROWSTATES {
+ SFSNEXTROW_FS,
+ SFSNEXTROW_FILESET,
+ SFSNEXTROW_BLOCKDATA,
+ SFSNEXTROW_BLOCKROW
+} SFSNEXTROWSTATES;
+
+typedef struct SFSNextRowIter {
+ SFSNEXTROWSTATES state; // [input]
+ STsdb *pTsdb; // [input]
+ SBlockIdx *pBlockIdxExp; // [input]
+ int32_t nFileSet;
+ int32_t iFileSet;
+ SArray *aDFileSet;
+ SDataFReader *pDataFReader;
+ SArray *aBlockIdx;
+ // SMapData blockIdxMap;
+ // SBlockIdx blockIdx;
+ SBlockIdx *pBlockIdx;
+ SMapData blockMap;
+ int32_t nBlock;
+ int32_t iBlock;
+ SBlock block;
+ SBlockData blockData;
+ SBlockData *pBlockData;
+ int32_t nRow;
+ int32_t iRow;
+ TSDBROW row;
+} SFSNextRowIter;
+
+static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) {
+ SFSNextRowIter *state = (SFSNextRowIter *)iter;
+ int32_t code = 0;
+
+ switch (state->state) {
+ case SFSNEXTROW_FS:
+ state->aDFileSet = state->pTsdb->fs->cState->aDFileSet;
+ state->nFileSet = taosArrayGetSize(state->aDFileSet);
+ state->iFileSet = state->nFileSet;
+
+ state->pBlockData = NULL;
+
+ case SFSNEXTROW_FILESET: {
+ SDFileSet *pFileSet = NULL;
+ _next_fileset:
+ if (--state->iFileSet >= 0) {
+ pFileSet = (SDFileSet *)taosArrayGet(state->aDFileSet, state->iFileSet);
+ } else {
+ // tBlockDataClear(&state->blockData);
+ if (state->pBlockData) {
+ tBlockDataClear(state->pBlockData);
+ state->pBlockData = NULL;
+ }
+
+ *ppRow = NULL;
+ return code;
+ }
+
+ code = tsdbDataFReaderOpen(&state->pDataFReader, state->pTsdb, pFileSet);
+ if (code) goto _err;
+
+ // tMapDataReset(&state->blockIdxMap);
+ // code = tsdbReadBlockIdx(state->pDataFReader, &state->blockIdxMap, NULL);
+ if (!state->aBlockIdx) {
+ state->aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx));
+ } else {
+ taosArrayClear(state->aBlockIdx);
+ }
+ code = tsdbReadBlockIdx(state->pDataFReader, state->aBlockIdx, NULL);
+ if (code) goto _err;
+
+ /* if (state->pBlockIdx) { */
+ /* tBlockIdxReset(state->blockIdx); */
+ /* } */
+ /* tBlockIdxReset(state->blockIdx); */
+ /* code = tMapDataSearch(&state->blockIdxMap, state->pBlockIdxExp, tGetBlockIdx, tCmprBlockIdx,
+ * &state->blockIdx);
+ */
+ state->pBlockIdx = taosArraySearch(state->aBlockIdx, state->pBlockIdxExp, tCmprBlockIdx, TD_EQ);
+ if (code) goto _err;
+
+ if (!state->pBlockIdx) {
+ goto _next_fileset;
+ }
+
+ tMapDataReset(&state->blockMap);
+ code = tsdbReadBlock(state->pDataFReader, state->pBlockIdx, &state->blockMap, NULL);
+ /* code = tsdbReadBlock(state->pDataFReader, &state->blockIdx, &state->blockMap, NULL); */
+ if (code) goto _err;
+
+ state->nBlock = state->blockMap.nItem;
+ state->iBlock = state->nBlock - 1;
+
+ if (!state->pBlockData) {
+ state->pBlockData = &state->blockData;
+
+ tBlockDataInit(&state->blockData);
+ }
+ }
+ case SFSNEXTROW_BLOCKDATA:
+ if (state->iBlock >= 0) {
+ SBlock block = {0};
+
+ tBlockReset(&block);
+ // tBlockDataReset(&state->blockData);
+ tBlockDataReset(state->pBlockData);
+
+ tMapDataGetItemByIdx(&state->blockMap, state->iBlock, &block, tGetBlock);
+ /* code = tsdbReadBlockData(state->pDataFReader, &state->blockIdx, &block, &state->blockData, NULL, NULL); */
+ code = tsdbReadBlockData(state->pDataFReader, state->pBlockIdx, &block, state->pBlockData, NULL, NULL);
+ if (code) goto _err;
+
+ state->nRow = state->blockData.nRow;
+ state->iRow = state->nRow - 1;
+
+ state->state = SFSNEXTROW_BLOCKROW;
+ }
+ case SFSNEXTROW_BLOCKROW:
+ if (state->iRow >= 0) {
+ state->row = tsdbRowFromBlockData(state->pBlockData, state->iRow);
+ *ppRow = &state->row;
+
+ if (--state->iRow < 0) {
+ state->state = SFSNEXTROW_BLOCKDATA;
+ if (--state->iBlock < 0) {
+ tsdbDataFReaderClose(&state->pDataFReader);
+ state->pDataFReader = NULL;
+
+ if (state->aBlockIdx) {
+ taosArrayDestroy(state->aBlockIdx);
+ state->aBlockIdx = NULL;
+ }
+
+ state->state = SFSNEXTROW_FILESET;
+ }
+ }
+ }
+
+ return code;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+_err:
+ if (state->pDataFReader) {
+ tsdbDataFReaderClose(&state->pDataFReader);
+ state->pDataFReader = NULL;
+ }
+ if (state->aBlockIdx) {
+ taosArrayDestroy(state->aBlockIdx);
+ state->aBlockIdx = NULL;
+ }
+ if (state->pBlockData) {
+ // tBlockDataClear(&state->blockData);
+ tBlockDataClear(state->pBlockData);
+ state->pBlockData = NULL;
+ }
+
+ *ppRow = NULL;
+
+ return code;
+}
+
+int32_t clearNextRowFromFS(void *iter) {
+ int32_t code = 0;
+
+ SFSNextRowIter *state = (SFSNextRowIter *)iter;
+ if (!state) {
+ return code;
+ }
+
+ if (state->pDataFReader) {
+ tsdbDataFReaderClose(&state->pDataFReader);
+ state->pDataFReader = NULL;
+ }
+ if (state->aBlockIdx) {
+ taosArrayDestroy(state->aBlockIdx);
+ state->aBlockIdx = NULL;
+ }
+ if (state->pBlockData) {
+ // tBlockDataClear(&state->blockData);
+ tBlockDataClear(state->pBlockData);
+ state->pBlockData = NULL;
+ }
+
+ return code;
+}
+
+typedef enum SMEMNEXTROWSTATES {
+ SMEMNEXTROW_ENTER,
+ SMEMNEXTROW_NEXT,
+} SMEMNEXTROWSTATES;
+
+typedef struct SMemNextRowIter {
+ SMEMNEXTROWSTATES state;
+ STbData *pMem; // [input]
+ STbDataIter iter; // mem buffer skip list iterator
+ // bool iterOpened;
+ // TSDBROW *curRow;
+} SMemNextRowIter;
+
+static int32_t getNextRowFromMem(void *iter, TSDBROW **ppRow) {
+ // static int32_t getNextRowFromMem(void *iter, SArray *pRowArray) {
+ SMemNextRowIter *state = (SMemNextRowIter *)iter;
+ int32_t code = 0;
+ /*
+ if (!state->iterOpened) {
+ if (state->pMem != NULL) {
+ tsdbTbDataIterOpen(state->pMem, NULL, 1, &state->iter);
+
+ state->iterOpened = true;
+
+ TSDBROW *pMemRow = tsdbTbDataIterGet(&state->iter);
+ if (pMemRow) {
+ state->curRow = pMemRow;
+ } else {
+ return code;
+ }
+ } else {
+ return code;
+ }
+ }
+
+ taosArrayPush(pRowArray, state->curRow);
+ while (tsdbTbDataIterNext(&state->iter)) {
+ TSDBROW *row = tsdbTbDataIterGet(&state->iter);
+
+ if (TSDBROW_TS(row) < TSDBROW_TS(state->curRow)) {
+ state->curRow = row;
+ break;
+ } else {
+ taosArrayPush(pRowArray, row);
+ }
+ }
+
+ return code;
+ */
+ switch (state->state) {
+ case SMEMNEXTROW_ENTER: {
+ if (state->pMem != NULL) {
+ tsdbTbDataIterOpen(state->pMem, NULL, 1, &state->iter);
+
+ TSDBROW *pMemRow = tsdbTbDataIterGet(&state->iter);
+ if (pMemRow) {
+ *ppRow = pMemRow;
+ state->state = SMEMNEXTROW_NEXT;
+
+ return code;
+ }
+ }
+
+ *ppRow = NULL;
+
+ return code;
+ }
+ case SMEMNEXTROW_NEXT:
+ if (tsdbTbDataIterNext(&state->iter)) {
+ *ppRow = tsdbTbDataIterGet(&state->iter);
+
+ return code;
+ } else {
+ *ppRow = NULL;
+
+ return code;
+ }
+ default:
+ ASSERT(0);
+ break;
+ }
+
+_err:
+ *ppRow = NULL;
+ return code;
+}
+
+static int32_t tsRowFromTsdbRow(STSchema *pTSchema, TSDBROW *pRow, STSRow **ppRow) {
+ int32_t code = 0;
+
+ SColVal *pColVal = &(SColVal){0};
+
+ if (pRow->type == 0) {
+ *ppRow = tdRowDup(pRow->pTSRow);
+ } else {
+ SArray *pArray = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal));
+ if (pArray == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+ TSDBKEY key = TSDBROW_KEY(pRow);
+ STColumn *pTColumn = &pTSchema->columns[0];
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = key.ts});
+
+ if (taosArrayPush(pArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+ for (int16_t iCol = 1; iCol < pTSchema->numOfCols; iCol++) {
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+ if (taosArrayPush(pArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ }
+
+ code = tdSTSRowNew(pArray, pTSchema, ppRow);
+ if (code) goto _exit;
+ }
+
+_exit:
+ return code;
+}
+
+static bool tsdbKeyDeleted(TSDBKEY *key, SArray *pSkyline, int64_t *iSkyline) {
+ bool deleted = false;
+ while (*iSkyline > 0) {
+ TSDBKEY *pItemBack = (TSDBKEY *)taosArrayGet(pSkyline, *iSkyline);
+ TSDBKEY *pItemFront = (TSDBKEY *)taosArrayGet(pSkyline, *iSkyline - 1);
+
+ if (key->ts > pItemBack->ts) {
+ return false;
+ } else if (key->ts >= pItemFront->ts && key->ts <= pItemBack->ts) {
+ if ((key->version <= pItemFront->version || key->ts == pItemBack->ts && key->version <= pItemBack->version)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (*iSkyline > 1) {
+ --*iSkyline;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ return deleted;
+}
+
+typedef int32_t (*_next_row_fn_t)(void *iter, TSDBROW **ppRow);
+// typedef int32_t (*_next_row_fn_t)(void *iter, SArray *pRowArray);
+typedef int32_t (*_next_row_clear_fn_t)(void *iter);
+
+// typedef struct TsdbNextRowState {
+typedef struct {
+ TSDBROW *pRow;
+ bool stop;
+ bool next;
+ void *iter;
+ _next_row_fn_t nextRowFn;
+ _next_row_clear_fn_t nextRowClearFn;
+} TsdbNextRowState;
+
+typedef struct {
+ // STsdb *pTsdb;
+ SArray *pSkyline;
+ int64_t iSkyline;
+
+ SBlockIdx idx;
+ SMemNextRowIter memState;
+ SMemNextRowIter imemState;
+ SFSNextRowIter fsState;
+ TSDBROW memRow, imemRow, fsRow;
+
+ TsdbNextRowState input[3];
+} CacheNextRowIter;
+
+static int32_t nextRowIterOpen(CacheNextRowIter *pIter, tb_uid_t uid, STsdb *pTsdb) {
+ int code = 0;
+
+ tb_uid_t suid = getTableSuidByUid(uid, pTsdb);
+
+ STbData *pMem = NULL;
+ if (pTsdb->mem) {
+ tsdbGetTbDataFromMemTable(pTsdb->mem, suid, uid, &pMem);
+ }
+
+ STbData *pIMem = NULL;
+ if (pTsdb->imem) {
+ tsdbGetTbDataFromMemTable(pTsdb->imem, suid, uid, &pIMem);
+ }
+
+ pIter->pSkyline = taosArrayInit(32, sizeof(TSDBKEY));
+
+ SDelIdx delIdx;
+
+ SDelFile *pDelFile = tsdbFSStateGetDelFile(pTsdb->fs->cState);
+ if (pDelFile) {
+ SDelFReader *pDelFReader;
+
+ code = tsdbDelFReaderOpen(&pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) goto _err;
+
+ code = getTableDelIdx(pDelFReader, suid, uid, &delIdx);
+ if (code) goto _err;
+
+ code = getTableDelSkyline(pMem, pIMem, pDelFReader, &delIdx, pIter->pSkyline);
+ if (code) goto _err;
+
+ tsdbDelFReaderClose(&pDelFReader);
+ } else {
+ code = getTableDelSkyline(pMem, pIMem, NULL, NULL, pIter->pSkyline);
+ if (code) goto _err;
+ }
+
+ pIter->iSkyline = taosArrayGetSize(pIter->pSkyline) - 1;
+
+ pIter->idx = (SBlockIdx){.suid = suid, .uid = uid};
+
+ pIter->fsState.state = SFSNEXTROW_FS;
+ pIter->fsState.pTsdb = pTsdb;
+ pIter->fsState.pBlockIdxExp = &pIter->idx;
+
+ pIter->input[0] = (TsdbNextRowState){&pIter->memRow, true, false, &pIter->memState, getNextRowFromMem, NULL};
+ pIter->input[1] = (TsdbNextRowState){&pIter->imemRow, true, false, &pIter->imemState, getNextRowFromMem, NULL};
+ pIter->input[2] =
+ (TsdbNextRowState){&pIter->fsRow, false, true, &pIter->fsState, getNextRowFromFS, clearNextRowFromFS};
+
+ if (pMem) {
+ pIter->memState.pMem = pMem;
+ pIter->memState.state = SMEMNEXTROW_ENTER;
+ pIter->input[0].stop = false;
+ pIter->input[0].next = true;
+ }
+
+ if (pIMem) {
+ pIter->imemState.pMem = pIMem;
+ pIter->imemState.state = SMEMNEXTROW_ENTER;
+ pIter->input[1].stop = false;
+ pIter->input[1].next = true;
+ }
+
+ return code;
+_err:
+ return code;
+}
+
+static int32_t nextRowIterClose(CacheNextRowIter *pIter) {
+ int code = 0;
+
+ for (int i = 0; i < 3; ++i) {
+ if (pIter->input[i].nextRowClearFn) {
+ pIter->input[i].nextRowClearFn(pIter->input[i].iter);
+ }
+ }
+
+ if (pIter->pSkyline) {
+ taosArrayDestroy(pIter->pSkyline);
+ }
+
+ return code;
+_err:
+ return code;
+}
+
+// iterate next row non deleted backward ts, version (from high to low)
+static int32_t nextRowIterGet(CacheNextRowIter *pIter, TSDBROW **ppRow) {
+ int code = 0;
+
+ for (int i = 0; i < 3; ++i) {
+ if (pIter->input[i].next && !pIter->input[i].stop) {
+ code = pIter->input[i].nextRowFn(pIter->input[i].iter, &pIter->input[i].pRow);
+ if (code) goto _err;
+
+ if (pIter->input[i].pRow == NULL) {
+ pIter->input[i].stop = true;
+ pIter->input[i].next = false;
+ }
+ }
+ }
+
+ if (pIter->input[0].stop && pIter->input[1].stop && pIter->input[2].stop) {
+ *ppRow = NULL;
+ return code;
+ }
+
+ // select maxpoint(s) from mem, imem, fs
+ TSDBROW *max[3] = {0};
+ int iMax[3] = {-1, -1, -1};
+ int nMax = 0;
+ TSKEY maxKey = TSKEY_MIN;
+
+ for (int i = 0; i < 3; ++i) {
+ if (!pIter->input[i].stop && pIter->input[i].pRow != NULL) {
+ TSDBKEY key = TSDBROW_KEY(pIter->input[i].pRow);
+
+ // merging & deduplicating on client side
+ if (maxKey <= key.ts) {
+ if (maxKey < key.ts) {
+ nMax = 0;
+ maxKey = key.ts;
+ }
+
+ iMax[nMax] = i;
+ max[nMax++] = pIter->input[i].pRow;
+ }
+ }
+ }
+
+ // delete detection
+ TSDBROW *merge[3] = {0};
+ int iMerge[3] = {-1, -1, -1};
+ int nMerge = 0;
+ for (int i = 0; i < nMax; ++i) {
+ TSDBKEY maxKey = TSDBROW_KEY(max[i]);
+
+ bool deleted = tsdbKeyDeleted(&maxKey, pIter->pSkyline, &pIter->iSkyline);
+ if (!deleted) {
+ iMerge[nMerge] = iMax[i];
+ merge[nMerge++] = max[i];
+ }
+
+ pIter->input[iMax[i]].next = deleted;
+ }
+
+ if (nMerge > 0) {
+ pIter->input[iMerge[0]].next = true;
+
+ *ppRow = merge[0];
+ } else {
+ *ppRow = NULL;
+ }
+
+ return code;
+_err:
+ return code;
+}
+
+static int32_t mergeLastRow2(tb_uid_t uid, STsdb *pTsdb, bool *dup, STSRow **ppRow) {
+ int32_t code = 0;
+
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+ int16_t nCol = pTSchema->numOfCols;
+ int16_t iCol = 0;
+ int16_t noneCol = 0;
+ bool setNoneCol = false;
+ SArray *pColArray = taosArrayInit(nCol, sizeof(SColVal));
+ SColVal *pColVal = &(SColVal){0};
+
+ // tb_uid_t suid = getTableSuidByUid(uid, pTsdb);
+
+ TSKEY lastRowTs = TSKEY_MAX;
+
+ CacheNextRowIter iter = {0};
+ nextRowIterOpen(&iter, uid, pTsdb);
+
+ do {
+ TSDBROW *pRow = NULL;
+ nextRowIterGet(&iter, &pRow);
+
+ if (!pRow) {
+ break;
+ }
+
+ if (lastRowTs == TSKEY_MAX) {
+ lastRowTs = TSDBROW_TS(pRow);
+ STColumn *pTColumn = &pTSchema->columns[0];
+
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = lastRowTs});
+ if (taosArrayPush(pColArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ for (iCol = 1; iCol < nCol; ++iCol) {
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+
+ if (taosArrayPush(pColArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ if (pColVal->isNone && !setNoneCol) {
+ noneCol = iCol;
+ setNoneCol = true;
+ }
+ }
+ if (!setNoneCol) {
+ // goto build the result ts row
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ if ((TSDBROW_TS(pRow) < lastRowTs)) {
+ // goto build the result ts row
+ break;
+ }
+
+ // merge into pColArray
+ setNoneCol = false;
+ for (iCol = noneCol; iCol < nCol; ++iCol) {
+ // high version's column value
+ SColVal *tColVal = (SColVal *)taosArrayGet(pColArray, iCol);
+
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+ if (tColVal->isNone && !pColVal->isNone) {
+ taosArraySet(pColArray, iCol, pColVal);
+ } else if (tColVal->isNone && pColVal->isNone && !setNoneCol) {
+ noneCol = iCol;
+ setNoneCol = true;
+ }
+ }
+ } while (setNoneCol);
+
+ // build the result ts row here
+ *dup = false;
+ if (taosArrayGetSize(pColArray) == nCol) {
+ code = tdSTSRowNew(pColArray, pTSchema, ppRow);
+ if (code) goto _err;
+ } else {
+ *ppRow = NULL;
+ }
+
+ nextRowIterClose(&iter);
+ taosArrayDestroy(pColArray);
+ taosMemoryFreeClear(pTSchema);
+ return code;
+
+_err:
+ nextRowIterClose(&iter);
+ taosArrayDestroy(pColArray);
+ taosMemoryFreeClear(pTSchema);
+ return code;
+}
+
+static int32_t mergeLast2(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray) {
+ int32_t code = 0;
+
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+ int16_t nCol = pTSchema->numOfCols;
+ int16_t iCol = 0;
+ int16_t noneCol = 0;
+ bool setNoneCol = false;
+ SArray *pColArray = taosArrayInit(nCol, sizeof(SLastCol));
+ SColVal *pColVal = &(SColVal){0};
+
+ // tb_uid_t suid = getTableSuidByUid(uid, pTsdb);
+
+ TSKEY lastRowTs = TSKEY_MAX;
+
+ CacheNextRowIter iter = {0};
+ nextRowIterOpen(&iter, uid, pTsdb);
+
+ do {
+ TSDBROW *pRow = NULL;
+ nextRowIterGet(&iter, &pRow);
+
+ if (!pRow) {
+ break;
+ }
+
+ TSKEY rowTs = TSDBROW_TS(pRow);
+
+ if (lastRowTs == TSKEY_MAX) {
+ lastRowTs = rowTs;
+ STColumn *pTColumn = &pTSchema->columns[0];
+
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = lastRowTs});
+ if (taosArrayPush(pColArray, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ for (iCol = 1; iCol < nCol; ++iCol) {
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+
+ if (taosArrayPush(pColArray, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ if ((pColVal->isNone || pColVal->isNull) && !setNoneCol) {
+ noneCol = iCol;
+ setNoneCol = true;
+ }
+ }
+ if (!setNoneCol) {
+ // goto build the result ts row
+ break;
+ } else {
+ continue;
+ }
+ }
+ /*
+ if ((TSDBROW_TS(pRow) < lastRowTs)) {
+ // goto build the result ts row
+ break;
+ }
+ */
+ // merge into pColArray
+ setNoneCol = false;
+ for (iCol = noneCol; iCol < nCol; ++iCol) {
+ // high version's column value
+ SColVal *tColVal = (SColVal *)taosArrayGet(pColArray, iCol);
+
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+ if ((tColVal->isNone || tColVal->isNull) && (!pColVal->isNone && !pColVal->isNull)) {
+ taosArraySet(pColArray, iCol, &(SLastCol){.ts = rowTs, .colVal = *pColVal});
+ //} else if (tColVal->isNone && pColVal->isNone && !setNoneCol) {
+ } else if ((tColVal->isNone || tColVal->isNull) && (pColVal->isNone || pColVal->isNull) && !setNoneCol) {
+ noneCol = iCol;
+ setNoneCol = true;
+ }
+ }
+ } while (setNoneCol);
+
+ // build the result ts row here
+ //*dup = false;
+ if (taosArrayGetSize(pColArray) <= 0) {
+ *ppLastArray = NULL;
+ taosArrayDestroy(pColArray);
+ } else {
+ *ppLastArray = pColArray;
+ }
+ /* if (taosArrayGetSize(pColArray) == nCol) {
+ code = tdSTSRowNew(pColArray, pTSchema, ppRow);
+ if (code) goto _err;
+ } else {
+ *ppRow = NULL;
+ }*/
+
+ nextRowIterClose(&iter);
+ // taosArrayDestroy(pColArray);
+ taosMemoryFreeClear(pTSchema);
+ return code;
+
+_err:
+ nextRowIterClose(&iter);
+ // taosArrayDestroy(pColArray);
+ taosMemoryFreeClear(pTSchema);
+ return code;
+}
+
+static int32_t mergeLastRow(tb_uid_t uid, STsdb *pTsdb, bool *dup, STSRow **ppRow) {
+ int32_t code = 0;
+ SArray *pSkyline = NULL;
+
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+ int16_t nCol = pTSchema->numOfCols;
+ SArray *pColArray = taosArrayInit(nCol, sizeof(SColVal));
+
+ tb_uid_t suid = getTableSuidByUid(uid, pTsdb);
+
+ STbData *pMem = NULL;
+ if (pTsdb->mem) {
+ tsdbGetTbDataFromMemTable(pTsdb->mem, suid, uid, &pMem);
+ }
+
+ STbData *pIMem = NULL;
+ if (pTsdb->imem) {
+ tsdbGetTbDataFromMemTable(pTsdb->imem, suid, uid, &pIMem);
+ }
+
+ *ppRow = NULL;
+
+ pSkyline = taosArrayInit(32, sizeof(TSDBKEY));
+
+ SDelIdx delIdx;
+
+ SDelFile *pDelFile = tsdbFSStateGetDelFile(pTsdb->fs->cState);
+ if (pDelFile) {
+ SDelFReader *pDelFReader;
+
+ code = tsdbDelFReaderOpen(&pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) goto _err;
+
+ code = getTableDelIdx(pDelFReader, suid, uid, &delIdx);
+ if (code) goto _err;
+
+ code = getTableDelSkyline(pMem, pIMem, pDelFReader, &delIdx, pSkyline);
+ if (code) goto _err;
+
+ tsdbDelFReaderClose(&pDelFReader);
+ } else {
+ code = getTableDelSkyline(pMem, pIMem, NULL, NULL, pSkyline);
+ if (code) goto _err;
+ }
+
+ int64_t iSkyline = taosArrayGetSize(pSkyline) - 1;
+
+ SBlockIdx idx = {.suid = suid, .uid = uid};
+
+ SFSNextRowIter fsState = {0};
+ fsState.state = SFSNEXTROW_FS;
+ fsState.pTsdb = pTsdb;
+ fsState.pBlockIdxExp = &idx;
+
+ SMemNextRowIter memState = {0};
+ SMemNextRowIter imemState = {0};
+ TSDBROW memRow, imemRow, fsRow;
+
+ TsdbNextRowState input[3] = {{&memRow, true, false, &memState, getNextRowFromMem, NULL},
+ {&imemRow, true, false, &imemState, getNextRowFromMem, NULL},
+ {&fsRow, false, true, &fsState, getNextRowFromFS, clearNextRowFromFS}};
+
+ if (pMem) {
+ memState.pMem = pMem;
+ memState.state = SMEMNEXTROW_ENTER;
+ input[0].stop = false;
+ input[0].next = true;
+ }
+ if (pIMem) {
+ imemState.pMem = pIMem;
+ imemState.state = SMEMNEXTROW_ENTER;
+ input[1].stop = false;
+ input[1].next = true;
+ }
+
+ int16_t nilColCount = nCol - 1; // count of null & none cols
+ int iCol = 0; // index of first nil col index from left to right
+ bool setICol = false;
+
+ do {
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].next && !input[i].stop) {
+ if (input[i].pRow == NULL) {
+ code = input[i].nextRowFn(input[i].iter, &input[i].pRow);
+ if (code) goto _err;
+
+ if (input[i].pRow == NULL) {
+ input[i].stop = true;
+ input[i].next = false;
+ }
+ }
+ }
+ }
+
+ if (input[0].stop && input[1].stop && input[2].stop) {
+ break;
+ }
+
+ // select maxpoint(s) from mem, imem, fs
+ TSDBROW *max[3] = {0};
+ int iMax[3] = {-1, -1, -1};
+ int nMax = 0;
+ TSKEY maxKey = TSKEY_MIN;
+
+ for (int i = 0; i < 3; ++i) {
+ if (!input[i].stop && input[i].pRow != NULL) {
+ TSDBKEY key = TSDBROW_KEY(input[i].pRow);
+
+ // merging & deduplicating on client side
+ if (maxKey <= key.ts) {
+ if (maxKey < key.ts) {
+ nMax = 0;
+ maxKey = key.ts;
+ }
+
+ iMax[nMax] = i;
+ max[nMax++] = input[i].pRow;
+ }
+ }
+ }
+
+ // delete detection
+ TSDBROW *merge[3] = {0};
+ int iMerge[3] = {-1, -1, -1};
+ int nMerge = 0;
+ for (int i = 0; i < nMax; ++i) {
+ TSDBKEY maxKey = TSDBROW_KEY(max[i]);
+
+ bool deleted = tsdbKeyDeleted(&maxKey, pSkyline, &iSkyline);
+ if (!deleted) {
+ iMerge[nMerge] = i;
+ merge[nMerge++] = max[i];
+ }
+
+ input[iMax[i]].next = deleted;
+ }
+
+ // merge if nMerge > 1
+ if (nMerge > 0) {
+ *dup = false;
+
+ if (nMerge == 1) {
+ code = tsRowFromTsdbRow(pTSchema, merge[nMerge - 1], ppRow);
+ if (code) goto _err;
+ } else {
+ // merge 2 or 3 rows
+ SRowMerger merger = {0};
+
+ tRowMergerInit(&merger, merge[0], pTSchema);
+ for (int i = 1; i < nMerge; ++i) {
+ tRowMerge(&merger, merge[i]);
+ }
+ tRowMergerGetRow(&merger, ppRow);
+ tRowMergerClear(&merger);
+ }
+ }
+
+ } while (1);
+
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].nextRowClearFn) {
+ input[i].nextRowClearFn(input[i].iter);
+ }
+ }
+ if (pSkyline) {
+ taosArrayDestroy(pSkyline);
+ }
+ taosMemoryFreeClear(pTSchema);
+
+ return code;
+_err:
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].nextRowClearFn) {
+ input[i].nextRowClearFn(input[i].iter);
+ }
+ }
+ if (pSkyline) {
+ taosArrayDestroy(pSkyline);
+ }
+ taosMemoryFreeClear(pTSchema);
+ tsdbError("vgId:%d merge last_row failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+// static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, STSRow **ppRow) {
+static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray) {
+ int32_t code = 0;
+ SArray *pSkyline = NULL;
+ STSRow *pRow = NULL;
+ STSRow **ppRow = &pRow;
+
+ STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1);
+ int16_t nCol = pTSchema->numOfCols;
+ // SArray *pColArray = taosArrayInit(nCol, sizeof(SColVal));
+ SArray *pColArray = taosArrayInit(nCol, sizeof(SLastCol));
+
+ tb_uid_t suid = getTableSuidByUid(uid, pTsdb);
+
+ STbData *pMem = NULL;
+ if (pTsdb->mem) {
+ tsdbGetTbDataFromMemTable(pTsdb->mem, suid, uid, &pMem);
+ }
+
+ STbData *pIMem = NULL;
+ if (pTsdb->imem) {
+ tsdbGetTbDataFromMemTable(pTsdb->imem, suid, uid, &pIMem);
+ }
+
+ *ppLastArray = NULL;
+
+ pSkyline = taosArrayInit(32, sizeof(TSDBKEY));
+
+ SDelIdx delIdx;
+
+ SDelFile *pDelFile = tsdbFSStateGetDelFile(pTsdb->fs->cState);
+ if (pDelFile) {
+ SDelFReader *pDelFReader;
+
+ code = tsdbDelFReaderOpen(&pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) goto _err;
+
+ code = getTableDelIdx(pDelFReader, suid, uid, &delIdx);
+ if (code) goto _err;
+
+ code = getTableDelSkyline(pMem, pIMem, pDelFReader, &delIdx, pSkyline);
+ if (code) goto _err;
+
+ tsdbDelFReaderClose(&pDelFReader);
+ } else {
+ code = getTableDelSkyline(pMem, pIMem, NULL, NULL, pSkyline);
+ if (code) goto _err;
+ }
+
+ int64_t iSkyline = taosArrayGetSize(pSkyline) - 1;
+
+ SBlockIdx idx = {.suid = suid, .uid = uid};
+
+ SFSNextRowIter fsState = {0};
+ fsState.state = SFSNEXTROW_FS;
+ fsState.pTsdb = pTsdb;
+ fsState.pBlockIdxExp = &idx;
+
+ SMemNextRowIter memState = {0};
+ SMemNextRowIter imemState = {0};
+ TSDBROW memRow, imemRow, fsRow;
+
+ TsdbNextRowState input[3] = {{&memRow, true, false, &memState, getNextRowFromMem, NULL},
+ {&imemRow, true, false, &imemState, getNextRowFromMem, NULL},
+ {&fsRow, false, true, &fsState, getNextRowFromFS, clearNextRowFromFS}};
+
+ if (pMem) {
+ memState.pMem = pMem;
+ memState.state = SMEMNEXTROW_ENTER;
+ input[0].stop = false;
+ input[0].next = true;
+ }
+ if (pIMem) {
+ imemState.pMem = pIMem;
+ imemState.state = SMEMNEXTROW_ENTER;
+ input[1].stop = false;
+ input[1].next = true;
+ }
+
+ int16_t nilColCount = nCol - 1; // count of null & none cols
+ int iCol = 0; // index of first nil col index from left to right
+ bool setICol = false;
+
+ do {
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].next && !input[i].stop) {
+ code = input[i].nextRowFn(input[i].iter, &input[i].pRow);
+ if (code) goto _err;
+
+ if (input[i].pRow == NULL) {
+ input[i].stop = true;
+ input[i].next = false;
+ }
+ }
+ }
+
+ if (input[0].stop && input[1].stop && input[2].stop) {
+ break;
+ }
+
+ // select maxpoint(s) from mem, imem, fs
+ TSDBROW *max[3] = {0};
+ int iMax[3] = {-1, -1, -1};
+ int nMax = 0;
+ TSKEY maxKey = TSKEY_MIN;
+
+ for (int i = 0; i < 3; ++i) {
+ if (!input[i].stop && input[i].pRow != NULL) {
+ TSDBKEY key = TSDBROW_KEY(input[i].pRow);
+
+ // merging & deduplicating on client side
+ if (maxKey <= key.ts) {
+ if (maxKey < key.ts) {
+ nMax = 0;
+ maxKey = key.ts;
+ }
+
+ iMax[nMax] = i;
+ max[nMax++] = input[i].pRow;
+ }
+ }
+ }
+
+ // delete detection
+ TSDBROW *merge[3] = {0};
+ int iMerge[3] = {-1, -1, -1};
+ int nMerge = 0;
+ for (int i = 0; i < nMax; ++i) {
+ TSDBKEY maxKey = TSDBROW_KEY(max[i]);
+
+ bool deleted = tsdbKeyDeleted(&maxKey, pSkyline, &iSkyline);
+ if (!deleted) {
+ iMerge[nMerge] = iMax[i];
+ merge[nMerge++] = max[i];
+ }
+
+ input[iMax[i]].next = deleted;
+ }
+
+ // merge if nMerge > 1
+ if (nMerge > 0) {
+ if (nMerge == 1) {
+ code = tsRowFromTsdbRow(pTSchema, merge[nMerge - 1], ppRow);
+ if (code) goto _err;
+ } else {
+ // merge 2 or 3 rows
+ SRowMerger merger = {0};
+
+ tRowMergerInit(&merger, merge[0], pTSchema);
+ for (int i = 1; i < nMerge; ++i) {
+ tRowMerge(&merger, merge[i]);
+ }
+ tRowMergerGetRow(&merger, ppRow);
+ tRowMergerClear(&merger);
+ }
+ } else {
+ /* *ppRow = NULL; */
+ /* return code; */
+ continue;
+ }
+
+ if (iCol == 0) {
+ STColumn *pTColumn = &pTSchema->columns[0];
+ SColVal *pColVal = &(SColVal){0};
+
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = maxKey});
+
+ // if (taosArrayPush(pColArray, pColVal) == NULL) {
+ if (taosArrayPush(pColArray, &(SLastCol){.ts = maxKey, .colVal = *pColVal}) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ ++iCol;
+
+ setICol = false;
+ for (int16_t i = iCol; i < nCol; ++i) {
+ // tsdbRowGetColVal(*ppRow, pTSchema, i, pColVal);
+ tTSRowGetVal(*ppRow, pTSchema, i, pColVal);
+ // if (taosArrayPush(pColArray, pColVal) == NULL) {
+ if (taosArrayPush(pColArray, &(SLastCol){.ts = maxKey, .colVal = *pColVal}) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ if (pColVal->isNull || pColVal->isNone) {
+ for (int j = 0; j < nMerge; ++j) {
+ SColVal jColVal = {0};
+ tsdbRowGetColVal(merge[j], pTSchema, i, &jColVal);
+ if (jColVal.isNull || jColVal.isNone) {
+ input[iMerge[j]].next = true;
+ }
+ }
+ if (!setICol) {
+ iCol = i;
+ setICol = true;
+ }
+ } else {
+ --nilColCount;
+ }
+ }
+
+ if (*ppRow) {
+ taosMemoryFreeClear(*ppRow);
+ }
+
+ continue;
+ }
+
+ setICol = false;
+ for (int16_t i = iCol; i < nCol; ++i) {
+ SColVal colVal = {0};
+ tTSRowGetVal(*ppRow, pTSchema, i, &colVal);
+ TSKEY rowTs = (*ppRow)->ts;
+
+ // SColVal *tColVal = (SColVal *)taosArrayGet(pColArray, i);
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pColArray, i);
+ SColVal *tColVal = &tTsVal->colVal;
+
+ if (!colVal.isNone && !colVal.isNull) {
+ if (tColVal->isNull || tColVal->isNone) {
+ // taosArraySet(pColArray, i, &colVal);
+ taosArraySet(pColArray, i, &(SLastCol){.ts = rowTs, .colVal = colVal});
+ --nilColCount;
+ }
+ } else {
+ if ((tColVal->isNull || tColVal->isNone) && !setICol) {
+ iCol = i;
+ setICol = true;
+
+ for (int j = 0; j < nMerge; ++j) {
+ SColVal jColVal = {0};
+ tsdbRowGetColVal(merge[j], pTSchema, i, &jColVal);
+ if (jColVal.isNull || jColVal.isNone) {
+ input[iMerge[j]].next = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (*ppRow) {
+ taosMemoryFreeClear(*ppRow);
+ }
+ } while (nilColCount > 0);
+
+ // if () new ts row from pColArray if non empty
+ /* if (taosArrayGetSize(pColArray) == nCol) { */
+ /* code = tdSTSRowNew(pColArray, pTSchema, ppRow); */
+ /* if (code) goto _err; */
+ /* } */
+ /* taosArrayDestroy(pColArray); */
+ if (taosArrayGetSize(pColArray) <= 0) {
+ *ppLastArray = NULL;
+ taosArrayDestroy(pColArray);
+ } else {
+ *ppLastArray = pColArray;
+ }
+ if (*ppRow) {
+ taosMemoryFreeClear(*ppRow);
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].nextRowClearFn) {
+ input[i].nextRowClearFn(input[i].iter);
+ }
+ }
+ if (pSkyline) {
+ taosArrayDestroy(pSkyline);
+ }
+ taosMemoryFreeClear(pTSchema);
+
+ return code;
+_err:
+ taosArrayDestroy(pColArray);
+ if (*ppRow) {
+ taosMemoryFreeClear(*ppRow);
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (input[i].nextRowClearFn) {
+ input[i].nextRowClearFn(input[i].iter);
+ }
+ }
+ if (pSkyline) {
+ taosArrayDestroy(pSkyline);
+ }
+ taosMemoryFreeClear(pTSchema);
+ tsdbError("vgId:%d merge last_row failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbCacheGetLastrowH(SLRUCache *pCache, tb_uid_t uid, STsdb *pTsdb, LRUHandle **handle) {
+ int32_t code = 0;
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "lr", key, &keyLen);
+ getTableCacheKey(uid, 0, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ //*ppRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ } else {
+ STSRow *pRow = NULL;
+ bool dup = false; // which is always false for now
+ code = mergeLastRow2(uid, pTsdb, &dup, &pRow);
+ // if table's empty or error, return code of -1
+ if (code < 0 || pRow == NULL) {
+ if (!dup && pRow) {
+ taosMemoryFree(pRow);
+ }
+
+ *handle = NULL;
+ return 0;
+ }
+
+ _taos_lru_deleter_t deleter = deleteTableCacheLastrow;
+ LRUStatus status =
+ taosLRUCacheInsert(pCache, key, keyLen, pRow, TD_ROW_LEN(pRow), deleter, NULL, TAOS_LRU_PRIORITY_LOW);
+ if (status != TAOS_LRU_STATUS_OK) {
+ code = -1;
+ }
+
+ // tsdbCacheInsertLastrow(pCache, pTsdb, uid, pRow, dup);
+ h = taosLRUCacheLookup(pCache, key, keyLen);
+ //*ppRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ }
+
+ *handle = h;
+
+ return code;
+}
+
+int32_t tsdbCacheLastArray2Row(SArray *pLastArray, STSRow **ppRow, STSchema *pTSchema) {
+ int32_t code = 0;
+ int16_t nCol = taosArrayGetSize(pLastArray);
+ SArray *pColArray = taosArrayInit(nCol, sizeof(SColVal));
+
+ for (int16_t iCol = 0; iCol < nCol; ++iCol) {
+ SLastCol *tTsVal = (SLastCol *)taosArrayGet(pLastArray, iCol);
+ SColVal *tColVal = &tTsVal->colVal;
+ taosArrayPush(pColArray, tColVal);
+ }
+
+ code = tdSTSRowNew(pColArray, pTSchema, ppRow);
+ if (code) goto _err;
+
+ taosArrayDestroy(pColArray);
+
+ return code;
+
+_err:
+ taosArrayDestroy(pColArray);
+
+ return code;
+}
+
+int32_t tsdbCacheGetLastH(SLRUCache *pCache, tb_uid_t uid, STsdb *pTsdb, LRUHandle **handle) {
+ int32_t code = 0;
+ char key[32] = {0};
+ int keyLen = 0;
+
+ // getTableCacheKey(uid, "l", key, &keyLen);
+ getTableCacheKey(uid, 1, key, &keyLen);
+ LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen);
+ if (h) {
+ //*ppRow = (STSRow *)taosLRUCacheValue(pCache, h);
+
+ } else {
+ // STSRow *pRow = NULL;
+ // code = mergeLast(uid, pTsdb, &pRow);
+ SArray *pLastArray = NULL;
+ // code = mergeLast(uid, pTsdb, &pLastArray);
+ code = mergeLast2(uid, pTsdb, &pLastArray);
+ // if table's empty or error, return code of -1
+ // if (code < 0 || pRow == NULL) {
+ if (code < 0 || pLastArray == NULL) {
+ *handle = NULL;
+ return 0;
+ }
+
+ _taos_lru_deleter_t deleter = deleteTableCacheLast;
+ LRUStatus status =
+ taosLRUCacheInsert(pCache, key, keyLen, pLastArray, pLastArray->capacity, deleter, NULL, TAOS_LRU_PRIORITY_LOW);
+ if (status != TAOS_LRU_STATUS_OK) {
+ code = -1;
+ }
+
+ h = taosLRUCacheLookup(pCache, key, keyLen);
+ //*ppRow = (STSRow *)taosLRUCacheValue(pCache, h);
+ }
+
+ *handle = h;
+
+ return code;
+}
+
+int32_t tsdbCacheRelease(SLRUCache *pCache, LRUHandle *h) {
+ int32_t code = 0;
+
+ taosLRUCacheRelease(pCache, h, false);
+
+ return code;
+}
+
+void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity) {
+ taosLRUCacheSetCapacity(pVnode->pTsdb->lruCache, capacity);
+}
+
+size_t tsdbCacheGetCapacity(SVnode *pVnode) { return taosLRUCacheGetCapacity(pVnode->pTsdb->lruCache); }
diff --git a/source/dnode/vnode/src/tsdb/tsdbCacheRead.c b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d3cfee592a027cd85342674b24b475eb982ee24
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "taoserror.h"
+#include "tarray.h"
+#include "tcommon.h"
+#include "tsdb.h"
+
+typedef struct SLastrowReader {
+ SVnode* pVnode;
+ STSchema* pSchema;
+ uint64_t uid;
+ char** transferBuf; // todo remove it soon
+ int32_t numOfCols;
+ int32_t type;
+ int32_t tableIndex; // currently returned result tables
+ SArray* pTableList; // table id list
+} SLastrowReader;
+
+static void saveOneRow(STSRow* pRow, SSDataBlock* pBlock, SLastrowReader* pReader, const int32_t* slotIds) {
+ ASSERT(pReader->numOfCols <= taosArrayGetSize(pBlock->pDataBlock));
+ int32_t numOfRows = pBlock->info.rows;
+
+ SColVal colVal = {0};
+ for (int32_t i = 0; i < pReader->numOfCols; ++i) {
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+
+ if (slotIds[i] == -1) {
+ colDataAppend(pColInfoData, numOfRows, (const char*)&pRow->ts, false);
+ } else {
+ int32_t slotId = slotIds[i];
+
+ tTSRowGetVal(pRow, pReader->pSchema, slotId, &colVal);
+
+ if (IS_VAR_DATA_TYPE(colVal.type)) {
+ if (colVal.isNull || colVal.isNone) {
+ colDataAppendNULL(pColInfoData, numOfRows);
+ } else {
+ varDataSetLen(pReader->transferBuf[slotId], colVal.value.nData);
+ memcpy(varDataVal(pReader->transferBuf[slotId]), colVal.value.pData, colVal.value.nData);
+ colDataAppend(pColInfoData, numOfRows, pReader->transferBuf[slotId], false);
+ }
+ } else {
+ colDataAppend(pColInfoData, numOfRows, (const char*)&colVal.value, colVal.isNull || colVal.isNone);
+ }
+ }
+ }
+
+ pBlock->info.rows += 1;
+}
+
+int32_t tsdbLastRowReaderOpen(void* pVnode, int32_t type, SArray* pTableIdList, int32_t numOfCols, void** pReader) {
+ SLastrowReader* p = taosMemoryCalloc(1, sizeof(SLastrowReader));
+ if (p == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ p->type = type;
+ p->pVnode = pVnode;
+ p->numOfCols = numOfCols;
+
+ if (taosArrayGetSize(pTableIdList) == 0) {
+ *pReader = p;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ STableKeyInfo* pKeyInfo = taosArrayGet(pTableIdList, 0);
+ p->pSchema = metaGetTbTSchema(p->pVnode->pMeta, pKeyInfo->uid, -1);
+ p->pTableList = pTableIdList;
+
+ p->transferBuf = taosMemoryCalloc(p->pSchema->numOfCols, POINTER_BYTES);
+ for (int32_t i = 0; i < p->pSchema->numOfCols; ++i) {
+ if (IS_VAR_DATA_TYPE(p->pSchema->columns[i].type)) {
+ p->transferBuf[i] = taosMemoryMalloc(p->pSchema->columns[i].bytes);
+ }
+ }
+
+ *pReader = p;
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t tsdbLastrowReaderClose(void* pReader) {
+ SLastrowReader* p = pReader;
+
+ if (p->pSchema != NULL) {
+ for (int32_t i = 0; i < p->pSchema->numOfCols; ++i) {
+ taosMemoryFreeClear(p->transferBuf[i]);
+ }
+
+ taosMemoryFree(p->transferBuf);
+ taosMemoryFree(p->pSchema);
+ }
+
+ taosMemoryFree(pReader);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t tsdbRetrieveLastRow(void* pReader, SSDataBlock* pResBlock, const int32_t* slotIds, SArray* pTableUidList) {
+ if (pReader == NULL || pResBlock == NULL) {
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ SLastrowReader* pr = pReader;
+
+ SLRUCache* lruCache = pr->pVnode->pTsdb->lruCache;
+ LRUHandle* h = NULL;
+ STSRow* pRow = NULL;
+ size_t numOfTables = taosArrayGetSize(pr->pTableList);
+
+ // retrieve the only one last row of all tables in the uid list.
+ if (pr->type == LASTROW_RETRIEVE_TYPE_SINGLE) {
+ int64_t lastKey = INT64_MIN;
+ bool internalResult = false;
+ for (int32_t i = 0; i < numOfTables; ++i) {
+ STableKeyInfo* pKeyInfo = taosArrayGet(pr->pTableList, i);
+
+ int32_t code = tsdbCacheGetLastrowH(lruCache, pKeyInfo->uid, pr->pVnode->pTsdb, &h);
+ // int32_t code = tsdbCacheGetLastH(lruCache, pKeyInfo->uid, pr->pVnode->pTsdb, &h);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+
+ if (h == NULL) {
+ continue;
+ }
+
+ pRow = (STSRow*)taosLRUCacheValue(lruCache, h);
+ // SArray* pLast = (SArray*)taosLRUCacheValue(lruCache, h);
+ // tsdbCacheLastArray2Row(pLast, &pRow, pr->pSchema);
+ if (pRow->ts > lastKey) {
+ // Set result row into the same rowIndex repeatly, so we need to check if the internal result row has already
+ // appended or not.
+ if (internalResult) {
+ pResBlock->info.rows -= 1;
+ taosArrayClear(pTableUidList);
+ }
+
+ saveOneRow(pRow, pResBlock, pr, slotIds);
+ taosArrayPush(pTableUidList, &pKeyInfo->uid);
+ internalResult = true;
+ lastKey = pRow->ts;
+ }
+
+ tsdbCacheRelease(lruCache, h);
+ }
+ } else if (pr->type == LASTROW_RETRIEVE_TYPE_ALL) {
+ for (int32_t i = pr->tableIndex; i < numOfTables; ++i) {
+ STableKeyInfo* pKeyInfo = taosArrayGet(pr->pTableList, i);
+
+ int32_t code = tsdbCacheGetLastrowH(lruCache, pKeyInfo->uid, pr->pVnode->pTsdb, &h);
+ // int32_t code = tsdbCacheGetLastH(lruCache, pKeyInfo->uid, pr->pVnode->pTsdb, &h);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+
+ // no data in the table of Uid
+ if (h == NULL) {
+ continue;
+ }
+
+ pRow = (STSRow*)taosLRUCacheValue(lruCache, h);
+ // SArray* pLast = (SArray*)taosLRUCacheValue(lruCache, h);
+ // tsdbCacheLastArray2Row(pLast, &pRow, pr->pSchema);
+
+ saveOneRow(pRow, pResBlock, pr, slotIds);
+ taosArrayPush(pTableUidList, &pKeyInfo->uid);
+
+ // taosMemoryFree(pRow);
+ tsdbCacheRelease(lruCache, h);
+
+ pr->tableIndex += 1;
+ if (pResBlock->info.rows >= pResBlock->info.capacity) {
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+ } else {
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/dnode/vnode/src/tsdb/tsdbCommit.c b/source/dnode/vnode/src/tsdb/tsdbCommit.c
index e98fd8ae1f6dc6cd0d6f47a2563055f7e452870a..8a189d98b33da4363b1ae3b192834fa913c3ae7e 100644
--- a/source/dnode/vnode/src/tsdb/tsdbCommit.c
+++ b/source/dnode/vnode/src/tsdb/tsdbCommit.c
@@ -14,1824 +14,1148 @@
*/
#include "tsdb.h"
-
-#define TSDB_MAX_SUBBLOCKS 8
-
typedef struct {
- STable *pTable;
- STbDataIter *pIter;
-} SCommitIter;
+ int64_t suid;
+ int64_t uid;
+ STSchema *pTSchema;
+} SSkmInfo;
typedef struct {
- SRtn rtn; // retention snapshot
- SFSIter fsIter; // tsdb file iterator
- int niters; // memory iterators
- SCommitIter *iters;
- bool isRFileSet; // read and commit FSET
- int32_t fid;
- SDFileSet *pSet;
- SReadH readh;
- SDFileSet wSet;
- bool isDFileSame;
- bool isLFileSame;
- TSKEY minKey;
- TSKEY maxKey;
- SArray *aBlkIdx; // SBlockIdx array
- STable *pTable;
- SArray *aSupBlk; // Table super-block array
- SArray *aSubBlk; // table sub-block array
- SDataCols *pDataCols;
-} SCommitH;
-
-#define TSDB_DEFAULT_BLOCK_ROWS(maxRows) ((maxRows)*4 / 5)
-
-#define TSDB_COMMIT_REPO(ch) TSDB_READ_REPO(&(ch->readh))
-#define TSDB_COMMIT_REPO_ID(ch) REPO_ID(TSDB_READ_REPO(&(ch->readh)))
-#define TSDB_COMMIT_WRITE_FSET(ch) (&((ch)->wSet))
-#define TSDB_COMMIT_TABLE(ch) ((ch)->pTable)
-#define TSDB_COMMIT_HEAD_FILE(ch) TSDB_DFILE_IN_SET(TSDB_COMMIT_WRITE_FSET(ch), TSDB_FILE_HEAD)
-#define TSDB_COMMIT_DATA_FILE(ch) TSDB_DFILE_IN_SET(TSDB_COMMIT_WRITE_FSET(ch), TSDB_FILE_DATA)
-#define TSDB_COMMIT_LAST_FILE(ch) TSDB_DFILE_IN_SET(TSDB_COMMIT_WRITE_FSET(ch), TSDB_FILE_LAST)
-#define TSDB_COMMIT_SMAD_FILE(ch) TSDB_DFILE_IN_SET(TSDB_COMMIT_WRITE_FSET(ch), TSDB_FILE_SMAD)
-#define TSDB_COMMIT_SMAL_FILE(ch) TSDB_DFILE_IN_SET(TSDB_COMMIT_WRITE_FSET(ch), TSDB_FILE_SMAL)
-#define TSDB_COMMIT_BUF(ch) TSDB_READ_BUF(&((ch)->readh))
-#define TSDB_COMMIT_COMP_BUF(ch) TSDB_READ_COMP_BUF(&((ch)->readh))
-#define TSDB_COMMIT_EXBUF(ch) TSDB_READ_EXBUF(&((ch)->readh))
-#define TSDB_COMMIT_DEFAULT_ROWS(ch) TSDB_DEFAULT_BLOCK_ROWS(TSDB_COMMIT_REPO(ch)->pVnode->config.tsdbCfg.maxRows)
-#define TSDB_COMMIT_TXN_VERSION(ch) FS_TXN_VERSION(REPO_FS(TSDB_COMMIT_REPO(ch)))
-
-static int32_t tsdbCommitData(SCommitH *pCommith);
-static int32_t tsdbCommitDel(SCommitH *pCommith);
-static int32_t tsdbCommitCache(SCommitH *pCommith);
-static int32_t tsdbStartCommit(STsdb *pTsdb, SCommitH *pCHandle);
-static int32_t tsdbEndCommit(SCommitH *pCHandle, int eno);
-
-static int tsdbInitCommitH(SCommitH *pCommith, STsdb *pRepo);
-static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key);
-static int tsdbNextCommitFid(SCommitH *pCommith);
-static void tsdbDestroyCommitH(SCommitH *pCommith);
-static int32_t tsdbCreateCommitIters(SCommitH *pCommith);
-static void tsdbDestroyCommitIters(SCommitH *pCommith);
-static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
-static int tsdbSetAndOpenCommitFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
-static int tsdbCommitToTable(SCommitH *pCommith, int tid);
-static bool tsdbCommitIsSameFile(SCommitH *pCommith, int bidx);
-static int tsdbMoveBlkIdx(SCommitH *pCommith, SBlockIdx *pIdx);
-static int tsdbSetCommitTable(SCommitH *pCommith, STable *pTable);
-static int tsdbComparKeyBlock(const void *arg1, const void *arg2);
-static int tsdbWriteBlockInfo(SCommitH *pCommih);
-static int tsdbCommitMemData(SCommitH *pCommith, SCommitIter *pIter, TSKEY keyLimit, bool toData);
-static int tsdbMergeMemData(SCommitH *pCommith, SCommitIter *pIter, int bidx);
-static int tsdbMoveBlock(SCommitH *pCommith, int bidx);
-static int tsdbCommitAddBlock(SCommitH *pCommith, const SBlock *pSupBlock, const SBlock *pSubBlocks, int nSubBlocks);
-static int tsdbMergeBlockData(SCommitH *pCommith, SCommitIter *pIter, SDataCols *pDataCols, TSKEY keyLimit,
- bool isLastOneBlock);
-static void tsdbResetCommitTable(SCommitH *pCommith);
-static void tsdbCloseCommitFile(SCommitH *pCommith, bool hasError);
-static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *pInfo);
-static void tsdbLoadAndMergeFromCache(STsdb *pTsdb, SDataCols *pDataCols, int *iter, SCommitIter *pCommitIter,
- SDataCols *pTarget, TSKEY maxKey, int maxRows, int8_t update);
-static int tsdbWriteBlockIdx(SDFile *pHeadf, SArray *pIdxA, void **ppBuf);
-static int tsdbApplyRtnOnFSet(STsdb *pRepo, SDFileSet *pSet, SRtn *pRtn);
-static int tsdbLoadDataFromCache(STsdb *pTsdb, STable *pTable, STbDataIter *pIter, TSKEY maxKey, int maxRowsToRead,
- SDataCols *pCols, TKEY *filterKeys, int nFilterKeys, bool keepDup,
- SMergeInfo *pMergeInfo);
+ STsdb *pTsdb;
+ /* commit data */
+ int64_t commitID;
+ int32_t minutes;
+ int8_t precision;
+ int32_t minRow;
+ int32_t maxRow;
+ int8_t cmprAlg;
+ // --------------
+ TSKEY nextKey; // reset by each table commit
+ int32_t commitFid;
+ TSKEY minKey;
+ TSKEY maxKey;
+ // commit file data
+ SDataFReader *pReader;
+ SArray *aBlockIdx; // SArray
+ SMapData oBlockMap; // SMapData, read from reader
+ SBlockData oBlockData;
+ SDataFWriter *pWriter;
+ SArray *aBlockIdxN; // SArray
+ SMapData nBlockMap; // SMapData
+ SBlockData nBlockData;
+ SSkmInfo skmTable;
+ SSkmInfo skmRow;
+ /* commit del */
+ SDelFReader *pDelFReader;
+ SDelFWriter *pDelFWriter;
+ SArray *aDelIdx; // SArray
+ SArray *aDelIdxN; // SArray
+ SArray *aDelData; // SArray
+} SCommitter;
+
+static int32_t tsdbStartCommit(STsdb *pTsdb, SCommitter *pCommitter);
+static int32_t tsdbCommitData(SCommitter *pCommitter);
+static int32_t tsdbCommitDel(SCommitter *pCommitter);
+static int32_t tsdbCommitCache(SCommitter *pCommitter);
+static int32_t tsdbEndCommit(SCommitter *pCommitter, int32_t eno);
int32_t tsdbBegin(STsdb *pTsdb) {
- if (!pTsdb) return 0;
+ int32_t code = 0;
- SMemTable *pMem;
+ if (!pTsdb) return code;
- if (tsdbMemTableCreate(pTsdb, &pTsdb->mem) < 0) {
- return -1;
- }
+ code = tsdbMemTableCreate(pTsdb, &pTsdb->mem);
+ if (code) goto _err;
+
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb begin failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
}
int32_t tsdbCommit(STsdb *pTsdb) {
if (!pTsdb) return 0;
int32_t code = 0;
- SCommitH commith = {0};
- SDFileSet *pSet = NULL;
- int fid;
+ SCommitter commith;
+ SMemTable *pMemTable = pTsdb->mem;
- ASSERT(pTsdb->imem == NULL && pTsdb->mem);
- pTsdb->imem = pTsdb->mem;
- pTsdb->mem = NULL;
+ // check
+ if (pMemTable->nRow == 0 && pMemTable->nDel == 0) {
+ // TODO: lock?
+ pTsdb->mem = NULL;
+ tsdbMemTableDestroy(pMemTable);
+ goto _exit;
+ }
// start commit
code = tsdbStartCommit(pTsdb, &commith);
- if (code) {
- goto _err;
- }
+ if (code) goto _err;
// commit impl
code = tsdbCommitData(&commith);
- if (code) {
- goto _err;
- }
+ if (code) goto _err;
code = tsdbCommitDel(&commith);
- if (code) {
- goto _err;
- }
+ if (code) goto _err;
code = tsdbCommitCache(&commith);
- if (code) {
- goto _err;
- }
+ if (code) goto _err;
// end commit
code = tsdbEndCommit(&commith, 0);
- if (code) {
- goto _err;
- }
+ if (code) goto _err;
+_exit:
return code;
_err:
+ tsdbEndCommit(&commith, code);
tsdbError("vgId:%d, failed to commit since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
return code;
}
-static int32_t tsdbCommitData(SCommitH *pCommith) {
- int32_t fid;
- SDFileSet *pSet = NULL;
+static int32_t tsdbCommitDelStart(SCommitter *pCommitter) {
int32_t code = 0;
- STsdb *pTsdb = TSDB_COMMIT_REPO(pCommith);
-
- // Skip expired memory data and expired FSET
- tsdbSeekCommitIter(pCommith, pCommith->rtn.minKey);
- while ((pSet = tsdbFSIterNext(&(pCommith->fsIter)))) {
- if (pSet->fid < pCommith->rtn.minFid) {
- tsdbInfo("vgId:%d, FSET %d on level %d disk id %d expires, remove it", REPO_ID(pTsdb), pSet->fid,
- TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet));
- } else {
- break;
- }
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SMemTable *pMemTable = pTsdb->imem;
+
+ pCommitter->aDelIdx = taosArrayInit(0, sizeof(SDelIdx));
+ if (pCommitter->aDelIdx == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
}
- // commit
- fid = tsdbNextCommitFid(pCommith);
- while (true) {
- // Loop over both on disk and memory
- if (pSet == NULL && fid == TSDB_IVLD_FID) break;
-
- if (pSet && (fid == TSDB_IVLD_FID || pSet->fid < fid)) {
- // Only has existing FSET but no memory data to commit in this
- // existing FSET, only check if file in correct retention
- if (tsdbApplyRtnOnFSet(TSDB_COMMIT_REPO(pCommith), pSet, &(pCommith->rtn)) < 0) {
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ pCommitter->aDelData = taosArrayInit(0, sizeof(SDelData));
+ if (pCommitter->aDelData == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
- pSet = tsdbFSIterNext(&(pCommith->fsIter));
- } else {
- // Has memory data to commit
- SDFileSet *pCSet;
- int cfid;
-
- if (pSet == NULL || pSet->fid > fid) {
- // Commit to a new FSET with fid: fid
- pCSet = NULL;
- cfid = fid;
- } else {
- // Commit to an existing FSET
- pCSet = pSet;
- cfid = pSet->fid;
- pSet = tsdbFSIterNext(&(pCommith->fsIter));
- }
+ pCommitter->aDelIdxN = taosArrayInit(0, sizeof(SDelIdx));
+ if (pCommitter->aDelIdxN == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
- if (tsdbCommitToFile(pCommith, pCSet, cfid) < 0) {
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ SDelFile *pDelFileR = pTsdb->fs->nState->pDelFile;
+ if (pDelFileR) {
+ code = tsdbDelFReaderOpen(&pCommitter->pDelFReader, pDelFileR, pTsdb, NULL);
+ if (code) goto _err;
- fid = tsdbNextCommitFid(pCommith);
- }
+ code = tsdbReadDelIdx(pCommitter->pDelFReader, pCommitter->aDelIdx, NULL);
+ if (code) goto _err;
}
- return code;
-}
+ // prepare new
+ SDelFile wDelFile = {.commitID = pCommitter->commitID, .size = 0, .offset = 0};
+ code = tsdbDelFWriterOpen(&pCommitter->pDelFWriter, &wDelFile, pTsdb);
+ if (code) goto _err;
-static int32_t tsdbCommitDel(SCommitH *pCommith) {
- int32_t code = 0;
- // TODO
+_exit:
+ tsdbDebug("vgId:%d commit del start", TD_VID(pTsdb->pVnode));
return code;
-}
-static int32_t tsdbCommitCache(SCommitH *pCommith) {
- int32_t code = 0;
- // TODO
+_err:
+ tsdbError("vgId:%d commit del start failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
return code;
}
-static int tsdbApplyRtnOnFSet(STsdb *pRepo, SDFileSet *pSet, SRtn *pRtn) {
- SDiskID did;
- SDFileSet nSet = {0};
- STsdbFS *pfs = REPO_FS(pRepo);
- int level;
+static int32_t tsdbCommitTableDel(SCommitter *pCommitter, STbData *pTbData, SDelIdx *pDelIdx) {
+ int32_t code = 0;
+ SDelData *pDelData;
+ tb_uid_t suid;
+ tb_uid_t uid;
- ASSERT(pSet->fid >= pRtn->minFid);
+ if (pTbData) {
+ suid = pTbData->suid;
+ uid = pTbData->uid;
- level = tsdbGetFidLevel(pSet->fid, pRtn);
-
- if (tfsAllocDisk(pRepo->pVnode->pTfs, level, &did) < 0) {
- terrno = TSDB_CODE_TDB_NO_AVAIL_DISK;
- return -1;
- }
-
- if (did.level > TSDB_FSET_LEVEL(pSet)) {
- // Need to move the FSET to higher level
- tsdbInitDFileSet(pRepo, &nSet, did, pSet->fid, FS_TXN_VERSION(pfs));
-
- if (tsdbCopyDFileSet(pSet, &nSet) < 0) {
- tsdbError("vgId:%d, failed to copy FSET %d from level %d to level %d since %s", REPO_ID(pRepo), pSet->fid,
- TSDB_FSET_LEVEL(pSet), did.level, tstrerror(terrno));
- return -1;
+ if (pTbData->pHead == NULL) {
+ pTbData = NULL;
}
+ }
- if (tsdbUpdateDFileSet(pfs, &nSet) < 0) {
- return -1;
- }
+ if (pDelIdx) {
+ suid = pDelIdx->suid;
+ uid = pDelIdx->uid;
- tsdbInfo("vgId:%d, FSET %d is copied from level %d disk id %d to level %d disk id %d", REPO_ID(pRepo), pSet->fid,
- TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet), did.level, did.id);
+ code = tsdbReadDelData(pCommitter->pDelFReader, pDelIdx, pCommitter->aDelData, NULL);
+ if (code) goto _err;
} else {
- // On a correct level
- if (tsdbUpdateDFileSet(pfs, pSet) < 0) {
- return -1;
- }
+ taosArrayClear(pCommitter->aDelData);
}
- return 0;
-}
+ if (pTbData == NULL && pDelIdx == NULL) goto _exit;
-void tsdbGetRtnSnap(STsdb *pRepo, SRtn *pRtn) {
- STsdbKeepCfg *pCfg = REPO_KEEP_CFG(pRepo);
- TSKEY minKey, midKey, maxKey, now;
-
- now = taosGetTimestamp(pCfg->precision);
- minKey = now - pCfg->keep2 * tsTickPerMin[pCfg->precision];
- midKey = now - pCfg->keep1 * tsTickPerMin[pCfg->precision];
- maxKey = now - pCfg->keep0 * tsTickPerMin[pCfg->precision];
-
- pRtn->minKey = minKey;
- pRtn->minFid = (int)(TSDB_KEY_FID(minKey, pCfg->days, pCfg->precision));
- pRtn->midFid = (int)(TSDB_KEY_FID(midKey, pCfg->days, pCfg->precision));
- pRtn->maxFid = (int)(TSDB_KEY_FID(maxKey, pCfg->days, pCfg->precision));
- tsdbDebug("vgId:%d, now:%" PRId64 " minKey:%" PRId64 " minFid:%d, midFid:%d, maxFid:%d", REPO_ID(pRepo), now, minKey,
- pRtn->minFid, pRtn->midFid, pRtn->maxFid);
-}
+ SDelIdx delIdx = {.suid = suid, .uid = uid};
-static int32_t tsdbStartCommit(STsdb *pTsdb, SCommitH *pCHandle) {
- int32_t code = 0;
+ // memory
+ pDelData = pTbData ? pTbData->pHead : NULL;
+ for (; pDelData; pDelData = pDelData->pNext) {
+ if (taosArrayPush(pCommitter->aDelData, pDelData) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
- tsdbInfo("vgId:%d, start to commit", REPO_ID(pTsdb));
+ // write
+ code = tsdbWriteDelData(pCommitter->pDelFWriter, pCommitter->aDelData, NULL, &delIdx);
+ if (code) goto _err;
- if (tsdbInitCommitH(pCHandle, pTsdb) < 0) {
- return -1;
+ // put delIdx
+ if (taosArrayPush(pCommitter->aDelIdxN, &delIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
}
- tsdbStartFSTxn(pTsdb, 0, 0);
-
+_exit:
return code;
-}
-
-static int32_t tsdbEndCommit(SCommitH *pCHandle, int eno) {
- int32_t code = 0;
- STsdb *pTsdb = TSDB_COMMIT_REPO(pCHandle);
-
- tsdbDestroyCommitH(pCHandle);
- tsdbEndFSTxn(pTsdb);
- tsdbMemTableDestroy(pTsdb->imem);
- pTsdb->imem = NULL;
-
- tsdbInfo("vgId:%d, commit over, %s", REPO_ID(pTsdb), (eno == TSDB_CODE_SUCCESS) ? "succeed" : "failed");
+_err:
+ tsdbError("vgId:%d commit table del failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
return code;
}
-static int tsdbInitCommitH(SCommitH *pCommith, STsdb *pRepo) {
- STsdbCfg *pCfg = REPO_CFG(pRepo);
-
- memset(pCommith, 0, sizeof(*pCommith));
- tsdbGetRtnSnap(pRepo, &(pCommith->rtn));
-
- TSDB_FSET_SET_CLOSED(TSDB_COMMIT_WRITE_FSET(pCommith));
+static int32_t tsdbCommitDelEnd(SCommitter *pCommitter) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
- // Init read handle
- if (tsdbInitReadH(&(pCommith->readh), pRepo) < 0) {
- return -1;
- }
+ code = tsdbWriteDelIdx(pCommitter->pDelFWriter, pCommitter->aDelIdxN, NULL);
+ if (code) goto _err;
- // Init file iterator
- tsdbFSIterInit(&(pCommith->fsIter), REPO_FS(pRepo), TSDB_FS_ITER_FORWARD);
+ code = tsdbUpdateDelFileHdr(pCommitter->pDelFWriter);
+ if (code) goto _err;
- if (tsdbCreateCommitIters(pCommith) < 0) {
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ code = tsdbFSStateUpsertDelFile(pTsdb->fs->nState, &pCommitter->pDelFWriter->fDel);
+ if (code) goto _err;
- pCommith->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
- if (pCommith->aBlkIdx == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ code = tsdbDelFWriterClose(&pCommitter->pDelFWriter, 1);
+ if (code) goto _err;
- pCommith->aSupBlk = taosArrayInit(1024, sizeof(SBlock));
- if (pCommith->aSupBlk == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyCommitH(pCommith);
- return -1;
+ if (pCommitter->pDelFReader) {
+ code = tsdbDelFReaderClose(&pCommitter->pDelFReader);
+ if (code) goto _err;
}
- pCommith->aSubBlk = taosArrayInit(1024, sizeof(SBlock));
- if (pCommith->aSubBlk == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ taosArrayDestroy(pCommitter->aDelIdx);
+ taosArrayDestroy(pCommitter->aDelData);
+ taosArrayDestroy(pCommitter->aDelIdxN);
- pCommith->pDataCols = tdNewDataCols(0, pCfg->maxRows);
- if (pCommith->pDataCols == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyCommitH(pCommith);
- return -1;
- }
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d commit del end failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
}
-// Skip all keys until key (not included)
-static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key) {
- for (int i = 0; i < pCommith->niters; i++) {
- SCommitIter *pIter = pCommith->iters + i;
- if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
-
- tsdbLoadDataFromCache(TSDB_COMMIT_REPO(pCommith), pIter->pTable, pIter->pIter, key - 1, INT32_MAX, NULL, NULL, 0,
- true, NULL);
- }
-}
+static int32_t tsdbCommitFileDataStart(SCommitter *pCommitter) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SDFileSet *pRSet = NULL;
+ SDFileSet wSet;
+
+ // memory
+ pCommitter->nextKey = TSKEY_MAX;
+
+ // old
+ taosArrayClear(pCommitter->aBlockIdx);
+ tMapDataReset(&pCommitter->oBlockMap);
+ tBlockDataReset(&pCommitter->oBlockData);
+ pRSet = tsdbFSStateGetDFileSet(pTsdb->fs->nState, pCommitter->commitFid);
+ if (pRSet) {
+ code = tsdbDataFReaderOpen(&pCommitter->pReader, pTsdb, pRSet);
+ if (code) goto _err;
+
+ code = tsdbReadBlockIdx(pCommitter->pReader, pCommitter->aBlockIdx, NULL);
+ if (code) goto _err;
+ }
+
+ // new
+ taosArrayClear(pCommitter->aBlockIdxN);
+ tMapDataReset(&pCommitter->nBlockMap);
+ tBlockDataReset(&pCommitter->nBlockData);
+ if (pRSet) {
+ wSet = (SDFileSet){.diskId = pRSet->diskId,
+ .fid = pCommitter->commitFid,
+ .fHead = {.commitID = pCommitter->commitID, .offset = 0, .size = 0},
+ .fData = pRSet->fData,
+ .fLast = {.commitID = pCommitter->commitID, .size = 0},
+ .fSma = pRSet->fSma};
+ } else {
+ STfs *pTfs = pTsdb->pVnode->pTfs;
+ SDiskID did = {.level = 0, .id = 0};
-static int tsdbNextCommitFid(SCommitH *pCommith) {
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbKeepCfg *pCfg = REPO_KEEP_CFG(pRepo);
- int fid = TSDB_IVLD_FID;
+ // TODO: alloc a new disk
+ // tfsAllocDisk(pTfs, 0, &did);
- for (int i = 0; i < pCommith->niters; i++) {
- SCommitIter *pIter = pCommith->iters + i;
- // if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
+ // create the directory
+ tfsMkdirRecurAt(pTfs, pTsdb->path, did);
- TSKEY nextKey = tsdbNextIterKey(pIter->pIter);
- if (nextKey == TSDB_DATA_TIMESTAMP_NULL) {
- continue;
- } else {
- int tfid = (int)(TSDB_KEY_FID(nextKey, pCfg->days, pCfg->precision));
- if (fid == TSDB_IVLD_FID || fid > tfid) {
- fid = tfid;
- }
- }
+ wSet = (SDFileSet){.diskId = did,
+ .fid = pCommitter->commitFid,
+ .fHead = {.commitID = pCommitter->commitID, .offset = 0, .size = 0},
+ .fData = {.commitID = pCommitter->commitID, .size = 0},
+ .fLast = {.commitID = pCommitter->commitID, .size = 0},
+ .fSma = {.commitID = pCommitter->commitID, .size = 0}};
}
+ code = tsdbDataFWriterOpen(&pCommitter->pWriter, pTsdb, &wSet);
+ if (code) goto _err;
- return fid;
-}
-
-static void tsdbDestroyCommitH(SCommitH *pCommith) {
- pCommith->pDataCols = tdFreeDataCols(pCommith->pDataCols);
- pCommith->aSubBlk = taosArrayDestroy(pCommith->aSubBlk);
- pCommith->aSupBlk = taosArrayDestroy(pCommith->aSupBlk);
- pCommith->aBlkIdx = taosArrayDestroy(pCommith->aBlkIdx);
- tsdbDestroyCommitIters(pCommith);
- tsdbDestroyReadH(&(pCommith->readh));
- tsdbCloseDFileSet(TSDB_COMMIT_WRITE_FSET(pCommith));
-}
-
-static int32_t tsdbCommitToFileStart(SCommitH *pCHandle, SDFileSet *pSet, int32_t fid) {
- int32_t code = 0;
- STsdb *pRepo = TSDB_COMMIT_REPO(pCHandle);
- STsdbKeepCfg *pCfg = REPO_KEEP_CFG(pRepo);
-
- ASSERT(pSet == NULL || pSet->fid == fid);
-
- pCHandle->fid = fid;
- pCHandle->pSet = pSet;
- pCHandle->isRFileSet = false;
- pCHandle->isDFileSame = false;
- pCHandle->isLFileSame = false;
- taosArrayClear(pCHandle->aBlkIdx);
-
- tsdbGetFidKeyRange(pCfg->days, pCfg->precision, fid, &(pCHandle->minKey), &(pCHandle->maxKey));
-
- code = tsdbSetAndOpenCommitFile(pCHandle, pSet, fid);
-
+_exit:
return code;
-}
-static int32_t tsdbCommitToFileImpl(SCommitH *pCHandle) {
- int32_t code = 0;
- // TODO
+
+_err:
+ tsdbError("vgId:%d commit file data start failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
return code;
}
-static int32_t tsdbCommitToFileEnd(SCommitH *pCommith) {
+
+static int32_t tsdbCommitterUpdateTableSchema(SCommitter *pCommitter, int64_t suid, int64_t uid, int32_t sver) {
int32_t code = 0;
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
-
- if (tsdbWriteBlockIdx(TSDB_COMMIT_HEAD_FILE(pCommith), pCommith->aBlkIdx, (void **)(&(TSDB_COMMIT_BUF(pCommith)))) <
- 0) {
- tsdbError("vgId:%d, failed to write SBlockIdx part to FSET %d since %s", REPO_ID(pRepo), pCommith->fid,
- tstrerror(terrno));
- tsdbCloseCommitFile(pCommith, true);
- // revert the file change
- tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pCommith->pSet);
- return -1;
- }
- if (tsdbUpdateDFileSetHeader(&(pCommith->wSet)) < 0) {
- tsdbError("vgId:%d, failed to update FSET %d header since %s", REPO_ID(pRepo), pCommith->fid, tstrerror(terrno));
- tsdbCloseCommitFile(pCommith, true);
- // revert the file change
- tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pCommith->pSet);
- return -1;
+ if (pCommitter->skmTable.pTSchema) {
+ if (pCommitter->skmTable.suid == suid) {
+ if (suid == 0) {
+ if (pCommitter->skmTable.uid == uid && sver == pCommitter->skmTable.pTSchema->version) goto _exit;
+ } else {
+ if (sver == pCommitter->skmTable.pTSchema->version) goto _exit;
+ }
+ }
}
- // Close commit file
- tsdbCloseCommitFile(pCommith, false);
-
- if (tsdbUpdateDFileSet(REPO_FS(pRepo), &(pCommith->wSet)) < 0) {
- return -1;
- }
+ pCommitter->skmTable.suid = suid;
+ pCommitter->skmTable.uid = uid;
+ tTSchemaDestroy(pCommitter->skmTable.pTSchema);
+ code = metaGetTbTSchemaEx(pCommitter->pTsdb->pVnode->pMeta, suid, uid, sver, &pCommitter->skmTable.pTSchema);
+ if (code) goto _exit;
+_exit:
return code;
}
-static int32_t tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid) {
- int32_t code = 0;
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbKeepCfg *pCfg = REPO_KEEP_CFG(pRepo);
-
- // commit to file start
- code = tsdbCommitToFileStart(pCommith, pSet, fid);
- if (code) {
- goto _err;
- }
-
- // Loop to commit each table data in mem and file
- int mIter = 0, fIter = 0;
- int nBlkIdx = taosArrayGetSize(pCommith->readh.aBlkIdx);
- while (true) {
- SBlockIdx *pIdx = NULL;
- SCommitIter *pIter = NULL;
- if (mIter < pCommith->niters) {
- pIter = pCommith->iters + mIter;
- if (fIter < nBlkIdx) {
- pIdx = taosArrayGet(pCommith->readh.aBlkIdx, fIter);
- }
- } else if (fIter < nBlkIdx) {
- pIdx = taosArrayGet(pCommith->readh.aBlkIdx, fIter);
- } else {
- break;
- }
-
- if (pIter && pIter->pTable &&
- (!pIdx || ((pIter->pTable->suid < pIdx->suid) ||
- ((pIter->pTable->suid == pIdx->suid) && (pIter->pTable->uid <= pIdx->uid))))) {
- if (tsdbCommitToTable(pCommith, mIter) < 0) {
- tsdbCloseCommitFile(pCommith, true);
- // revert the file change
- tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
- return -1;
- }
+static int32_t tsdbCommitterUpdateRowSchema(SCommitter *pCommitter, int64_t suid, int64_t uid, int32_t sver) {
+ int32_t code = 0;
- if (pIdx && ((pIter->pTable->uid == pIdx->uid) && (pIter->pTable->suid == pIdx->suid))) {
- ++fIter;
- }
- ++mIter;
- } else if (pIter && !pIter->pTable) {
- // When table already dropped during commit, pIter is not NULL but pIter->pTable is NULL.
- ++mIter; // skip the table and do nothing
- } else if (pIdx) {
- if (tsdbMoveBlkIdx(pCommith, pIdx) < 0) {
- tsdbCloseCommitFile(pCommith, true);
- // revert the file change
- tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
- return -1;
+ if (pCommitter->skmRow.pTSchema) {
+ if (pCommitter->skmRow.suid == suid) {
+ if (suid == 0) {
+ if (pCommitter->skmRow.uid == uid && sver == pCommitter->skmRow.pTSchema->version) goto _exit;
+ } else {
+ if (sver == pCommitter->skmRow.pTSchema->version) goto _exit;
}
- ++fIter;
- } else {
- ASSERT(0);
}
}
- // commit to file end
- code = tsdbCommitToFileEnd(pCommith);
+ pCommitter->skmRow.suid = suid;
+ pCommitter->skmRow.uid = uid;
+ tTSchemaDestroy(pCommitter->skmRow.pTSchema);
+ code = metaGetTbTSchemaEx(pCommitter->pTsdb->pVnode->pMeta, suid, uid, sver, &pCommitter->skmRow.pTSchema);
if (code) {
- goto _err;
+ goto _exit;
}
- return code;
-
-_err:
+_exit:
return code;
}
-static int32_t tsdbCreateCommitIters(SCommitH *pCommith) {
- int32_t code = 0;
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- SMemTable *pMem = pRepo->imem;
- STbData *pTbData;
- SCommitIter *pCommitIter;
- STSchema *pTSchema = NULL;
-
- pCommith->niters = taosArrayGetSize(pMem->aTbData);
- pCommith->iters = (SCommitIter *)taosMemoryCalloc(pCommith->niters, sizeof(SCommitIter));
- if (pCommith->iters == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- goto _err;
- }
-
- for (int32_t iIter = 0; iIter < pCommith->niters; iIter++) {
- pTbData = (STbData *)taosArrayGetP(pMem->aTbData, iIter);
- pCommitIter = &pCommith->iters[iIter];
-
- pTSchema = metaGetTbTSchema(REPO_META(pRepo), pTbData->uid, -1);
- if (pTSchema) {
- tsdbTbDataIterCreate(pTbData, NULL, 0, &pCommitIter->pIter);
+static int32_t tsdbCommitBlockData(SCommitter *pCommitter, SBlockData *pBlockData, SBlock *pBlock, SBlockIdx *pBlockIdx,
+ int8_t toDataOnly) {
+ int32_t code = 0;
- pCommitIter->pTable = (STable *)taosMemoryMalloc(sizeof(STable));
- pCommitIter->pTable->uid = pTbData->uid;
- pCommitIter->pTable->suid = pTbData->suid;
- pCommitIter->pTable->pSchema = pTSchema;
- pCommitIter->pTable->pCacheSchema = NULL;
+ if (pBlock->nSubBlock == 0) {
+ if (!toDataOnly && pBlockData->nRow < pCommitter->minRow) {
+ pBlock->last = 1;
+ } else {
+ pBlock->last = 0;
}
}
+ code = tsdbWriteBlockData(pCommitter->pWriter, pBlockData, NULL, NULL, pBlockIdx, pBlock, pCommitter->cmprAlg);
+ if (code) goto _err;
+
+ code = tMapDataPutItem(&pCommitter->nBlockMap, pBlock, tPutBlock);
+ if (code) goto _err;
+
return code;
_err:
return code;
}
-static void tsdbDestroyCommitIters(SCommitH *pCommith) {
- if (pCommith->iters == NULL) return;
-
- for (int i = 1; i < pCommith->niters; i++) {
- tsdbTbDataIterDestroy(pCommith->iters[i].pIter);
- if (pCommith->iters[i].pTable) {
- tdFreeSchema(pCommith->iters[i].pTable->pSchema);
- tdFreeSchema(pCommith->iters[i].pTable->pCacheSchema);
- taosMemoryFreeClear(pCommith->iters[i].pTable);
- }
- }
-
- taosMemoryFree(pCommith->iters);
- pCommith->iters = NULL;
- pCommith->niters = 0;
-}
-
-static int tsdbSetAndOpenCommitFile(SCommitH *pCommith, SDFileSet *pSet, int fid) {
- SDiskID did;
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- SDFileSet *pWSet = TSDB_COMMIT_WRITE_FSET(pCommith);
-
- if (tfsAllocDisk(REPO_TFS(pRepo), tsdbGetFidLevel(fid, &(pCommith->rtn)), &did) < 0) {
- terrno = TSDB_CODE_TDB_NO_AVAIL_DISK;
- return -1;
- }
-
- // Open read FSET
- if (pSet) {
- if (tsdbSetAndOpenReadFSet(&(pCommith->readh), pSet) < 0) {
- return -1;
- }
-
- pCommith->isRFileSet = true;
-
- if (tsdbLoadBlockIdx(&(pCommith->readh)) < 0) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
+static int32_t tsdbMergeTableData(SCommitter *pCommitter, STbDataIter *pIter, SBlock *pBlockMerge, TSDBKEY toKey,
+ int8_t toDataOnly) {
+ int32_t code = 0;
+ SBlockIdx *pBlockIdx = &(SBlockIdx){.suid = pIter->pTbData->suid, .uid = pIter->pTbData->uid};
+ SBlockData *pBlockDataMerge = &pCommitter->oBlockData;
+ SBlockData *pBlockData = &pCommitter->nBlockData;
+ SBlock block;
+ SBlock *pBlock = █
+ TSDBROW *pRow1;
+ TSDBROW row2;
+ TSDBROW *pRow2 = &row2;
+
+ // read SBlockData
+ code = tsdbReadBlockData(pCommitter->pReader, pBlockIdx, pBlockMerge, pBlockDataMerge, NULL, NULL);
+ if (code) goto _err;
+
+ code = tBlockDataSetSchema(pBlockData, pCommitter->skmTable.pTSchema);
+ if (code) goto _err;
+
+ // loop to merge
+ pRow1 = tsdbTbDataIterGet(pIter);
+ *pRow2 = tsdbRowFromBlockData(pBlockDataMerge, 0);
+ ASSERT(pRow1 && tsdbKeyCmprFn(&TSDBROW_KEY(pRow1), &toKey) < 0);
+ ASSERT(tsdbKeyCmprFn(&TSDBROW_KEY(pRow2), &toKey) < 0);
+ code = tsdbCommitterUpdateRowSchema(pCommitter, pBlockIdx->suid, pBlockIdx->uid, TSDBROW_SVERSION(pRow1));
+ if (code) goto _err;
+
+ tBlockReset(pBlock);
+ tBlockDataClearData(pBlockData);
+ while (true) {
+ if (pRow1 == NULL && pRow2 == NULL) {
+ if (pBlockData->nRow == 0) {
+ break;
+ } else {
+ goto _write_block;
+ }
}
- tsdbDebug("vgId:%d, FSET %d at level %d disk id %d is opened to read to commit", REPO_ID(pRepo),
- TSDB_FSET_FID(pSet), TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet));
- } else {
- pCommith->isRFileSet = false;
- }
-
- // Set and open commit FSET
- if (pSet == NULL || did.level > TSDB_FSET_LEVEL(pSet)) {
- // Create a new FSET to write data
- tsdbInitDFileSet(pRepo, pWSet, did, fid, FS_TXN_VERSION(REPO_FS(pRepo)));
-
- if (tsdbCreateDFileSet(pRepo, pWSet, true) < 0) {
- tsdbError("vgId:%d, failed to create FSET %d at level %d disk id %d since %s", REPO_ID(pRepo),
- TSDB_FSET_FID(pWSet), TSDB_FSET_LEVEL(pWSet), TSDB_FSET_ID(pWSet), tstrerror(terrno));
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
+ if (pRow1 && pRow2) {
+ int32_t c = tsdbRowCmprFn(pRow1, pRow2);
+ if (c < 0) {
+ goto _append_mem_row;
+ } else if (c > 0) {
+ goto _append_block_row;
+ } else {
+ ASSERT(0);
}
- return -1;
+ } else if (pRow1) {
+ goto _append_mem_row;
+ } else {
+ goto _append_block_row;
}
- pCommith->isDFileSame = false;
- pCommith->isLFileSame = false;
+ _append_mem_row:
+ code = tBlockDataAppendRow(pBlockData, pRow1, pCommitter->skmRow.pTSchema);
+ if (code) goto _err;
- tsdbDebug("vgId:%d, FSET %d at level %d disk id %d is created to commit", REPO_ID(pRepo), TSDB_FSET_FID(pWSet),
- TSDB_FSET_LEVEL(pWSet), TSDB_FSET_ID(pWSet));
- } else {
- did.level = TSDB_FSET_LEVEL(pSet);
- did.id = TSDB_FSET_ID(pSet);
-
- pCommith->wSet.fid = fid;
- pCommith->wSet.state = 0;
-
- // TSDB_FILE_HEAD
- SDFile *pWHeadf = TSDB_COMMIT_HEAD_FILE(pCommith);
- tsdbInitDFile(pRepo, pWHeadf, did, fid, FS_TXN_VERSION(REPO_FS(pRepo)), TSDB_FILE_HEAD);
- if (tsdbCreateDFile(pRepo, pWHeadf, true, TSDB_FILE_HEAD) < 0) {
- tsdbError("vgId:%d, failed to create file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWHeadf),
- tstrerror(terrno));
-
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
+ tsdbTbDataIterNext(pIter);
+ pRow1 = tsdbTbDataIterGet(pIter);
+ if (pRow1) {
+ if (tsdbKeyCmprFn(&TSDBROW_KEY(pRow1), &toKey) < 0) {
+ code = tsdbCommitterUpdateRowSchema(pCommitter, pBlockIdx->suid, pBlockIdx->uid, TSDBROW_SVERSION(pRow1));
+ if (code) goto _err;
+ } else {
+ pRow1 = NULL;
}
}
- // TSDB_FILE_DATA
- SDFile *pRDataf = TSDB_READ_DATA_FILE(&(pCommith->readh));
- SDFile *pWDataf = TSDB_COMMIT_DATA_FILE(pCommith);
- tsdbInitDFileEx(pWDataf, pRDataf);
- // if (tsdbOpenDFile(pWDataf, O_WRONLY) < 0) {
- if (tsdbOpenDFile(pWDataf, TD_FILE_WRITE) < 0) {
- tsdbError("vgId:%d, failed to open file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWDataf),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
- pCommith->isDFileSame = true;
-
- // TSDB_FILE_LAST
- SDFile *pRLastf = TSDB_READ_LAST_FILE(&(pCommith->readh));
- SDFile *pWLastf = TSDB_COMMIT_LAST_FILE(pCommith);
- if (pRLastf->info.size < 32 * 1024) {
- tsdbInitDFileEx(pWLastf, pRLastf);
- pCommith->isLFileSame = true;
-
- // if (tsdbOpenDFile(pWLastf, O_WRONLY) < 0) {
- if (tsdbOpenDFile(pWLastf, TD_FILE_WRITE) < 0) {
- tsdbError("vgId:%d, failed to open file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWLastf),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ if (pBlockData->nRow >= pCommitter->maxRow * 4 / 5) {
+ goto _write_block;
} else {
- tsdbInitDFile(pRepo, pWLastf, did, fid, FS_TXN_VERSION(REPO_FS(pRepo)), TSDB_FILE_LAST);
- pCommith->isLFileSame = false;
-
- if (tsdbCreateDFile(pRepo, pWLastf, true, TSDB_FILE_LAST) < 0) {
- tsdbError("vgId:%d, failed to create file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWLastf),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- (void)tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ continue;
}
- // TSDB_FILE_SMAD
- SDFile *pRSmadF = TSDB_READ_SMAD_FILE(&(pCommith->readh));
- SDFile *pWSmadF = TSDB_COMMIT_SMAD_FILE(pCommith);
-
- if (!taosCheckExistFile(TSDB_FILE_FULL_NAME(pRSmadF))) {
- tsdbDebug("vgId:%d, create data file %s as not exist", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pRSmadF));
- tsdbInitDFile(pRepo, pWSmadF, did, fid, FS_TXN_VERSION(REPO_FS(pRepo)), TSDB_FILE_SMAD);
-
- if (tsdbCreateDFile(pRepo, pWSmadF, true, TSDB_FILE_SMAD) < 0) {
- tsdbError("vgId:%d, failed to create file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWSmadF),
- tstrerror(terrno));
+ _append_block_row:
+ code = tBlockDataAppendRow(pBlockData, pRow2, NULL);
+ if (code) goto _err;
- tsdbCloseDFileSet(pWSet);
- (void)tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ if (pRow2->iRow + 1 < pBlockDataMerge->nRow) {
+ *pRow2 = tsdbRowFromBlockData(pBlockDataMerge, pRow2->iRow + 1);
} else {
- tsdbInitDFileEx(pWSmadF, pRSmadF);
- if (tsdbOpenDFile(pWSmadF, O_RDWR) < 0) {
- tsdbError("vgId:%d, failed to open file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWSmadF),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ pRow2 = NULL;
}
- // TSDB_FILE_SMAL
- SDFile *pRSmalF = TSDB_READ_SMAL_FILE(&(pCommith->readh));
- SDFile *pWSmalF = TSDB_COMMIT_SMAL_FILE(pCommith);
-
- if ((pCommith->isLFileSame) && taosCheckExistFile(TSDB_FILE_FULL_NAME(pRSmalF))) {
- tsdbInitDFileEx(pWSmalF, pRSmalF);
- if (tsdbOpenDFile(pWSmalF, O_RDWR) < 0) {
- tsdbError("vgId:%d, failed to open file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWSmalF),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ if (pBlockData->nRow >= pCommitter->maxRow * 4 / 5) {
+ goto _write_block;
} else {
- tsdbDebug("vgId:%d, create data file %s as not exist", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pRSmalF));
- tsdbInitDFile(pRepo, pWSmalF, did, fid, FS_TXN_VERSION(REPO_FS(pRepo)), TSDB_FILE_SMAL);
-
- if (tsdbCreateDFile(pRepo, pWSmalF, true, TSDB_FILE_SMAL) < 0) {
- tsdbError("vgId:%d, failed to create file %s to commit since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pWSmalF),
- tstrerror(terrno));
-
- tsdbCloseDFileSet(pWSet);
- (void)tsdbRemoveDFile(pWHeadf);
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
- return -1;
- }
- }
+ continue;
}
- }
- return 0;
-}
+ _write_block:
+ code = tsdbCommitBlockData(pCommitter, pBlockData, pBlock, pBlockIdx, toDataOnly);
+ if (code) goto _err;
-// extern int32_t tsTsdbMetaCompactRatio;
-
-static int tsdbWriteBlockInfoImpl(SDFile *pHeadf, STable *pTable, SArray *pSupA, SArray *pSubA, void **ppBuf,
- SBlockIdx *pIdx) {
- size_t nSupBlocks;
- size_t nSubBlocks;
- uint32_t tlen;
- SBlockInfo *pBlkInfo;
- int64_t offset;
- SBlock *pBlock;
-
- memset(pIdx, 0, sizeof(*pIdx));
-
- nSupBlocks = taosArrayGetSize(pSupA);
- nSubBlocks = (pSubA == NULL) ? 0 : taosArrayGetSize(pSubA);
-
- if (nSupBlocks <= 0) {
- // No data (data all deleted)
- return 0;
+ tBlockReset(pBlock);
+ tBlockDataClearData(pBlockData);
}
- tlen = (uint32_t)(sizeof(SBlockInfo) + sizeof(SBlock) * (nSupBlocks + nSubBlocks) + sizeof(TSCKSUM));
- if (tsdbMakeRoom(ppBuf, tlen) < 0) return -1;
- pBlkInfo = *ppBuf;
-
- pBlkInfo->delimiter = TSDB_FILE_DELIMITER;
- pBlkInfo->suid = pTable->suid;
- pBlkInfo->uid = pTable->uid;
-
- memcpy((void *)(pBlkInfo->blocks), taosArrayGet(pSupA, 0), nSupBlocks * sizeof(SBlock));
- if (nSubBlocks > 0) {
- memcpy((void *)(pBlkInfo->blocks + nSupBlocks), taosArrayGet(pSubA, 0), nSubBlocks * sizeof(SBlock));
+ return code;
- for (int i = 0; i < nSupBlocks; i++) {
- pBlock = pBlkInfo->blocks + i;
+_err:
+ tsdbError("vgId:%d tsdb merge block and mem failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- if (pBlock->numOfSubBlocks > 1) {
- pBlock->offset += (sizeof(SBlockInfo) + sizeof(SBlock) * nSupBlocks);
+static int32_t tsdbCommitTableMemData(SCommitter *pCommitter, STbDataIter *pIter, TSDBKEY toKey, int8_t toDataOnly) {
+ int32_t code = 0;
+ TSDBROW *pRow;
+ SBlock block;
+ SBlock *pBlock = █
+ SBlockData *pBlockData = &pCommitter->nBlockData;
+ int64_t suid = pIter->pTbData->suid;
+ int64_t uid = pIter->pTbData->uid;
+
+ code = tBlockDataSetSchema(pBlockData, pCommitter->skmTable.pTSchema);
+ if (code) goto _err;
+
+ tBlockReset(pBlock);
+ tBlockDataClearData(pBlockData);
+ pRow = tsdbTbDataIterGet(pIter);
+ ASSERT(pRow && tsdbKeyCmprFn(&TSDBROW_KEY(pRow), &toKey) < 0);
+ while (true) {
+ if (pRow == NULL) {
+ if (pBlockData->nRow > 0) {
+ goto _write_block;
+ } else {
+ break;
}
}
- }
- taosCalcChecksumAppend(0, (uint8_t *)pBlkInfo, tlen);
-
- if (tsdbAppendDFile(pHeadf, (void *)pBlkInfo, tlen, &offset) < 0) {
- return -1;
- }
-
- tsdbUpdateDFileMagic(pHeadf, POINTER_SHIFT(pBlkInfo, tlen - sizeof(TSCKSUM)));
+ // update schema
+ code = tsdbCommitterUpdateRowSchema(pCommitter, suid, uid, TSDBROW_SVERSION(pRow));
+ if (code) goto _err;
+
+ // append
+ code = tBlockDataAppendRow(pBlockData, pRow, pCommitter->skmRow.pTSchema);
+ if (code) goto _err;
+
+ tsdbTbDataIterNext(pIter);
+ pRow = tsdbTbDataIterGet(pIter);
+ // if (pRow && tsdbKeyCmprFn(&TSDBROW_KEY(pRow), &toKey) >= 0) pRow = NULL;
+ // crash on CI, use the block following
+ if (pRow) {
+ TSDBKEY tmpKey = TSDBROW_KEY(pRow);
+ if (tsdbKeyCmprFn(&tmpKey, &toKey) >= 0) {
+ pRow = NULL;
+ }
+ }
- // Set pIdx
- pBlock = taosArrayGetLast(pSupA);
+ if (pBlockData->nRow >= pCommitter->maxRow * 4 / 5) goto _write_block;
+ continue;
- pIdx->suid = pTable->suid;
- pIdx->uid = pTable->uid;
- pIdx->hasLast = pBlock->last ? 1 : 0;
- pIdx->maxKey = pBlock->maxKey;
- pIdx->numOfBlocks = (uint32_t)nSupBlocks;
- pIdx->len = tlen;
- pIdx->offset = (uint32_t)offset;
+ _write_block:
+ code = tsdbCommitBlockData(pCommitter, pBlockData, pBlock, &(SBlockIdx){.suid = suid, .uid = uid}, toDataOnly);
+ if (code) goto _err;
- return 0;
-}
-
-static int tsdbWriteBlockIdx(SDFile *pHeadf, SArray *pIdxA, void **ppBuf) {
- SBlockIdx *pBlkIdx;
- size_t nidx = taosArrayGetSize(pIdxA);
- int tlen = 0, size;
- int64_t offset;
-
- if (nidx <= 0) {
- // All data are deleted
- pHeadf->info.offset = 0;
- pHeadf->info.len = 0;
- return 0;
+ tBlockReset(pBlock);
+ tBlockDataClearData(pBlockData);
}
- for (size_t i = 0; i < nidx; i++) {
- pBlkIdx = (SBlockIdx *)taosArrayGet(pIdxA, i);
-
- size = tsdbEncodeSBlockIdx(NULL, pBlkIdx);
- if (tsdbMakeRoom(ppBuf, tlen + size) < 0) return -1;
+ return code;
- void *ptr = POINTER_SHIFT(*ppBuf, tlen);
- tsdbEncodeSBlockIdx(&ptr, pBlkIdx);
+_err:
+ tsdbError("vgId:%d tsdb commit table mem data failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- tlen += size;
- }
+static int32_t tsdbCommitTableDiskData(SCommitter *pCommitter, SBlock *pBlock, SBlockIdx *pBlockIdx) {
+ int32_t code = 0;
+ SBlock block;
- tlen += sizeof(TSCKSUM);
- if (tsdbMakeRoom(ppBuf, tlen) < 0) return -1;
- taosCalcChecksumAppend(0, (uint8_t *)(*ppBuf), tlen);
+ if (pBlock->last) {
+ code = tsdbReadBlockData(pCommitter->pReader, pBlockIdx, pBlock, &pCommitter->oBlockData, NULL, NULL);
+ if (code) goto _err;
- if (tsdbAppendDFile(pHeadf, *ppBuf, tlen, &offset) < tlen) {
- return -1;
+ tBlockReset(&block);
+ code = tsdbCommitBlockData(pCommitter, &pCommitter->oBlockData, &block, pBlockIdx, 0);
+ if (code) goto _err;
+ } else {
+ code = tMapDataPutItem(&pCommitter->nBlockMap, pBlock, tPutBlock);
+ if (code) goto _err;
}
- tsdbUpdateDFileMagic(pHeadf, POINTER_SHIFT(*ppBuf, tlen - sizeof(TSCKSUM)));
- pHeadf->info.offset = (uint32_t)offset;
- pHeadf->info.len = tlen;
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb commit table disk data failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
}
-// =================== Commit Time-Series Data
-static int tsdbCommitToTable(SCommitH *pCommith, int tid) {
- SCommitIter *pIter = pCommith->iters + tid;
- TSKEY nextKey = tsdbNextIterKey(pIter->pIter);
-
- tsdbResetCommitTable(pCommith);
+static int32_t tsdbCommitTableDataEnd(SCommitter *pCommitter, int64_t suid, int64_t uid) {
+ int32_t code = 0;
+ SBlockIdx blockIdx = {.suid = suid, .uid = uid};
+ SBlockIdx *pBlockIdx = &blockIdx;
- // Set commit table
- if (tsdbSetCommitTable(pCommith, pIter->pTable) < 0) {
- return -1;
- }
+ code = tsdbWriteBlock(pCommitter->pWriter, &pCommitter->nBlockMap, NULL, pBlockIdx);
+ if (code) goto _err;
- // No disk data and no memory data, just return
- if (pCommith->readh.pBlkIdx == NULL && (nextKey == TSDB_DATA_TIMESTAMP_NULL || nextKey > pCommith->maxKey)) {
- return 0;
+ if (taosArrayPush(pCommitter->aBlockIdxN, pBlockIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
}
- // Must has disk data or has memory data
- int nBlocks;
- int bidx = 0;
- SBlock *pBlock;
-
- if (pCommith->readh.pBlkIdx) {
- if (tsdbLoadBlockInfo(&(pCommith->readh), NULL) < 0) {
- return -1;
- }
+ return code;
- nBlocks = pCommith->readh.pBlkIdx->numOfBlocks;
- } else {
- nBlocks = 0;
- }
+_err:
+ tsdbError("vgId:%d commit table data end failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- if (bidx < nBlocks) {
- pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- } else {
- pBlock = NULL;
- }
+static int32_t tsdbGetOvlpNRow(STbDataIter *pIter, SBlock *pBlock) {
+ int32_t nRow = 0;
+ TSDBROW *pRow;
+ TSDBKEY key;
+ int32_t c = 0;
+ STbDataIter iter = *pIter;
+ iter.pRow = NULL;
while (true) {
- if (pBlock == NULL && (nextKey == TSDB_DATA_TIMESTAMP_NULL || nextKey > pCommith->maxKey)) break;
+ pRow = tsdbTbDataIterGet(&iter);
- if ((nextKey == TSDB_DATA_TIMESTAMP_NULL || nextKey > pCommith->maxKey) ||
- (pBlock && (!pBlock->last) && tsdbComparKeyBlock((void *)(&nextKey), pBlock) > 0)) {
- if (tsdbMoveBlock(pCommith, bidx) < 0) {
- return -1;
- }
+ if (pRow == NULL) break;
+ key = TSDBROW_KEY(pRow);
- bidx++;
- if (bidx < nBlocks) {
- pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- } else {
- pBlock = NULL;
- }
- } else if (pBlock && (pBlock->last || tsdbComparKeyBlock((void *)(&nextKey), pBlock) == 0)) {
- // merge pBlock data and memory data
- if (tsdbMergeMemData(pCommith, pIter, bidx) < 0) {
- return -1;
- }
-
- bidx++;
- if (bidx < nBlocks) {
- pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- } else {
- pBlock = NULL;
- }
- nextKey = tsdbNextIterKey(pIter->pIter);
+ c = tBlockCmprFn(&(SBlock){.maxKey = key, .minKey = key}, pBlock);
+ if (c == 0) {
+ nRow++;
+ tsdbTbDataIterNext(&iter);
+ } else if (c > 0) {
+ break;
} else {
- // Only commit memory data
- if (pBlock == NULL) {
- if (tsdbCommitMemData(pCommith, pIter, pCommith->maxKey, false) < 0) {
- return -1;
- }
- } else {
- if (tsdbCommitMemData(pCommith, pIter, pBlock->minKey.ts - 1, true) < 0) {
- return -1;
- }
- }
- nextKey = tsdbNextIterKey(pIter->pIter);
+ ASSERT(0);
}
}
- if (tsdbWriteBlockInfo(pCommith) < 0) {
- tsdbError("vgId:%d, failed to write SBlockInfo part into file %s since %s", TSDB_COMMIT_REPO_ID(pCommith),
- TSDB_FILE_FULL_NAME(TSDB_COMMIT_HEAD_FILE(pCommith)), tstrerror(terrno));
- return -1;
- }
-
- return 0;
+ return nRow;
}
-static int tsdbMoveBlkIdx(SCommitH *pCommith, SBlockIdx *pIdx) {
- SReadH *pReadh = &pCommith->readh;
- STsdb *pTsdb = TSDB_READ_REPO(pReadh);
- STSchema *pTSchema = NULL;
- int nBlocks = pIdx->numOfBlocks;
- int bidx = 0;
+static int32_t tsdbMergeAsSubBlock(SCommitter *pCommitter, STbDataIter *pIter, SBlock *pBlock) {
+ int32_t code = 0;
+ SBlockData *pBlockData = &pCommitter->nBlockData;
+ SBlockIdx *pBlockIdx = &(SBlockIdx){.suid = pIter->pTbData->suid, .uid = pIter->pTbData->uid};
+ SBlock block;
+ TSDBROW *pRow;
- tsdbResetCommitTable(pCommith);
+ code = tBlockDataSetSchema(pBlockData, pCommitter->skmTable.pTSchema);
+ if (code) goto _err;
- pReadh->pBlkIdx = pIdx;
-
- if (tsdbLoadBlockInfo(pReadh, NULL) < 0) {
- return -1;
- }
-
- STable table = {.suid = pIdx->suid, .uid = pIdx->uid, .pSchema = NULL};
- pCommith->pTable = &table;
-
- while (bidx < nBlocks) {
- if (!pTSchema && !tsdbCommitIsSameFile(pCommith, bidx)) {
- // Set commit table
- pTSchema = metaGetTbTSchema(REPO_META(pTsdb), pIdx->uid, -1); // TODO: schema version
- if (!pTSchema) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
- table.pSchema = pTSchema;
- if (tsdbSetCommitTable(pCommith, &table) < 0) {
- taosMemoryFreeClear(pTSchema);
- return -1;
+ pRow = tsdbTbDataIterGet(pIter);
+ code = tsdbCommitterUpdateRowSchema(pCommitter, pBlockIdx->suid, pBlockIdx->uid, TSDBROW_SVERSION(pRow));
+ if (code) goto _err;
+ while (true) {
+ if (pRow == NULL) break;
+ code = tBlockDataAppendRow(pBlockData, pRow, pCommitter->skmRow.pTSchema);
+ if (code) goto _err;
+
+ tsdbTbDataIterNext(pIter);
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow) {
+ TSDBKEY key = TSDBROW_KEY(pRow);
+ int32_t c = tBlockCmprFn(&(SBlock){.minKey = key, .maxKey = key}, pBlock);
+
+ if (c == 0) {
+ code =
+ tsdbCommitterUpdateRowSchema(pCommitter, pIter->pTbData->suid, pIter->pTbData->uid, TSDBROW_SVERSION(pRow));
+ if (code) goto _err;
+ } else if (c > 0) {
+ pRow = NULL;
+ } else {
+ ASSERT(0);
}
}
-
- if (tsdbMoveBlock(pCommith, bidx) < 0) {
- tsdbError("vgId:%d, failed to move block into file %s since %s", TSDB_COMMIT_REPO_ID(pCommith),
- TSDB_FILE_FULL_NAME(TSDB_COMMIT_HEAD_FILE(pCommith)), tstrerror(terrno));
- taosMemoryFreeClear(pTSchema);
- return -1;
- }
-
- ++bidx;
}
- if (tsdbWriteBlockInfo(pCommith) < 0) {
- tsdbError("vgId:%d, failed to write SBlockInfo part into file %s since %s", TSDB_COMMIT_REPO_ID(pCommith),
- TSDB_FILE_FULL_NAME(TSDB_COMMIT_HEAD_FILE(pCommith)), tstrerror(terrno));
- taosMemoryFreeClear(pTSchema);
- return -1;
- }
+ block = *pBlock;
+ code = tsdbCommitBlockData(pCommitter, pBlockData, &block, pBlockIdx, 0);
+ if (code) goto _err;
+
+ return code;
- taosMemoryFreeClear(pTSchema);
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb merge as subblock failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static int tsdbSetCommitTable(SCommitH *pCommith, STable *pTable) {
- STSchema *pSchema = tsdbGetTableSchemaImpl(TSDB_COMMIT_REPO(pCommith), pTable, false, false, -1);
+static int32_t tsdbCommitTableData(SCommitter *pCommitter, STbData *pTbData, SBlockIdx *pBlockIdx) {
+ int32_t code = 0;
+ STbDataIter iter = {0};
+ STbDataIter *pIter = &iter;
+ TSDBROW *pRow;
+ int32_t iBlock;
+ int32_t nBlock;
+ int64_t suid;
+ int64_t uid;
+
+ if (pTbData) {
+ tsdbTbDataIterOpen(pTbData, &(TSDBKEY){.ts = pCommitter->minKey, .version = VERSION_MIN}, 0, pIter);
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow && TSDBROW_TS(pRow) > pCommitter->maxKey) pRow = NULL;
+
+ suid = pTbData->suid;
+ uid = pTbData->uid;
+ } else {
+ pIter = NULL;
+ pRow = NULL;
+ }
- pCommith->pTable = pTable;
+ if (pBlockIdx) {
+ code = tsdbReadBlock(pCommitter->pReader, pBlockIdx, &pCommitter->oBlockMap, NULL);
+ if (code) goto _err;
- if (tdInitDataCols(pCommith->pDataCols, pSchema) < 0) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
+ nBlock = pCommitter->oBlockMap.nItem;
+ ASSERT(nBlock > 0);
- if (pCommith->isRFileSet) {
- if (tsdbSetReadTable(&(pCommith->readh), pTable) < 0) {
- return -1;
- }
+ suid = pBlockIdx->suid;
+ uid = pBlockIdx->uid;
} else {
- pCommith->readh.pBlkIdx = NULL;
+ nBlock = 0;
}
- return 0;
-}
-static int tsdbComparKeyBlock(const void *arg1, const void *arg2) {
- TSKEY key = *(TSKEY *)arg1;
- SBlock *pBlock = (SBlock *)arg2;
+ if (pRow == NULL && nBlock == 0) goto _exit;
- if (key < pBlock->minKey.ts) {
- return -1;
- } else if (key > pBlock->maxKey.ts) {
- return 1;
+ // start ===========
+ tMapDataReset(&pCommitter->nBlockMap);
+ SBlock block;
+ SBlock *pBlock = █
+
+ iBlock = 0;
+ if (iBlock < nBlock) {
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock, pBlock, tGetBlock);
} else {
- return 0;
+ pBlock = NULL;
}
-}
-/**
- * @brief Write SDataCols to data file.
- *
- * @param pRepo
- * @param pTable
- * @param pDFile
- * @param pDFileAggr
- * @param pDataCols The pDataCols would be generated from mem/imem directly with 2 bits bitmap or from tsdbRead
- * interface with 1 bit bitmap.
- * @param pBlock
- * @param isLast
- * @param isSuper
- * @param ppBuf
- * @param ppCBuf
- * @param ppExBuf
- * @return int
- */
-static int tsdbWriteBlockImpl(STsdb *pRepo, STable *pTable, SDFile *pDFile, SDFile *pDFileAggr, SDataCols *pDataCols,
- SBlock *pBlock, bool isLast, bool isSuper, void **ppBuf, void **ppCBuf, void **ppExBuf) {
- STsdbCfg *pCfg = REPO_CFG(pRepo);
- SBlockData *pBlockData = NULL;
- SAggrBlkData *pAggrBlkData = NULL;
- STSchema *pSchema = pTable->pSchema;
- int64_t offset = 0, offsetAggr = 0;
- int rowsToWrite = pDataCols->numOfRows;
-
- ASSERT(rowsToWrite > 0 && rowsToWrite <= pCfg->maxRows);
- ASSERT((!isLast) || rowsToWrite < pCfg->minRows);
-
- // Make buffer space
- if (tsdbMakeRoom(ppBuf, tsdbBlockStatisSize(pDataCols->numOfCols, SBlockVerLatest)) < 0) {
- return -1;
+ if (pRow) {
+ code = tsdbCommitterUpdateTableSchema(pCommitter, pTbData->suid, pTbData->uid, pTbData->maxSkmVer);
+ if (code) goto _err;
}
- pBlockData = (SBlockData *)(*ppBuf);
- if (tsdbMakeRoom(ppExBuf, tsdbBlockAggrSize(pDataCols->numOfCols, SBlockVerLatest)) < 0) {
- return -1;
- }
- pAggrBlkData = (SAggrBlkData *)(*ppExBuf);
-
- // Get # of cols not all NULL(not including key column)
- col_id_t nColsNotAllNull = 0;
- col_id_t nColsOfBlockSma = 0;
- for (int ncol = 1; ncol < pDataCols->numOfCols; ++ncol) { // ncol from 1, we skip the timestamp column
- STColumn *pColumn = pSchema->columns + ncol;
- SDataCol *pDataCol = pDataCols->cols + ncol;
- SBlockCol *pBlockCol = pBlockData->cols + nColsNotAllNull;
- SAggrBlkCol *pAggrBlkCol = (SAggrBlkCol *)pAggrBlkData + nColsOfBlockSma;
-
- if (isAllRowsNull(pDataCol)) { // all data to commit are NULL, just ignore it
- continue;
- }
+ // merge ===========
+ while (true) {
+ if (pRow == NULL && pBlock == NULL) break;
+
+ if (pRow && pBlock) {
+ if (pBlock->last) {
+ code = tsdbMergeTableData(pCommitter, pIter, pBlock,
+ (TSDBKEY){.ts = pCommitter->maxKey + 1, .version = VERSION_MIN}, 0);
+ if (code) goto _err;
+
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow && TSDBROW_TS(pRow) > pCommitter->maxKey) pRow = NULL;
+ iBlock++;
+ if (iBlock < nBlock) {
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock, pBlock, tGetBlock);
+ } else {
+ pBlock = NULL;
+ }
- memset(pBlockCol, 0, sizeof(*pBlockCol));
- memset(pAggrBlkCol, 0, sizeof(*pAggrBlkCol));
-
- pBlockCol->colId = pDataCol->colId;
- pBlockCol->type = pDataCol->type;
- pAggrBlkCol->colId = pDataCol->colId;
-
- if (isSuper && IS_BSMA_ON(pColumn) && tDataTypes[pDataCol->type].statisFunc) {
-#if 0
- (*tDataTypes[pDataCol->type].statisFunc)(pDataCol->pData, rowsToWrite, &(pBlockCol->min), &(pBlockCol->max),
- &(pBlockCol->sum), &(pBlockCol->minIndex), &(pBlockCol->maxIndex),
- &(pBlockCol->numOfNull));
-#endif
- (*tDataTypes[pDataCol->type].statisFunc)(pDataCols->bitmapMode, pDataCol->pBitmap, pDataCol->pData, rowsToWrite,
- &(pAggrBlkCol->min), &(pAggrBlkCol->max), &(pAggrBlkCol->sum),
- &(pAggrBlkCol->minIndex), &(pAggrBlkCol->maxIndex),
- &(pAggrBlkCol->numOfNull));
-
- if (pAggrBlkCol->numOfNull == 0) {
- pBlockCol->blen = 0;
+ ASSERT(pRow == NULL && pBlock == NULL);
} else {
- pBlockCol->blen = 1;
- }
- ++nColsOfBlockSma;
- } else if (tdIsBitmapBlkNorm(pDataCol->pBitmap, rowsToWrite, pDataCols->bitmapMode)) {
- // check if all rows normal
- pBlockCol->blen = 0;
- } else {
- pBlockCol->blen = 1;
- }
-
- ++nColsNotAllNull;
- }
-
- ASSERT(nColsNotAllNull >= 0 && nColsNotAllNull <= pDataCols->numOfCols);
-
- // Compress the data if neccessary
- int tcol = 0; // counter of not all NULL and written columns
- uint32_t toffset = 0;
- int32_t tsize = (int32_t)tsdbBlockStatisSize(nColsNotAllNull, SBlockVerLatest);
- int32_t lsize = tsize;
- uint32_t tsizeAggr = (uint32_t)tsdbBlockAggrSize(nColsOfBlockSma, SBlockVerLatest);
- int32_t keyLen = 0;
- int32_t nBitmaps = (int32_t)TD_BITMAP_BYTES(rowsToWrite);
- int32_t sBitmaps = isSuper ? (int32_t)TD_BITMAP_BYTES_I(rowsToWrite) : nBitmaps;
-
- for (int ncol = 0; ncol < pDataCols->numOfCols; ++ncol) {
- // All not NULL columns finish
- if (ncol != 0 && tcol >= nColsNotAllNull) break;
-
- SDataCol *pDataCol = pDataCols->cols + ncol;
- SBlockCol *pBlockCol = pBlockData->cols + tcol;
-
- if (ncol != 0 && (pDataCol->colId != pBlockCol->colId)) continue;
-
- int32_t flen; // final length
- int32_t tlen = dataColGetNEleLen(pDataCol, rowsToWrite, pDataCols->bitmapMode);
+ int32_t c = tBlockCmprFn(&(SBlock){.maxKey = TSDBROW_KEY(pRow), .minKey = TSDBROW_KEY(pRow)}, pBlock);
+ if (c > 0) {
+ // only disk data
+ code = tsdbCommitTableDiskData(pCommitter, pBlock, pBlockIdx);
+ if (code) goto _err;
+
+ iBlock++;
+ if (iBlock < nBlock) {
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock, pBlock, tGetBlock);
+ } else {
+ pBlock = NULL;
+ }
+ } else if (c < 0) {
+ // only memory data
+ code = tsdbCommitTableMemData(pCommitter, pIter, pBlock->minKey, 1);
+ if (code) goto _err;
-#ifdef TD_SUPPORT_BITMAP
- int32_t tBitmaps = 0;
- int32_t tBitmapsLen = 0;
- if ((ncol != 0) && (pBlockCol->blen > 0)) {
- tBitmaps = isSuper ? sBitmaps : nBitmaps;
- }
-#endif
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow && TSDBROW_TS(pRow) > pCommitter->maxKey) pRow = NULL;
+ } else {
+ // merge memory and disk
+ int32_t nOvlp = tsdbGetOvlpNRow(pIter, pBlock);
+ ASSERT(nOvlp);
+ if (pBlock->nRow + nOvlp <= pCommitter->maxRow && pBlock->nSubBlock < TSDB_MAX_SUBBLOCKS) {
+ code = tsdbMergeAsSubBlock(pCommitter, pIter, pBlock);
+ if (code) goto _err;
+ } else {
+ TSDBKEY toKey = {.ts = pCommitter->maxKey + 1, .version = VERSION_MIN};
+ int8_t toDataOnly = 0;
- void *tptr, *bptr;
+ if (iBlock < nBlock - 1) {
+ toDataOnly = 1;
- // Make room
- if (tsdbMakeRoom(ppBuf, lsize + tlen + tBitmaps + 2 * COMP_OVERFLOW_BYTES + sizeof(TSCKSUM)) < 0) {
- return -1;
- }
- pBlockData = (SBlockData *)(*ppBuf);
- pBlockCol = pBlockData->cols + tcol;
- tptr = POINTER_SHIFT(pBlockData, lsize);
+ SBlock nextBlock = {0};
+ tBlockReset(&nextBlock);
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock + 1, &nextBlock, tGetBlock);
+ toKey = nextBlock.minKey;
+ }
- if (pCfg->compression == TWO_STAGE_COMP && tsdbMakeRoom(ppCBuf, tlen + COMP_OVERFLOW_BYTES) < 0) {
- return -1;
- }
+ code = tsdbMergeTableData(pCommitter, pIter, pBlock, toKey, toDataOnly);
+ if (code) goto _err;
+ }
- // Compress or just copy
- if (pCfg->compression) {
-#if 0
- flen = (*(tDataTypes[pDataCol->type].compFunc))((char *)pDataCol->pData, tlen, rowsToWrite + tBitmaps, tptr,
- tlen + COMP_OVERFLOW_BYTES, pCfg->compression, *ppCBuf,
- tlen + COMP_OVERFLOW_BYTES);
-#endif
- flen = (*(tDataTypes[pDataCol->type].compFunc))((char *)pDataCol->pData, tlen, rowsToWrite, tptr,
- tlen + COMP_OVERFLOW_BYTES, pCfg->compression, *ppCBuf,
- tlen + COMP_OVERFLOW_BYTES);
- if (tBitmaps > 0) {
- bptr = POINTER_SHIFT(pBlockData, lsize + flen);
- if (isSuper && !tdDataColsIsBitmapI(pDataCols)) {
- tdMergeBitmap((uint8_t *)pDataCol->pBitmap, rowsToWrite, (uint8_t *)pDataCol->pBitmap);
- }
- tBitmapsLen =
- tsCompressTinyint((char *)pDataCol->pBitmap, tBitmaps, tBitmaps, bptr, tBitmaps + COMP_OVERFLOW_BYTES,
- pCfg->compression, *ppCBuf, tBitmaps + COMP_OVERFLOW_BYTES);
- TASSERT((tBitmapsLen > 0) && (tBitmapsLen <= (tBitmaps + COMP_OVERFLOW_BYTES)));
- flen += tBitmapsLen;
- }
- } else {
- flen = tlen;
- memcpy(tptr, pDataCol->pData, flen);
- if (tBitmaps > 0) {
- bptr = POINTER_SHIFT(pBlockData, lsize + flen);
- if (isSuper && !tdDataColsIsBitmapI(pDataCols)) {
- tdMergeBitmap((uint8_t *)pDataCol->pBitmap, rowsToWrite, (uint8_t *)pDataCol->pBitmap);
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow && TSDBROW_TS(pRow) > pCommitter->maxKey) pRow = NULL;
+ iBlock++;
+ if (iBlock < nBlock) {
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock, pBlock, tGetBlock);
+ } else {
+ pBlock = NULL;
+ }
}
- memcpy(bptr, pDataCol->pBitmap, tBitmaps);
- tBitmapsLen = tBitmaps;
- flen += tBitmapsLen;
}
- }
+ } else if (pBlock) {
+ code = tsdbCommitTableDiskData(pCommitter, pBlock, pBlockIdx);
+ if (code) goto _err;
- // Add checksum
- ASSERT(flen > 0);
- ASSERT(tBitmapsLen <= 1024);
- flen += sizeof(TSCKSUM);
- taosCalcChecksumAppend(0, (uint8_t *)tptr, flen);
- tsdbUpdateDFileMagic(pDFile, POINTER_SHIFT(tptr, flen - sizeof(TSCKSUM)));
-
- if (ncol != 0) {
- pBlockCol->offset = toffset;
- pBlockCol->len = flen; // data + bitmaps
- pBlockCol->blen = tBitmapsLen;
- ++tcol;
+ iBlock++;
+ if (iBlock < nBlock) {
+ tMapDataGetItemByIdx(&pCommitter->oBlockMap, iBlock, pBlock, tGetBlock);
+ } else {
+ pBlock = NULL;
+ }
} else {
- keyLen = flen;
- }
+ code =
+ tsdbCommitTableMemData(pCommitter, pIter, (TSDBKEY){.ts = pCommitter->maxKey + 1, .version = VERSION_MIN}, 0);
+ if (code) goto _err;
- toffset += flen;
- lsize += flen;
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow && TSDBROW_TS(pRow) > pCommitter->maxKey) pRow = NULL;
+ ASSERT(pRow == NULL);
+ }
}
- pBlockData->delimiter = TSDB_FILE_DELIMITER;
- pBlockData->uid = pTable->uid;
- pBlockData->numOfCols = nColsNotAllNull;
+ // end =====================
+ code = tsdbCommitTableDataEnd(pCommitter, suid, uid);
+ if (code) goto _err;
- taosCalcChecksumAppend(0, (uint8_t *)pBlockData, tsize);
- tsdbUpdateDFileMagic(pDFile, POINTER_SHIFT(pBlockData, tsize - sizeof(TSCKSUM)));
-
- // Write the whole block to file
- if (tsdbAppendDFile(pDFile, (void *)pBlockData, lsize, &offset) < lsize) {
- return -1;
+_exit:
+ if (pIter) {
+ pRow = tsdbTbDataIterGet(pIter);
+ if (pRow) pCommitter->nextKey = TMIN(pCommitter->nextKey, TSDBROW_TS(pRow));
}
+ return code;
- uint32_t aggrStatus = nColsOfBlockSma > 0 ? 1 : 0;
- if (aggrStatus > 0) {
- taosCalcChecksumAppend(0, (uint8_t *)pAggrBlkData, tsizeAggr);
- tsdbUpdateDFileMagic(pDFileAggr, POINTER_SHIFT(pAggrBlkData, tsizeAggr - sizeof(TSCKSUM)));
+_err:
+ tsdbError("vgId:%d tsdb commit table data failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- // Write the whole block to file
- if (tsdbAppendDFile(pDFileAggr, (void *)pAggrBlkData, tsizeAggr, &offsetAggr) < tsizeAggr) {
- return -1;
- }
- }
+static int32_t tsdbCommitFileDataEnd(SCommitter *pCommitter) {
+ int32_t code = 0;
- // Update pBlock membership variables
- pBlock->last = isLast;
- pBlock->offset = offset;
- pBlock->algorithm = pCfg->compression;
- pBlock->numOfRows = rowsToWrite;
- pBlock->len = lsize;
- pBlock->keyLen = keyLen;
- pBlock->numOfSubBlocks = isSuper ? 1 : 0;
- pBlock->numOfCols = nColsNotAllNull;
- pBlock->numOfBSma = nColsOfBlockSma;
- pBlock->minKey.ts = dataColsKeyFirst(pDataCols);
- pBlock->maxKey.ts = dataColsKeyLast(pDataCols);
- pBlock->aggrStat = aggrStatus;
- pBlock->blkVer = SBlockVerLatest;
- pBlock->aggrOffset = (uint64_t)offsetAggr;
-
- tsdbDebug("vgId:%d, uid:%" PRId64 " a block of data is written to file %s, offset %" PRId64
- " numOfRows %d len %d numOfCols %" PRId16 " keyFirst %" PRId64 " keyLast %" PRId64,
- REPO_ID(pRepo), pTable->uid, TSDB_FILE_FULL_NAME(pDFile), offset, rowsToWrite, pBlock->len,
- pBlock->numOfCols, pBlock->minKey.ts, pBlock->maxKey.ts);
-
- return 0;
-}
+ // write blockIdx
+ code = tsdbWriteBlockIdx(pCommitter->pWriter, pCommitter->aBlockIdxN, NULL);
+ if (code) goto _err;
-static int tsdbWriteBlock(SCommitH *pCommith, SDFile *pDFile, SDataCols *pDataCols, SBlock *pBlock, bool isLast,
- bool isSuper) {
- return tsdbWriteBlockImpl(TSDB_COMMIT_REPO(pCommith), TSDB_COMMIT_TABLE(pCommith), pDFile,
- isLast ? TSDB_COMMIT_SMAL_FILE(pCommith) : TSDB_COMMIT_SMAD_FILE(pCommith), pDataCols,
- pBlock, isLast, isSuper, (void **)(&(TSDB_COMMIT_BUF(pCommith))),
- (void **)(&(TSDB_COMMIT_COMP_BUF(pCommith))), (void **)(&(TSDB_COMMIT_EXBUF(pCommith))));
-}
+ // update file header
+ code = tsdbUpdateDFileSetHeader(pCommitter->pWriter);
+ if (code) goto _err;
-static int tsdbWriteBlockInfo(SCommitH *pCommih) {
- SDFile *pHeadf = TSDB_COMMIT_HEAD_FILE(pCommih);
- SBlockIdx blkIdx;
- STable *pTable = TSDB_COMMIT_TABLE(pCommih);
+ // upsert SDFileSet
+ code = tsdbFSStateUpsertDFileSet(pCommitter->pTsdb->fs->nState, tsdbDataFWriterGetWSet(pCommitter->pWriter));
+ if (code) goto _err;
- if (tsdbWriteBlockInfoImpl(pHeadf, pTable, pCommih->aSupBlk, pCommih->aSubBlk, (void **)(&(TSDB_COMMIT_BUF(pCommih))),
- &blkIdx) < 0) {
- return -1;
- }
+ // close and sync
+ code = tsdbDataFWriterClose(&pCommitter->pWriter, 1);
+ if (code) goto _err;
- if (blkIdx.numOfBlocks == 0) {
- return 0;
+ if (pCommitter->pReader) {
+ code = tsdbDataFReaderClose(&pCommitter->pReader);
+ if (code) goto _err;
}
- if (taosArrayPush(pCommih->aBlkIdx, (void *)(&blkIdx)) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
+_exit:
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d commit file data end failed since %s", TD_VID(pCommitter->pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static int tsdbCommitMemData(SCommitH *pCommith, SCommitIter *pIter, TSKEY keyLimit, bool toData) {
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbCfg *pCfg = REPO_CFG(pRepo);
- SMergeInfo mInfo;
- int32_t defaultRows = TSDB_COMMIT_DEFAULT_ROWS(pCommith);
- SDFile *pDFile;
- bool isLast;
- SBlock block;
-
- while (true) {
- tsdbLoadDataFromCache(TSDB_COMMIT_REPO(pCommith), pIter->pTable, pIter->pIter, keyLimit, defaultRows,
- pCommith->pDataCols, NULL, 0, pCfg->update, &mInfo);
-
- if (pCommith->pDataCols->numOfRows <= 0) break;
-
- if (toData || pCommith->pDataCols->numOfRows >= pCfg->minRows) {
- pDFile = TSDB_COMMIT_DATA_FILE(pCommith);
- isLast = false;
+static int32_t tsdbCommitFileData(SCommitter *pCommitter) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SMemTable *pMemTable = pTsdb->imem;
+
+ // commit file data start
+ code = tsdbCommitFileDataStart(pCommitter);
+ if (code) goto _err;
+
+ // commit file data impl
+ int32_t iTbData = 0;
+ int32_t nTbData = taosArrayGetSize(pMemTable->aTbData);
+ int32_t iBlockIdx = 0;
+ int32_t nBlockIdx = taosArrayGetSize(pCommitter->aBlockIdx);
+ STbData *pTbData;
+ SBlockIdx *pBlockIdx;
+
+ ASSERT(nTbData > 0);
+
+ pTbData = (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData);
+ pBlockIdx = (iBlockIdx < nBlockIdx) ? (SBlockIdx *)taosArrayGet(pCommitter->aBlockIdx, iBlockIdx) : NULL;
+ while (pTbData || pBlockIdx) {
+ if (pTbData && pBlockIdx) {
+ int32_t c = tTABLEIDCmprFn(pTbData, pBlockIdx);
+
+ if (c == 0) {
+ goto _commit_table_mem_and_disk;
+ } else if (c < 0) {
+ goto _commit_table_mem_data;
+ } else {
+ goto _commit_table_disk_data;
+ }
+ } else if (pBlockIdx) {
+ goto _commit_table_disk_data;
} else {
- pDFile = TSDB_COMMIT_LAST_FILE(pCommith);
- isLast = true;
+ goto _commit_table_mem_data;
}
- if (tsdbWriteBlock(pCommith, pDFile, pCommith->pDataCols, &block, isLast, true) < 0) return -1;
+ _commit_table_mem_data:
+ code = tsdbCommitTableData(pCommitter, pTbData, NULL);
+ if (code) goto _err;
- if (tsdbCommitAddBlock(pCommith, &block, NULL, 0) < 0) {
- return -1;
- }
- }
+ iTbData++;
+ pTbData = (iTbData < nTbData) ? (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData) : NULL;
+ continue;
- return 0;
-}
-
-static int tsdbMergeMemData(SCommitH *pCommith, SCommitIter *pIter, int bidx) {
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbCfg *pCfg = REPO_CFG(pRepo);
- int nBlocks = pCommith->readh.pBlkIdx->numOfBlocks;
- SBlock *pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- TSKEY keyLimit;
- int16_t colId = PRIMARYKEY_TIMESTAMP_COL_ID;
- SMergeInfo mInfo;
- SBlock subBlocks[TSDB_MAX_SUBBLOCKS];
- SBlock block, supBlock;
- SDFile *pDFile;
-
- if (bidx == nBlocks - 1) {
- keyLimit = pCommith->maxKey;
- } else {
- keyLimit = pBlock[1].minKey.ts - 1;
- }
+ _commit_table_disk_data:
+ code = tsdbCommitTableData(pCommitter, NULL, pBlockIdx);
+ if (code) goto _err;
- STbDataIter titer = *(pIter->pIter);
- if (tsdbLoadBlockDataCols(&(pCommith->readh), pBlock, NULL, &colId, 1, false) < 0) return -1;
+ iBlockIdx++;
+ pBlockIdx = (iBlockIdx < nBlockIdx) ? (SBlockIdx *)taosArrayGet(pCommitter->aBlockIdx, iBlockIdx) : NULL;
+ continue;
- tsdbLoadDataFromCache(TSDB_COMMIT_REPO(pCommith), pIter->pTable, &titer, keyLimit, INT32_MAX, NULL,
- pCommith->readh.pDCols[0]->cols[0].pData, pCommith->readh.pDCols[0]->numOfRows, pCfg->update,
- &mInfo);
+ _commit_table_mem_and_disk:
+ code = tsdbCommitTableData(pCommitter, pTbData, pBlockIdx);
+ if (code) goto _err;
- if (mInfo.nOperations == 0) {
- // no new data to insert (all updates denied)
- if (tsdbMoveBlock(pCommith, bidx) < 0) {
- return -1;
- }
- *(pIter->pIter) = titer;
- } else if (pBlock->numOfRows + mInfo.rowsInserted - mInfo.rowsDeleteSucceed == 0) {
- // Ignore the block
- ASSERT(0);
- *(pIter->pIter) = titer;
- } else if (tsdbCanAddSubBlock(pCommith, pBlock, &mInfo)) {
- // Add a sub-block
- tsdbLoadDataFromCache(TSDB_COMMIT_REPO(pCommith), pIter->pTable, pIter->pIter, keyLimit, INT32_MAX,
- pCommith->pDataCols, pCommith->readh.pDCols[0]->cols[0].pData,
- pCommith->readh.pDCols[0]->numOfRows, pCfg->update, &mInfo);
- if (pBlock->last) {
- pDFile = TSDB_COMMIT_LAST_FILE(pCommith);
- } else {
- pDFile = TSDB_COMMIT_DATA_FILE(pCommith);
- }
+ iBlockIdx++;
+ pBlockIdx = (iBlockIdx < nBlockIdx) ? (SBlockIdx *)taosArrayGet(pCommitter->aBlockIdx, iBlockIdx) : NULL;
+ iTbData++;
+ pTbData = (iTbData < nTbData) ? (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData) : NULL;
+ continue;
+ }
- if (tsdbWriteBlock(pCommith, pDFile, pCommith->pDataCols, &block, pBlock->last, false) < 0) return -1;
+ // commit file data end
+ code = tsdbCommitFileDataEnd(pCommitter);
+ if (code) goto _err;
- if (pBlock->numOfSubBlocks == 1) {
- subBlocks[0] = *pBlock;
- subBlocks[0].numOfSubBlocks = 0;
- } else {
- memcpy(subBlocks, POINTER_SHIFT(pCommith->readh.pBlkInfo, pBlock->offset),
- sizeof(SBlock) * pBlock->numOfSubBlocks);
- }
- subBlocks[pBlock->numOfSubBlocks] = block;
- supBlock = *pBlock;
- supBlock.minKey.ts = mInfo.keyFirst;
- supBlock.maxKey.ts = mInfo.keyLast;
- supBlock.numOfSubBlocks++;
- supBlock.numOfRows = pBlock->numOfRows + mInfo.rowsInserted - mInfo.rowsDeleteSucceed;
- supBlock.offset = taosArrayGetSize(pCommith->aSubBlk) * sizeof(SBlock);
-
- if (tsdbCommitAddBlock(pCommith, &supBlock, subBlocks, supBlock.numOfSubBlocks) < 0) return -1;
- } else {
- if (tsdbLoadBlockData(&(pCommith->readh), pBlock, NULL) < 0) return -1;
- if (tsdbMergeBlockData(pCommith, pIter, pCommith->readh.pDCols[0], keyLimit, bidx == (nBlocks - 1)) < 0) return -1;
- }
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d commit file data failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ tsdbDataFReaderClose(&pCommitter->pReader);
+ tsdbDataFWriterClose(&pCommitter->pWriter, 0);
+ return code;
}
-static bool tsdbCommitIsSameFile(SCommitH *pCommith, int bidx) {
- SBlock *pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- if (pBlock->last) {
- return pCommith->isLFileSame;
- }
- return pCommith->isDFileSame;
-}
+// ----------------------------------------------------------------------------
+static int32_t tsdbStartCommit(STsdb *pTsdb, SCommitter *pCommitter) {
+ int32_t code = 0;
-static int tsdbMoveBlock(SCommitH *pCommith, int bidx) {
- SBlock *pBlock = pCommith->readh.pBlkInfo->blocks + bidx;
- SDFile *pDFile;
- SBlock block;
- bool isSameFile;
+ memset(pCommitter, 0, sizeof(*pCommitter));
+ ASSERT(pTsdb->mem && pTsdb->imem == NULL);
- ASSERT(pBlock->numOfSubBlocks > 0);
+ // lock();
+ pTsdb->imem = pTsdb->mem;
+ pTsdb->mem = NULL;
+ // unlock();
- if (pBlock->last) {
- pDFile = TSDB_COMMIT_LAST_FILE(pCommith);
- isSameFile = pCommith->isLFileSame;
- } else {
- pDFile = TSDB_COMMIT_DATA_FILE(pCommith);
- isSameFile = pCommith->isDFileSame;
- }
+ pCommitter->pTsdb = pTsdb;
+ pCommitter->commitID = pTsdb->pVnode->state.commitID;
+ pCommitter->minutes = pTsdb->keepCfg.days;
+ pCommitter->precision = pTsdb->keepCfg.precision;
+ pCommitter->minRow = pTsdb->pVnode->config.tsdbCfg.minRows;
+ pCommitter->maxRow = pTsdb->pVnode->config.tsdbCfg.maxRows;
+ pCommitter->cmprAlg = pTsdb->pVnode->config.tsdbCfg.compression;
- if (isSameFile) {
- if (pBlock->numOfSubBlocks == 1) {
- if (tsdbCommitAddBlock(pCommith, pBlock, NULL, 0) < 0) {
- return -1;
- }
- } else {
- block = *pBlock;
- block.offset = sizeof(SBlock) * taosArrayGetSize(pCommith->aSubBlk);
+ code = tsdbFSBegin(pTsdb->fs);
+ if (code) goto _err;
- if (tsdbCommitAddBlock(pCommith, &block, POINTER_SHIFT(pCommith->readh.pBlkInfo, pBlock->offset),
- pBlock->numOfSubBlocks) < 0) {
- return -1;
- }
- }
- } else {
- if (tsdbLoadBlockData(&(pCommith->readh), pBlock, NULL) < 0) return -1;
- if (tsdbWriteBlock(pCommith, pDFile, pCommith->readh.pDCols[0], &block, pBlock->last, true) < 0) return -1;
- if (tsdbCommitAddBlock(pCommith, &block, NULL, 0) < 0) return -1;
- }
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb start commit failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static int tsdbCommitAddBlock(SCommitH *pCommith, const SBlock *pSupBlock, const SBlock *pSubBlocks, int nSubBlocks) {
- if (taosArrayPush(pCommith->aSupBlk, pSupBlock) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
+static int32_t tsdbCommitDataStart(SCommitter *pCommitter) {
+ int32_t code = 0;
+
+ pCommitter->aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx));
+ if (pCommitter->aBlockIdx == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
}
- if (pSubBlocks && taosArrayAddBatch(pCommith->aSubBlk, pSubBlocks, nSubBlocks) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
+ pCommitter->aBlockIdxN = taosArrayInit(0, sizeof(SBlockIdx));
+ if (pCommitter->aBlockIdxN == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
}
- return 0;
+ code = tBlockDataInit(&pCommitter->oBlockData);
+ if (code) goto _exit;
+
+ code = tBlockDataInit(&pCommitter->nBlockData);
+ if (code) goto _exit;
+
+_exit:
+ return code;
}
-static int tsdbMergeBlockData(SCommitH *pCommith, SCommitIter *pIter, SDataCols *pDataCols, TSKEY keyLimit,
- bool isLastOneBlock) {
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbCfg *pCfg = REPO_CFG(pRepo);
- SBlock block;
- SDFile *pDFile;
- bool isLast;
- int32_t defaultRows = TSDB_COMMIT_DEFAULT_ROWS(pCommith);
+static void tsdbCommitDataEnd(SCommitter *pCommitter) {
+ taosArrayDestroy(pCommitter->aBlockIdx);
+ tMapDataClear(&pCommitter->oBlockMap);
+ tBlockDataClear(&pCommitter->oBlockData);
+ taosArrayDestroy(pCommitter->aBlockIdxN);
+ tMapDataClear(&pCommitter->nBlockMap);
+ tBlockDataClear(&pCommitter->nBlockData);
+ tTSchemaDestroy(pCommitter->skmTable.pTSchema);
+ tTSchemaDestroy(pCommitter->skmRow.pTSchema);
+}
- int biter = 0;
- while (true) {
- tsdbLoadAndMergeFromCache(TSDB_COMMIT_REPO(pCommith), pCommith->readh.pDCols[0], &biter, pIter, pCommith->pDataCols,
- keyLimit, defaultRows, pCfg->update);
+static int32_t tsdbCommitData(SCommitter *pCommitter) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SMemTable *pMemTable = pTsdb->imem;
- if (pCommith->pDataCols->numOfRows == 0) break;
+ // check
+ if (pMemTable->nRow == 0) goto _exit;
- if (isLastOneBlock) {
- if (pCommith->pDataCols->numOfRows < pCfg->minRows) {
- pDFile = TSDB_COMMIT_LAST_FILE(pCommith);
- isLast = true;
- } else {
- pDFile = TSDB_COMMIT_DATA_FILE(pCommith);
- isLast = false;
- }
- } else {
- pDFile = TSDB_COMMIT_DATA_FILE(pCommith);
- isLast = false;
- }
+ // start ====================
+ code = tsdbCommitDataStart(pCommitter);
+ if (code) goto _err;
- if (tsdbWriteBlock(pCommith, pDFile, pCommith->pDataCols, &block, isLast, true) < 0) return -1;
- if (tsdbCommitAddBlock(pCommith, &block, NULL, 0) < 0) return -1;
+ // impl ====================
+ pCommitter->nextKey = pMemTable->minKey;
+ while (pCommitter->nextKey < TSKEY_MAX) {
+ pCommitter->commitFid = tsdbKeyFid(pCommitter->nextKey, pCommitter->minutes, pCommitter->precision);
+ tsdbFidKeyRange(pCommitter->commitFid, pCommitter->minutes, pCommitter->precision, &pCommitter->minKey,
+ &pCommitter->maxKey);
+ code = tsdbCommitFileData(pCommitter);
+ if (code) goto _err;
}
- return 0;
+ // end ====================
+ tsdbCommitDataEnd(pCommitter);
+
+_exit:
+ tsdbDebug("vgId:%d commit data done, nRow:%" PRId64, TD_VID(pTsdb->pVnode), pMemTable->nRow);
+ return code;
+
+_err:
+ tsdbCommitDataEnd(pCommitter);
+ tsdbError("vgId:%d commit data failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static void tsdbLoadAndMergeFromCache(STsdb *pTsdb, SDataCols *pDataCols, int *iter, SCommitIter *pCommitIter,
- SDataCols *pTarget, TSKEY maxKey, int maxRows, int8_t update) {
- TSKEY key1 = INT64_MAX;
- TSKEY key2 = INT64_MAX;
- TSKEY lastKey = TSKEY_INITIAL_VAL;
- STSchema *pSchema = NULL;
+static int32_t tsdbCommitDel(SCommitter *pCommitter) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SMemTable *pMemTable = pTsdb->imem;
- ASSERT(maxRows > 0 && dataColsKeyLast(pDataCols) <= maxKey);
- tdResetDataCols(pTarget);
+ if (pMemTable->nDel == 0) {
+ goto _exit;
+ }
- pTarget->bitmapMode = pDataCols->bitmapMode;
- // TODO: filter Multi-Version
- // TODO: support delete function
- while (true) {
- key1 = (*iter >= pDataCols->numOfRows) ? INT64_MAX : dataColsKeyAt(pDataCols, *iter);
- STSRow *row = tsdbNextIterRow(pCommitIter->pIter);
- if (row == NULL || TD_ROW_KEY(row) > maxKey) {
- key2 = INT64_MAX;
- } else {
- key2 = TD_ROW_KEY(row);
- }
+ // start
+ code = tsdbCommitDelStart(pCommitter);
+ if (code) {
+ goto _err;
+ }
- if (key1 == INT64_MAX && key2 == INT64_MAX) break;
+ // impl
+ int32_t iDelIdx = 0;
+ int32_t nDelIdx = taosArrayGetSize(pCommitter->aDelIdx);
+ int32_t iTbData = 0;
+ int32_t nTbData = taosArrayGetSize(pMemTable->aTbData);
+ STbData *pTbData;
+ SDelIdx *pDelIdx;
- if (key1 < key2) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pTarget->numOfRows;
- }
- for (int i = 0; i < pDataCols->numOfCols; ++i) {
- // TODO: dataColAppendVal may fail
- SCellVal sVal = {0};
- if (tdGetColDataOfRow(&sVal, pDataCols->cols + i, *iter, pDataCols->bitmapMode) < 0) {
- TASSERT(0);
- }
- tdAppendValToDataCol(pTarget->cols + i, sVal.valType, sVal.val, pTarget->numOfRows, pTarget->maxPoints,
- pTarget->bitmapMode, false);
- }
+ ASSERT(nTbData > 0);
- lastKey = key1;
- ++(*iter);
- } else if (key1 > key2) {
- if (pSchema == NULL || schemaVersion(pSchema) != TD_ROW_SVER(row)) {
- pSchema = tsdbGetTableSchemaImpl(pTsdb, pCommitIter->pTable, false, false, TD_ROW_SVER(row));
- ASSERT(pSchema != NULL);
- }
+ pTbData = (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData);
+ pDelIdx = (iDelIdx < nDelIdx) ? (SDelIdx *)taosArrayGet(pCommitter->aDelIdx, iDelIdx) : NULL;
+ while (true) {
+ if (pTbData == NULL && pDelIdx == NULL) break;
- if (key2 == lastKey) {
- if (TD_SUPPORT_UPDATE(update)) {
- tdAppendSTSRowToDataCol(row, pSchema, pTarget, true);
- }
+ if (pTbData && pDelIdx) {
+ int32_t c = tTABLEIDCmprFn(pTbData, pDelIdx);
+
+ if (c == 0) {
+ goto _commit_mem_and_disk_del;
+ } else if (c < 0) {
+ goto _commit_mem_del;
} else {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pTarget->numOfRows;
- }
- tdAppendSTSRowToDataCol(row, pSchema, pTarget, false);
- lastKey = key2;
+ goto _commit_disk_del;
}
-
- tsdbTbDataIterNext(pCommitIter->pIter);
+ } else if (pTbData) {
+ goto _commit_mem_del;
} else {
- if (lastKey != key1) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pTarget->numOfRows;
- }
- lastKey = key1;
- }
+ goto _commit_disk_del;
+ }
- // copy disk data
- for (int i = 0; i < pDataCols->numOfCols; ++i) {
- SCellVal sVal = {0};
- // no duplicated TS keys in pDataCols from file
- if (tdGetColDataOfRow(&sVal, pDataCols->cols + i, *iter, pDataCols->bitmapMode) < 0) {
- TASSERT(0);
- }
- // TODO: tdAppendValToDataCol may fail
- tdAppendValToDataCol(pTarget->cols + i, sVal.valType, sVal.val, pTarget->numOfRows, pTarget->maxPoints,
- pTarget->bitmapMode, false);
- }
+ _commit_mem_del:
+ code = tsdbCommitTableDel(pCommitter, pTbData, NULL);
+ if (code) goto _err;
- if (TD_SUPPORT_UPDATE(update)) {
- // copy mem data(Multi-Version)
- if (pSchema == NULL || schemaVersion(pSchema) != TD_ROW_SVER(row)) {
- pSchema = tsdbGetTableSchemaImpl(pTsdb, pCommitIter->pTable, false, false, TD_ROW_SVER(row));
- ASSERT(pSchema != NULL);
- }
+ iTbData++;
+ pTbData = (iTbData < nTbData) ? (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData) : NULL;
+ continue;
- // TODO: merge with Multi-Version
- tdAppendSTSRowToDataCol(row, pSchema, pTarget, true);
- }
- ++(*iter);
- tsdbTbDataIterNext(pCommitIter->pIter);
- }
+ _commit_disk_del:
+ code = tsdbCommitTableDel(pCommitter, NULL, pDelIdx);
+ if (code) goto _err;
- if (pTarget->numOfRows >= (maxRows - 1)) break;
- }
+ iDelIdx++;
+ pDelIdx = (iDelIdx < nDelIdx) ? (SDelIdx *)taosArrayGet(pCommitter->aDelIdx, iDelIdx) : NULL;
+ continue;
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pTarget->numOfRows;
- }
-}
-
-static void tsdbResetCommitTable(SCommitH *pCommith) {
- taosArrayClear(pCommith->aSubBlk);
- taosArrayClear(pCommith->aSupBlk);
- pCommith->pTable = NULL;
-}
+ _commit_mem_and_disk_del:
+ code = tsdbCommitTableDel(pCommitter, pTbData, pDelIdx);
+ if (code) goto _err;
-static void tsdbCloseCommitFile(SCommitH *pCommith, bool hasError) {
- if (pCommith->isRFileSet) {
- tsdbCloseAndUnsetFSet(&(pCommith->readh));
+ iTbData++;
+ pTbData = (iTbData < nTbData) ? (STbData *)taosArrayGetP(pMemTable->aTbData, iTbData) : NULL;
+ iDelIdx++;
+ pDelIdx = (iDelIdx < nDelIdx) ? (SDelIdx *)taosArrayGet(pCommitter->aDelIdx, iDelIdx) : NULL;
+ continue;
}
- if (!hasError) {
- TSDB_FSET_FSYNC(TSDB_COMMIT_WRITE_FSET(pCommith));
+ // end
+ code = tsdbCommitDelEnd(pCommitter);
+ if (code) {
+ goto _err;
}
- tsdbCloseDFileSet(TSDB_COMMIT_WRITE_FSET(pCommith));
-}
-
-static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *pInfo) {
- STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
- STsdbCfg *pCfg = REPO_CFG(pRepo);
- int mergeRows = pBlock->numOfRows + pInfo->rowsInserted - pInfo->rowsDeleteSucceed;
-
- ASSERT(mergeRows > 0);
- if (pBlock->numOfSubBlocks < TSDB_MAX_SUBBLOCKS && pInfo->nOperations <= pCfg->maxRows) {
- if (pBlock->last) {
- if (pCommith->isLFileSame && mergeRows < pCfg->minRows) return true;
- } else {
- if (pCommith->isDFileSame && mergeRows <= pCfg->maxRows) return true;
- }
- }
+_exit:
+ tsdbDebug("vgId:%d commit del done, nDel:%" PRId64, TD_VID(pTsdb->pVnode), pMemTable->nDel);
+ return code;
- return false;
+_err:
+ tsdbError("vgId:%d commit del failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static int tsdbAppendTableRowToCols(STsdb *pTsdb, STable *pTable, SDataCols *pCols, STSchema **ppSchema, STSRow *row,
- bool merge) {
- if (pCols) {
- if (*ppSchema == NULL || schemaVersion(*ppSchema) != TD_ROW_SVER(row)) {
- *ppSchema = tsdbGetTableSchemaImpl(pTsdb, pTable, false, false, TD_ROW_SVER(row));
- if (*ppSchema == NULL) {
- ASSERT(false);
- return -1;
- }
- }
-
- tdAppendSTSRowToDataCol(row, *ppSchema, pCols, merge);
- }
-
- return 0;
+static int32_t tsdbCommitCache(SCommitter *pCommitter) {
+ int32_t code = 0;
+ // TODO
+ return code;
}
-static int tsdbLoadDataFromCache(STsdb *pTsdb, STable *pTable, STbDataIter *pIter, TSKEY maxKey, int maxRowsToRead,
- SDataCols *pCols, TKEY *filterKeys, int nFilterKeys, bool keepDup,
- SMergeInfo *pMergeInfo) {
- ASSERT(maxRowsToRead > 0 && nFilterKeys >= 0);
- if (pIter == NULL) return 0;
- STSchema *pSchema = NULL;
- TSKEY rowKey = 0;
- TSKEY fKey = 0;
- // only fetch lastKey from mem data as file data not used in this function actually
- TSKEY lastKey = TSKEY_INITIAL_VAL;
- bool isRowDel = false;
- int filterIter = 0;
- STSRow *row = NULL;
- SMergeInfo mInfo;
-
- // TODO: support Multi-Version(the rows with the same TS keys in memory can't be merged if its version refered by
- // query handle)
-
- if (pMergeInfo == NULL) pMergeInfo = &mInfo;
-
- memset(pMergeInfo, 0, sizeof(*pMergeInfo));
- pMergeInfo->keyFirst = INT64_MAX;
- pMergeInfo->keyLast = INT64_MIN;
- if (pCols) tdResetDataCols(pCols);
-
- row = tsdbNextIterRow(pIter);
- if (row == NULL || TD_ROW_KEY(row) > maxKey) {
- rowKey = INT64_MAX;
- isRowDel = false;
- } else {
- rowKey = TD_ROW_KEY(row);
- isRowDel = TD_ROW_IS_DELETED(row);
- }
+static int32_t tsdbEndCommit(SCommitter *pCommitter, int32_t eno) {
+ int32_t code = 0;
+ STsdb *pTsdb = pCommitter->pTsdb;
+ SMemTable *pMemTable = pTsdb->imem;
- if (filterIter >= nFilterKeys) {
- fKey = INT64_MAX;
+ if (eno == 0) {
+ code = tsdbFSCommit(pTsdb->fs);
} else {
- fKey = tdGetKey(filterKeys[filterIter]);
+ code = tsdbFSRollback(pTsdb->fs);
}
- // 1. fkey - no dup since merged up to maxVersion of each query handle by tsdbLoadBlockDataCols
- // 2. rowKey - would dup since Multi-Version supported
- while (true) {
- if (fKey == INT64_MAX && rowKey == INT64_MAX) break;
-
- if (fKey < rowKey) {
- pMergeInfo->keyFirst = TMIN(pMergeInfo->keyFirst, fKey);
- pMergeInfo->keyLast = TMAX(pMergeInfo->keyLast, fKey);
-
- filterIter++;
- if (filterIter >= nFilterKeys) {
- fKey = INT64_MAX;
- } else {
- fKey = tdGetKey(filterKeys[filterIter]);
- }
-#if 1
- } else if (fKey > rowKey) {
- if (isRowDel) {
- // TODO: support delete function
- pMergeInfo->rowsDeleteFailed++;
- } else {
- if (pMergeInfo->rowsInserted - pMergeInfo->rowsDeleteSucceed >= maxRowsToRead) break;
- if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
-
- if (lastKey != rowKey) {
- pMergeInfo->rowsInserted++;
- pMergeInfo->nOperations++;
- pMergeInfo->keyFirst = TMIN(pMergeInfo->keyFirst, rowKey);
- pMergeInfo->keyLast = TMAX(pMergeInfo->keyLast, rowKey);
- if (pCols) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pCols->numOfRows;
- }
- tsdbAppendTableRowToCols(pTsdb, pTable, pCols, &pSchema, row, false);
- }
- lastKey = rowKey;
- } else {
- if (keepDup) {
- tsdbAppendTableRowToCols(pTsdb, pTable, pCols, &pSchema, row, true);
- } else {
- // discard
- }
- }
- }
-
- tsdbTbDataIterNext(pIter);
- row = tsdbNextIterRow(pIter);
- if (row == NULL || TD_ROW_KEY(row) > maxKey) {
- rowKey = INT64_MAX;
- isRowDel = false;
- } else {
- rowKey = TD_ROW_KEY(row);
- isRowDel = TD_ROW_IS_DELETED(row);
- }
- } else { // fkey == rowKey
- if (isRowDel) { // TODO: support delete function(How to stands for delete in file? rowVersion = -1?)
- ASSERT(!keepDup);
- if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
- pMergeInfo->rowsDeleteSucceed++;
- pMergeInfo->nOperations++;
- tsdbAppendTableRowToCols(pTsdb, pTable, pCols, &pSchema, row, false);
- } else {
- if (keepDup) {
- if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
- if (lastKey != rowKey) {
- pMergeInfo->rowsUpdated++;
- pMergeInfo->nOperations++;
- pMergeInfo->keyFirst = TMIN(pMergeInfo->keyFirst, rowKey);
- pMergeInfo->keyLast = TMAX(pMergeInfo->keyLast, rowKey);
- if (pCols) {
- if (lastKey != TSKEY_INITIAL_VAL) {
- ++pCols->numOfRows;
- }
- tsdbAppendTableRowToCols(pTsdb, pTable, pCols, &pSchema, row, false);
- }
- lastKey = rowKey;
- } else {
- tsdbAppendTableRowToCols(pTsdb, pTable, pCols, &pSchema, row, true);
- }
- } else {
- pMergeInfo->keyFirst = TMIN(pMergeInfo->keyFirst, fKey);
- pMergeInfo->keyLast = TMAX(pMergeInfo->keyLast, fKey);
- }
- }
- tsdbTbDataIterNext(pIter);
- row = tsdbNextIterRow(pIter);
- if (row == NULL || TD_ROW_KEY(row) > maxKey) {
- rowKey = INT64_MAX;
- isRowDel = false;
- } else {
- rowKey = TD_ROW_KEY(row);
- isRowDel = TD_ROW_IS_DELETED(row);
- }
+ tsdbMemTableDestroy(pMemTable);
+ pTsdb->imem = NULL;
- filterIter++;
- if (filterIter >= nFilterKeys) {
- fKey = INT64_MAX;
- } else {
- fKey = tdGetKey(filterKeys[filterIter]);
- }
- }
-#endif
- }
- if (pCols && (lastKey != TSKEY_INITIAL_VAL)) {
- ++pCols->numOfRows;
- }
+ tsdbInfo("vgId:%d tsdb end commit", TD_VID(pTsdb->pVnode));
+ return code;
- return 0;
-}
\ No newline at end of file
+_err:
+ tsdbError("vgId:%d tsdb end commit failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
diff --git a/source/dnode/vnode/src/tsdb/tsdbDelete.c b/source/dnode/vnode/src/tsdb/tsdbDelete.c
deleted file mode 100644
index 6dea4a4e57392be988126c579648f39a8270b9bf..0000000000000000000000000000000000000000
--- a/source/dnode/vnode/src/tsdb/tsdbDelete.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbFS.c b/source/dnode/vnode/src/tsdb/tsdbFS.c
index 055b6c62de47a3cbf05870ad7e23d8ce23fa449b..53b6735c30bb1b4c44edecfedb44c5aaa63d231f 100644
--- a/source/dnode/vnode/src/tsdb/tsdbFS.c
+++ b/source/dnode/vnode/src/tsdb/tsdbFS.c
@@ -15,1054 +15,689 @@
#include "tsdb.h"
-extern const char *TSDB_LEVEL_DNAME[];
-
-typedef enum { TSDB_TXN_TEMP_FILE = 0, TSDB_TXN_CURR_FILE } TSDB_TXN_FILE_T;
-static const char *tsdbTxnFname[] = {"current.t", "current"};
-#define TSDB_MAX_FSETS(keep, days) ((keep) / (days) + 3)
-#define TSDB_MAX_INIT_FSETS (365000)
-
-static int tsdbComparFidFSet(const void *arg1, const void *arg2);
-static void tsdbResetFSStatus(SFSStatus *pStatus);
-static int tsdbSaveFSStatus(STsdb *pRepo, SFSStatus *pStatus);
-static void tsdbApplyFSTxnOnDisk(SFSStatus *pFrom, SFSStatus *pTo);
-static void tsdbGetTxnFname(STsdb *pRepo, TSDB_TXN_FILE_T ftype, char fname[]);
-static int tsdbOpenFSFromCurrent(STsdb *pRepo);
-static int tsdbScanAndTryFixFS(STsdb *pRepo);
-static int tsdbScanRootDir(STsdb *pRepo);
-static int tsdbScanDataDir(STsdb *pRepo);
-static bool tsdbIsTFileInFS(STsdbFS *pfs, const STfsFile *pf);
-static int tsdbRestoreCurrent(STsdb *pRepo);
-static int tsdbComparTFILE(const void *arg1, const void *arg2);
-static void tsdbScanAndTryFixDFilesHeader(STsdb *pRepo, int32_t *nExpired);
-// static int tsdbProcessExpiredFS(STsdb *pRepo);
-// static int tsdbCreateMeta(STsdb *pRepo);
-
-static void tsdbGetRootDir(int repoid, const char *dir, char dirName[]) {
- snprintf(dirName, TSDB_FILENAME_LEN, "vnode/vnode%d/%s", repoid, dir);
-}
-
-static void tsdbGetDataDir(int repoid, const char *dir, char dirName[]) {
- snprintf(dirName, TSDB_FILENAME_LEN, "vnode/vnode%d/%s/data", repoid, dir);
-}
-
-// For backward compatibility
-// ================== CURRENT file header info
-static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) {
- int tlen = 0;
-
- tlen += taosEncodeFixedU32(buf, pHeader->version);
- tlen += taosEncodeFixedU32(buf, pHeader->len);
-
- return tlen;
-}
-
-static void *tsdbDecodeFSHeader(void *buf, SFSHeader *pHeader) {
- buf = taosDecodeFixedU32(buf, &(pHeader->version));
- buf = taosDecodeFixedU32(buf, &(pHeader->len));
-
- return buf;
-}
-
-// ================== STsdbFSMeta
-static int tsdbEncodeFSMeta(void **buf, STsdbFSMeta *pMeta) {
- int tlen = 0;
-
- tlen += taosEncodeFixedU32(buf, pMeta->version);
- tlen += taosEncodeFixedI64(buf, pMeta->totalPoints);
- tlen += taosEncodeFixedI64(buf, pMeta->totalStorage);
-
- return tlen;
-}
-
-static void *tsdbDecodeFSMeta(void *buf, STsdbFSMeta *pMeta) {
- buf = taosDecodeFixedU32(buf, &(pMeta->version));
- buf = taosDecodeFixedI64(buf, &(pMeta->totalPoints));
- buf = taosDecodeFixedI64(buf, &(pMeta->totalStorage));
-
- return buf;
-}
-
-// ================== SFSStatus
-static int tsdbEncodeDFileSetArray(void **buf, SArray *pArray) {
- int tlen = 0;
- uint64_t nset = taosArrayGetSize(pArray);
-
- tlen += taosEncodeFixedU64(buf, nset);
- for (size_t i = 0; i < nset; i++) {
- SDFileSet *pSet = taosArrayGet(pArray, i);
+// =================================================================================================
+static int32_t tPutFSState(uint8_t *p, STsdbFSState *pState) {
+ int32_t n = 0;
+ int8_t hasDel = pState->pDelFile ? 1 : 0;
+ uint32_t nDFileSet = taosArrayGetSize(pState->aDFileSet);
- tlen += tsdbEncodeDFileSet(buf, pSet);
+ // SDelFile
+ n += tPutI8(p ? p + n : p, hasDel);
+ if (hasDel) {
+ n += tPutDelFile(p ? p + n : p, pState->pDelFile);
}
- return tlen;
-}
-
-static void *tsdbDecodeDFileSetArray(STsdb *pRepo, void *buf, SArray *pArray) {
- uint64_t nset = 0;
-
- taosArrayClear(pArray);
-
- buf = taosDecodeFixedU64(buf, &nset);
- for (size_t i = 0; i < nset; i++) {
- SDFileSet dset = {0};
- buf = tsdbDecodeDFileSet(pRepo, buf, &dset);
- taosArrayPush(pArray, (void *)(&dset));
+ // SArray
+ n += tPutU32v(p ? p + n : p, nDFileSet);
+ for (uint32_t iDFileSet = 0; iDFileSet < nDFileSet; iDFileSet++) {
+ n += tPutDFileSet(p ? p + n : p, (SDFileSet *)taosArrayGet(pState->aDFileSet, iDFileSet));
}
- return buf;
-}
-static int tsdbEncodeFSStatus(void **buf, SFSStatus *pStatus) {
- // ASSERT(pStatus->pmf);
-
- int tlen = 0;
-
- // tlen += tsdbEncodeSMFile(buf, pStatus->pmf);
- tlen += tsdbEncodeDFileSetArray(buf, pStatus->df);
-
- return tlen;
+ return n;
}
-static void *tsdbDecodeFSStatus(STsdb *pRepo, void *buf, SFSStatus *pStatus) {
- tsdbResetFSStatus(pStatus);
-
- // pStatus->pmf = &(pStatus->mf);
-
- // buf = tsdbDecodeSMFile(buf, pStatus->pmf);
- buf = tsdbDecodeDFileSetArray(pRepo, buf, pStatus->df);
-
- return buf;
-}
-
-static SFSStatus *tsdbNewFSStatus(int maxFSet) {
- SFSStatus *pStatus = (SFSStatus *)taosMemoryCalloc(1, sizeof(*pStatus));
- if (pStatus == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return NULL;
- }
-
- // TSDB_FILE_SET_CLOSED(&(pStatus->mf));
-
- pStatus->df = taosArrayInit(maxFSet, sizeof(SDFileSet));
- if (pStatus->df == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- taosMemoryFree(pStatus);
- return NULL;
- }
-
- return pStatus;
-}
+static int32_t tGetFSState(uint8_t *p, STsdbFSState *pState) {
+ int32_t n = 0;
+ int8_t hasDel;
+ uint32_t nDFileSet;
+ SDFileSet *pSet = &(SDFileSet){0};
-static SFSStatus *tsdbFreeFSStatus(SFSStatus *pStatus) {
- if (pStatus) {
- pStatus->df = taosArrayDestroy(pStatus->df);
- taosMemoryFree(pStatus);
+ // SDelFile
+ n += tGetI8(p + n, &hasDel);
+ if (hasDel) {
+ pState->pDelFile = &pState->delFile;
+ n += tGetDelFile(p + n, pState->pDelFile);
+ } else {
+ pState->pDelFile = NULL;
}
- return NULL;
-}
-
-static void tsdbResetFSStatus(SFSStatus *pStatus) {
- if (pStatus == NULL) {
- return;
+ // SArray
+ taosArrayClear(pState->aDFileSet);
+ n += tGetU32v(p + n, &nDFileSet);
+ for (uint32_t iDFileSet = 0; iDFileSet < nDFileSet; iDFileSet++) {
+ n += tGetDFileSet(p + n, pSet);
+ taosArrayPush(pState->aDFileSet, pSet);
}
- // TSDB_FILE_SET_CLOSED(&(pStatus->mf));
-
- // pStatus->pmf = NULL;
- taosArrayClear(pStatus->df);
+ return n;
}
-// static void tsdbSetStatusMFile(SFSStatus *pStatus, const SMFile *pMFile) {
-// ASSERT(pStatus->pmf == NULL);
-
-// pStatus->pmf = &(pStatus->mf);
-// tsdbInitMFileEx(pStatus->pmf, (SMFile *)pMFile);
-// }
+static int32_t tsdbGnrtCurrent(const char *fname, STsdbFSState *pState) {
+ int32_t code = 0;
+ int64_t n;
+ int64_t size;
+ uint8_t *pData;
+ TdFilePtr pFD = NULL;
-static int tsdbAddDFileSetToStatus(SFSStatus *pStatus, const SDFileSet *pSet) {
- if (taosArrayPush(pStatus->df, (void *)pSet) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
-
- TSDB_FSET_SET_CLOSED(((SDFileSet *)taosArrayGetLast(pStatus->df)));
-
- return 0;
-}
-
-// ================== STsdbFS
-STsdbFS *tsdbNewFS(const STsdbKeepCfg *pCfg) {
- int keep = pCfg->keep2;
- int days = pCfg->days;
- int maxFSet = TSDB_MAX_FSETS(keep, days);
- STsdbFS *pfs;
-
- pfs = (STsdbFS *)taosMemoryCalloc(1, sizeof(*pfs));
- if (pfs == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return NULL;
- }
-
- int code = taosThreadRwlockInit(&(pfs->lock), NULL);
- if (code) {
- terrno = TAOS_SYSTEM_ERROR(code);
- taosMemoryFree(pfs);
- return NULL;
- }
-
- if (maxFSet > TSDB_MAX_INIT_FSETS) {
- maxFSet = TSDB_MAX_INIT_FSETS;
+ // to binary
+ size = tPutFSState(NULL, pState) + sizeof(TSCKSUM);
+ pData = taosMemoryMalloc(size);
+ if (pData == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
}
+ n = tPutFSState(pData, pState);
+ ASSERT(n + sizeof(TSCKSUM) == size);
+ taosCalcChecksumAppend(0, pData, size);
- pfs->cstatus = tsdbNewFSStatus(maxFSet);
- if (pfs->cstatus == NULL) {
- tsdbFreeFS(pfs);
- return NULL;
+ // create and write
+ pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE);
+ if (pFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- pfs->intxn = false;
- pfs->nstatus = tsdbNewFSStatus(maxFSet);
- if (pfs->nstatus == NULL) {
- tsdbFreeFS(pfs);
- return NULL;
+ n = taosWriteFile(pFD, pData, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- return pfs;
-}
-
-void *tsdbFreeFS(STsdbFS *pfs) {
- if (pfs) {
- pfs->nstatus = tsdbFreeFSStatus(pfs->nstatus);
- pfs->cstatus = tsdbFreeFSStatus(pfs->cstatus);
- taosThreadRwlockDestroy(&(pfs->lock));
- taosMemoryFree(pfs);
+ if (taosFsyncFile(pFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- return NULL;
-}
+ taosCloseFile(&pFD);
-int tsdbOpenFS(STsdb *pRepo) {
- STsdbFS *pfs = REPO_FS(pRepo);
- char current[TSDB_FILENAME_LEN] = "\0";
- int nExpired = 0;
-
- ASSERT(pfs != NULL);
-
- tsdbGetTxnFname(pRepo, TSDB_TXN_CURR_FILE, current);
-
- tsdbGetRtnSnap(pRepo, &pRepo->rtn);
- if (taosCheckExistFile(current)) {
- if (tsdbOpenFSFromCurrent(pRepo) < 0) {
- tsdbError("vgId:%d, failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
- }
+ if (pData) taosMemoryFree(pData);
+ return code;
- tsdbScanAndTryFixDFilesHeader(pRepo, &nExpired);
- // if (nExpired > 0) {
- // tsdbProcessExpiredFS(pRepo);
- // }
+_err:
+ tsdbError("tsdb gnrt current failed since %s", tstrerror(code));
+ if (pData) taosMemoryFree(pData);
+ return code;
+}
+
+static int32_t tsdbLoadCurrentState(STsdbFS *pFS, STsdbFSState *pState) {
+ int32_t code = 0;
+ int64_t size;
+ int64_t n;
+ char fname[TSDB_FILENAME_LEN];
+ uint8_t *pData = NULL;
+ TdFilePtr pFD;
+
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
+ pFS->pTsdb->path, TD_DIRSEP);
+
+ if (!taosCheckExistFile(fname)) {
+ // create an empry CURRENT file if not exists
+ code = tsdbGnrtCurrent(fname, pState);
+ if (code) goto _err;
} else {
- // should skip expired fileset inside of the function
- if (tsdbRestoreCurrent(pRepo) < 0) {
- tsdbError("vgId:%d, failed to restore current file since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
+ // open the file and load
+ pFD = taosOpenFile(fname, TD_FILE_READ);
+ if (pFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- }
- if (tsdbScanAndTryFixFS(pRepo) < 0) {
- tsdbError("vgId:%d, failed to scan and fix FS since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
- }
-
- // // Load meta cache if has meta file
- // if ((!(pRepo->state & TSDB_STATE_BAD_META)) && tsdbLoadMetaCache(pRepo, true) < 0) {
- // tsdbError("vgId:%d, failed to open FS while loading meta cache since %s", REPO_ID(pRepo), tstrerror(terrno));
- // return -1;
- // }
-
- return 0;
-}
+ if (taosFStatFile(pFD, &size, NULL) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
-void tsdbCloseFS(STsdb *pRepo) {
- // Do nothing
-}
+ pData = taosMemoryMalloc(size);
+ if (pData == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
-// Start a new transaction to modify the file system
-void tsdbStartFSTxn(STsdb *pRepo, int64_t pointsAdd, int64_t storageAdd) {
- STsdbFS *pfs = REPO_FS(pRepo);
- ASSERT(pfs->intxn == false);
-
- pfs->intxn = true;
- tsdbResetFSStatus(pfs->nstatus);
- pfs->nstatus->meta = pfs->cstatus->meta;
- // if (pfs->cstatus->pmf == NULL) {
- pfs->nstatus->meta.version += 1;
- // } else {
- // pfs->nstatus->meta.version = pfs->cstatus->meta.version + 1;
- // }
- pfs->nstatus->meta.totalPoints = pfs->cstatus->meta.totalPoints + pointsAdd;
- pfs->nstatus->meta.totalStorage = pfs->cstatus->meta.totalStorage += storageAdd;
-}
+ n = taosReadFile(pFD, pData, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
-void tsdbUpdateFSTxnMeta(STsdbFS *pfs, STsdbFSMeta *pMeta) { pfs->nstatus->meta = *pMeta; }
+ if (!taosCheckChecksumWhole(pData, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
-int tsdbEndFSTxn(STsdb *pRepo) {
- STsdbFS *pfs = REPO_FS(pRepo);
- ASSERT(FS_IN_TXN(pfs));
- SFSStatus *pStatus;
+ taosCloseFile(&pFD);
- // Write current file system snapshot
- if (tsdbSaveFSStatus(pRepo, pfs->nstatus) < 0) {
- tsdbEndFSTxnWithError(pfs);
- return -1;
+ // decode
+ tGetFSState(pData, pState);
}
- // Make new
- tsdbWLockFS(pfs);
- pStatus = pfs->cstatus;
- pfs->cstatus = pfs->nstatus;
- pfs->nstatus = pStatus;
- tsdbUnLockFS(pfs);
-
- // Apply actual change to each file and SDFileSet
- tsdbApplyFSTxnOnDisk(pfs->nstatus, pfs->cstatus);
-
- pfs->intxn = false;
- return 0;
-}
+ if (pData) taosMemoryFree(pData);
+ return code;
-int tsdbEndFSTxnWithError(STsdbFS *pfs) {
- tsdbApplyFSTxnOnDisk(pfs->nstatus, pfs->cstatus);
- // TODO: if mf change, reload pfs->metaCache
- pfs->intxn = false;
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb load current state failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ if (pData) taosMemoryFree(pData);
+ return code;
}
-// void tsdbUpdateMFile(STsdbFS *pfs, const SMFile *pMFile) { tsdbSetStatusMFile(pfs->nstatus, pMFile); }
-
-int tsdbUpdateDFileSet(STsdbFS *pfs, const SDFileSet *pSet) { return tsdbAddDFileSetToStatus(pfs->nstatus, pSet); }
-
-static int tsdbSaveFSStatus(STsdb *pRepo, SFSStatus *pStatus) {
- SFSHeader fsheader;
- void *pBuf = NULL;
- void *ptr;
- char hbuf[TSDB_FILE_HEAD_SIZE] = "\0";
- char tfname[TSDB_FILENAME_LEN] = "\0";
- char cfname[TSDB_FILENAME_LEN] = "\0";
+static int32_t tsdbApplyDFileSetChange(STsdbFS *pFS, SDFileSet *pFrom, SDFileSet *pTo) {
+ int32_t code = 0;
+ char fname[TSDB_FILENAME_LEN];
- tsdbGetTxnFname(pRepo, TSDB_TXN_TEMP_FILE, tfname);
- tsdbGetTxnFname(pRepo, TSDB_TXN_CURR_FILE, cfname);
-
- TdFilePtr pFile = taosOpenFile(tfname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
- if (pFile == NULL) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
-
- fsheader.version = TSDB_LATEST_SFS_VER;
- if (taosArrayGetSize(pStatus->df) == 0) {
- fsheader.len = 0;
- } else {
- fsheader.len = tsdbEncodeFSStatus(NULL, pStatus) + sizeof(TSCKSUM);
- }
-
- // Encode header part and write
- ptr = hbuf;
- tsdbEncodeFSHeader(&ptr, &fsheader);
- tsdbEncodeFSMeta(&ptr, &(pStatus->meta));
-
- taosCalcChecksumAppend(0, (uint8_t *)hbuf, TSDB_FILE_HEAD_SIZE);
-
- if (taosWriteFile(pFile, hbuf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- taosCloseFile(&pFile);
- taosRemoveFile(tfname);
- return -1;
- }
-
- // Encode file status and write to file
- if (fsheader.len > 0) {
- if (tsdbMakeRoom(&(pBuf), fsheader.len) < 0) {
- taosCloseFile(&pFile);
- taosRemoveFile(tfname);
- return -1;
+ if (pFrom && pTo) {
+ // head
+ if (tsdbFileIsSame(pFrom, pTo, TSDB_HEAD_FILE)) {
+ ASSERT(pFrom->fHead.size == pTo->fHead.size);
+ ASSERT(pFrom->fHead.offset == pTo->fHead.offset);
+ } else {
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_HEAD_FILE, fname);
+ taosRemoveFile(fname);
}
- ptr = pBuf;
- tsdbEncodeFSStatus(&ptr, pStatus);
- taosCalcChecksumAppend(0, (uint8_t *)pBuf, fsheader.len);
-
- if (taosWriteFile(pFile, pBuf, fsheader.len) < fsheader.len) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- taosCloseFile(&pFile);
- (void)taosRemoveFile(tfname);
- taosTZfree(pBuf);
- return -1;
+ // data
+ if (tsdbFileIsSame(pFrom, pTo, TSDB_DATA_FILE)) {
+ if (pFrom->fData.size > pTo->fData.size) {
+ code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_DATA_FILE);
+ if (code) goto _err;
+ }
+ } else {
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_DATA_FILE, fname);
+ taosRemoveFile(fname);
}
- }
- // fsync, close and rename
- if (taosFsyncFile(pFile) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- taosCloseFile(&pFile);
- taosRemoveFile(tfname);
- taosTZfree(pBuf);
- return -1;
- }
-
- (void)taosCloseFile(&pFile);
- (void)taosRenameFile(tfname, cfname);
- taosTZfree(pBuf);
-
- return 0;
-}
-
-static void tsdbApplyFSTxnOnDisk(SFSStatus *pFrom, SFSStatus *pTo) {
- int ifrom = 0;
- int ito = 0;
- size_t sizeFrom, sizeTo;
- SDFileSet *pSetFrom;
- SDFileSet *pSetTo;
+ // last
+ if (tsdbFileIsSame(pFrom, pTo, TSDB_LAST_FILE)) {
+ if (pFrom->fLast.size > pTo->fLast.size) {
+ code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_LAST_FILE);
+ if (code) goto _err;
+ }
+ } else {
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_LAST_FILE, fname);
+ taosRemoveFile(fname);
+ }
- sizeFrom = taosArrayGetSize(pFrom->df);
- sizeTo = taosArrayGetSize(pTo->df);
+ // sma
+ if (tsdbFileIsSame(pFrom, pTo, TSDB_SMA_FILE)) {
+ if (pFrom->fSma.size > pTo->fSma.size) {
+ code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_SMA_FILE);
+ if (code) goto _err;
+ }
+ } else {
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_SMA_FILE, fname);
+ taosRemoveFile(fname);
+ }
+ } else if (pFrom) {
+ // head
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_HEAD_FILE, fname);
+ taosRemoveFile(fname);
- // Apply meta file change
- // (void)tsdbApplyMFileChange(pFrom->pmf, pTo->pmf);
+ // data
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_DATA_FILE, fname);
+ taosRemoveFile(fname);
- // Apply SDFileSet change
- if (ifrom >= sizeFrom) {
- pSetFrom = NULL;
- } else {
- pSetFrom = taosArrayGet(pFrom->df, ifrom);
- }
+ // last
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_LAST_FILE, fname);
+ taosRemoveFile(fname);
- if (ito >= sizeTo) {
- pSetTo = NULL;
- } else {
- pSetTo = taosArrayGet(pTo->df, ito);
+ // fsm
+ tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_SMA_FILE, fname);
+ taosRemoveFile(fname);
}
- while (true) {
- if ((pSetTo == NULL) && (pSetFrom == NULL)) break;
-
- if (pSetTo == NULL || (pSetFrom && pSetFrom->fid < pSetTo->fid)) {
- tsdbApplyDFileSetChange(pSetFrom, NULL);
+ return code;
- ifrom++;
- if (ifrom >= sizeFrom) {
- pSetFrom = NULL;
- } else {
- pSetFrom = taosArrayGet(pFrom->df, ifrom);
- }
- } else if (pSetFrom == NULL || pSetFrom->fid > pSetTo->fid) {
- // Do nothing
- ito++;
- if (ito >= sizeTo) {
- pSetTo = NULL;
- } else {
- pSetTo = taosArrayGet(pTo->df, ito);
- }
- } else {
- tsdbApplyDFileSetChange(pSetFrom, pSetTo);
+_err:
+ tsdbError("vgId:%d tsdb apply disk file set change failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- ifrom++;
- if (ifrom >= sizeFrom) {
- pSetFrom = NULL;
- } else {
- pSetFrom = taosArrayGet(pFrom->df, ifrom);
- }
+static int32_t tsdbApplyDelFileChange(STsdbFS *pFS, SDelFile *pFrom, SDelFile *pTo) {
+ int32_t code = 0;
+ char fname[TSDB_FILENAME_LEN];
- ito++;
- if (ito >= sizeTo) {
- pSetTo = NULL;
- } else {
- pSetTo = taosArrayGet(pTo->df, ito);
+ if (pFrom && pTo) {
+ if (pFrom != pTo) {
+ tsdbDelFileName(pFS->pTsdb, pFrom, fname);
+ if (taosRemoveFile(fname) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
}
+ } else if (pFrom) {
+ tsdbDelFileName(pFS->pTsdb, pFrom, fname);
+ if (taosRemoveFile(fname) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ } else {
+ // do nothing
}
-}
-
-// ================== SFSIter
-// ASSUMPTIONS: the FS Should be read locked when calling these functions
-void tsdbFSIterInit(SFSIter *pIter, STsdbFS *pfs, int direction) {
- pIter->pfs = pfs;
- pIter->direction = direction;
- size_t size = taosArrayGetSize(pfs->cstatus->df);
+ return code;
- pIter->version = pfs->cstatus->meta.version;
-
- if (size == 0) {
- pIter->index = -1;
- pIter->fid = TSDB_IVLD_FID;
- } else {
- if (direction == TSDB_FS_ITER_FORWARD) {
- pIter->index = 0;
+_err:
+ tsdbError("vgId:%d tsdb apply del file change failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbFSApplyDiskChange(STsdbFS *pFS, STsdbFSState *pFrom, STsdbFSState *pTo) {
+ int32_t code = 0;
+ int32_t iFrom = 0;
+ int32_t nFrom = taosArrayGetSize(pFrom->aDFileSet);
+ int32_t iTo = 0;
+ int32_t nTo = taosArrayGetSize(pTo->aDFileSet);
+ SDFileSet *pDFileSetFrom;
+ SDFileSet *pDFileSetTo;
+
+ // SDelFile
+ code = tsdbApplyDelFileChange(pFS, pFrom->pDelFile, pTo->pDelFile);
+ if (code) goto _err;
+
+ // SDFileSet
+ while (iFrom < nFrom && iTo < nTo) {
+ pDFileSetFrom = (SDFileSet *)taosArrayGet(pFrom->aDFileSet, iFrom);
+ pDFileSetTo = (SDFileSet *)taosArrayGet(pTo->aDFileSet, iTo);
+
+ if (pDFileSetFrom->fid == pDFileSetTo->fid) {
+ code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, pDFileSetTo);
+ if (code) goto _err;
+
+ iFrom++;
+ iTo++;
+ } else if (pDFileSetFrom->fid < pDFileSetTo->fid) {
+ code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, NULL);
+ if (code) goto _err;
+
+ iFrom++;
} else {
- pIter->index = (int)(size - 1);
+ iTo++;
}
-
- pIter->fid = ((SDFileSet *)taosArrayGet(pfs->cstatus->df, pIter->index))->fid;
}
-}
-void tsdbFSIterSeek(SFSIter *pIter, int fid) {
- STsdbFS *pfs = pIter->pfs;
- size_t size = taosArrayGetSize(pfs->cstatus->df);
+ while (iFrom < nFrom) {
+ pDFileSetFrom = (SDFileSet *)taosArrayGet(pFrom->aDFileSet, iFrom);
+ code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, NULL);
+ if (code) goto _err;
- int flags;
- if (pIter->direction == TSDB_FS_ITER_FORWARD) {
- flags = TD_GE;
- } else {
- flags = TD_LE;
+ iFrom++;
}
- void *ptr = taosbsearch(&fid, pfs->cstatus->df->pData, size, sizeof(SDFileSet), tsdbComparFidFSet, flags);
- if (ptr == NULL) {
- pIter->index = -1;
- pIter->fid = TSDB_IVLD_FID;
- } else {
- pIter->index = (int)(TARRAY_ELEM_IDX(pfs->cstatus->df, ptr));
- pIter->fid = ((SDFileSet *)ptr)->fid;
- }
-}
+#if 0
+ // do noting
+ while (iTo < nTo) {
+ pDFileSetTo = (SDFileSet *)taosArrayGetP(pTo->aDFileSet, iTo);
+ code = tsdbApplyDFileSetChange(pFS, NULL, pDFileSetTo);
+ if (code) goto _err;
-SDFileSet *tsdbFSIterNext(SFSIter *pIter) {
- STsdbFS *pfs = pIter->pfs;
- SDFileSet *pSet;
-
- if (pIter->index < 0) {
- ASSERT(pIter->fid == TSDB_IVLD_FID);
- return NULL;
+ iTo++;
}
+#endif
- ASSERT(pIter->fid != TSDB_IVLD_FID);
+ return code;
- if (pIter->version != pfs->cstatus->meta.version) {
- pIter->version = pfs->cstatus->meta.version;
- tsdbFSIterSeek(pIter, pIter->fid);
- }
-
- if (pIter->index < 0) {
- return NULL;
- }
+_err:
+ tsdbError("vgId:%d tsdb fs apply disk change failed sicne %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- pSet = (SDFileSet *)taosArrayGet(pfs->cstatus->df, pIter->index);
- ASSERT(pSet->fid == pIter->fid);
+static void tsdbFSDestroy(STsdbFS *pFS) {
+ if (pFS) {
+ if (pFS->nState) {
+ taosArrayDestroy(pFS->nState->aDFileSet);
+ taosMemoryFree(pFS->nState);
+ }
- if (pIter->direction == TSDB_FS_ITER_FORWARD) {
- pIter->index++;
- if (pIter->index >= taosArrayGetSize(pfs->cstatus->df)) {
- pIter->index = -1;
+ if (pFS->cState) {
+ taosArrayDestroy(pFS->cState->aDFileSet);
+ taosMemoryFree(pFS->cState);
}
- } else {
- pIter->index--;
- }
- if (pIter->index >= 0) {
- pIter->fid = ((SDFileSet *)taosArrayGet(pfs->cstatus->df, pIter->index))->fid;
- } else {
- pIter->fid = TSDB_IVLD_FID;
+ taosThreadRwlockDestroy(&pFS->lock);
+ taosMemoryFree(pFS);
}
-
- return pSet;
+ // TODO
}
-static int tsdbComparFidFSet(const void *arg1, const void *arg2) {
- int fid = *(int *)arg1;
- SDFileSet *pSet = (SDFileSet *)arg2;
+static int32_t tsdbFSCreate(STsdb *pTsdb, STsdbFS **ppFS) {
+ int32_t code = 0;
+ STsdbFS *pFS = NULL;
- if (fid < pSet->fid) {
- return -1;
- } else if (fid == pSet->fid) {
- return 0;
- } else {
- return 1;
+ pFS = (STsdbFS *)taosMemoryCalloc(1, sizeof(*pFS));
+ if (pFS == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
}
-}
+ pFS->pTsdb = pTsdb;
-static void tsdbGetTxnFname(STsdb *pRepo, TSDB_TXN_FILE_T ftype, char fname[]) {
- snprintf(fname, TSDB_FILENAME_LEN, "%s/vnode/vnode%d/%s/%s", tfsGetPrimaryPath(REPO_TFS(pRepo)), REPO_ID(pRepo),
- pRepo->dir, tsdbTxnFname[ftype]);
-}
-
-static int tsdbOpenFSFromCurrent(STsdb *pRepo) {
- STsdbFS *pfs = REPO_FS(pRepo);
- TdFilePtr pFile = NULL;
- void *buffer = NULL;
- SFSHeader fsheader;
- char current[TSDB_FILENAME_LEN] = "\0";
- void *ptr;
-
- tsdbGetTxnFname(pRepo, TSDB_TXN_CURR_FILE, current);
-
- // current file exists, try to recover
- pFile = taosOpenFile(current, TD_FILE_READ);
- if (pFile == NULL) {
- tsdbError("vgId:%d, failed to open file %s since %s", REPO_ID(pRepo), current, strerror(errno));
- terrno = TAOS_SYSTEM_ERROR(errno);
+ code = taosThreadRwlockInit(&pFS->lock, NULL);
+ if (code) {
+ taosMemoryFree(pFS);
+ code = TAOS_SYSTEM_ERROR(code);
goto _err;
}
- if (tsdbMakeRoom(&buffer, TSDB_FILE_HEAD_SIZE) < 0) {
+ pFS->inTxn = 0;
+
+ pFS->cState = (STsdbFSState *)taosMemoryCalloc(1, sizeof(STsdbFSState));
+ if (pFS->cState == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
-
- int nread = (int)taosReadFile(pFile, buffer, TSDB_FILE_HEAD_SIZE);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to read %d bytes from file %s since %s", REPO_ID(pRepo), TSDB_FILENAME_LEN, current,
- strerror(errno));
- terrno = TAOS_SYSTEM_ERROR(errno);
+ pFS->cState->aDFileSet = taosArrayInit(0, sizeof(SDFileSet));
+ if (pFS->cState->aDFileSet == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
- if (nread < TSDB_FILE_HEAD_SIZE) {
- tsdbError("vgId:%d, failed to read header of file %s, read bytes:%d", REPO_ID(pRepo), current, nread);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
+ pFS->nState = (STsdbFSState *)taosMemoryCalloc(1, sizeof(STsdbFSState));
+ if (pFS->nState == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
-
- if (!taosCheckChecksumWhole((uint8_t *)buffer, TSDB_FILE_HEAD_SIZE)) {
- tsdbError("vgId:%d, header of file %s failed checksum check", REPO_ID(pRepo), current);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
+ pFS->nState->aDFileSet = taosArrayInit(0, sizeof(SDFileSet));
+ if (pFS->nState->aDFileSet == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
- SFSStatus *pStatus = pfs->cstatus;
- ptr = buffer;
- ptr = tsdbDecodeFSHeader(ptr, &fsheader);
- ptr = tsdbDecodeFSMeta(ptr, &(pStatus->meta));
-
- if (fsheader.version != TSDB_LATEST_SFS_VER) {
- // TODO: handle file version change
- }
+ *ppFS = pFS;
+ return code;
- if (fsheader.len > 0) {
- if (tsdbMakeRoom(&buffer, fsheader.len) < 0) {
+_err:
+ tsdbError("vgId:%d tsdb fs create failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ tsdbFSDestroy(pFS);
+ *ppFS = NULL;
+ return code;
+}
+
+static int32_t tsdbScanAndTryFixFS(STsdbFS *pFS, int8_t deepScan) {
+ int32_t code = 0;
+ STsdb *pTsdb = pFS->pTsdb;
+ STfs *pTfs = pTsdb->pVnode->pTfs;
+ int64_t size;
+ char fname[TSDB_FILENAME_LEN];
+ char pHdr[TSDB_FHDR_SIZE];
+ TdFilePtr pFD;
+
+ // SDelFile
+ if (pFS->cState->pDelFile) {
+ tsdbDelFileName(pTsdb, pFS->cState->pDelFile, fname);
+ if (taosStatFile(fname, &size, NULL)) {
+ code = TAOS_SYSTEM_ERROR(errno);
goto _err;
}
- nread = (int)taosReadFile(pFile, buffer, fsheader.len);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to read file %s since %s", REPO_ID(pRepo), current, strerror(errno));
- terrno = TAOS_SYSTEM_ERROR(errno);
+ if (size != pFS->cState->pDelFile->size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
goto _err;
}
- if (nread < fsheader.len) {
- tsdbError("vgId:%d, failed to read %d bytes from file %s", REPO_ID(pRepo), fsheader.len, current);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- goto _err;
+ if (deepScan) {
+ // TODO
}
+ }
+
+ // SArray
+ for (int32_t iSet = 0; iSet < taosArrayGetSize(pFS->cState->aDFileSet); iSet++) {
+ SDFileSet *pDFileSet = (SDFileSet *)taosArrayGet(pFS->cState->aDFileSet, iSet);
- if (!taosCheckChecksumWhole((uint8_t *)buffer, fsheader.len)) {
- tsdbError("vgId:%d, file %s is corrupted since wrong checksum", REPO_ID(pRepo), current);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
+ // head =========
+ tsdbDataFileName(pTsdb, pDFileSet, TSDB_HEAD_FILE, fname);
+ if (taosStatFile(fname, &size, NULL)) {
+ code = TAOS_SYSTEM_ERROR(errno);
goto _err;
}
- ptr = buffer;
- ptr = tsdbDecodeFSStatus(pRepo, ptr, pStatus);
- } else {
- tsdbResetFSStatus(pStatus);
- }
+ if (deepScan) {
+ // TODO
+ }
- taosTZfree(buffer);
- taosCloseFile(&pFile);
+ // data =========
+ tsdbDataFileName(pTsdb, pDFileSet, TSDB_DATA_FILE, fname);
+ if (taosStatFile(fname, &size, NULL)) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
- return 0;
+ if (size < pDFileSet->fData.size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ } else if (size > pDFileSet->fData.size) {
+ ASSERT(0);
+ // need to rollback the file
+ }
-_err:
- if (pFile != NULL) {
- taosCloseFile(&pFile);
- }
- taosTZfree(buffer);
- return -1;
-}
+ if (deepScan) {
+ // TODO
+ }
-// Scan and try to fix incorrect files
-static int tsdbScanAndTryFixFS(STsdb *pRepo) {
- STsdbFS *pfs = REPO_FS(pRepo);
- SFSStatus *pStatus = pfs->cstatus;
+ // last ===========
+ tsdbDataFileName(pTsdb, pDFileSet, TSDB_LAST_FILE, fname);
+ if (taosStatFile(fname, &size, NULL)) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
- // if (tsdbScanAndTryFixMFile(pRepo) < 0) {
- // tsdbError("vgId:%d, failed to fix MFile since %s", REPO_ID(pRepo), tstrerror(terrno));
- // return -1;
- // }
+ if (size < pDFileSet->fLast.size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ } else if (size > pDFileSet->fLast.size) {
+ ASSERT(0);
+ // need to rollback the file
+ }
- size_t size = taosArrayGetSize(pStatus->df);
+ if (deepScan) {
+ // TODO
+ }
- for (size_t i = 0; i < size; i++) {
- SDFileSet *pSet = (SDFileSet *)taosArrayGet(pStatus->df, i);
+ // sma =============
+ tsdbDataFileName(pTsdb, pDFileSet, TSDB_SMA_FILE, fname);
+ if (taosStatFile(fname, &size, NULL)) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
- if (tsdbScanAndTryFixDFileSet(pRepo, pSet) < 0) {
- tsdbError("vgId:%d, failed to fix MFile since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
+ if (size < pDFileSet->fSma.size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ } else if (size > pDFileSet->fSma.size) {
+ ASSERT(0);
+ // need to rollback the file
}
- }
- // remove those unused files
- tsdbScanRootDir(pRepo);
- tsdbScanDataDir(pRepo);
- return 0;
-}
+ if (deepScan) {
+ // TODO
+ }
+ }
-static int tsdbScanRootDir(STsdb *pRepo) {
- char rootDir[TSDB_FILENAME_LEN];
- char bname[TSDB_FILENAME_LEN];
- STsdbFS *pfs = REPO_FS(pRepo);
+ // remove those invalid files (todo)
+#if 0
+ STfsDir *tdir;
const STfsFile *pf;
- tsdbGetRootDir(REPO_ID(pRepo), pRepo->dir, rootDir);
- STfsDir *tdir = tfsOpendir(REPO_TFS(pRepo), rootDir);
+ tdir = tfsOpendir(pTfs, pTsdb->path);
if (tdir == NULL) {
- tsdbError("vgId:%d, failed to open directory %s since %s", REPO_ID(pRepo), rootDir, tstrerror(terrno));
- return -1;
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
while ((pf = tfsReaddir(tdir))) {
- tfsBasename(pf, bname);
-
- if (strcmp(bname, tsdbTxnFname[TSDB_TXN_CURR_FILE]) == 0 || strcmp(bname, "data") == 0) {
- // Skip current file and data directory
- continue;
- }
-
- // if (/*pfs->cstatus->pmf && */ tfsIsSameFile(pf, &(pfs->cstatus->pmf->f))) {
- // continue;
- // }
-
- (void)tfsRemoveFile(pf);
- tsdbDebug("vgId:%d, invalid file %s is removed", REPO_ID(pRepo), pf->aname);
+ tfsBasename(pf, fname);
}
tfsClosedir(tdir);
+#endif
- return 0;
-}
+ return code;
-static int tsdbScanDataDir(STsdb *pRepo) {
- char dataDir[TSDB_FILENAME_LEN];
- char bname[TSDB_FILENAME_LEN];
- STsdbFS *pfs = REPO_FS(pRepo);
- const STfsFile *pf;
+_err:
+ tsdbError("vgId:%d tsdb scan and try fix fs failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- tsdbGetDataDir(REPO_ID(pRepo), pRepo->dir, dataDir);
- STfsDir *tdir = tfsOpendir(REPO_TFS(pRepo), dataDir);
- if (tdir == NULL) {
- tsdbError("vgId:%d, failed to open directory %s since %s", REPO_ID(pRepo), dataDir, tstrerror(terrno));
+static int32_t tDFileSetCmprFn(const void *p1, const void *p2) {
+ if (((SDFileSet *)p1)->fid < ((SDFileSet *)p2)->fid) {
return -1;
+ } else if (((SDFileSet *)p1)->fid > ((SDFileSet *)p2)->fid) {
+ return 1;
}
- while ((pf = tfsReaddir(tdir))) {
- tfsBasename(pf, bname);
-
- if (!tsdbIsTFileInFS(pfs, pf)) {
- (void)tfsRemoveFile(pf);
- tsdbDebug("vgId:%d, invalid file %s is removed", REPO_ID(pRepo), pf->aname);
- }
- }
-
- tfsClosedir(tdir);
-
return 0;
}
-static bool tsdbIsTFileInFS(STsdbFS *pfs, const STfsFile *pf) {
- SFSIter fsiter;
- tsdbFSIterInit(&fsiter, pfs, TSDB_FS_ITER_FORWARD);
- SDFileSet *pSet;
+// EXPOSED APIS ====================================================================================
+int32_t tsdbFSOpen(STsdb *pTsdb, STsdbFS **ppFS) {
+ int32_t code = 0;
- while ((pSet = tsdbFSIterNext(&fsiter))) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- SDFile *pDFile = TSDB_DFILE_IN_SET(pSet, ftype);
- if (tfsIsSameFile(pf, TSDB_FILE_F(pDFile))) {
- return true;
- }
- }
- }
+ // create handle
+ code = tsdbFSCreate(pTsdb, ppFS);
+ if (code) goto _err;
- return false;
-}
-
-static int tsdbRestoreDFileSet(STsdb *pRepo) {
- char dataDir[TSDB_FILENAME_LEN];
- char bname[TSDB_FILENAME_LEN];
- STfsDir *tdir = NULL;
- const STfsFile *pf = NULL;
- const char *pattern = "^v[0-9]+f[0-9]+\\.(head|data|last|smad|smal)(-ver[0-9]+)?$";
- SArray *fArray = NULL;
- regex_t regex;
- STsdbFS *pfs = REPO_FS(pRepo);
-
- tsdbGetDataDir(REPO_ID(pRepo), pRepo->dir, dataDir);
-
- // Resource allocation and init
- regcomp(®ex, pattern, REG_EXTENDED);
-
- fArray = taosArrayInit(1024, sizeof(STfsFile));
- if (fArray == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbError("vgId:%d, failed to restore DFileSet while open directory %s since %s", REPO_ID(pRepo), dataDir,
- tstrerror(terrno));
- regfree(®ex);
- return -1;
- }
-
- tdir = tfsOpendir(REPO_TFS(pRepo), dataDir);
- if (tdir == NULL) {
- tsdbError("vgId:%d, failed to restore DFileSet while open directory %s since %s", REPO_ID(pRepo), dataDir,
- tstrerror(terrno));
- taosArrayDestroy(fArray);
- regfree(®ex);
- return -1;
+ // load current state
+ code = tsdbLoadCurrentState(*ppFS, (*ppFS)->cState);
+ if (code) {
+ tsdbFSDestroy(*ppFS);
+ goto _err;
}
- while ((pf = tfsReaddir(tdir))) {
- tfsBasename(pf, bname);
-
- int code = regexec(®ex, bname, 0, NULL, 0);
- if (code == 0) {
- if (taosArrayPush(fArray, (void *)pf) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tfsClosedir(tdir);
- taosArrayDestroy(fArray);
- regfree(®ex);
- return -1;
- }
- } else if (code == REG_NOMATCH) {
- // Not match
- tsdbInfo("vgId:%d, invalid file %s exists, remove it", REPO_ID(pRepo), pf->aname);
- (void)tfsRemoveFile(pf);
- continue;
- } else {
- // Has other error
- tsdbError("vgId:%d, failed to restore DFileSet Array while run regexec since %s", REPO_ID(pRepo), strerror(code));
- terrno = TAOS_SYSTEM_ERROR(code);
- tfsClosedir(tdir);
- taosArrayDestroy(fArray);
- regfree(®ex);
- return -1;
- }
+ // scan and fix FS
+ code = tsdbScanAndTryFixFS(*ppFS, 0);
+ if (code) {
+ tsdbFSDestroy(*ppFS);
+ goto _err;
}
- tfsClosedir(tdir);
- regfree(®ex);
+ return code;
- // Sort the array according to file name
- taosArraySort(fArray, tsdbComparTFILE);
-
- size_t index = 0;
- // Loop to recover each file set
- for (;;) {
- if (index >= taosArrayGetSize(fArray)) {
- break;
- }
+_err:
+ *ppFS = NULL;
+ tsdbError("vgId:%d tsdb fs open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- SDFileSet fset = {0};
+int32_t tsdbFSClose(STsdbFS *pFS) {
+ int32_t code = 0;
+ tsdbFSDestroy(pFS);
+ return code;
+}
- TSDB_FSET_SET_CLOSED(&fset);
+int32_t tsdbFSBegin(STsdbFS *pFS) {
+ int32_t code = 0;
- // Loop to recover ONE fset
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- SDFile *pDFile = TSDB_DFILE_IN_SET(&fset, ftype);
+ ASSERT(!pFS->inTxn);
- if (index >= taosArrayGetSize(fArray)) {
- tsdbError("vgId:%d, incomplete DFileSet, fid:%d", REPO_ID(pRepo), fset.fid);
- taosArrayDestroy(fArray);
- return -1;
- }
+ // SDelFile
+ pFS->nState->pDelFile = NULL;
+ if (pFS->cState->pDelFile) {
+ pFS->nState->delFile = pFS->cState->delFile;
+ pFS->nState->pDelFile = &pFS->nState->delFile;
+ }
- pf = taosArrayGet(fArray, index);
+ // SArray
+ taosArrayClear(pFS->nState->aDFileSet);
+ for (int32_t iSet = 0; iSet < taosArrayGetSize(pFS->cState->aDFileSet); iSet++) {
+ SDFileSet *pDFileSet = (SDFileSet *)taosArrayGet(pFS->cState->aDFileSet, iSet);
- int tvid, tfid;
- TSDB_FILE_T ttype;
- uint32_t tversion;
- char _bname[TSDB_FILENAME_LEN];
+ if (taosArrayPush(pFS->nState->aDFileSet, pDFileSet) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
- tfsBasename(pf, _bname);
- tsdbParseDFilename(_bname, &tvid, &tfid, &ttype, &tversion);
+ pFS->inTxn = 1;
+ return code;
- ASSERT(tvid == REPO_ID(pRepo));
+_err:
+ tsdbError("vgId:%d tsdb fs begin failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- if (tfid < pRepo->rtn.minFid) { // skip file expired
- ++index;
- continue;
- }
+int32_t tsdbFSCommit(STsdbFS *pFS) {
+ int32_t code = 0;
+ STsdbFSState *pState = pFS->nState;
+ char tfname[TSDB_FILENAME_LEN];
+ char fname[TSDB_FILENAME_LEN];
- if (ftype == 0) {
- fset.fid = tfid;
- } else {
- if (tfid != fset.fid) {
- tsdbError("vgId:%d, incomplete dFileSet, fid:%d", REPO_ID(pRepo), fset.fid);
- taosArrayDestroy(fArray);
- return -1;
- }
- }
+ // need lock (todo)
+ pFS->nState = pFS->cState;
+ pFS->cState = pState;
- if (ttype != ftype) {
- tsdbError("vgId:%d, incomplete dFileSet, fid:%d", REPO_ID(pRepo), fset.fid);
- taosArrayDestroy(fArray);
- return -1;
- }
+ snprintf(tfname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT.t", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
+ pFS->pTsdb->path, TD_DIRSEP);
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
+ pFS->pTsdb->path, TD_DIRSEP);
- pDFile->f = *pf;
+ // gnrt CURRENT.t
+ code = tsdbGnrtCurrent(tfname, pFS->cState);
+ if (code) goto _err;
- // if (tsdbOpenDFile(pDFile, O_RDONLY) < 0) {
- if (tsdbOpenDFile(pDFile, TD_FILE_READ) < 0) {
- tsdbError("vgId:%d, failed to open DFile %s since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
- tstrerror(terrno));
- taosArrayDestroy(fArray);
- return -1;
- }
+ // rename
+ code = taosRenameFile(tfname, fname);
+ if (code) {
+ code = TAOS_SYSTEM_ERROR(code);
+ goto _err;
+ }
- if (tsdbLoadDFileHeader(pDFile, &(pDFile->info)) < 0) {
- tsdbError("vgId:%d, failed to load DFile %s header since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
- tstrerror(terrno));
- taosArrayDestroy(fArray);
- return -1;
- }
+ // apply commit on disk
+ code = tsdbFSApplyDiskChange(pFS, pFS->nState, pFS->cState);
+ if (code) goto _err;
- if (tsdbForceKeepFile) {
- int64_t file_size;
- // Get real file size
- if (taosFStatFile(pDFile->pFile, &file_size, NULL) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- taosArrayDestroy(fArray);
- return -1;
- }
-
- if (pDFile->info.size != file_size) {
- int64_t tfsize = pDFile->info.size;
- pDFile->info.size = file_size;
- tsdbInfo("vgId:%d, file %s header size is changed from %" PRId64 " to %" PRId64, REPO_ID(pRepo),
- TSDB_FILE_FULL_NAME(pDFile), tfsize, pDFile->info.size);
- }
- }
+ pFS->inTxn = 0;
- tsdbCloseDFile(pDFile);
- index++;
- }
+ return code;
- tsdbInfo("vgId:%d, FSET %d is restored", REPO_ID(pRepo), fset.fid);
- taosArrayPush(pfs->cstatus->df, &fset);
- }
+_err:
+ tsdbError("vgId:%d tsdb fs commit failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
- // Resource release
- taosArrayDestroy(fArray);
+int32_t tsdbFSRollback(STsdbFS *pFS) {
+ int32_t code = 0;
- return 0;
-}
+ code = tsdbFSApplyDiskChange(pFS, pFS->nState, pFS->cState);
+ if (code) goto _err;
-static int tsdbRestoreCurrent(STsdb *pRepo) {
- if (tsdbRestoreDFileSet(pRepo) < 0) {
- tsdbError("vgId:%d, failed to restore DFileSet since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
- }
+ pFS->inTxn = 0;
- if (tsdbSaveFSStatus(pRepo, pRepo->fs->cstatus) < 0) {
- tsdbError("vgId:%d, failed to restore current since %s", REPO_ID(pRepo), tstrerror(terrno));
- return -1;
- }
+ return code;
- return 0;
+_err:
+ tsdbError("vgId:%d tsdb fs rollback failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
+ return code;
}
-static int tsdbComparTFILE(const void *arg1, const void *arg2) {
- STfsFile *pf1 = (STfsFile *)arg1;
- STfsFile *pf2 = (STfsFile *)arg2;
-
- int vid1, fid1, vid2, fid2;
- TSDB_FILE_T ftype1, ftype2;
- uint32_t version1, version2;
- char bname1[TSDB_FILENAME_LEN];
- char bname2[TSDB_FILENAME_LEN];
+int32_t tsdbFSStateUpsertDelFile(STsdbFSState *pState, SDelFile *pDelFile) {
+ int32_t code = 0;
+ pState->delFile = *pDelFile;
+ pState->pDelFile = &pState->delFile;
+ return code;
+}
- tfsBasename(pf1, bname1);
- tfsBasename(pf2, bname2);
- tsdbParseDFilename(bname1, &vid1, &fid1, &ftype1, &version1);
- tsdbParseDFilename(bname2, &vid2, &fid2, &ftype2, &version2);
+int32_t tsdbFSStateUpsertDFileSet(STsdbFSState *pState, SDFileSet *pSet) {
+ int32_t code = 0;
+ int32_t idx = taosArraySearchIdx(pState->aDFileSet, pSet, tDFileSetCmprFn, TD_GE);
- if (fid1 < fid2) {
- return -1;
- } else if (fid1 > fid2) {
- return 1;
+ if (idx < 0) {
+ if (taosArrayPush(pState->aDFileSet, pSet) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
} else {
- if (ftype1 < ftype2) {
- return -1;
- } else if (ftype1 > ftype2) {
- return 1;
+ SDFileSet *tDFileSet = (SDFileSet *)taosArrayGet(pState->aDFileSet, idx);
+ int32_t c = tDFileSetCmprFn(pSet, tDFileSet);
+ if (c == 0) {
+ taosArraySet(pState->aDFileSet, idx, pSet);
} else {
- return 0;
+ if (taosArrayInsert(pState->aDFileSet, idx, pSet) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
}
}
-}
-
-static void tsdbScanAndTryFixDFilesHeader(STsdb *pRepo, int32_t *nExpired) {
- STsdbFS *pfs = REPO_FS(pRepo);
- SFSStatus *pStatus = pfs->cstatus;
- SDFInfo info;
- for (size_t i = 0; i < taosArrayGetSize(pStatus->df); i++) {
- SDFileSet fset;
- tsdbInitDFileSetEx(&fset, (SDFileSet *)taosArrayGet(pStatus->df, i));
- if (fset.fid < pRepo->rtn.minFid) {
- ++*nExpired;
- }
- tsdbDebug("vgId:%d, scan DFileSet %d header", REPO_ID(pRepo), fset.fid);
+_exit:
+ return code;
+}
- // if (tsdbOpenDFileSet(&fset, O_RDWR) < 0) {
- if (tsdbOpenDFileSet(&fset, TD_FILE_WRITE | TD_FILE_READ) < 0) {
- tsdbError("vgId:%d, failed to open DFileSet %d since %s, continue", REPO_ID(pRepo), fset.fid, tstrerror(terrno));
- continue;
- }
+void tsdbFSStateDeleteDFileSet(STsdbFSState *pState, int32_t fid) {
+ int32_t idx;
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- SDFile *pDFile = TSDB_DFILE_IN_SET(&fset, ftype);
-
- if ((tsdbLoadDFileHeader(pDFile, &info) < 0) || pDFile->info.size != info.size ||
- pDFile->info.magic != info.magic) {
- if (tsdbUpdateDFileHeader(pDFile) < 0) {
- tsdbError("vgId:%d, failed to update DFile header of %s since %s, continue", REPO_ID(pRepo),
- TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno));
- } else {
- tsdbInfo("vgId:%d, DFile header of %s is updated", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
- TSDB_FILE_FSYNC(pDFile);
- }
- } else {
- tsdbDebug("vgId:%d, DFile header of %s is correct", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
- }
- }
-
- tsdbCloseDFileSet(&fset);
- }
+ idx = taosArraySearchIdx(pState->aDFileSet, &(SDFileSet){.fid = fid}, tDFileSetCmprFn, TD_EQ);
+ ASSERT(idx >= 0);
+ taosArrayRemove(pState->aDFileSet, idx);
}
-int tsdbRLockFS(STsdbFS *pFs) {
- int code = taosThreadRwlockRdlock(&(pFs->lock));
- if (code != 0) {
- terrno = TAOS_SYSTEM_ERROR(code);
- return -1;
- }
- return 0;
-}
+SDelFile *tsdbFSStateGetDelFile(STsdbFSState *pState) { return pState->pDelFile; }
-int tsdbWLockFS(STsdbFS *pFs) {
- int code = taosThreadRwlockWrlock(&(pFs->lock));
- if (code != 0) {
- terrno = TAOS_SYSTEM_ERROR(code);
- return -1;
- }
- return 0;
+SDFileSet *tsdbFSStateGetDFileSet(STsdbFSState *pState, int32_t fid) {
+ return (SDFileSet *)taosArraySearch(pState->aDFileSet, &(SDFileSet){.fid = fid}, tDFileSetCmprFn, TD_EQ);
}
-
-int tsdbUnLockFS(STsdbFS *pFs) {
- int code = taosThreadRwlockUnlock(&(pFs->lock));
- if (code != 0) {
- terrno = TAOS_SYSTEM_ERROR(code);
- return -1;
- }
- return 0;
-}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbFile.c b/source/dnode/vnode/src/tsdb/tsdbFile.c
index 11d206dc35c7ea337d1f550124374e4cb5132572..e7f8cb4789042f32c55a126f19a7925bbe31ba53 100644
--- a/source/dnode/vnode/src/tsdb/tsdbFile.c
+++ b/source/dnode/vnode/src/tsdb/tsdbFile.c
@@ -15,568 +15,287 @@
#include "tsdb.h"
-static const char *TSDB_FNAME_SUFFIX[] = {
- "head", // TSDB_FILE_HEAD
- "data", // TSDB_FILE_DATA
- "last", // TSDB_FILE_LAST
- "smad", // TSDB_FILE_SMAD
- "smal", // TSDB_FILE_SMAL
- "", // TSDB_FILE_MAX
- "meta", // TSDB_FILE_META
-};
-
-static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, const char *dname, char *fname);
-static int tsdbEncodeDFInfo(void **buf, SDFInfo *pInfo);
-static void *tsdbDecodeDFInfo(void *buf, SDFInfo *pInfo);
-static int tsdbRollBackDFile(SDFile *pDFile);
-
-// ============== Operations on SDFile
-void tsdbInitDFile(STsdb *pRepo, SDFile *pDFile, SDiskID did, int fid, uint32_t ver, TSDB_FILE_T ftype) {
- char fname[TSDB_FILENAME_LEN];
-
- TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_OK);
-
- TSDB_FILE_SET_CLOSED(pDFile);
-
- memset(&(pDFile->info), 0, sizeof(pDFile->info));
- pDFile->info.magic = TSDB_FILE_INIT_MAGIC;
- pDFile->info.fver = tsdbGetDFSVersion(ftype);
-
- tsdbGetFilename(REPO_ID(pRepo), fid, ver, ftype, pRepo->dir, fname);
- tfsInitFile(REPO_TFS(pRepo), &(pDFile->f), did, fname);
-}
-
-void tsdbInitDFileEx(SDFile *pDFile, SDFile *pODFile) {
- *pDFile = *pODFile;
- TSDB_FILE_SET_CLOSED(pDFile);
-}
-
-int tsdbEncodeSDFile(void **buf, SDFile *pDFile) {
- int tlen = 0;
-
- tlen += tsdbEncodeDFInfo(buf, &(pDFile->info));
- tlen += tfsEncodeFile(buf, &(pDFile->f));
-
- return tlen;
-}
+static int32_t tPutHeadFile(uint8_t *p, SHeadFile *pHeadFile) {
+ int32_t n = 0;
-void *tsdbDecodeSDFile(STsdb *pRepo, void *buf, SDFile *pDFile) {
- buf = tsdbDecodeDFInfo(buf, &(pDFile->info));
- buf = tfsDecodeFile(REPO_TFS(pRepo), buf, &(pDFile->f));
- TSDB_FILE_SET_CLOSED(pDFile);
+ n += tPutI64v(p ? p + n : p, pHeadFile->commitID);
+ n += tPutI64v(p ? p + n : p, pHeadFile->size);
+ n += tPutI64v(p ? p + n : p, pHeadFile->offset);
- return buf;
+ return n;
}
-static int tsdbEncodeSDFileEx(void **buf, SDFile *pDFile) {
- int tlen = 0;
+static int32_t tGetHeadFile(uint8_t *p, SHeadFile *pHeadFile) {
+ int32_t n = 0;
- tlen += tsdbEncodeDFInfo(buf, &(pDFile->info));
- tlen += taosEncodeString(buf, TSDB_FILE_FULL_NAME(pDFile));
+ n += tGetI64v(p + n, &pHeadFile->commitID);
+ n += tGetI64v(p + n, &pHeadFile->size);
+ n += tGetI64v(p + n, &pHeadFile->offset);
- return tlen;
+ return n;
}
-static void *tsdbDecodeSDFileEx(void *buf, SDFile *pDFile) {
- char *aname = NULL;
+static int32_t tPutDataFile(uint8_t *p, SDataFile *pDataFile) {
+ int32_t n = 0;
- buf = tsdbDecodeDFInfo(buf, &(pDFile->info));
- buf = taosDecodeString(buf, &aname);
- strncpy(TSDB_FILE_FULL_NAME(pDFile), aname, TSDB_FILENAME_LEN);
- TSDB_FILE_SET_CLOSED(pDFile);
- taosMemoryFreeClear(aname);
+ n += tPutI64v(p ? p + n : p, pDataFile->commitID);
+ n += tPutI64v(p ? p + n : p, pDataFile->size);
- return buf;
+ return n;
}
-int tsdbCreateDFile(STsdb *pRepo, SDFile *pDFile, bool updateHeader, TSDB_FILE_T fType) {
- ASSERT(pDFile->info.size == 0 && pDFile->info.magic == TSDB_FILE_INIT_MAGIC);
-
- pDFile->pFile = taosOpenFile(TSDB_FILE_FULL_NAME(pDFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
- if (pDFile->pFile == NULL) {
- if (errno == ENOENT) {
- // Try to create directory recursively
- char *s = strdup(TSDB_FILE_REL_NAME(pDFile));
- if (tfsMkdirRecurAt(REPO_TFS(pRepo), taosDirName(s), TSDB_FILE_DID(pDFile)) < 0) {
- taosMemoryFreeClear(s);
- return -1;
- }
- taosMemoryFreeClear(s);
-
- pDFile->pFile = taosOpenFile(TSDB_FILE_FULL_NAME(pDFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
- if (pDFile->pFile == NULL) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
- } else {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
- }
-
- if (!updateHeader) {
- return 0;
- }
+static int32_t tGetDataFile(uint8_t *p, SDataFile *pDataFile) {
+ int32_t n = 0;
- pDFile->info.size += TSDB_FILE_HEAD_SIZE;
- pDFile->info.fver = tsdbGetDFSVersion(fType);
+ n += tGetI64v(p + n, &pDataFile->commitID);
+ n += tGetI64v(p + n, &pDataFile->size);
- if (tsdbUpdateDFileHeader(pDFile) < 0) {
- tsdbCloseDFile(pDFile);
- tsdbRemoveDFile(pDFile);
- return -1;
- }
-
- return 0;
+ return n;
}
-int tsdbUpdateDFileHeader(SDFile *pDFile) {
- char buf[TSDB_FILE_HEAD_SIZE] = "\0";
-
- if (tsdbSeekDFile(pDFile, 0, SEEK_SET) < 0) {
- return -1;
- }
-
- void *ptr = buf;
- // taosEncodeFixedU32(&ptr, 0); // fver moved to SDFInfo and saved to current
- tsdbEncodeDFInfo(&ptr, &(pDFile->info));
+static int32_t tPutLastFile(uint8_t *p, SLastFile *pLastFile) {
+ int32_t n = 0;
- taosCalcChecksumAppend(0, (uint8_t *)buf, TSDB_FILE_HEAD_SIZE);
- if (tsdbWriteDFile(pDFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
- return -1;
- }
+ n += tPutI64v(p ? p + n : p, pLastFile->commitID);
+ n += tPutI64v(p ? p + n : p, pLastFile->size);
- return 0;
+ return n;
}
-int tsdbLoadDFileHeader(SDFile *pDFile, SDFInfo *pInfo) {
- char buf[TSDB_FILE_HEAD_SIZE] = "\0";
- uint32_t _version;
-
- ASSERT(TSDB_FILE_OPENED(pDFile));
+static int32_t tGetLastFile(uint8_t *p, SLastFile *pLastFile) {
+ int32_t n = 0;
- if (tsdbSeekDFile(pDFile, 0, SEEK_SET) < 0) {
- return -1;
- }
-
- if (tsdbReadDFile(pDFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
- return -1;
- }
+ n += tGetI64v(p + n, &pLastFile->commitID);
+ n += tGetI64v(p + n, &pLastFile->size);
- if (!taosCheckChecksumWhole((uint8_t *)buf, TSDB_FILE_HEAD_SIZE)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- return -1;
- }
-
- void *pBuf = buf;
- // pBuf = taosDecodeFixedU32(pBuf, &_version);
- pBuf = tsdbDecodeDFInfo(pBuf, pInfo);
- return 0;
+ return n;
}
-static int tsdbScanAndTryFixDFile(STsdb *pRepo, SDFile *pDFile) {
- SDFile df;
-
- tsdbInitDFileEx(&df, pDFile);
-
- if (!taosCheckExistFile(TSDB_FILE_FULL_NAME(pDFile))) {
- tsdbError("vgId:%d, data file %s not exit, report to upper layer to fix it", REPO_ID(pRepo),
- TSDB_FILE_FULL_NAME(pDFile));
- // pRepo->state |= TSDB_STATE_BAD_DATA;
- TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_BAD);
- return 0;
- }
- int64_t file_size = 0;
- if (taosStatFile(TSDB_FILE_FULL_NAME(&df), &file_size, NULL) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
+static int32_t tPutSmaFile(uint8_t *p, SSmaFile *pSmaFile) {
+ int32_t n = 0;
- if (pDFile->info.size < file_size) {
- // if (tsdbOpenDFile(&df, O_WRONLY) < 0) {
- if (tsdbOpenDFile(&df, TD_FILE_WRITE) < 0) {
- return -1;
- }
-
- if (taosFtruncateFile(df.pFile, df.info.size) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- tsdbCloseDFile(&df);
- return -1;
- }
-
- if (tsdbUpdateDFileHeader(&df) < 0) {
- tsdbCloseDFile(&df);
- return -1;
- }
-
- tsdbCloseDFile(&df);
- tsdbInfo("vgId:%d, file %s is truncated from %" PRId64 " to %" PRId64, REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
- file_size, pDFile->info.size);
- } else if (pDFile->info.size > file_size) {
- tsdbError("vgId:%d, data file %s has wrong size %" PRId64 " expected %" PRId64 ", report to upper layer to fix it",
- REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile), file_size, pDFile->info.size);
- // pRepo->state |= TSDB_STATE_BAD_DATA;
- TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_BAD);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- return 0;
- } else {
- tsdbDebug("vgId:%d, file %s passes the scan", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
- }
+ n += tPutI64v(p ? p + n : p, pSmaFile->commitID);
+ n += tPutI64v(p ? p + n : p, pSmaFile->size);
- return 0;
+ return n;
}
-static int tsdbEncodeDFInfo(void **buf, SDFInfo *pInfo) {
- int tlen = 0;
+static int32_t tGetSmaFile(uint8_t *p, SSmaFile *pSmaFile) {
+ int32_t n = 0;
- tlen += taosEncodeFixedU32(buf, pInfo->magic);
- tlen += taosEncodeFixedU32(buf, pInfo->fver);
- tlen += taosEncodeFixedU32(buf, pInfo->len);
- tlen += taosEncodeFixedU32(buf, pInfo->totalBlocks);
- tlen += taosEncodeFixedU32(buf, pInfo->totalSubBlocks);
- tlen += taosEncodeFixedU32(buf, pInfo->offset);
- tlen += taosEncodeFixedU64(buf, pInfo->size);
- tlen += taosEncodeFixedU64(buf, pInfo->tombSize);
+ n += tGetI64v(p + n, &pSmaFile->commitID);
+ n += tGetI64v(p + n, &pSmaFile->size);
- return tlen;
+ return n;
}
-static void *tsdbDecodeDFInfo(void *buf, SDFInfo *pInfo) {
- buf = taosDecodeFixedU32(buf, &(pInfo->magic));
- buf = taosDecodeFixedU32(buf, &(pInfo->fver));
- buf = taosDecodeFixedU32(buf, &(pInfo->len));
- buf = taosDecodeFixedU32(buf, &(pInfo->totalBlocks));
- buf = taosDecodeFixedU32(buf, &(pInfo->totalSubBlocks));
- buf = taosDecodeFixedU32(buf, &(pInfo->offset));
- buf = taosDecodeFixedU64(buf, &(pInfo->size));
- buf = taosDecodeFixedU64(buf, &(pInfo->tombSize));
-
- return buf;
-}
+// EXPOSED APIS ==================================================
+void tsdbDataFileName(STsdb *pTsdb, SDFileSet *pDFileSet, EDataFileT ftype, char fname[]) {
+ STfs *pTfs = pTsdb->pVnode->pTfs;
-static int tsdbApplyDFileChange(SDFile *from, SDFile *to) {
- ASSERT(from != NULL || to != NULL);
-
- if (from != NULL) {
- if (to == NULL) {
- tsdbRemoveDFile(from);
- } else {
- if (tfsIsSameFile(TSDB_FILE_F(from), TSDB_FILE_F(to))) {
- if (from->info.size > to->info.size) {
- tsdbRollBackDFile(to);
- }
- } else {
- (void)tsdbRemoveDFile(from);
- }
- }
+ switch (ftype) {
+ case TSDB_HEAD_FILE:
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sv%df%dver%" PRId64 "%s", tfsGetDiskPath(pTfs, pDFileSet->diskId),
+ TD_DIRSEP, pTsdb->path, TD_DIRSEP, TD_VID(pTsdb->pVnode), pDFileSet->fid, pDFileSet->fHead.commitID,
+ ".head");
+ break;
+ case TSDB_DATA_FILE:
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sv%df%dver%" PRId64 "%s", tfsGetDiskPath(pTfs, pDFileSet->diskId),
+ TD_DIRSEP, pTsdb->path, TD_DIRSEP, TD_VID(pTsdb->pVnode), pDFileSet->fid, pDFileSet->fData.commitID,
+ ".data");
+ break;
+ case TSDB_LAST_FILE:
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sv%df%dver%" PRId64 "%s", tfsGetDiskPath(pTfs, pDFileSet->diskId),
+ TD_DIRSEP, pTsdb->path, TD_DIRSEP, TD_VID(pTsdb->pVnode), pDFileSet->fid, pDFileSet->fLast.commitID,
+ ".last");
+ break;
+ case TSDB_SMA_FILE:
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sv%df%dver%" PRId64 "%s", tfsGetDiskPath(pTfs, pDFileSet->diskId),
+ TD_DIRSEP, pTsdb->path, TD_DIRSEP, TD_VID(pTsdb->pVnode), pDFileSet->fid, pDFileSet->fSma.commitID,
+ ".sma");
+ break;
+ default:
+ ASSERT(0);
+ break;
}
-
- return 0;
}
-static int tsdbRollBackDFile(SDFile *pDFile) {
- SDFile df = *pDFile;
-
- // if (tsdbOpenDFile(&df, O_WRONLY) < 0) {
- if (tsdbOpenDFile(&df, TD_FILE_WRITE) < 0) {
- return -1;
- }
-
- if (taosFtruncateFile(TSDB_FILE_PFILE(&df), pDFile->info.size) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- tsdbCloseDFile(&df);
- return -1;
+bool tsdbFileIsSame(SDFileSet *pDFileSet1, SDFileSet *pDFileSet2, EDataFileT ftype) {
+ if (pDFileSet1->diskId.level != pDFileSet2->diskId.level || pDFileSet1->diskId.id != pDFileSet2->diskId.id) {
+ return false;
}
- if (tsdbUpdateDFileHeader(&df) < 0) {
- tsdbCloseDFile(&df);
- return -1;
+ switch (ftype) {
+ case TSDB_HEAD_FILE:
+ return pDFileSet1->fHead.commitID == pDFileSet2->fHead.commitID;
+ case TSDB_DATA_FILE:
+ return pDFileSet1->fData.commitID == pDFileSet2->fData.commitID;
+ case TSDB_LAST_FILE:
+ return pDFileSet1->fLast.commitID == pDFileSet2->fLast.commitID;
+ case TSDB_SMA_FILE:
+ return pDFileSet1->fSma.commitID == pDFileSet2->fSma.commitID;
+ default:
+ ASSERT(0);
+ break;
}
-
- TSDB_FILE_FSYNC(&df);
-
- tsdbCloseDFile(&df);
- return 0;
}
-// ============== Operations on SDFileSet
-void tsdbInitDFileSet(STsdb *pRepo, SDFileSet *pSet, SDiskID did, int fid, uint32_t ver) {
- TSDB_FSET_FID(pSet) = fid;
- TSDB_FSET_VER(pSet) = TSDB_LATEST_FSET_VER;
- TSDB_FSET_STATE(pSet) = 0;
- pSet->reserve = 0;
+int32_t tsdbUpdateDFileHdr(TdFilePtr pFD, SDFileSet *pSet, EDataFileT ftype) {
+ int32_t code = 0;
+ int64_t n;
+ char hdr[TSDB_FHDR_SIZE];
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- SDFile *pDFile = TSDB_DFILE_IN_SET(pSet, ftype);
- tsdbInitDFile(pRepo, pDFile, did, fid, ver, ftype);
- }
-}
+ memset(hdr, 0, TSDB_FHDR_SIZE);
+ tPutDataFileHdr(hdr, pSet, ftype);
+ taosCalcChecksumAppend(0, hdr, TSDB_FHDR_SIZE);
-void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet) {
- TSDB_FSET_FID(pSet) = TSDB_FSET_FID(pOSet);
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- tsdbInitDFileEx(TSDB_DFILE_IN_SET(pSet, ftype), TSDB_DFILE_IN_SET(pOSet, ftype));
+ n = taosLSeekFile(pFD, 0, SEEK_SET);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _exit;
}
-}
-int tsdbEncodeDFileSet(void **buf, SDFileSet *pSet) {
- int tlen = 0;
-
- tlen += taosEncodeFixedI32(buf, TSDB_FSET_FID(pSet));
- // state not included
- tlen += taosEncodeFixedU8(buf, TSDB_FSET_VER(pSet));
- tlen += taosEncodeFixedU16(buf, pSet->reserve);
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- tlen += tsdbEncodeSDFile(buf, TSDB_DFILE_IN_SET(pSet, ftype));
+ n = taosWriteFile(pFD, hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _exit;
}
- return tlen;
+_exit:
+ return code;
}
-void *tsdbDecodeDFileSet(STsdb *pRepo, void *buf, SDFileSet *pSet) {
- buf = taosDecodeFixedI32(buf, &(TSDB_FSET_FID(pSet)));
- TSDB_FSET_STATE(pSet) = 0;
- buf = taosDecodeFixedU8(buf, &(TSDB_FSET_VER(pSet)));
- buf = taosDecodeFixedU16(buf, &(pSet->reserve));
+int32_t tsdbDFileRollback(STsdb *pTsdb, SDFileSet *pSet, EDataFileT ftype) {
+ int32_t code = 0;
+ int64_t size;
+ TdFilePtr pFD;
+ char fname[TSDB_FILENAME_LEN];
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- buf = tsdbDecodeSDFile(pRepo, buf, TSDB_DFILE_IN_SET(pSet, ftype));
- }
- return buf;
-}
+ tsdbDataFileName(pTsdb, pSet, ftype, fname);
-int tsdbEncodeDFileSetEx(void **buf, SDFileSet *pSet) {
- int tlen = 0;
-
- tlen += taosEncodeFixedI32(buf, TSDB_FSET_FID(pSet));
- tlen += taosEncodeFixedU8(buf, TSDB_FSET_VER(pSet));
- tlen += taosEncodeFixedU16(buf, pSet->reserve);
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- tlen += tsdbEncodeSDFileEx(buf, TSDB_DFILE_IN_SET(pSet, ftype));
+ // open
+ pFD = taosOpenFile(fname, TD_FILE_WRITE);
+ if (pFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- return tlen;
-}
-
-void *tsdbDecodeDFileSetEx(void *buf, SDFileSet *pSet) {
- buf = taosDecodeFixedI32(buf, &(TSDB_FSET_FID(pSet)));
- buf = taosDecodeFixedU8(buf, &(TSDB_FSET_VER(pSet)));
- buf = taosDecodeFixedU16(buf, &(pSet->reserve));
-
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- buf = tsdbDecodeSDFileEx(buf, TSDB_DFILE_IN_SET(pSet, ftype));
+ // truncate
+ switch (ftype) {
+ case TSDB_HEAD_FILE:
+ size = pSet->fHead.size;
+ break;
+ case TSDB_DATA_FILE:
+ size = pSet->fData.size;
+ break;
+ case TSDB_LAST_FILE:
+ size = pSet->fLast.size;
+ break;
+ case TSDB_SMA_FILE:
+ size = pSet->fSma.size;
+ break;
+ default:
+ ASSERT(0);
}
- return buf;
-}
-
-int tsdbApplyDFileSetChange(SDFileSet *from, SDFileSet *to) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- SDFile *pDFileFrom = (from) ? TSDB_DFILE_IN_SET(from, ftype) : NULL;
- SDFile *pDFileTo = (to) ? TSDB_DFILE_IN_SET(to, ftype) : NULL;
- if (tsdbApplyDFileChange(pDFileFrom, pDFileTo) < 0) {
- return -1;
- }
+ if (taosFtruncateFile(pFD, size) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- return 0;
-}
+ // update header
+ code = tsdbUpdateDFileHdr(pFD, pSet, ftype);
+ if (code) goto _err;
-int tsdbCreateDFileSet(STsdb *pRepo, SDFileSet *pSet, bool updateHeader) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (tsdbCreateDFile(pRepo, TSDB_DFILE_IN_SET(pSet, ftype), updateHeader, ftype) < 0) {
- tsdbCloseDFileSet(pSet);
- tsdbRemoveDFileSet(pSet);
- return -1;
- }
+ // sync
+ if (taosFsyncFile(pFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
}
- return 0;
-}
+ // close
+ taosCloseFile(&pFD);
-int tsdbUpdateDFileSetHeader(SDFileSet *pSet) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (tsdbUpdateDFileHeader(TSDB_DFILE_IN_SET(pSet, ftype)) < 0) {
- return -1;
- }
- }
- return 0;
-}
+ return code;
-int tsdbScanAndTryFixDFileSet(STsdb *pRepo, SDFileSet *pSet) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (tsdbScanAndTryFixDFile(pRepo, TSDB_DFILE_IN_SET(pSet, ftype)) < 0) {
- return -1;
- }
- }
- return 0;
+_err:
+ return code;
}
-int tsdbParseDFilename(const char *fname, int *vid, int *fid, TSDB_FILE_T *ftype, uint32_t *_version) {
- char *p = NULL;
- *_version = 0;
- *ftype = TSDB_FILE_MAX;
+int32_t tPutDataFileHdr(uint8_t *p, SDFileSet *pSet, EDataFileT ftype) {
+ int32_t n = 0;
- sscanf(fname, "v%df%d.%m[a-z]-ver%" PRIu32, vid, fid, &p, _version);
- for (TSDB_FILE_T i = 0; i < TSDB_FILE_MAX; i++) {
- if (strcmp(p, TSDB_FNAME_SUFFIX[i]) == 0) {
- *ftype = i;
+ switch (ftype) {
+ case TSDB_HEAD_FILE:
+ n += tPutHeadFile(p ? p + n : p, &pSet->fHead);
break;
- }
- }
-
- taosMemoryFreeClear(p);
- return 0;
-}
-
-static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, const char *dname, char *fname) {
- ASSERT(ftype != TSDB_FILE_MAX);
-
- if (ftype < TSDB_FILE_MAX) {
- if (ver == 0) {
- snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/%s/data/v%df%d.%s", vid, dname, vid, fid,
- TSDB_FNAME_SUFFIX[ftype]);
- } else {
- snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/%s/data/v%df%d.%s-ver%" PRIu32, vid, dname, vid, fid,
- TSDB_FNAME_SUFFIX[ftype], ver);
- }
- } else {
- if (ver == 0) {
- snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/%s", vid, TSDB_FNAME_SUFFIX[ftype]);
- } else {
- snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/%s-ver%" PRIu32, vid, TSDB_FNAME_SUFFIX[ftype], ver);
- }
- }
-}
-
-int tsdbOpenDFile(SDFile *pDFile, int flags) {
- ASSERT(!TSDB_FILE_OPENED(pDFile));
-
- pDFile->pFile = taosOpenFile(TSDB_FILE_FULL_NAME(pDFile), flags);
- if (pDFile->pFile == NULL) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
-
- return 0;
-}
-
-void tsdbCloseDFile(SDFile *pDFile) {
- if (TSDB_FILE_OPENED(pDFile)) {
- taosCloseFile(&pDFile->pFile);
- TSDB_FILE_SET_CLOSED(pDFile);
- }
-}
-
-int64_t tsdbSeekDFile(SDFile *pDFile, int64_t offset, int whence) {
- // ASSERT(TSDB_FILE_OPENED(pDFile));
-
- int64_t loffset = taosLSeekFile(TSDB_FILE_PFILE(pDFile), offset, whence);
- if (loffset < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
+ case TSDB_DATA_FILE:
+ n += tPutDataFile(p ? p + n : p, &pSet->fData);
+ break;
+ case TSDB_LAST_FILE:
+ n += tPutLastFile(p ? p + n : p, &pSet->fLast);
+ break;
+ case TSDB_SMA_FILE:
+ n += tPutSmaFile(p ? p + n : p, &pSet->fSma);
+ break;
+ default:
+ ASSERT(0);
}
- return loffset;
+ return n;
}
-int64_t tsdbWriteDFile(SDFile *pDFile, void *buf, int64_t nbyte) {
- ASSERT(TSDB_FILE_OPENED(pDFile));
+int32_t tPutDFileSet(uint8_t *p, SDFileSet *pSet) {
+ int32_t n = 0;
- int64_t nwrite = taosWriteFile(pDFile->pFile, buf, nbyte);
- if (nwrite < nbyte) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
+ n += tPutI32v(p ? p + n : p, pSet->diskId.level);
+ n += tPutI32v(p ? p + n : p, pSet->diskId.id);
+ n += tPutI32v(p ? p + n : p, pSet->fid);
+ n += tPutHeadFile(p ? p + n : p, &pSet->fHead);
+ n += tPutDataFile(p ? p + n : p, &pSet->fData);
+ n += tPutLastFile(p ? p + n : p, &pSet->fLast);
+ n += tPutSmaFile(p ? p + n : p, &pSet->fSma);
- return nwrite;
+ return n;
}
-void tsdbUpdateDFileMagic(SDFile *pDFile, void *pCksm) {
- pDFile->info.magic = taosCalcChecksum(pDFile->info.magic, (uint8_t *)(pCksm), sizeof(TSCKSUM));
-}
-
-int tsdbAppendDFile(SDFile *pDFile, void *buf, int64_t nbyte, int64_t *offset) {
- ASSERT(TSDB_FILE_OPENED(pDFile));
-
- int64_t toffset;
-
- if ((toffset = tsdbSeekDFile(pDFile, 0, SEEK_END)) < 0) {
- return -1;
- }
-
- ASSERT(pDFile->info.size == toffset);
-
- if (offset) {
- *offset = toffset;
- }
-
- if (tsdbWriteDFile(pDFile, buf, nbyte) < 0) {
- return -1;
- }
+int32_t tGetDFileSet(uint8_t *p, SDFileSet *pSet) {
+ int32_t n = 0;
- pDFile->info.size += nbyte;
+ n += tGetI32v(p + n, &pSet->diskId.level);
+ n += tGetI32v(p + n, &pSet->diskId.id);
+ n += tGetI32v(p + n, &pSet->fid);
+ n += tGetHeadFile(p + n, &pSet->fHead);
+ n += tGetDataFile(p + n, &pSet->fData);
+ n += tGetLastFile(p + n, &pSet->fLast);
+ n += tGetSmaFile(p + n, &pSet->fSma);
- return (int)nbyte;
+ return n;
}
-int tsdbRemoveDFile(SDFile *pDFile) { return tfsRemoveFile(TSDB_FILE_F(pDFile)); }
+// SDelFile ===============================================
+void tsdbDelFileName(STsdb *pTsdb, SDelFile *pFile, char fname[]) {
+ STfs *pTfs = pTsdb->pVnode->pTfs;
-int64_t tsdbReadDFile(SDFile *pDFile, void *buf, int64_t nbyte) {
- ASSERT(TSDB_FILE_OPENED(pDFile));
-
- int64_t nread = taosReadFile(pDFile->pFile, buf, nbyte);
- if (nread < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
-
- return nread;
+ snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sv%dver%" PRId64 "%s", tfsGetPrimaryPath(pTfs), TD_DIRSEP, pTsdb->path,
+ TD_DIRSEP, TD_VID(pTsdb->pVnode), pFile->commitID, ".del");
}
-int tsdbCopyDFile(SDFile *pSrc, SDFile *pDest) {
- if (tfsCopyFile(TSDB_FILE_F(pSrc), TSDB_FILE_F(pDest)) < 0) {
- terrno = TAOS_SYSTEM_ERROR(errno);
- return -1;
- }
+int32_t tPutDelFile(uint8_t *p, SDelFile *pDelFile) {
+ int32_t n = 0;
- pDest->info = pSrc->info;
- return 0;
-}
+ n += tPutI64v(p ? p + n : p, pDelFile->commitID);
+ n += tPutI64v(p ? p + n : p, pDelFile->size);
+ n += tPutI64v(p ? p + n : p, pDelFile->offset);
-void tsdbCloseDFileSet(SDFileSet *pSet) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- tsdbCloseDFile(TSDB_DFILE_IN_SET(pSet, ftype));
- }
+ return n;
}
-int tsdbOpenDFileSet(SDFileSet *pSet, int flags) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (tsdbOpenDFile(TSDB_DFILE_IN_SET(pSet, ftype), flags) < 0) {
- tsdbCloseDFileSet(pSet);
- return -1;
- }
- }
- return 0;
-}
-
-void tsdbRemoveDFileSet(SDFileSet *pSet) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- (void)tsdbRemoveDFile(TSDB_DFILE_IN_SET(pSet, ftype));
- }
-}
+int32_t tGetDelFile(uint8_t *p, SDelFile *pDelFile) {
+ int32_t n = 0;
-int tsdbCopyDFileSet(SDFileSet *pSrc, SDFileSet *pDest) {
- for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
- if (tsdbCopyDFile(TSDB_DFILE_IN_SET(pSrc, ftype), TSDB_DFILE_IN_SET(pDest, ftype)) < 0) {
- tsdbRemoveDFileSet(pDest);
- return -1;
- }
- }
+ n += tGetI64v(p + n, &pDelFile->commitID);
+ n += tGetI64v(p + n, &pDelFile->size);
+ n += tGetI64v(p + n, &pDelFile->offset);
- return 0;
+ return n;
}
-
-void tsdbGetFidKeyRange(int days, int8_t precision, int fid, TSKEY *minKey, TSKEY *maxKey) {
- *minKey = fid * days * tsTickPerMin[precision];
- *maxKey = *minKey + days * tsTickPerMin[precision] - 1;
-}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable.c b/source/dnode/vnode/src/tsdb/tsdbMemTable.c
index d8bc87d47142d59d3564c3cbcf89bfe4d6a0e84e..82de931872f0d205069d2775ba4ab7d96838d556 100644
--- a/source/dnode/vnode/src/tsdb/tsdbMemTable.c
+++ b/source/dnode/vnode/src/tsdb/tsdbMemTable.c
@@ -25,8 +25,6 @@
#define SL_MOVE_BACKWARD 0x1
#define SL_MOVE_FROM_POS 0x2
-static int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow);
-static int32_t tGetTSDBRow(uint8_t *p, TSDBROW *pRow);
static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *pKey, int32_t flags);
static int32_t tsdbGetOrCreateTbData(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t uid, STbData **ppTbData);
static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, int64_t version,
@@ -44,10 +42,12 @@ int32_t tsdbMemTableCreate(STsdb *pTsdb, SMemTable **ppMemTable) {
taosInitRWLatch(&pMemTable->latch);
pMemTable->pTsdb = pTsdb;
pMemTable->nRef = 1;
- pMemTable->minKey = (TSDBKEY){.ts = TSKEY_MAX, .version = INT64_MAX};
- pMemTable->maxKey = (TSDBKEY){.ts = TSKEY_MIN, .version = -1};
+ pMemTable->minKey = TSKEY_MAX;
+ pMemTable->maxKey = TSKEY_MIN;
+ pMemTable->minVersion = VERSION_MAX;
+ pMemTable->maxVersion = VERSION_MIN;
pMemTable->nRow = 0;
- pMemTable->nDelOp = 0;
+ pMemTable->nDel = 0;
pMemTable->aTbData = taosArrayInit(128, sizeof(STbData *));
if (pMemTable->aTbData == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
@@ -105,7 +105,7 @@ int32_t tsdbInsertTableData(STsdb *pTsdb, int64_t version, SSubmitMsgIter *pMsgI
// check if table exists (todo: refact)
SMetaReader mr = {0};
- SMetaEntry me = {0};
+ // SMetaEntry me = {0};
metaReaderInit(&mr, pTsdb->pVnode->pMeta, 0);
if (metaGetTableEntryByUid(&mr, pMsgIter->uid) < 0) {
metaReaderClear(&mr);
@@ -117,6 +117,8 @@ int32_t tsdbInsertTableData(STsdb *pTsdb, int64_t version, SSubmitMsgIter *pMsgI
if (mr.me.type == TSDB_NORMAL_TABLE) {
sverNew = mr.me.ntbEntry.schemaRow.version;
} else {
+ tDecoderClear(&mr.coder);
+
metaGetTableEntryByUid(&mr, mr.me.ctbEntry.suid);
sverNew = mr.me.stbEntry.schemaRow.version;
}
@@ -146,6 +148,7 @@ int32_t tsdbDeleteTableData(STsdb *pTsdb, int64_t version, tb_uid_t suid, tb_uid
SMemTable *pMemTable = pTsdb->mem;
STbData *pTbData = NULL;
SVBufPool *pPool = pTsdb->pVnode->inUse;
+ TSDBKEY lastKey = {.version = version, .ts = eKey};
// check if table exists (todo)
@@ -155,26 +158,36 @@ int32_t tsdbDeleteTableData(STsdb *pTsdb, int64_t version, tb_uid_t suid, tb_uid
}
// do delete
- SDelOp *pDelOp = (SDelOp *)vnodeBufPoolMalloc(pPool, sizeof(*pDelOp));
- if (pDelOp == NULL) {
+ SDelData *pDelData = (SDelData *)vnodeBufPoolMalloc(pPool, sizeof(*pDelData));
+ if (pDelData == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
- pDelOp->version = version;
- pDelOp->sKey = sKey;
- pDelOp->eKey = eKey;
- pDelOp->pNext = NULL;
+ pDelData->version = version;
+ pDelData->sKey = sKey;
+ pDelData->eKey = eKey;
+ pDelData->pNext = NULL;
if (pTbData->pHead == NULL) {
ASSERT(pTbData->pTail == NULL);
- pTbData->pHead = pTbData->pTail = pDelOp;
+ pTbData->pHead = pTbData->pTail = pDelData;
} else {
- pTbData->pTail->pNext = pDelOp;
- pTbData->pTail = pDelOp;
+ pTbData->pTail->pNext = pDelData;
+ pTbData->pTail = pDelData;
}
// update the state of pMemTable and other (todo)
- pMemTable->nDelOp++;
+ pMemTable->minVersion = TMIN(pMemTable->minVersion, version);
+ pMemTable->maxVersion = TMAX(pMemTable->maxVersion, version);
+ pMemTable->nDel++;
+
+ if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config) && tsdbKeyCmprFn(&lastKey, &pTbData->maxKey) >= 0) {
+ tsdbCacheDeleteLastrow(pTsdb->lruCache, pTbData->uid, eKey);
+ }
+
+ if (TSDB_CACHE_LAST(pMemTable->pTsdb->pVnode->config)) {
+ tsdbCacheDeleteLast(pTsdb->lruCache, pTbData->uid, eKey);
+ }
tsdbError("vgId:%d, delete data from table suid:%" PRId64 " uid:%" PRId64 " skey:%" PRId64 " eKey:%" PRId64
" since %s",
@@ -213,9 +226,15 @@ void *tsdbTbDataIterDestroy(STbDataIter *pIter) {
void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter *pIter) {
SMemSkipListNode *pos[SL_MAX_LEVEL];
+ SMemSkipListNode *pHead;
+ SMemSkipListNode *pTail;
+ pHead = pTbData->sl.pHead;
+ pTail = pTbData->sl.pTail;
pIter->pTbData = pTbData;
pIter->backward = backward;
+ pIter->pRow = NULL;
+ pIter->row.type = 0;
if (pFrom == NULL) {
// create from head or tail
if (backward) {
@@ -239,6 +258,7 @@ bool tsdbTbDataIterNext(STbDataIter *pIter) {
SMemSkipListNode *pHead = pIter->pTbData->sl.pHead;
SMemSkipListNode *pTail = pIter->pTbData->sl.pTail;
+ pIter->pRow = NULL;
if (pIter->backward) {
ASSERT(pIter->pNode != pTail);
@@ -266,31 +286,29 @@ bool tsdbTbDataIterNext(STbDataIter *pIter) {
return true;
}
-bool tsdbTbDataIterGet(STbDataIter *pIter, TSDBROW *pRow) {
- SMemSkipListNode *pHead = pIter->pTbData->sl.pHead;
- SMemSkipListNode *pTail = pIter->pTbData->sl.pTail;
- TSDBROW row = {0};
+TSDBROW *tsdbTbDataIterGet(STbDataIter *pIter) {
+ // we add here for commit usage
+ if (pIter == NULL) return NULL;
- if (pRow == NULL) {
- pRow = &row;
+ if (pIter->pRow) {
+ goto _exit;
}
if (pIter->backward) {
- ASSERT(pIter->pNode != pTail);
-
- if (pIter->pNode == pHead) {
- return false;
+ if (pIter->pNode == pIter->pTbData->sl.pHead) {
+ goto _exit;
}
} else {
- ASSERT(pIter->pNode != pHead);
-
- if (pIter->pNode == pTail) {
- return false;
+ if (pIter->pNode == pIter->pTbData->sl.pTail) {
+ goto _exit;
}
}
- tGetTSDBRow((uint8_t *)SL_NODE_DATA(pIter->pNode), pRow);
- return true;
+ tGetTSDBRow((uint8_t *)SL_NODE_DATA(pIter->pNode), &pIter->row);
+ pIter->pRow = &pIter->row;
+
+_exit:
+ return pIter->pRow;
}
static int32_t tsdbGetOrCreateTbData(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t uid, STbData **ppTbData) {
@@ -317,8 +335,11 @@ static int32_t tsdbGetOrCreateTbData(SMemTable *pMemTable, tb_uid_t suid, tb_uid
}
pTbData->suid = suid;
pTbData->uid = uid;
- pTbData->minKey = (TSDBKEY){.ts = TSKEY_MAX, .version = INT64_MAX};
- pTbData->maxKey = (TSDBKEY){.ts = TSKEY_MIN, .version = -1};
+ pTbData->minKey = TSKEY_MAX;
+ pTbData->maxKey = TSKEY_MIN;
+ pTbData->minVersion = VERSION_MAX;
+ pTbData->maxVersion = VERSION_MIN;
+ pTbData->maxSkmVer = -1;
pTbData->pHead = NULL;
pTbData->pTail = NULL;
pTbData->sl.seed = taosRand();
@@ -493,8 +514,9 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i
SSubmitBlkIter blkIter = {0};
TSDBKEY key = {.version = version};
SMemSkipListNode *pos[SL_MAX_LEVEL];
- TSDBROW row = {.version = version, .pTSRow = NULL};
+ TSDBROW row = tsdbRowFromTSRow(version, NULL);
int32_t nRow = 0;
+ STSRow *pLastRow = NULL;
tInitSubmitBlkIter(pMsgIter, pBlock, &blkIter);
@@ -508,13 +530,9 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i
goto _err;
}
- if (tsdbKeyCmprFn(&key, &pTbData->minKey) < 0) {
- pTbData->minKey = key;
- }
+ pTbData->minKey = TMIN(pTbData->minKey, key.ts);
- if (tsdbKeyCmprFn(&key, &pMemTable->minKey) < 0) {
- pMemTable->minKey = key;
- }
+ pLastRow = row.pTSRow;
// forward put rest data
row.pTSRow = tGetSubmitBlkNext(&blkIter);
@@ -531,18 +549,37 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i
goto _err;
}
+ pLastRow = row.pTSRow;
+
row.pTSRow = tGetSubmitBlkNext(&blkIter);
} while (row.pTSRow);
}
- if (tsdbKeyCmprFn(&key, &pTbData->maxKey) > 0) {
- pTbData->maxKey = key;
+ if (key.ts >= pTbData->maxKey) {
+ if (key.ts > pTbData->maxKey) {
+ pTbData->maxKey = key.ts;
+ }
+
+ if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config) && pLastRow != NULL) {
+ tsdbCacheInsertLastrow(pMemTable->pTsdb->lruCache, pMemTable->pTsdb, pTbData->uid, pLastRow, true);
+ }
}
- if (tsdbKeyCmprFn(&key, &pMemTable->maxKey) > 0) {
- pMemTable->maxKey = key;
+ if (TSDB_CACHE_LAST(pMemTable->pTsdb->pVnode->config)) {
+ tsdbCacheInsertLast(pMemTable->pTsdb->lruCache, pTbData->uid, pLastRow, pMemTable->pTsdb);
}
- pMemTable->nRef++;
+
+ pTbData->minVersion = TMIN(pTbData->minVersion, version);
+ pTbData->maxVersion = TMAX(pTbData->maxVersion, version);
+ pTbData->maxSkmVer = TMAX(pTbData->maxSkmVer, pMsgIter->sversion);
+
+ // SMemTable
+ pMemTable->minKey = TMIN(pMemTable->minKey, pTbData->minKey);
+ pMemTable->maxKey = TMAX(pMemTable->maxKey, pTbData->maxKey);
+ pMemTable->minVersion = TMIN(pMemTable->minVersion, pTbData->minVersion);
+ pMemTable->maxVersion = TMAX(pMemTable->maxVersion, pTbData->maxVersion);
+ pMemTable->nRow += nRow;
+
pRsp->numOfRows = nRow;
pRsp->affectedRows = nRow;
@@ -552,22 +589,4 @@ _err:
return code;
}
-static int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow) {
- int32_t n = 0;
-
- n += tPutI64(p, pRow->version);
- if (p) memcpy(p + n, pRow->pTSRow, pRow->pTSRow->len);
- n += pRow->pTSRow->len;
-
- return n;
-}
-
-static int32_t tGetTSDBRow(uint8_t *p, TSDBROW *pRow) {
- int32_t n = 0;
-
- n += tGetI64(p, &pRow->version);
- pRow->pTSRow = (STSRow *)(p + n);
- n += pRow->pTSRow->len;
-
- return n;
-}
\ No newline at end of file
+int32_t tsdbGetNRowsInTbData(STbData *pTbData) { return pTbData->sl.size; }
diff --git a/source/dnode/vnode/src/tsdb/tsdbOpen.c b/source/dnode/vnode/src/tsdb/tsdbOpen.c
index 943263e1a3c65ebf980b353e6a1b69ba52868a22..1fa582fae552e6fef224f0fb30c50a4eab421cc8 100644
--- a/source/dnode/vnode/src/tsdb/tsdbOpen.c
+++ b/source/dnode/vnode/src/tsdb/tsdbOpen.c
@@ -17,7 +17,6 @@
static int tsdbSetKeepCfg(STsdbKeepCfg *pKeepCfg, STsdbCfg *pCfg);
-
// implementation
static int tsdbSetKeepCfg(STsdbKeepCfg *pKeepCfg, STsdbCfg *pCfg) {
@@ -42,7 +41,7 @@ int tsdbOpen(SVnode *pVnode, STsdb **ppTsdb, const char *dir, STsdbKeepCfg *pKee
int slen = 0;
*ppTsdb = NULL;
- slen = strlen(tfsGetPrimaryPath(pVnode->pTfs)) + strlen(pVnode->path) + strlen(dir) + 3;
+ slen = strlen(pVnode->path) + strlen(dir) + 2;
// create handle
pTsdb = (STsdb *)taosMemoryCalloc(1, sizeof(*pTsdb) + slen);
@@ -51,10 +50,8 @@ int tsdbOpen(SVnode *pVnode, STsdb **ppTsdb, const char *dir, STsdbKeepCfg *pKee
return -1;
}
- ASSERT(strlen(dir) < TSDB_DATA_DIR_LEN);
- memcpy(pTsdb->dir, dir, strlen(dir));
pTsdb->path = (char *)&pTsdb[1];
- sprintf(pTsdb->path, "%s%s%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path, TD_DIRSEP, dir);
+ sprintf(pTsdb->path, "%s%s%s", pVnode->path, TD_DIRSEP, dir);
taosRealPath(pTsdb->path, NULL, slen);
pTsdb->pVnode = pVnode;
pTsdb->repoLocked = false;
@@ -64,13 +61,17 @@ int tsdbOpen(SVnode *pVnode, STsdb **ppTsdb, const char *dir, STsdbKeepCfg *pKee
} else {
memcpy(&pTsdb->keepCfg, pKeepCfg, sizeof(STsdbKeepCfg));
}
- pTsdb->fs = tsdbNewFS(REPO_KEEP_CFG(pTsdb));
+ // pTsdb->fs = tsdbNewFS(REPO_KEEP_CFG(pTsdb));
- // create dir (TODO: use tfsMkdir)
- taosMkDir(pTsdb->path);
+ // create dir
+ tfsMkdir(pVnode->pTfs, pTsdb->path);
// open tsdb
- if (tsdbOpenFS(pTsdb) < 0) {
+ if (tsdbFSOpen(pTsdb, &pTsdb->fs) < 0) {
+ goto _err;
+ }
+
+ if (tsdbOpenCache(pTsdb) < 0) {
goto _err;
}
@@ -87,10 +88,9 @@ _err:
int tsdbClose(STsdb **pTsdb) {
if (*pTsdb) {
- // TODO: destroy mem/imem
taosThreadMutexDestroy(&(*pTsdb)->mutex);
- tsdbCloseFS(*pTsdb);
- tsdbFreeFS((*pTsdb)->fs);
+ tsdbFSClose((*pTsdb)->fs);
+ tsdbCloseCache((*pTsdb)->lruCache);
taosMemoryFreeClear(*pTsdb);
}
return 0;
@@ -99,7 +99,7 @@ int tsdbClose(STsdb **pTsdb) {
int tsdbLockRepo(STsdb *pTsdb) {
int code = taosThreadMutexLock(&pTsdb->mutex);
if (code != 0) {
- tsdbError("vgId:%d, failed to lock tsdb since %s", REPO_ID(pTsdb), strerror(errno));
+ tsdbError("vgId:%d, failed to lock tsdb since %s", TD_VID(pTsdb->pVnode), strerror(errno));
terrno = TAOS_SYSTEM_ERROR(code);
return -1;
}
@@ -108,13 +108,13 @@ int tsdbLockRepo(STsdb *pTsdb) {
}
int tsdbUnlockRepo(STsdb *pTsdb) {
- ASSERT(IS_REPO_LOCKED(pTsdb));
+ // ASSERT(IS_REPO_LOCKED(pTsdb));
pTsdb->repoLocked = false;
int code = taosThreadMutexUnlock(&pTsdb->mutex);
if (code != 0) {
- tsdbError("vgId:%d, failed to unlock tsdb since %s", REPO_ID(pTsdb), strerror(errno));
+ tsdbError("vgId:%d, failed to unlock tsdb since %s", TD_VID(pTsdb->pVnode), strerror(errno));
terrno = TAOS_SYSTEM_ERROR(code);
return -1;
}
return 0;
-}
\ No newline at end of file
+}
diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c
index ce73246e51adcb3906b16a56084d44cf2fb0bed4..5e30fcd5b2efbae26232e5340cf00f1617ad90c1 100644
--- a/source/dnode/vnode/src/tsdb/tsdbRead.c
+++ b/source/dnode/vnode/src/tsdb/tsdbRead.c
@@ -14,2814 +14,2711 @@
*/
#include "tsdb.h"
-#include "vnode.h"
-
-#define EXTRA_BYTES 2
-#define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC)
-#define QH_GET_NUM_OF_COLS(handle) ((size_t)(taosArrayGetSize((handle)->pColumns)))
-
-#define GET_FILE_DATA_BLOCK_INFO(_checkInfo, _block) \
- ((SDataBlockInfo){.window = {.skey = (_block)->minKey.ts, .ekey = (_block)->maxKey.ts}, \
- .numOfCols = (_block)->numOfCols, \
- .rows = (_block)->numOfRows, \
- .uid = (_checkInfo)->tableId})
-
-enum {
- TSDB_QUERY_TYPE_ALL = 1,
- TSDB_QUERY_TYPE_LAST = 2,
-};
-
-enum {
- TSDB_CACHED_TYPE_NONE = 0,
- TSDB_CACHED_TYPE_LASTROW = 1,
- TSDB_CACHED_TYPE_LAST = 2,
-};
-
-typedef struct SQueryFilePos {
- int32_t fid;
- int32_t slot;
- int32_t pos;
- int64_t lastKey;
- int32_t rows;
- bool mixBlock;
- bool blockCompleted;
- STimeWindow win;
-} SQueryFilePos;
-
-typedef struct SDataBlockLoadInfo {
- SDFileSet* fileGroup;
- int32_t slot;
- uint64_t uid;
- SArray* pLoadedCols;
-} SDataBlockLoadInfo;
-
-typedef struct SLoadCompBlockInfo {
- int32_t tid; /* table tid */
- int32_t fileId;
-} SLoadCompBlockInfo;
-
-enum {
- CHECKINFO_CHOSEN_MEM = 0,
- CHECKINFO_CHOSEN_IMEM = 1,
- CHECKINFO_CHOSEN_BOTH = 2 // for update=2(merge case)
-};
-
-typedef struct STableCheckInfo {
- uint64_t suid;
- uint64_t tableId;
- TSKEY lastKey;
- SBlockInfo* pCompInfo;
- int32_t compSize;
- int32_t numOfBlocks : 29; // number of qualified data blocks not the original blocks
- uint8_t chosen : 2; // indicate which iterator should move forward
- bool initBuf : 1; // whether to initialize the in-memory skip list iterator or not
- STbDataIter* iter; // mem buffer skip list iterator
- STbDataIter* iiter; // imem buffer skip list iterator
-} STableCheckInfo;
-
-typedef struct STableBlockInfo {
- SBlock* compBlock;
- STableCheckInfo* pTableCheckInfo;
-} STableBlockInfo;
+#define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC)
+
+typedef struct {
+ STbDataIter* iter;
+ int32_t index;
+ bool hasVal;
+} SIterInfo;
+
+typedef struct STableBlockScanInfo {
+ uint64_t uid;
+ TSKEY lastKey;
+ SBlockIdx blockIdx;
+ SArray* pBlockList; // block data index list
+ SIterInfo iter; // mem buffer skip list iterator
+ SIterInfo iiter; // imem buffer skip list iterator
+ SArray* delSkyline; // delete info for this table
+ int32_t fileDelIndex;
+ bool iterInit; // whether to initialize the in-memory skip list iterator or not
+} STableBlockScanInfo;
+
+typedef struct SBlockOrderWrapper {
+ int64_t uid;
+ SBlock* pBlock;
+} SBlockOrderWrapper;
typedef struct SBlockOrderSupporter {
- int32_t numOfTables;
- STableBlockInfo** pDataBlockInfo;
- int32_t* blockIndexArray;
- int32_t* numOfBlocksPerTable;
+ SBlockOrderWrapper** pDataBlockInfo;
+ int32_t* indexPerTable;
+ int32_t* numOfBlocksPerTable;
+ int32_t numOfTables;
} SBlockOrderSupporter;
typedef struct SIOCostSummary {
int64_t blockLoadTime;
- int64_t statisInfoLoadTime;
+ int64_t smaLoadTime;
int64_t checkForNextTime;
int64_t headFileLoad;
int64_t headFileLoadTime;
} SIOCostSummary;
typedef struct SBlockLoadSuppInfo {
- SColumnDataAgg* pstatis;
+ SArray* pColAgg;
+ SColumnDataAgg tsColAgg;
SColumnDataAgg** plist;
- SArray* defaultLoadColumn; // default load column
- int32_t* slotIds; // colId to slotId
+ int16_t* colIds; // column ids for loading file block data
+ char** buildBuf; // build string tmp buffer, todo remove it later after all string format being updated.
} SBlockLoadSuppInfo;
-typedef struct STsdbReadHandle {
- STsdb* pTsdb;
- uint64_t suid;
- SQueryFilePos cur; // current position
- int16_t order;
- STimeWindow window; // the primary query time window that applies to all queries
- // SColumnDataAgg* statis; // query level statistics, only one table block statistics info exists at any time
- // SColumnDataAgg** pstatis;// the ptr array list to return to caller
- int32_t numOfBlocks;
- SArray* pColumns; // column list, SColumnInfoData array list
- bool locateStart;
- int32_t outputCapacity;
- int32_t realNumOfRows;
- SArray* pTableCheckInfo; // SArray
- int32_t activeIndex;
- bool checkFiles; // check file stage
- int8_t cachelastrow; // check if last row cached
- bool loadExternalRow; // load time window external data rows
- bool currentLoadExternalRows; // current load external rows
- int32_t loadType; // block load type
- char* idStr; // query info handle, for debug purpose
- int32_t type; // query type: retrieve all data blocks, 2. retrieve only last row, 3. retrieve direct prev|next rows
- SDFileSet* pFileGroup;
- SFSIter fileIter;
- SReadH rhelper;
- STableBlockInfo* pDataBlockInfo;
- SDataCols* pDataCols; // in order to hold current file data block
- int32_t allocSize; // allocated data block size
- SDataBlockLoadInfo dataBlockLoadInfo; /* record current block load information */
- SLoadCompBlockInfo compBlockLoadInfo; /* record current compblock information in SQueryAttr */
- SBlockLoadSuppInfo suppInfo;
- SArray* prev; // previous row which is before than time window
- SArray* next; // next row which is after the query time window
- SIOCostSummary cost;
- STSchema* pSchema;
-} STsdbReadHandle;
-
-static STimeWindow updateLastrowForEachGroup(STableListInfo* pList);
-static int32_t checkForCachedLastRow(STsdbReadHandle* pTsdbReadHandle, STableListInfo* pList);
-static int32_t checkForCachedLast(STsdbReadHandle* pTsdbReadHandle);
-// static int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey);
-
-static void changeQueryHandleForInterpQuery(tsdbReaderT pHandle);
-static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock);
-static int32_t tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
- STsdbReadHandle* pTsdbReadHandle);
-static int32_t tsdbCheckInfoCompar(const void* key1, const void* key2);
-// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, void* pMemRef);
-// static void* doFreeColumnInfoData(SArray* pColumnInfoData);
-// static void* destroyTableCheckInfo(SArray* pTableCheckInfo);
-static bool tsdbGetExternalRow(tsdbReaderT pHandle);
-
-static STsdb* getTsdbByRetentions(SVnode* pVnode, STsdbReadHandle* pReadHandle, TSKEY winSKey, SRetention* retentions);
-
-static void tsdbInitDataBlockLoadInfo(SDataBlockLoadInfo* pBlockLoadInfo) {
- pBlockLoadInfo->slot = -1;
- pBlockLoadInfo->uid = 0;
- pBlockLoadInfo->fileGroup = NULL;
-}
-
-static void tsdbInitCompBlockLoadInfo(SLoadCompBlockInfo* pCompBlockLoadInfo) {
- pCompBlockLoadInfo->tid = -1;
- pCompBlockLoadInfo->fileId = -1;
-}
-
-static SArray* getColumnIdList(STsdbReadHandle* pTsdbReadHandle) {
- size_t numOfCols = QH_GET_NUM_OF_COLS(pTsdbReadHandle);
- assert(numOfCols <= TSDB_MAX_COLUMNS);
-
- SArray* pIdList = taosArrayInit(numOfCols, sizeof(int16_t));
- for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData* pCol = taosArrayGet(pTsdbReadHandle->pColumns, i);
- taosArrayPush(pIdList, &pCol->info.colId);
- }
+typedef struct SFilesetIter {
+ int32_t numOfFiles; // number of total files
+ int32_t index; // current accessed index in the list
+ SArray* pFileList; // data file list
+ int32_t order;
+} SFilesetIter;
- return pIdList;
-}
+typedef struct SFileDataBlockInfo {
+ int32_t
+ tbBlockIdx; // index position in STableBlockScanInfo in order to check whether neighbor block overlaps with it
+ uint64_t uid;
+} SFileDataBlockInfo;
-static SArray* getDefaultLoadColumns(STsdbReadHandle* pTsdbReadHandle, bool loadTS) {
- SArray* pLocalIdList = getColumnIdList(pTsdbReadHandle);
+typedef struct SDataBlockIter {
+ int32_t numOfBlocks;
+ int32_t index;
+ SArray* blockList; // SArray
+ int32_t order;
+} SDataBlockIter;
+
+typedef struct SFileBlockDumpInfo {
+ int32_t totalRows;
+ int32_t rowIndex;
+ int64_t lastKey;
+ bool allDumped;
+} SFileBlockDumpInfo;
+
+typedef struct SVersionRange {
+ uint64_t minVer;
+ uint64_t maxVer;
+} SVersionRange;
+
+typedef struct SReaderStatus {
+ bool loadFromFile; // check file stage
+ SHashObj* pTableMap; // SHash
+ STableBlockScanInfo* pTableIter; // table iterator used in building in-memory buffer data blocks.
+ SFileBlockDumpInfo fBlockDumpInfo;
+
+ SDFileSet* pCurrentFileset; // current opened file set
+ SBlockData fileBlockData;
+ SFilesetIter fileIter;
+ SDataBlockIter blockIter;
+ bool composedDataBlock; // the returned data block is a composed block or not
+} SReaderStatus;
+
+struct STsdbReader {
+ STsdb* pTsdb;
+ uint64_t suid;
+ int16_t order;
+ STimeWindow window; // the primary query time window that applies to all queries
+ SSDataBlock* pResBlock;
+ int32_t capacity;
+ SReaderStatus status;
+ char* idStr; // query info handle, for debug purpose
+ int32_t type; // query type: 1. retrieve all data blocks, 2. retrieve direct prev|next rows
+ SBlockLoadSuppInfo suppInfo;
- // check if the primary time stamp column needs to load
- int16_t colId = *(int16_t*)taosArrayGet(pLocalIdList, 0);
+ SIOCostSummary cost;
+ STSchema* pSchema;
+ SDataFReader* pFileReader;
+ SVersionRange verRange;
+};
- // the primary timestamp column does not be included in the the specified load column list, add it
- if (loadTS && colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
- int16_t columnId = PRIMARYKEY_TIMESTAMP_COL_ID;
- taosArrayInsert(pLocalIdList, 0, &columnId);
+static SFileDataBlockInfo* getCurrentBlockInfo(SDataBlockIter* pBlockIter);
+static int buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity,
+ STsdbReader* pReader);
+static TSDBROW* getValidRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* pReader);
+static int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader,
+ SRowMerger* pMerger);
+static int32_t doMergeRowsInBuf(SIterInfo* pIter, int64_t ts, SArray* pDelList, SRowMerger* pMerger,
+ STsdbReader* pReader);
+static int32_t doAppendOneRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* pTSRow);
+static void setComposedBlockFlag(STsdbReader* pReader, bool composed);
+static void updateSchema(TSDBROW* pRow, uint64_t uid, STsdbReader* pReader);
+static bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32_t order);
+
+static void doMergeMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, SArray* pDelList, STSRow** pTSRow,
+ STsdbReader* pReader);
+static void doMergeMemIMemRows(TSDBROW* pRow, TSDBROW* piRow, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader,
+ STSRow** pTSRow);
+static int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, STbData* pMemTbData,
+ STbData* piMemTbData);
+static STsdb* getTsdbByRetentions(SVnode* pVnode, TSKEY winSKey, SRetention* retentions, const char* idstr,
+ int8_t* pLevel);
+static SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level);
+
+static int32_t setColumnIdSlotList(STsdbReader* pReader, SSDataBlock* pBlock) {
+ SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
+
+ size_t numOfCols = blockDataGetNumOfCols(pBlock);
+
+ pSupInfo->colIds = taosMemoryMalloc(numOfCols * sizeof(int16_t));
+ pSupInfo->buildBuf = taosMemoryCalloc(numOfCols, POINTER_BYTES);
+ if (pSupInfo->buildBuf == NULL || pSupInfo->colIds == NULL) {
+ taosMemoryFree(pSupInfo->colIds);
+ taosMemoryFree(pSupInfo->buildBuf);
+ return TSDB_CODE_OUT_OF_MEMORY;
}
- return pLocalIdList;
-}
-
-int64_t tsdbGetNumOfRowsInMemTable(tsdbReaderT* pHandle) {
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
+ pSupInfo->colIds[i] = pCol->info.colId;
- int64_t rows = 0;
- SMemTable* pMemTable = NULL; // pTsdbReadHandle->pMemTable;
- if (pMemTable == NULL) {
- return rows;
+ if (IS_VAR_DATA_TYPE(pCol->info.type)) {
+ pSupInfo->buildBuf[i] = taosMemoryMalloc(pCol->info.bytes);
+ }
}
- size_t size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- for (int32_t i = 0; i < size; ++i) {
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
-
- // if (pMemT && pCheckInfo->tableId < pMemT->maxTables) {
- // pMem = pMemT->tData[pCheckInfo->tableId];
- // rows += (pMem && pMem->uid == pCheckInfo->tableId) ? pMem->numOfRows : 0;
- // }
- // if (pIMemT && pCheckInfo->tableId < pIMemT->maxTables) {
- // pIMem = pIMemT->tData[pCheckInfo->tableId];
- // rows += (pIMem && pIMem->uid == pCheckInfo->tableId) ? pIMem->numOfRows : 0;
- // }
- }
- return rows;
+ return TSDB_CODE_SUCCESS;
}
-static SArray* createCheckInfoFromTableGroup(STsdbReadHandle* pTsdbReadHandle, STableListInfo* pTableList) {
- size_t tableSize = taosArrayGetSize(pTableList->pTableList);
- assert(tableSize >= 1);
-
+static SHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, const STableKeyInfo* idList, int32_t numOfTables) {
// allocate buffer in order to load data blocks from file
- SArray* pTableCheckInfo = taosArrayInit(tableSize, sizeof(STableCheckInfo));
- if (pTableCheckInfo == NULL) {
+ // todo use simple hash instead
+ SHashObj* pTableMap =
+ taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
+ if (pTableMap == NULL) {
return NULL;
}
- // todo apply the lastkey of table check to avoid to load header file
- for (int32_t j = 0; j < tableSize; ++j) {
- STableKeyInfo* pKeyInfo = (STableKeyInfo*)taosArrayGet(pTableList->pTableList, j);
-
- STableCheckInfo info = {.lastKey = pKeyInfo->lastKey, .tableId = pKeyInfo->uid};
- info.suid = pTsdbReadHandle->suid;
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- if (info.lastKey == INT64_MIN || info.lastKey < pTsdbReadHandle->window.skey) {
- info.lastKey = pTsdbReadHandle->window.skey;
+ for (int32_t j = 0; j < numOfTables; ++j) {
+ STableBlockScanInfo info = {.lastKey = 0, .uid = idList[j].uid};
+ if (ASCENDING_TRAVERSE(pTsdbReader->order)) {
+ if (info.lastKey == INT64_MIN || info.lastKey < pTsdbReader->window.skey) {
+ info.lastKey = pTsdbReader->window.skey;
}
- assert(info.lastKey >= pTsdbReadHandle->window.skey && info.lastKey <= pTsdbReadHandle->window.ekey);
+ ASSERT(info.lastKey >= pTsdbReader->window.skey && info.lastKey <= pTsdbReader->window.ekey);
} else {
- info.lastKey = pTsdbReadHandle->window.skey;
+ info.lastKey = pTsdbReader->window.skey;
}
- taosArrayPush(pTableCheckInfo, &info);
- tsdbDebug("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pTsdbReadHandle, info.tableId, info.lastKey,
- pTsdbReadHandle->idStr);
+ taosHashPut(pTableMap, &info.uid, sizeof(uint64_t), &info, sizeof(info));
+ tsdbDebug("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pTsdbReader, info.uid, info.lastKey,
+ pTsdbReader->idStr);
}
- // TODO group table according to the tag value.
- taosArraySort(pTableCheckInfo, tsdbCheckInfoCompar);
- return pTableCheckInfo;
+ return pTableMap;
}
-static void resetCheckInfo(STsdbReadHandle* pTsdbReadHandle) {
- size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- assert(numOfTables >= 1);
+static void resetDataBlockScanInfo(SHashObj* pTableMap) {
+ STableBlockScanInfo* p = NULL;
- // todo apply the lastkey of table check to avoid to load header file
- for (int32_t i = 0; i < numOfTables; ++i) {
- STableCheckInfo* pCheckInfo = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
- pCheckInfo->lastKey = pTsdbReadHandle->window.skey;
- pCheckInfo->iter = tsdbTbDataIterDestroy(pCheckInfo->iter);
- pCheckInfo->iiter = tsdbTbDataIterDestroy(pCheckInfo->iiter);
- pCheckInfo->initBuf = false;
-
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.skey);
- } else {
- assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.skey);
+ while ((p = taosHashIterate(pTableMap, p)) != NULL) {
+ p->iterInit = false;
+ p->iiter.hasVal = false;
+ if (p->iter.iter != NULL) {
+ p->iter.iter = tsdbTbDataIterDestroy(p->iter.iter);
}
+
+ p->delSkyline = taosArrayDestroy(p->delSkyline);
}
}
-// only one table, not need to sort again
-static SArray* createCheckInfoFromCheckInfo(STableCheckInfo* pCheckInfo, TSKEY skey, SArray** psTable) {
- SArray* pNew = taosArrayInit(1, sizeof(STableCheckInfo));
+static void destroyBlockScanInfo(SHashObj* pTableMap) {
+ STableBlockScanInfo* p = NULL;
- STableCheckInfo info = {.lastKey = skey};
+ while ((p = taosHashIterate(pTableMap, p)) != NULL) {
+ p->iterInit = false;
+ p->iiter.hasVal = false;
- info.tableId = pCheckInfo->tableId;
- taosArrayPush(pNew, &info);
- return pNew;
-}
+ if (p->iter.iter != NULL) {
+ p->iter.iter = tsdbTbDataIterDestroy(p->iter.iter);
+ }
-static bool emptyQueryTimewindow(STsdbReadHandle* pTsdbReadHandle) {
- assert(pTsdbReadHandle != NULL);
+ if (p->iiter.iter != NULL) {
+ p->iiter.iter = tsdbTbDataIterDestroy(p->iiter.iter);
+ }
+
+ p->delSkyline = taosArrayDestroy(p->delSkyline);
+ p->pBlockList = taosArrayDestroy(p->pBlockList);
+ }
- STimeWindow* w = &pTsdbReadHandle->window;
- bool asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+ taosHashCleanup(pTableMap);
+}
- return ((asc && w->skey > w->ekey) || (!asc && w->ekey > w->skey));
+static bool isEmptyQueryTimeWindow(STimeWindow* pWindow) {
+ ASSERT(pWindow != NULL);
+ return pWindow->skey > pWindow->ekey;
}
// Update the query time window according to the data time to live(TTL) information, in order to avoid to return
// the expired data to client, even it is queried already.
-static int64_t getEarliestValidTimestamp(STsdb* pTsdb) {
- STsdbKeepCfg* pCfg = REPO_KEEP_CFG(pTsdb);
+static STimeWindow updateQueryTimeWindow(STsdb* pTsdb, STimeWindow* pWindow) {
+ STsdbKeepCfg* pCfg = &pTsdb->keepCfg;
int64_t now = taosGetTimestamp(pCfg->precision);
- return now - (tsTickPerMin[pCfg->precision] * pCfg->keep2) + 1; // needs to add one tick
-}
-
-static void setQueryTimewindow(STsdbReadHandle* pTsdbReadHandle, SQueryTableDataCond* pCond, int32_t tWinIdx) {
- pTsdbReadHandle->window = pCond->twindows[tWinIdx];
+ int64_t earilyTs = now - (tsTickPerMin[pCfg->precision] * pCfg->keep2) + 1; // needs to add one tick
- bool updateTs = false;
- int64_t startTs = getEarliestValidTimestamp(pTsdbReadHandle->pTsdb);
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- if (startTs > pTsdbReadHandle->window.skey) {
- pTsdbReadHandle->window.skey = startTs;
- pCond->twindows[tWinIdx].skey = startTs;
- updateTs = true;
- }
- } else {
- if (startTs > pTsdbReadHandle->window.ekey) {
- pTsdbReadHandle->window.ekey = startTs;
- pCond->twindows[tWinIdx].ekey = startTs;
- updateTs = true;
- }
+ STimeWindow win = *pWindow;
+ if (win.skey < earilyTs) {
+ win.skey = earilyTs;
}
- if (updateTs) {
- tsdbDebug("%p update the query time window, old:%" PRId64 " - %" PRId64 ", new:%" PRId64 " - %" PRId64 ", %s",
- pTsdbReadHandle, pCond->twindows[tWinIdx].skey, pCond->twindows[tWinIdx].ekey,
- pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
- }
+ return win;
}
-static STsdb* getTsdbByRetentions(SVnode* pVnode, STsdbReadHandle* pReadHandle, TSKEY winSKey, SRetention* retentions) {
- if (VND_IS_RSMA(pVnode)) {
- int level = 0;
- int64_t now = taosGetTimestamp(pVnode->config.tsdbCfg.precision);
-
- for (int i = 0; i < TSDB_RETENTION_MAX; ++i) {
- SRetention* pRetention = retentions + level;
- if (pRetention->keep <= 0) {
- if (level > 0) {
- --level;
- }
- break;
- }
- if ((now - pRetention->keep) <= winSKey) {
- break;
- }
- ++level;
- }
+static void limitOutputBufferSize(const SQueryTableDataCond* pCond, int32_t* capacity) {
+ int32_t rowLen = 0;
+ for (int32_t i = 0; i < pCond->numOfCols; ++i) {
+ rowLen += pCond->colList[i].bytes;
+ }
- if (level == TSDB_RETENTION_L0) {
- tsdbDebug("vgId:%d, read handle %p rsma level %d is selected to query", TD_VID(pVnode), pReadHandle,
- TSDB_RETENTION_L0);
- return VND_RSMA0(pVnode);
- } else if (level == TSDB_RETENTION_L1) {
- tsdbDebug("vgId:%d, read handle %p rsma level %d is selected to query", TD_VID(pVnode), pReadHandle,
- TSDB_RETENTION_L1);
- return VND_RSMA1(pVnode);
- } else {
- tsdbDebug("vgId:%d, read handle %p rsma level %d is selected to query", TD_VID(pVnode), pReadHandle,
- TSDB_RETENTION_L2);
- return VND_RSMA2(pVnode);
- }
+ // make sure the output SSDataBlock size be less than 2MB.
+ const int32_t TWOMB = 2 * 1024 * 1024;
+ if ((*capacity) * rowLen > TWOMB) {
+ (*capacity) = TWOMB / rowLen;
}
- return VND_TSDB(pVnode);
}
-static STsdbReadHandle* tsdbQueryTablesImpl(SVnode* pVnode, SQueryTableDataCond* pCond, uint64_t qId, uint64_t taskId) {
- STsdbReadHandle* pReadHandle = taosMemoryCalloc(1, sizeof(STsdbReadHandle));
- if (pReadHandle == NULL) {
- goto _end;
- }
+// init file iterator
+static int32_t initFilesetIterator(SFilesetIter* pIter, const STsdbFSState* pFState, int32_t order, const char* idstr) {
+ size_t numOfFileset = taosArrayGetSize(pFState->aDFileSet);
- STsdb* pTsdb = getTsdbByRetentions(pVnode, pReadHandle, pCond->twindows[0].skey, pVnode->config.tsdbCfg.retentions);
+ pIter->index = ASCENDING_TRAVERSE(order) ? -1 : numOfFileset;
+ pIter->order = order;
+ pIter->pFileList = taosArrayDup(pFState->aDFileSet);
+ pIter->numOfFiles = numOfFileset;
- pReadHandle->order = pCond->order;
- pReadHandle->pTsdb = pTsdb;
- pReadHandle->type = TSDB_QUERY_TYPE_ALL;
- pReadHandle->cur.fid = INT32_MIN;
- pReadHandle->cur.win = TSWINDOW_INITIALIZER;
- pReadHandle->checkFiles = true;
- pReadHandle->activeIndex = 0; // current active table index
- pReadHandle->allocSize = 0;
- pReadHandle->locateStart = false;
- pReadHandle->loadType = pCond->type;
+ tsdbDebug("init fileset iterator, total files:%d %s", pIter->numOfFiles, idstr);
+ return TSDB_CODE_SUCCESS;
+}
- pReadHandle->suid = pCond->suid;
- pReadHandle->outputCapacity = 4096; //((STsdb*)tsdb)->config.maxRowsPerFileBlock;
- pReadHandle->loadExternalRow = pCond->loadExternalRows;
- pReadHandle->currentLoadExternalRows = pCond->loadExternalRows;
+static void cleanupFilesetIterator(SFilesetIter* pIter) { taosArrayDestroy(pIter->pFileList); }
- char buf[128] = {0};
- snprintf(buf, tListLen(buf), "TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, qId);
- pReadHandle->idStr = strdup(buf);
+static bool filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader) {
+ bool asc = ASCENDING_TRAVERSE(pIter->order);
+ int32_t step = asc ? 1 : -1;
+ pIter->index += step;
- if (tsdbInitReadH(&pReadHandle->rhelper, pReadHandle->pTsdb) != 0) {
- goto _end;
+ if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) {
+ return false;
}
- assert(pCond != NULL);
- setQueryTimewindow(pReadHandle, pCond, 0);
+ // check file the time range of coverage
+ STimeWindow win = {0};
- if (pCond->numOfCols > 0) {
- int32_t rowLen = 0;
- for (int32_t i = 0; i < pCond->numOfCols; ++i) {
- rowLen += pCond->colList[i].bytes;
+ while (1) {
+ if (pReader->pFileReader != NULL) {
+ tsdbDataFReaderClose(&pReader->pFileReader);
}
- // make sure the output SSDataBlock size be less than 2MB.
- int32_t TWOMB = 2 * 1024 * 1024;
- if (pReadHandle->outputCapacity * rowLen > TWOMB) {
- pReadHandle->outputCapacity = TWOMB / rowLen;
- }
+ pReader->status.pCurrentFileset = (SDFileSet*)taosArrayGet(pIter->pFileList, pIter->index);
- // allocate buffer in order to load data blocks from file
- pReadHandle->suppInfo.pstatis = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnDataAgg));
- if (pReadHandle->suppInfo.pstatis == NULL) {
- goto _end;
+ int32_t code = tsdbDataFReaderOpen(&pReader->pFileReader, pReader->pTsdb, pReader->status.pCurrentFileset);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _err;
}
- // todo: use list instead of array?
- pReadHandle->pColumns = taosArrayInit(pCond->numOfCols, sizeof(SColumnInfoData));
- if (pReadHandle->pColumns == NULL) {
- goto _end;
- }
+ int32_t fid = pReader->status.pCurrentFileset->fid;
+ tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &win.skey, &win.ekey);
- for (int32_t i = 0; i < pCond->numOfCols; ++i) {
- SColumnInfoData colInfo = {{0}, 0};
- colInfo.info = pCond->colList[i];
+ // current file are no longer overlapped with query time window, ignore remain files
+ if ((asc && win.skey > pReader->window.ekey) || (!asc && win.ekey < pReader->window.skey)) {
+ tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pReader,
+ pReader->window.skey, pReader->window.ekey, pReader->idStr);
+ return false;
+ }
- int32_t code = colInfoDataEnsureCapacity(&colInfo, 0, pReadHandle->outputCapacity);
- if (code != TSDB_CODE_SUCCESS) {
- goto _end;
+ if ((asc && (win.ekey < pReader->window.skey)) || ((!asc) && (win.skey > pReader->window.ekey))) {
+ pIter->index += step;
+ if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) {
+ return false;
}
-
- taosArrayPush(pReadHandle->pColumns, &colInfo);
+ continue;
}
- pReadHandle->suppInfo.defaultLoadColumn = getDefaultLoadColumns(pReadHandle, true);
-
- size_t size = taosArrayGetSize(pReadHandle->suppInfo.defaultLoadColumn);
- pReadHandle->suppInfo.slotIds = taosMemoryCalloc(size, sizeof(int32_t));
- pReadHandle->suppInfo.plist = taosMemoryCalloc(size, POINTER_BYTES);
- }
-
- pReadHandle->pDataCols = tdNewDataCols(1000, pVnode->config.tsdbCfg.maxRows);
- if (pReadHandle->pDataCols == NULL) {
- tsdbError("%p failed to malloc buf for pDataCols, %s", pReadHandle, pReadHandle->idStr);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- goto _end;
+ tsdbDebug("%p file found fid:%d for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pReader, fid, pReader->window.skey,
+ pReader->window.ekey, pReader->idStr);
+ return true;
}
- tsdbInitDataBlockLoadInfo(&pReadHandle->dataBlockLoadInfo);
- tsdbInitCompBlockLoadInfo(&pReadHandle->compBlockLoadInfo);
-
- return (tsdbReaderT)pReadHandle;
-
-_end:
- tsdbCleanupReadHandle(pReadHandle);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return NULL;
+_err:
+ return false;
}
-static int32_t setCurrentSchema(SVnode* pVnode, STsdbReadHandle* pTsdbReadHandle) {
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, 0);
-
- int32_t sversion = 1;
-
- SMetaReader mr = {0};
- metaReaderInit(&mr, pVnode->pMeta, 0);
- int32_t code = metaGetTableEntryByUid(&mr, pCheckInfo->tableId);
- if (code != TSDB_CODE_SUCCESS) {
- terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
- metaReaderClear(&mr);
- return terrno;
- }
-
- if (mr.me.type == TSDB_CHILD_TABLE) {
- tb_uid_t suid = mr.me.ctbEntry.suid;
- code = metaGetTableEntryByUid(&mr, suid);
- if (code != TSDB_CODE_SUCCESS) {
- terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
- metaReaderClear(&mr);
- return terrno;
- }
- sversion = mr.me.stbEntry.schemaRow.version;
+static void resetDataBlockIterator(SDataBlockIter* pIter, int32_t order) {
+ pIter->order = order;
+ pIter->index = -1;
+ pIter->numOfBlocks = -1;
+ if (pIter->blockList == NULL) {
+ pIter->blockList = taosArrayInit(4, sizeof(SFileDataBlockInfo));
} else {
- ASSERT(mr.me.type == TSDB_NORMAL_TABLE);
- sversion = mr.me.ntbEntry.schemaRow.version;
+ taosArrayClear(pIter->blockList);
}
+}
- metaReaderClear(&mr);
- pTsdbReadHandle->pSchema = metaGetTbTSchema(pVnode->pMeta, pCheckInfo->tableId, sversion);
- return TSDB_CODE_SUCCESS;
+static void cleanupDataBlockIterator(SDataBlockIter* pIter) { taosArrayDestroy(pIter->blockList); }
+
+static void initReaderStatus(SReaderStatus* pStatus) {
+ pStatus->pTableIter = NULL;
+ pStatus->loadFromFile = true;
}
-tsdbReaderT tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, STableListInfo* tableList, uint64_t qId,
- uint64_t taskId) {
- STsdbReadHandle* pTsdbReadHandle = tsdbQueryTablesImpl(pVnode, pCond, qId, taskId);
- if (pTsdbReadHandle == NULL) {
+static SSDataBlock* createResBlock(SQueryTableDataCond* pCond, int32_t capacity) {
+ SSDataBlock* pResBlock = createDataBlock();
+ if (pResBlock == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
- if (emptyQueryTimewindow(pTsdbReadHandle)) {
- return (tsdbReaderT)pTsdbReadHandle;
- }
-
- // todo apply the lastkey of table check to avoid to load header file
- pTsdbReadHandle->pTableCheckInfo = createCheckInfoFromTableGroup(pTsdbReadHandle, tableList);
- if (pTsdbReadHandle->pTableCheckInfo == NULL) {
- // tsdbCleanupReadHandle(pTsdbReadHandle);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return NULL;
+ for (int32_t i = 0; i < pCond->numOfCols; ++i) {
+ SColumnInfoData colInfo = {{0}, 0};
+ colInfo.info = pCond->colList[i];
+ blockDataAppendColInfo(pResBlock, &colInfo);
}
- int32_t code = setCurrentSchema(pVnode, pTsdbReadHandle);
+ int32_t code = blockDataEnsureCapacity(pResBlock, capacity);
if (code != TSDB_CODE_SUCCESS) {
terrno = code;
+ taosMemoryFree(pResBlock);
return NULL;
}
- int32_t numOfCols = taosArrayGetSize(pTsdbReadHandle->suppInfo.defaultLoadColumn);
- int16_t* ids = pTsdbReadHandle->suppInfo.defaultLoadColumn->pData;
-
- STSchema* pSchema = pTsdbReadHandle->pSchema;
+ return pResBlock;
+}
- int32_t i = 0, j = 0;
- while (i < numOfCols && j < pSchema->numOfCols) {
- if (ids[i] == pSchema->columns[j].colId) {
- pTsdbReadHandle->suppInfo.slotIds[i] = j;
- i++;
- j++;
- } else if (ids[i] > pSchema->columns[j].colId) {
- j++;
- } else {
- // tsdbCleanupReadHandle(pTsdbReadHandle);
- terrno = TSDB_CODE_INVALID_PARA;
- return NULL;
- }
+static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, STsdbReader** ppReader, const char* idstr) {
+ int32_t code = 0;
+ int8_t level = 0;
+ STsdbReader* pReader = (STsdbReader*)taosMemoryCalloc(1, sizeof(*pReader));
+ if (pReader == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _end;
}
- tsdbDebug("%p total numOfTable:%" PRIzu " in this query, table %" PRIzu " %s", pTsdbReadHandle,
- taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo), taosArrayGetSize(tableList->pTableList),
- pTsdbReadHandle->idStr);
+ initReaderStatus(&pReader->status);
- return (tsdbReaderT)pTsdbReadHandle;
-}
+ pReader->pTsdb = getTsdbByRetentions(pVnode, pCond->twindows.skey, pVnode->config.tsdbCfg.retentions, idstr, &level);
+ pReader->suid = pCond->suid;
+ pReader->order = pCond->order;
+ pReader->capacity = 4096;
+ pReader->idStr = (idstr != NULL) ? strdup(idstr) : NULL;
+ pReader->verRange = getQueryVerRange(pVnode, pCond, level);
+ pReader->type = pCond->type;
+ pReader->window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows);
-void tsdbResetReadHandle(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, int32_t tWinIdx) {
- STsdbReadHandle* pTsdbReadHandle = queryHandle;
+ ASSERT(pCond->numOfCols > 0);
- if (emptyQueryTimewindow(pTsdbReadHandle)) {
- if (pCond->order != pTsdbReadHandle->order) {
- pTsdbReadHandle->order = pCond->order;
- TSWAP(pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey);
- }
+ limitOutputBufferSize(pCond, &pReader->capacity);
- return;
+ // allocate buffer in order to load data blocks from file
+ SBlockLoadSuppInfo* pSup = &pReader->suppInfo;
+ pSup->pColAgg = taosArrayInit(4, sizeof(SColumnDataAgg));
+ pSup->plist = taosMemoryCalloc(pCond->numOfCols, POINTER_BYTES);
+ if (pSup->pColAgg == NULL || pSup->plist == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _end;
}
- pTsdbReadHandle->order = pCond->order;
- setQueryTimewindow(pTsdbReadHandle, pCond, tWinIdx);
- pTsdbReadHandle->type = TSDB_QUERY_TYPE_ALL;
- pTsdbReadHandle->cur.fid = -1;
- pTsdbReadHandle->cur.win = TSWINDOW_INITIALIZER;
- pTsdbReadHandle->checkFiles = true;
- pTsdbReadHandle->activeIndex = 0; // current active table index
- pTsdbReadHandle->locateStart = false;
- pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
+ pSup->tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID;
- if (ASCENDING_TRAVERSE(pCond->order)) {
- assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
- } else {
- assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
+ pReader->pResBlock = createResBlock(pCond, pReader->capacity);
+ if (pReader->pResBlock == NULL) {
+ code = terrno;
+ goto _end;
}
- // allocate buffer in order to load data blocks from file
- memset(pTsdbReadHandle->suppInfo.pstatis, 0, sizeof(SColumnDataAgg));
- memset(pTsdbReadHandle->suppInfo.plist, 0, POINTER_BYTES);
+ setColumnIdSlotList(pReader, pReader->pResBlock);
- tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
- tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
+ *ppReader = pReader;
+ return code;
- resetCheckInfo(pTsdbReadHandle);
+_end:
+ tsdbReaderClose(pReader);
+ *ppReader = NULL;
+ return code;
}
-void tsdbResetQueryHandleForNewTable(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, STableListInfo* tableList,
- int32_t tWinIdx) {
- STsdbReadHandle* pTsdbReadHandle = queryHandle;
-
- pTsdbReadHandle->order = pCond->order;
- pTsdbReadHandle->window = pCond->twindows[tWinIdx];
- pTsdbReadHandle->type = TSDB_QUERY_TYPE_ALL;
- pTsdbReadHandle->cur.fid = -1;
- pTsdbReadHandle->cur.win = TSWINDOW_INITIALIZER;
- pTsdbReadHandle->checkFiles = true;
- pTsdbReadHandle->activeIndex = 0; // current active table index
- pTsdbReadHandle->locateStart = false;
- pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
-
- if (ASCENDING_TRAVERSE(pCond->order)) {
- assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
- } else {
- assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
+// void tsdbResetQueryHandleForNewTable(STsdbReader* queryHandle, SQueryTableDataCond* pCond, STableListInfo* tableList,
+// int32_t tWinIdx) {
+// STsdbReader* pTsdbReadHandle = queryHandle;
+
+// pTsdbReadHandle->order = pCond->order;
+// pTsdbReadHandle->window = pCond->twindows[tWinIdx];
+// pTsdbReadHandle->type = TSDB_QUERY_TYPE_ALL;
+// pTsdbReadHandle->cur.fid = -1;
+// pTsdbReadHandle->cur.win = TSWINDOW_INITIALIZER;
+// pTsdbReadHandle->checkFiles = true;
+// pTsdbReadHandle->activeIndex = 0; // current active table index
+// pTsdbReadHandle->locateStart = false;
+// pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
+
+// if (ASCENDING_TRAVERSE(pCond->order)) {
+// assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
+// } else {
+// assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
+// }
+
+// // allocate buffer in order to load data blocks from file
+// memset(pTsdbReadHandle->suppInfo.pstatis, 0, sizeof(SColumnDataAgg));
+// memset(pTsdbReadHandle->suppInfo.plist, 0, POINTER_BYTES);
+
+// tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
+// tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
+
+// SArray* pTable = NULL;
+// // STsdbMeta* pMeta = tsdbGetMeta(pTsdbReadHandle->pTsdb);
+
+// // pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
+
+// pTsdbReadHandle->pTableCheckInfo = NULL; // createDataBlockScanInfo(pTsdbReadHandle, groupList, pMeta,
+// // &pTable);
+// if (pTsdbReadHandle->pTableCheckInfo == NULL) {
+// // tsdbReaderClose(pTsdbReadHandle);
+// terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
+// }
+
+// // pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
+// // pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
+// }
+
+// SArray* tsdbGetQueriedTableList(STsdbReader** pHandle) {
+// assert(pHandle != NULL);
+
+// STsdbReader* pTsdbReadHandle = (STsdbReader*)pHandle;
+
+// size_t size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
+// SArray* res = taosArrayInit(size, POINTER_BYTES);
+// return res;
+// }
+
+// static TSKEY extractFirstTraverseKey(STableBlockScanInfo* pCheckInfo, int32_t order, int32_t update, TDRowVerT
+// maxVer) {
+// TSDBROW row = {0};
+// STSRow *rmem = NULL, *rimem = NULL;
+
+// if (pCheckInfo->iter) {
+// if (tsdbTbDataIterGet(pCheckInfo->iter, &row)) {
+// rmem = row.pTSRow;
+// }
+// }
+
+// if (pCheckInfo->iiter) {
+// if (tsdbTbDataIterGet(pCheckInfo->iiter, &row)) {
+// rimem = row.pTSRow;
+// }
+// }
+
+// if (rmem == NULL && rimem == NULL) {
+// return TSKEY_INITIAL_VAL;
+// }
+
+// if (rmem != NULL && rimem == NULL) {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
+// return TD_ROW_KEY(rmem);
+// }
+
+// if (rmem == NULL && rimem != NULL) {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
+// return TD_ROW_KEY(rimem);
+// }
+
+// TSKEY r1 = TD_ROW_KEY(rmem);
+// TSKEY r2 = TD_ROW_KEY(rimem);
+
+// if (r1 == r2) {
+// if (TD_SUPPORT_UPDATE(update)) {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
+// } else {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
+// tsdbTbDataIterNext(pCheckInfo->iter);
+// }
+// return r1;
+// } else if (r1 < r2 && ASCENDING_TRAVERSE(order)) {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
+// return r1;
+// } else {
+// pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
+// return r2;
+// }
+// }
+
+// static bool moveToNextRowInMem(STableBlockScanInfo* pCheckInfo) {
+// bool hasNext = false;
+// if (pCheckInfo->chosen == CHECKINFO_CHOSEN_MEM) {
+// if (pCheckInfo->iter != NULL) {
+// hasNext = tsdbTbDataIterNext(pCheckInfo->iter);
+// }
+
+// if (hasNext) {
+// return hasNext;
+// }
+
+// if (pCheckInfo->iiter != NULL) {
+// return tsdbTbDataIterGet(pCheckInfo->iiter, NULL);
+// }
+// } else if (pCheckInfo->chosen == CHECKINFO_CHOSEN_IMEM) {
+// if (pCheckInfo->iiter != NULL) {
+// hasNext = tsdbTbDataIterNext(pCheckInfo->iiter);
+// }
+
+// if (hasNext) {
+// return hasNext;
+// }
+
+// if (pCheckInfo->iter != NULL) {
+// return tsdbTbDataIterGet(pCheckInfo->iter, NULL);
+// }
+// } else {
+// if (pCheckInfo->iter != NULL) {
+// hasNext = tsdbTbDataIterNext(pCheckInfo->iter);
+// }
+// if (pCheckInfo->iiter != NULL) {
+// hasNext = tsdbTbDataIterNext(pCheckInfo->iiter) || hasNext;
+// }
+// }
+
+// return hasNext;
+// }
+
+// static int32_t binarySearchForBlock(SBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) {
+// int32_t firstSlot = 0;
+// int32_t lastSlot = numOfBlocks - 1;
+
+// int32_t midSlot = firstSlot;
+
+// while (1) {
+// numOfBlocks = lastSlot - firstSlot + 1;
+// midSlot = (firstSlot + (numOfBlocks >> 1));
+
+// if (numOfBlocks == 1) break;
+
+// if (skey > pBlock[midSlot].maxKey.ts) {
+// if (numOfBlocks == 2) break;
+// if ((order == TSDB_ORDER_DESC) && (skey < pBlock[midSlot + 1].minKey.ts)) break;
+// firstSlot = midSlot + 1;
+// } else if (skey < pBlock[midSlot].minKey.ts) {
+// if ((order == TSDB_ORDER_ASC) && (skey > pBlock[midSlot - 1].maxKey.ts)) break;
+// lastSlot = midSlot - 1;
+// } else {
+// break; // got the slot
+// }
+// }
+
+// return midSlot;
+// }
+
+static int32_t doLoadBlockIndex(STsdbReader* pReader, SDataFReader* pFileReader, SArray* pIndexList) {
+ SArray* aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx));
+
+ int32_t code = tsdbReadBlockIdx(pFileReader, aBlockIdx, NULL);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _end;
}
- // allocate buffer in order to load data blocks from file
- memset(pTsdbReadHandle->suppInfo.pstatis, 0, sizeof(SColumnDataAgg));
- memset(pTsdbReadHandle->suppInfo.plist, 0, POINTER_BYTES);
-
- tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
- tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
-
- SArray* pTable = NULL;
- // STsdbMeta* pMeta = tsdbGetMeta(pTsdbReadHandle->pTsdb);
-
- // pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
-
- pTsdbReadHandle->pTableCheckInfo = NULL; // createCheckInfoFromTableGroup(pTsdbReadHandle, groupList, pMeta,
- // &pTable);
- if (pTsdbReadHandle->pTableCheckInfo == NULL) {
- // tsdbCleanupReadHandle(pTsdbReadHandle);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
+ if (taosArrayGetSize(aBlockIdx) == 0) {
+ taosArrayClear(aBlockIdx);
+ return TSDB_CODE_SUCCESS;
}
- // pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
- // pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
-}
+ SBlockIdx* pBlockIdx;
+ for (int32_t i = 0; i < taosArrayGetSize(aBlockIdx); ++i) {
+ pBlockIdx = (SBlockIdx*)taosArrayGet(aBlockIdx, i);
-tsdbReaderT tsdbQueryLastRow(SVnode* pVnode, SQueryTableDataCond* pCond, STableListInfo* pList, uint64_t qId,
- uint64_t taskId) {
- pCond->twindows[0] = updateLastrowForEachGroup(pList);
+ // uid check
+ if (pBlockIdx->suid != pReader->suid) {
+ continue;
+ }
- // no qualified table
- if (taosArrayGetSize(pList->pTableList) == 0) {
- return NULL;
- }
+ // this block belongs to a table that is not queried.
+ void* p = taosHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(uint64_t));
+ if (p == NULL) {
+ continue;
+ }
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbReaderOpen(pVnode, pCond, pList, qId, taskId);
- if (pTsdbReadHandle == NULL) {
- return NULL;
- }
+ // todo: not valid info in bockIndex
+ // time range check
+ // if (pBlockIdx->minKey > pReader->window.ekey || pBlockIdx->maxKey < pReader->window.skey) {
+ // continue;
+ // }
- int32_t code = checkForCachedLastRow(pTsdbReadHandle, pList);
- if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0
- terrno = code;
- return NULL;
- }
+ // version check
+ // if (pBlockIdx->minVersion > pReader->verRange.maxVer || pBlockIdx->maxVersion < pReader->verRange.minVer) {
+ // continue;
+ // }
+
+ STableBlockScanInfo* pScanInfo = p;
+ if (pScanInfo->pBlockList == NULL) {
+ pScanInfo->pBlockList = taosArrayInit(16, sizeof(SBlock));
+ }
- assert(pCond->order == TSDB_ORDER_ASC && pCond->twindows[0].skey <= pCond->twindows[0].ekey);
- if (pTsdbReadHandle->cachelastrow) {
- pTsdbReadHandle->type = TSDB_QUERY_TYPE_LAST;
+ pScanInfo->blockIdx = *pBlockIdx;
+ taosArrayPush(pIndexList, pBlockIdx);
}
- return pTsdbReadHandle;
+_end:
+ taosArrayDestroy(aBlockIdx);
+ return code;
}
-#if 0
-tsdbReaderT tsdbQueryCacheLastT(STsdb *tsdb, SQueryTableDataCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemTable* pMemRef) {
- STsdbReadHandle *pTsdbReadHandle = (STsdbReadHandle*) tsdbQueryTablesT(tsdb, pCond, groupList, qId, pMemRef);
- if (pTsdbReadHandle == NULL) {
- return NULL;
- }
+static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, uint32_t* numOfValidTables,
+ int32_t* numOfBlocks) {
+ size_t numOfTables = taosArrayGetSize(pIndexList);
- int32_t code = checkForCachedLast(pTsdbReadHandle);
- if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0
- terrno = code;
- return NULL;
- }
+ *numOfValidTables = 0;
- if (pTsdbReadHandle->cachelastrow) {
- pTsdbReadHandle->type = TSDB_QUERY_TYPE_LAST;
- }
-
- return pTsdbReadHandle;
-}
+ STableBlockScanInfo* px = NULL;
+ while (1) {
+ px = taosHashIterate(pReader->status.pTableMap, px);
+ if (px == NULL) {
+ break;
+ }
-#endif
-SArray* tsdbGetQueriedTableList(tsdbReaderT* pHandle) {
- assert(pHandle != NULL);
+ taosArrayClear(px->pBlockList);
+ }
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
+ for (int32_t i = 0; i < numOfTables; ++i) {
+ SBlockIdx* pBlockIdx = taosArrayGet(pIndexList, i);
- size_t size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- SArray* res = taosArrayInit(size, POINTER_BYTES);
- return res;
-}
+ SMapData mapData = {0};
+ tMapDataReset(&mapData);
+ tsdbReadBlock(pReader->pFileReader, pBlockIdx, &mapData, NULL);
-// leave only one table for each group
-// static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGroupList) {
-// assert(pGroupList);
-// size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);
-//
-// STableGroupInfo* pNew = taosMemoryCalloc(1, sizeof(STableGroupInfo));
-// pNew->pGroupList = taosArrayInit(numOfGroup, POINTER_BYTES);
-//
-// for (int32_t i = 0; i < numOfGroup; ++i) {
-// SArray* oneGroup = taosArrayGetP(pGroupList->pGroupList, i);
-// size_t numOfTables = taosArrayGetSize(oneGroup);
-//
-// SArray* px = taosArrayInit(4, sizeof(STableKeyInfo));
-// for (int32_t j = 0; j < numOfTables; ++j) {
-// STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(oneGroup, j);
-// // if (window->skey <= pInfo->lastKey && ((STable*)pInfo->pTable)->lastKey != TSKEY_INITIAL_VAL) {
-// // taosArrayPush(px, pInfo);
-// // pNew->numOfTables += 1;
-// // break;
-// // }
-// }
-//
-// // there are no data in this group
-// if (taosArrayGetSize(px) == 0) {
-// taosArrayDestroy(px);
-// } else {
-// taosArrayPush(pNew->pGroupList, &px);
-// }
-// }
-//
-// return pNew;
-//}
+ STableBlockScanInfo* pScanInfo = taosHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(int64_t));
+ for (int32_t j = 0; j < mapData.nItem; ++j) {
+ SBlock block = {0};
-// tsdbReaderT tsdbQueryRowsInExternalWindow(SVnode* pVnode, SQueryTableDataCond* pCond, STableGroupInfo* groupList,
-// uint64_t qId, uint64_t taskId) {
-// STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);
-//
-// if (pNew->numOfTables == 0) {
-// tsdbDebug("update query time range to invalidate time window");
-//
-// assert(taosArrayGetSize(pNew->pGroupList) == 0);
-// bool asc = ASCENDING_TRAVERSE(pCond->order);
-// if (asc) {
-// pCond->twindow.ekey = pCond->twindow.skey - 1;
-// } else {
-// pCond->twindow.skey = pCond->twindow.ekey - 1;
-// }
-// }
-//
-// STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbQueryTables(pVnode, pCond, pNew, qId, taskId);
-// pTsdbReadHandle->loadExternalRow = true;
-// pTsdbReadHandle->currentLoadExternalRows = true;
-//
-// return pTsdbReadHandle;
-//}
+ tMapDataGetItemByIdx(&mapData, j, &block, tGetBlock);
-static bool initTableMemIterator(STsdbReadHandle* pHandle, STableCheckInfo* pCheckInfo) {
- if (pCheckInfo->initBuf) {
- return true;
- }
+ // 1. time range check
+ if (block.minKey.ts > pReader->window.ekey || block.maxKey.ts < pReader->window.skey) {
+ continue;
+ }
- pCheckInfo->initBuf = true;
- int32_t order = pHandle->order;
+ // 2. version range check
+ if (block.minVersion > pReader->verRange.maxVer || block.maxVersion < pReader->verRange.minVer) {
+ continue;
+ }
- STbData* pMem = NULL;
- STbData* pIMem = NULL;
- int8_t backward = (pHandle->order == TSDB_ORDER_DESC) ? 1 : 0;
+ void* p = taosArrayPush(pScanInfo->pBlockList, &block);
+ if (p == NULL) {
+ tMapDataClear(&mapData);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
- TSKEY tLastKey = keyToTkey(pCheckInfo->lastKey);
- if (pHandle->pTsdb->mem != NULL) {
- tsdbGetTbDataFromMemTable(pHandle->pTsdb->mem, pCheckInfo->suid, pCheckInfo->tableId, &pMem);
- if (pMem != NULL) {
- tsdbTbDataIterCreate(pMem, &(TSDBKEY){.version = 0, .ts = tLastKey}, backward, &pCheckInfo->iter);
+ (*numOfBlocks) += 1;
}
- }
- if (pHandle->pTsdb->imem != NULL) {
- tsdbGetTbDataFromMemTable(pHandle->pTsdb->mem, pCheckInfo->suid, pCheckInfo->tableId, &pIMem);
- if (pIMem != NULL) {
- tsdbTbDataIterCreate(pIMem, &(TSDBKEY){.version = 0, .ts = tLastKey}, backward, &pCheckInfo->iiter);
+ tMapDataClear(&mapData);
+ if (pScanInfo->pBlockList != NULL && taosArrayGetSize(pScanInfo->pBlockList) > 0) {
+ (*numOfValidTables) += 1;
}
}
- // both iterators are NULL, no data in buffer right now
- if (pCheckInfo->iter == NULL && pCheckInfo->iiter == NULL) {
- return false;
- }
-
- bool memEmpty =
- (pCheckInfo->iter == NULL) || (pCheckInfo->iter != NULL && !tsdbTbDataIterGet(pCheckInfo->iter, NULL));
- bool imemEmpty =
- (pCheckInfo->iiter == NULL) || (pCheckInfo->iiter != NULL && !tsdbTbDataIterGet(pCheckInfo->iiter, NULL));
- if (memEmpty && imemEmpty) { // buffer is empty
- return false;
- }
+ return TSDB_CODE_SUCCESS;
+}
- if (!memEmpty) {
- TSDBROW row;
+// todo remove pblock parameter
+static void setBlockAllDumped(SFileBlockDumpInfo* pDumpInfo, SBlock* pBlock, int32_t order) {
+ int32_t step = ASCENDING_TRAVERSE(order) ? 1 : -1;
- tsdbTbDataIterGet(pCheckInfo->iter, &row);
- TSKEY key = row.pTSRow->ts; // first timestamp in buffer
- tsdbDebug("%p uid:%" PRId64 ", check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
- "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
- pHandle, pCheckInfo->tableId, key, order, pMem->minKey.ts, pMem->maxKey.ts, pCheckInfo->lastKey,
- pMem->sl.size, pHandle->idStr);
+ pDumpInfo->allDumped = true;
+ pDumpInfo->lastKey = pBlock->maxKey.ts + step;
+}
- if (ASCENDING_TRAVERSE(order)) {
- assert(pCheckInfo->lastKey <= key);
+static void doCopyColVal(SColumnInfoData* pColInfoData, int32_t rowIndex, int32_t colIndex, SColVal* pColVal,
+ SBlockLoadSuppInfo* pSup) {
+ if (IS_VAR_DATA_TYPE(pColVal->type)) {
+ if (pColVal->isNull || pColVal->isNone) {
+ colDataAppendNULL(pColInfoData, rowIndex);
} else {
- assert(pCheckInfo->lastKey >= key);
+ varDataSetLen(pSup->buildBuf[colIndex], pColVal->value.nData);
+ memcpy(varDataVal(pSup->buildBuf[colIndex]), pColVal->value.pData, pColVal->value.nData);
+ colDataAppend(pColInfoData, rowIndex, pSup->buildBuf[colIndex], false);
}
-
} else {
- tsdbDebug("%p uid:%" PRId64 ", no data in mem, %s", pHandle, pCheckInfo->tableId, pHandle->idStr);
+ colDataAppend(pColInfoData, rowIndex, (const char*)&pColVal->value, pColVal->isNull || pColVal->isNone);
}
+}
- if (!imemEmpty) {
- TSDBROW row;
-
- tsdbTbDataIterGet(pCheckInfo->iter, &row);
- TSKEY key = row.pTSRow->ts; // first timestamp in buffer
- tsdbDebug("%p uid:%" PRId64 ", check data in imem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
- "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
- pHandle, pCheckInfo->tableId, key, order, pIMem->minKey.ts, pIMem->maxKey.ts, pCheckInfo->lastKey,
- pIMem->sl.size, pHandle->idStr);
+static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo) {
+ SReaderStatus* pStatus = &pReader->status;
+ SDataBlockIter* pBlockIter = &pStatus->blockIter;
- if (ASCENDING_TRAVERSE(order)) {
- assert(pCheckInfo->lastKey <= key);
- } else {
- assert(pCheckInfo->lastKey >= key);
- }
- } else {
- tsdbDebug("%p uid:%" PRId64 ", no data in imem, %s", pHandle, pCheckInfo->tableId, pHandle->idStr);
- }
+ SBlockData* pBlockData = &pStatus->fileBlockData;
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ SBlock* pBlock = taosArrayGet(pBlockScanInfo->pBlockList, pFBlock->tbBlockIdx);
+ SSDataBlock* pResBlock = pReader->pResBlock;
+ int32_t numOfCols = blockDataGetNumOfCols(pResBlock);
- return true;
-}
+ SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
-static void destroyTableMemIterator(STableCheckInfo* pCheckInfo) {
- tsdbTbDataIterDestroy(pCheckInfo->iter);
- tsdbTbDataIterDestroy(pCheckInfo->iiter);
-}
+ int64_t st = taosGetTimestampUs();
-static TSKEY extractFirstTraverseKey(STableCheckInfo* pCheckInfo, int32_t order, int32_t update, TDRowVerT maxVer) {
- TSDBROW row = {0};
- STSRow *rmem = NULL, *rimem = NULL;
+ SColVal cv = {0};
+ int32_t colIndex = 0;
- if (pCheckInfo->iter) {
- if (tsdbTbDataIterGet(pCheckInfo->iter, &row)) {
- rmem = row.pTSRow;
- }
- }
+ bool asc = ASCENDING_TRAVERSE(pReader->order);
+ int32_t step = asc ? 1 : -1;
- if (pCheckInfo->iiter) {
- if (tsdbTbDataIterGet(pCheckInfo->iiter, &row)) {
- rimem = row.pTSRow;
- }
- }
+ int32_t rowIndex = 0;
+ int32_t remain = asc ? (pBlockData->nRow - pDumpInfo->rowIndex) : (pDumpInfo->rowIndex + 1);
- if (rmem == NULL && rimem == NULL) {
- return TSKEY_INITIAL_VAL;
+ int32_t endIndex = 0;
+ if (remain <= pReader->capacity) {
+ endIndex = pBlockData->nRow;
+ } else {
+ endIndex = pDumpInfo->rowIndex + step * pReader->capacity;
+ remain = pReader->capacity;
}
- if (rmem != NULL && rimem == NULL) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
- return TD_ROW_KEY(rmem);
+ int32_t i = 0;
+ SColumnInfoData* pColData = taosArrayGet(pResBlock->pDataBlock, i);
+ if (pColData->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
+ for (int32_t j = pDumpInfo->rowIndex; j < endIndex && j >= 0; j += step) {
+ colDataAppend(pColData, rowIndex++, (const char*)&pBlockData->aTSKEY[j], false);
+ }
+ i += 1;
}
- if (rmem == NULL && rimem != NULL) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return TD_ROW_KEY(rimem);
- }
+ while (i < numOfCols && colIndex < taosArrayGetSize(pBlockData->aIdx)) {
+ rowIndex = 0;
+ pColData = taosArrayGet(pResBlock->pDataBlock, i);
- TSKEY r1 = TD_ROW_KEY(rmem);
- TSKEY r2 = TD_ROW_KEY(rimem);
+ SColData* pData = tBlockDataGetColDataByIdx(pBlockData, colIndex);
- if (r1 == r2) {
-#if 0
- if (update == TD_ROW_DISCARD_UPDATE) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- tSkipListIterNext(pCheckInfo->iter);
- } else if (update == TD_ROW_OVERWRITE_UPDATE) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
- tSkipListIterNext(pCheckInfo->iiter);
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
- }
-#endif
- if (TD_SUPPORT_UPDATE(update)) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- tsdbTbDataIterNext(pCheckInfo->iter);
+ if (pData->cid == pColData->info.colId) {
+ for (int32_t j = pDumpInfo->rowIndex; j < endIndex && j >= 0; j += step) {
+ tColDataGetValue(pData, j, &cv);
+ doCopyColVal(pColData, rowIndex++, i, &cv, pSupInfo);
+ }
+ colIndex += 1;
+ } else { // the specified column does not exist in file block, fill with null data
+ colDataAppendNNULL(pColData, 0, remain);
}
- return r1;
- } else if (r1 < r2 && ASCENDING_TRAVERSE(order)) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
- return r1;
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return r2;
- }
-}
-static STSRow* getSRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order, int32_t update, STSRow** extraRow,
- TDRowVerT maxVer) {
- TSDBROW row;
- STSRow *rmem = NULL, *rimem = NULL;
- if (pCheckInfo->iter) {
- if (tsdbTbDataIterGet(pCheckInfo->iter, &row)) {
- rmem = row.pTSRow;
- }
+ ASSERT(rowIndex == remain);
+ i += 1;
}
- if (pCheckInfo->iiter) {
- if (tsdbTbDataIterGet(pCheckInfo->iiter, &row)) {
- rimem = row.pTSRow;
- }
+ while (i < numOfCols) {
+ pColData = taosArrayGet(pResBlock->pDataBlock, i);
+ colDataAppendNNULL(pColData, 0, remain);
+ i += 1;
}
- if (rmem == NULL && rimem == NULL) {
- return NULL;
- }
+ pResBlock->info.rows = remain;
+ pDumpInfo->rowIndex += step * remain;
- if (rmem != NULL && rimem == NULL) {
- pCheckInfo->chosen = 0;
- return rmem;
- }
+ setBlockAllDumped(pDumpInfo, pBlock, pReader->order);
- if (rmem == NULL && rimem != NULL) {
- pCheckInfo->chosen = 1;
- return rimem;
- }
+ int64_t elapsedTime = (taosGetTimestampUs() - st);
+ pReader->cost.blockLoadTime += elapsedTime;
- TSKEY r1 = TD_ROW_KEY(rmem);
- TSKEY r2 = TD_ROW_KEY(rimem);
+ int32_t unDumpedRows = asc ? pBlock->nRow - pDumpInfo->rowIndex : pDumpInfo->rowIndex + 1;
+ tsdbDebug("%p load file block into buffer, global index:%d, table index:%d, brange:%" PRId64 "-%" PRId64
+ ", rows:%d, remain:%d, minVer:%" PRId64 ", maxVer:%" PRId64 ", elapsed time:%" PRId64 " us, %s",
+ pReader, pBlockIter->index, pFBlock->tbBlockIdx, pBlock->minKey.ts, pBlock->maxKey.ts, remain, unDumpedRows,
+ pBlock->minVersion, pBlock->maxVersion, elapsedTime, pReader->idStr);
- if (r1 == r2) {
-#if 0
- if (update == TD_ROW_DISCARD_UPDATE) {
- tSkipListIterNext(pCheckInfo->iter);
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return rimem;
- } else if (update == TD_ROW_OVERWRITE_UPDATE) {
- tSkipListIterNext(pCheckInfo->iiter);
- pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
- return rmem;
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
- *extraRow = rimem;
- return rmem;
- }
-#endif
- if (TD_SUPPORT_UPDATE(update)) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
- *extraRow = rimem;
- return rmem;
- } else {
- tsdbTbDataIterNext(pCheckInfo->iter);
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return rimem;
- }
- } else {
- if (ASCENDING_TRAVERSE(order)) {
- if (r1 < r2) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
- return rmem;
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return rimem;
- }
- } else {
- if (r1 < r2) {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return rimem;
- } else {
- pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
- return rmem;
- }
- }
- }
+ return TSDB_CODE_SUCCESS;
}
-static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
- bool hasNext = false;
- if (pCheckInfo->chosen == CHECKINFO_CHOSEN_MEM) {
- if (pCheckInfo->iter != NULL) {
- hasNext = tsdbTbDataIterNext(pCheckInfo->iter);
- }
-
- if (hasNext) {
- return hasNext;
- }
+// todo consider the output buffer size
+static int32_t doLoadFileBlockData(STsdbReader* pReader, SDataBlockIter* pBlockIter,
+ STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData) {
+ int64_t st = taosGetTimestampUs();
- if (pCheckInfo->iiter != NULL) {
- return tsdbTbDataIterGet(pCheckInfo->iiter, NULL);
- }
- } else if (pCheckInfo->chosen == CHECKINFO_CHOSEN_IMEM) {
- if (pCheckInfo->iiter != NULL) {
- hasNext = tsdbTbDataIterNext(pCheckInfo->iiter);
- }
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ SBlock* pBlock = taosArrayGet(pBlockScanInfo->pBlockList, pFBlock->tbBlockIdx);
+ SSDataBlock* pResBlock = pReader->pResBlock;
+ int32_t numOfCols = blockDataGetNumOfCols(pResBlock);
- if (hasNext) {
- return hasNext;
- }
+ SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
- if (pCheckInfo->iter != NULL) {
- return tsdbTbDataIterGet(pCheckInfo->iter, NULL);
- }
- } else {
- if (pCheckInfo->iter != NULL) {
- hasNext = tsdbTbDataIterNext(pCheckInfo->iter);
- }
- if (pCheckInfo->iiter != NULL) {
- hasNext = tsdbTbDataIterNext(pCheckInfo->iiter) || hasNext;
- }
+ uint8_t *pb = NULL, *pb1 = NULL;
+ int32_t code = tsdbReadColData(pReader->pFileReader, &pBlockScanInfo->blockIdx, pBlock, pSupInfo->colIds, numOfCols,
+ pBlockData, &pb, &pb1);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
}
- return hasNext;
-}
+ int64_t elapsedTime = (taosGetTimestampUs() - st);
+ pReader->cost.blockLoadTime += elapsedTime;
-static bool hasMoreDataInCache(STsdbReadHandle* pHandle) {
- STsdbCfg* pCfg = REPO_CFG(pHandle->pTsdb);
- size_t size = taosArrayGetSize(pHandle->pTableCheckInfo);
- assert(pHandle->activeIndex < size && pHandle->activeIndex >= 0 && size >= 1);
- pHandle->cur.fid = INT32_MIN;
+ pDumpInfo->allDumped = false;
+ tsdbDebug("%p load file block into buffer, global index:%d, table index:%d, brange:%" PRId64 "-%" PRId64
+ ", rows:%d, minVer:%" PRId64 ", maxVer:%" PRId64 ", elapsed time:%" PRId64 " us, %s",
+ pReader, pBlockIter->index, pFBlock->tbBlockIdx, pBlock->minKey.ts, pBlock->maxKey.ts, pBlock->nRow,
+ pBlock->minVersion, pBlock->maxVersion, elapsedTime, pReader->idStr);
+ return TSDB_CODE_SUCCESS;
- STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
- if (!pCheckInfo->initBuf) {
- initTableMemIterator(pHandle, pCheckInfo);
- }
+_error:
+ tsdbError("%p error occurs in loading file block, global index:%d, table index:%d, brange:%" PRId64 "-%" PRId64
+ ", rows:%d, %s",
+ pReader, pBlockIter->index, pFBlock->tbBlockIdx, pBlock->minKey.ts, pBlock->maxKey.ts, pBlock->nRow,
+ pReader->idStr);
+ return code;
+}
- STSRow* row = getSRowInTableMem(pCheckInfo, pHandle->order, pCfg->update, NULL, TD_VER_MAX);
- if (row == NULL) {
- return false;
+// static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
+// int firstPos, lastPos, midPos = -1;
+// int numOfRows;
+// TSKEY* keyList;
+
+// assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
+
+// if (num <= 0) return -1;
+
+// keyList = (TSKEY*)pValue;
+// firstPos = 0;
+// lastPos = num - 1;
+
+// if (order == TSDB_ORDER_DESC) {
+// // find the first position which is smaller than the key
+// while (1) {
+// if (key >= keyList[lastPos]) return lastPos;
+// if (key == keyList[firstPos]) return firstPos;
+// if (key < keyList[firstPos]) return firstPos - 1;
+
+// numOfRows = lastPos - firstPos + 1;
+// midPos = (numOfRows >> 1) + firstPos;
+
+// if (key < keyList[midPos]) {
+// lastPos = midPos - 1;
+// } else if (key > keyList[midPos]) {
+// firstPos = midPos + 1;
+// } else {
+// break;
+// }
+// }
+
+// } else {
+// // find the first position which is bigger than the key
+// while (1) {
+// if (key <= keyList[firstPos]) return firstPos;
+// if (key == keyList[lastPos]) return lastPos;
+
+// if (key > keyList[lastPos]) {
+// lastPos = lastPos + 1;
+// if (lastPos >= num)
+// return -1;
+// else
+// return lastPos;
+// }
+
+// numOfRows = lastPos - firstPos + 1;
+// midPos = (numOfRows >> 1) + firstPos;
+
+// if (key < keyList[midPos]) {
+// lastPos = midPos - 1;
+// } else if (key > keyList[midPos]) {
+// firstPos = midPos + 1;
+// } else {
+// break;
+// }
+// }
+// }
+
+// return midPos;
+// }
+
+// static void doCheckGeneratedBlockRange(STsdbReader* pTsdbReadHandle) {
+// SQueryFilePos* cur = &pTsdbReadHandle->cur;
+
+// if (cur->rows > 0) {
+// if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
+// assert(cur->win.skey >= pTsdbReadHandle->window.skey && cur->win.ekey <= pTsdbReadHandle->window.ekey);
+// } else {
+// assert(cur->win.skey >= pTsdbReadHandle->window.ekey && cur->win.ekey <= pTsdbReadHandle->window.skey);
+// }
+
+// SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, 0);
+// assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] &&
+// cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows - 1]);
+// } else {
+// cur->win = pTsdbReadHandle->window;
+
+// int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
+// cur->lastKey = pTsdbReadHandle->window.ekey + step;
+// }
+// }
+
+// static void copyAllRemainRowsFromFileBlock(STsdbReader* pTsdbReadHandle, STableBlockScanInfo* pCheckInfo,
+// SDataBlockInfo* pBlockInfo, int32_t endPos) {
+// SQueryFilePos* cur = &pTsdbReadHandle->cur;
+
+// SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
+// TSKEY* tsArray = pCols->cols[0].pData;
+
+// bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+
+// int32_t step = ascScan ? 1 : -1;
+
+// int32_t start = cur->pos;
+// int32_t end = endPos;
+
+// if (!ascScan) {
+// TSWAP(start, end);
+// }
+
+// assert(pTsdbReadHandle->outputCapacity >= (end - start + 1));
+// int32_t numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, start, end);
+
+// // the time window should always be ascending order: skey <= ekey
+// cur->win = (STimeWindow){.skey = tsArray[start], .ekey = tsArray[end]};
+// cur->mixBlock = (numOfRows != pBlockInfo->rows);
+// cur->lastKey = tsArray[endPos] + step;
+// cur->blockCompleted = (ascScan ? (endPos == pBlockInfo->rows - 1) : (endPos == 0));
+
+// // The value of pos may be -1 or pBlockInfo->rows, and it is invalid in both cases.
+// int32_t pos = endPos + step;
+// updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
+// doCheckGeneratedBlockRange(pTsdbReadHandle);
+
+// tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
+// pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
+// pTsdbReadHandle->idStr);
+// }
+
+// // only return the qualified data to client in terms of query time window, data rows in the same block but do not
+// // be included in the query time window will be discarded
+// static void doMergeTwoLevelData(STsdbReader* pTsdbReadHandle, STableBlockScanInfo* pCheckInfo, SBlock* pBlock) {
+// SQueryFilePos* cur = &pTsdbReadHandle->cur;
+// SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
+// STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
+
+// initTableMemIterator(pTsdbReadHandle, pCheckInfo);
+
+// SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
+// assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_ID &&
+// cur->pos >= 0 && cur->pos < pBlock->numOfRows);
+// // Even Multi-Version supported, the records with duplicated TSKEY would be merged inside of tsdbLoadData
+// interface. TSKEY* tsArray = pCols->cols[0].pData; assert(pCols->numOfRows == pBlock->numOfRows && tsArray[0] ==
+// pBlock->minKey.ts &&
+// tsArray[pBlock->numOfRows - 1] == pBlock->maxKey.ts);
+
+// bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+// int32_t step = ascScan ? 1 : -1;
+
+// // for search the endPos, so the order needs to reverse
+// int32_t order = ascScan ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
+
+// int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
+// int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &blockInfo);
+
+// STimeWindow* pWin = &blockInfo.window;
+// tsdbDebug("%p uid:%" PRIu64 " start merge data block, file block range:%" PRIu64 "-%" PRIu64
+// " rows:%d, start:%d, end:%d, %s",
+// pTsdbReadHandle, pCheckInfo->tableId, pWin->skey, pWin->ekey, blockInfo.rows, cur->pos, endPos,
+// pTsdbReadHandle->idStr);
+
+// // compared with the data from in-memory buffer, to generate the correct timestamp array list
+// int32_t numOfRows = 0;
+// int32_t curRow = 0;
+
+// int16_t rv1 = -1;
+// int16_t rv2 = -1;
+// STSchema* pSchema1 = NULL;
+// STSchema* pSchema2 = NULL;
+
+// int32_t pos = cur->pos;
+// cur->win = TSWINDOW_INITIALIZER;
+// bool adjustPos = false;
+
+// // no data in buffer, load data from file directly
+// if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) {
+// copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &blockInfo, endPos);
+// return;
+// } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) {
+// SSkipListNode* node = NULL;
+// TSKEY lastKeyAppend = TSKEY_INITIAL_VAL;
+
+// do {
+// STSRow* row2 = NULL;
+// STSRow* row1 = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, &row2, TD_VER_MAX);
+// if (row1 == NULL) {
+// break;
+// }
+
+// TSKEY key = TD_ROW_KEY(row1);
+// if ((key > pTsdbReadHandle->window.ekey && ascScan) || (key < pTsdbReadHandle->window.ekey && !ascScan)) {
+// break;
+// }
+
+// if (adjustPos) {
+// if (key == lastKeyAppend) {
+// pos -= step;
+// }
+// adjustPos = false;
+// }
+
+// if (((pos > endPos || tsArray[pos] > pTsdbReadHandle->window.ekey) && ascScan) ||
+// ((pos < endPos || tsArray[pos] < pTsdbReadHandle->window.ekey) && !ascScan)) {
+// break;
+// }
+
+// if ((key < tsArray[pos] && ascScan) || (key > tsArray[pos] && !ascScan)) {
+// if (rv1 != TD_ROW_SVER(row1)) {
+// // pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
+// rv1 = TD_ROW_SVER(row1);
+// }
+// if (row2 && rv2 != TD_ROW_SVER(row2)) {
+// // pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
+// rv2 = TD_ROW_SVER(row2);
+// }
+
+// numOfRows +=
+// mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols,
+// pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastKeyAppend);
+// if (cur->win.skey == TSKEY_INITIAL_VAL) {
+// cur->win.skey = key;
+// }
+
+// cur->win.ekey = key;
+// cur->lastKey = key + step;
+// cur->mixBlock = true;
+// moveToNextRowInMem(pCheckInfo);
+// } else if (key == tsArray[pos]) { // data in buffer has the same timestamp of data in file block, ignore it
+// if (TD_SUPPORT_UPDATE(pCfg->update)) {
+// if (lastKeyAppend != key) {
+// if (lastKeyAppend != TSKEY_INITIAL_VAL) {
+// ++curRow;
+// }
+// lastKeyAppend = key;
+// }
+// // load data from file firstly
+// numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, curRow, pos, pos);
+
+// if (rv1 != TD_ROW_SVER(row1)) {
+// rv1 = TD_ROW_SVER(row1);
+// }
+// if (row2 && rv2 != TD_ROW_SVER(row2)) {
+// rv2 = TD_ROW_SVER(row2);
+// }
+
+// // still assign data into current row
+// numOfRows +=
+// mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols,
+// pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastKeyAppend);
+
+// if (cur->win.skey == TSKEY_INITIAL_VAL) {
+// cur->win.skey = key;
+// }
+
+// cur->win.ekey = key;
+// cur->lastKey = key + step;
+// cur->mixBlock = true;
+
+// moveToNextRowInMem(pCheckInfo);
+
+// pos += step;
+// adjustPos = true;
+// } else {
+// // discard the memory record
+// moveToNextRowInMem(pCheckInfo);
+// }
+// } else if ((key > tsArray[pos] && ascScan) || (key < tsArray[pos] && !ascScan)) {
+// if (cur->win.skey == TSKEY_INITIAL_VAL) {
+// cur->win.skey = tsArray[pos];
+// }
+
+// int32_t end = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, key, order);
+// assert(end != -1);
+
+// if (tsArray[end] == key) { // the value of key in cache equals to the end timestamp value, ignore it
+// #if 0
+// if (pCfg->update == TD_ROW_DISCARD_UPDATE) {
+// moveToNextRowInMem(pCheckInfo);
+// } else {
+// end -= step;
+// }
+// #endif
+// if (!TD_SUPPORT_UPDATE(pCfg->update)) {
+// moveToNextRowInMem(pCheckInfo);
+// } else {
+// end -= step;
+// }
+// }
+
+// int32_t qstart = 0, qend = 0;
+// getQualifiedRowsPos(pTsdbReadHandle, pos, end, numOfRows, &qstart, &qend);
+
+// if ((lastKeyAppend != TSKEY_INITIAL_VAL) && (lastKeyAppend != (ascScan ? tsArray[qstart] : tsArray[qend]))) {
+// ++curRow;
+// }
+
+// numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, curRow, qstart, qend);
+// pos += (qend - qstart + 1) * step;
+// if (numOfRows > 0) {
+// curRow = numOfRows - 1;
+// }
+
+// cur->win.ekey = ascScan ? tsArray[qend] : tsArray[qstart];
+// cur->lastKey = cur->win.ekey + step;
+// lastKeyAppend = cur->win.ekey;
+// }
+// } while (numOfRows < pTsdbReadHandle->outputCapacity);
+
+// if (numOfRows < pTsdbReadHandle->outputCapacity) {
+// /**
+// * if cache is empty, load remain file block data. In contrast, if there are remain data in cache, do NOT
+// * copy them all to result buffer, since it may be overlapped with file data block.
+// */
+// if (node == NULL || ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) > pTsdbReadHandle->window.ekey) && ascScan)
+// ||
+// ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) < pTsdbReadHandle->window.ekey) && !ascScan)) {
+// // no data in cache or data in cache is greater than the ekey of time window, load data from file block
+// if (cur->win.skey == TSKEY_INITIAL_VAL) {
+// cur->win.skey = tsArray[pos];
+// }
+
+// int32_t start = -1, end = -1;
+// getQualifiedRowsPos(pTsdbReadHandle, pos, endPos, numOfRows, &start, &end);
+
+// numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, start, end);
+// pos += (end - start + 1) * step;
+
+// cur->win.ekey = ascScan ? tsArray[end] : tsArray[start];
+// cur->lastKey = cur->win.ekey + step;
+// cur->mixBlock = true;
+// }
+// }
+// }
+
+// cur->blockCompleted = (((pos > endPos || cur->lastKey > pTsdbReadHandle->window.ekey) && ascScan) ||
+// ((pos < endPos || cur->lastKey < pTsdbReadHandle->window.ekey) && !ascScan));
+
+// if (!ascScan) {
+// TSWAP(cur->win.skey, cur->win.ekey);
+// }
+
+// updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
+// doCheckGeneratedBlockRange(pTsdbReadHandle);
+
+// tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
+// pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
+// pTsdbReadHandle->idStr);
+// }
+
+static void cleanupBlockOrderSupporter(SBlockOrderSupporter* pSup) {
+ taosMemoryFreeClear(pSup->numOfBlocksPerTable);
+ taosMemoryFreeClear(pSup->indexPerTable);
+
+ for (int32_t i = 0; i < pSup->numOfTables; ++i) {
+ SBlockOrderWrapper* pBlockInfo = pSup->pDataBlockInfo[i];
+ taosMemoryFreeClear(pBlockInfo);
}
- pCheckInfo->lastKey = TD_ROW_KEY(row); // first timestamp in buffer
- tsdbDebug("%p uid:%" PRId64 ", check data in buffer from skey:%" PRId64 ", order:%d, %s", pHandle,
- pCheckInfo->tableId, pCheckInfo->lastKey, pHandle->order, pHandle->idStr);
-
- // all data in mem are checked already.
- if ((pCheckInfo->lastKey > pHandle->window.ekey && ASCENDING_TRAVERSE(pHandle->order)) ||
- (pCheckInfo->lastKey < pHandle->window.ekey && !ASCENDING_TRAVERSE(pHandle->order))) {
- return false;
- }
+ taosMemoryFreeClear(pSup->pDataBlockInfo);
+}
- int32_t step = ASCENDING_TRAVERSE(pHandle->order) ? 1 : -1;
- STimeWindow* win = &pHandle->cur.win;
- pHandle->cur.rows = tsdbReadRowsFromCache(pCheckInfo, pHandle->window.ekey, pHandle->outputCapacity, win, pHandle);
+static int32_t initBlockOrderSupporter(SBlockOrderSupporter* pSup, int32_t numOfTables) {
+ ASSERT(numOfTables >= 1);
- // update the last key value
- pCheckInfo->lastKey = win->ekey + step;
- pHandle->cur.lastKey = win->ekey + step;
- pHandle->cur.mixBlock = true;
+ pSup->numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
+ pSup->indexPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
+ pSup->pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
- if (!ASCENDING_TRAVERSE(pHandle->order)) {
- TSWAP(win->skey, win->ekey);
+ if (pSup->numOfBlocksPerTable == NULL || pSup->indexPerTable == NULL || pSup->pDataBlockInfo == NULL) {
+ cleanupBlockOrderSupporter(pSup);
+ return TSDB_CODE_OUT_OF_MEMORY;
}
- return true;
+ return TSDB_CODE_SUCCESS;
}
-static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precision) {
- assert(precision >= TSDB_TIME_PRECISION_MICRO || precision <= TSDB_TIME_PRECISION_NANO);
- if (key == TSKEY_INITIAL_VAL) {
- return INT32_MIN;
- }
+static int32_t fileDataBlockOrderCompar(const void* pLeft, const void* pRight, void* param) {
+ int32_t leftIndex = *(int32_t*)pLeft;
+ int32_t rightIndex = *(int32_t*)pRight;
- if (key < 0) {
- key -= (daysPerFile * tsTickPerMin[precision]);
- }
+ SBlockOrderSupporter* pSupporter = (SBlockOrderSupporter*)param;
- int64_t fid = (int64_t)(key / (daysPerFile * tsTickPerMin[precision])); // set the starting fileId
- if (fid < 0L && llabs(fid) > INT32_MAX) { // data value overflow for INT32
- fid = INT32_MIN;
- }
+ int32_t leftTableBlockIndex = pSupporter->indexPerTable[leftIndex];
+ int32_t rightTableBlockIndex = pSupporter->indexPerTable[rightIndex];
- if (fid > 0L && fid > INT32_MAX) {
- fid = INT32_MAX;
+ if (leftTableBlockIndex > pSupporter->numOfBlocksPerTable[leftIndex]) {
+ /* left block is empty */
+ return 1;
+ } else if (rightTableBlockIndex > pSupporter->numOfBlocksPerTable[rightIndex]) {
+ /* right block is empty */
+ return -1;
}
- return (int32_t)fid;
+ SBlockOrderWrapper* pLeftBlock = &pSupporter->pDataBlockInfo[leftIndex][leftTableBlockIndex];
+ SBlockOrderWrapper* pRightBlock = &pSupporter->pDataBlockInfo[rightIndex][rightTableBlockIndex];
+
+ return pLeftBlock->pBlock->aSubBlock[0].offset > pRightBlock->pBlock->aSubBlock[0].offset ? 1 : -1;
}
-static int32_t binarySearchForBlock(SBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) {
- int32_t firstSlot = 0;
- int32_t lastSlot = numOfBlocks - 1;
+static int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int32_t numOfBlocks) {
+ bool asc = ASCENDING_TRAVERSE(pReader->order);
- int32_t midSlot = firstSlot;
+ pBlockIter->numOfBlocks = numOfBlocks;
+ taosArrayClear(pBlockIter->blockList);
- while (1) {
- numOfBlocks = lastSlot - firstSlot + 1;
- midSlot = (firstSlot + (numOfBlocks >> 1));
-
- if (numOfBlocks == 1) break;
-
- if (skey > pBlock[midSlot].maxKey.ts) {
- if (numOfBlocks == 2) break;
- if ((order == TSDB_ORDER_DESC) && (skey < pBlock[midSlot + 1].minKey.ts)) break;
- firstSlot = midSlot + 1;
- } else if (skey < pBlock[midSlot].minKey.ts) {
- if ((order == TSDB_ORDER_ASC) && (skey > pBlock[midSlot - 1].maxKey.ts)) break;
- lastSlot = midSlot - 1;
- } else {
- break; // got the slot
- }
+ // access data blocks according to the offset of each block in asc/desc order.
+ int32_t numOfTables = (int32_t)taosHashGetSize(pReader->status.pTableMap);
+
+ SBlockOrderSupporter sup = {0};
+
+ int32_t code = initBlockOrderSupporter(&sup, numOfTables);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
}
- return midSlot;
-}
+ int32_t cnt = 0;
+ void* ptr = NULL;
+ while (1) {
+ ptr = taosHashIterate(pReader->status.pTableMap, ptr);
+ if (ptr == NULL) {
+ break;
+ }
-static int32_t loadBlockInfo(STsdbReadHandle* pTsdbReadHandle, int32_t index, int32_t* numOfBlocks) {
- int32_t code = 0;
+ STableBlockScanInfo* pTableScanInfo = (STableBlockScanInfo*)ptr;
+ if (pTableScanInfo->pBlockList == NULL || taosArrayGetSize(pTableScanInfo->pBlockList) == 0) {
+ continue;
+ }
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, index);
- pCheckInfo->numOfBlocks = 0;
+ size_t num = taosArrayGetSize(pTableScanInfo->pBlockList);
+ sup.numOfBlocksPerTable[sup.numOfTables] = num;
- STable table = {.uid = pCheckInfo->tableId, .suid = pCheckInfo->suid};
- table.pSchema = pTsdbReadHandle->pSchema;
+ char* buf = taosMemoryMalloc(sizeof(SBlockOrderWrapper) * num);
+ if (buf == NULL) {
+ cleanupBlockOrderSupporter(&sup);
+ return TSDB_CODE_TDB_OUT_OF_MEMORY;
+ }
- if (tsdbSetReadTable(&pTsdbReadHandle->rhelper, &table) != TSDB_CODE_SUCCESS) {
- code = terrno;
- return code;
- }
+ sup.pDataBlockInfo[sup.numOfTables] = (SBlockOrderWrapper*)buf;
+ for (int32_t k = 0; k < num; ++k) {
+ SBlockOrderWrapper wrapper = {0};
+ wrapper.pBlock = (SBlock*)taosArrayGet(pTableScanInfo->pBlockList, k);
+ wrapper.uid = pTableScanInfo->uid;
- SBlockIdx* compIndex = pTsdbReadHandle->rhelper.pBlkIdx;
+ sup.pDataBlockInfo[sup.numOfTables][k] = wrapper;
+ cnt++;
+ }
- // no data block in this file, try next file
- if (compIndex == NULL || compIndex->uid != pCheckInfo->tableId) {
- return 0; // no data blocks in the file belongs to pCheckInfo->pTable
+ sup.numOfTables += 1;
}
- if (pCheckInfo->compSize < (int32_t)compIndex->len) {
- assert(compIndex->len > 0);
+ ASSERT(numOfBlocks == cnt);
- char* t = taosMemoryRealloc(pCheckInfo->pCompInfo, compIndex->len);
- if (t == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- code = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return code;
+ // since there is only one table qualified, blocks are not sorted
+ if (sup.numOfTables == 1) {
+ for (int32_t i = 0; i < numOfBlocks; ++i) {
+ SFileDataBlockInfo blockInfo = {.uid = sup.pDataBlockInfo[0][i].uid, .tbBlockIdx = i};
+ taosArrayPush(pBlockIter->blockList, &blockInfo);
}
+ tsdbDebug("%p create blocks info struct completed for one table, %d blocks not sorted %s", pReader, cnt,
+ pReader->idStr);
- pCheckInfo->pCompInfo = (SBlockInfo*)t;
- pCheckInfo->compSize = compIndex->len;
- }
+ pBlockIter->index = asc ? 0 : (numOfBlocks - 1);
- if (tsdbLoadBlockInfo(&(pTsdbReadHandle->rhelper), (void*)(pCheckInfo->pCompInfo)) < 0) {
- return terrno;
+ cleanupBlockOrderSupporter(&sup);
+ return TSDB_CODE_SUCCESS;
}
- SBlockInfo* pCompInfo = pCheckInfo->pCompInfo;
- TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL;
+ tsdbDebug("%p create data blocks info struct completed, %d blocks in %d tables %s", pReader, cnt, sup.numOfTables,
+ pReader->idStr);
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.ekey &&
- pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
- } else {
- assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.ekey &&
- pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
+ assert(cnt <= numOfBlocks && sup.numOfTables <= numOfTables);
+
+ SMultiwayMergeTreeInfo* pTree = NULL;
+ uint8_t ret = tMergeTreeCreate(&pTree, sup.numOfTables, &sup, fileDataBlockOrderCompar);
+ if (ret != TSDB_CODE_SUCCESS) {
+ cleanupBlockOrderSupporter(&sup);
+ return TSDB_CODE_TDB_OUT_OF_MEMORY;
}
- s = TMIN(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
- e = TMAX(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
+ int32_t numOfTotal = 0;
+ while (numOfTotal < cnt) {
+ int32_t pos = tMergeTreeGetChosenIndex(pTree);
+ int32_t index = sup.indexPerTable[pos]++;
+
+ SFileDataBlockInfo blockInfo = {.uid = sup.pDataBlockInfo[pos][index].uid, .tbBlockIdx = index};
+ taosArrayPush(pBlockIter->blockList, &blockInfo);
- // discard the unqualified data block based on the query time window
- int32_t start = binarySearchForBlock(pCompInfo->blocks, compIndex->numOfBlocks, s, TSDB_ORDER_ASC);
- int32_t end = start;
+ // set data block index overflow, in order to disable the offset comparator
+ if (sup.indexPerTable[pos] >= sup.numOfBlocksPerTable[pos]) {
+ sup.indexPerTable[pos] = sup.numOfBlocksPerTable[pos] + 1;
+ }
- if (s > pCompInfo->blocks[start].maxKey.ts) {
- return 0;
+ numOfTotal += 1;
+ tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
}
- // todo speedup the procedure of located end block
- while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].minKey.ts <= e)) {
- end += 1;
- }
+ tsdbDebug("%p %d data blocks sort completed, %s", pReader, cnt, pReader->idStr);
+ cleanupBlockOrderSupporter(&sup);
+ taosMemoryFree(pTree);
- pCheckInfo->numOfBlocks = (end - start);
+ pBlockIter->index = asc ? 0 : (numOfBlocks - 1);
+ return TSDB_CODE_SUCCESS;
+}
- if (start > 0) {
- memmove(pCompInfo->blocks, &pCompInfo->blocks[start], pCheckInfo->numOfBlocks * sizeof(SBlock));
+static bool blockIteratorNext(SDataBlockIter* pBlockIter) {
+ bool asc = ASCENDING_TRAVERSE(pBlockIter->order);
+
+ int32_t step = asc ? 1 : -1;
+ if ((pBlockIter->index >= pBlockIter->numOfBlocks - 1 && asc) || (pBlockIter->index <= 0 && (!asc))) {
+ return false;
}
- (*numOfBlocks) += pCheckInfo->numOfBlocks;
- return 0;
+ pBlockIter->index += step;
+ return true;
}
-static int32_t getFileCompInfo(STsdbReadHandle* pTsdbReadHandle, int32_t* numOfBlocks) {
- // load all the comp offset value for all tables in this file
- int32_t code = TSDB_CODE_SUCCESS;
- *numOfBlocks = 0;
-
- pTsdbReadHandle->cost.headFileLoad += 1;
- int64_t s = taosGetTimestampUs();
+/**
+ * This is an two rectangles overlap cases.
+ */
+static int32_t dataBlockPartiallyRequired(STimeWindow* pWindow, SVersionRange* pVerRange, SBlock* pBlock) {
+ return (pWindow->ekey < pBlock->maxKey.ts && pWindow->ekey >= pBlock->minKey.ts) ||
+ (pWindow->skey > pBlock->minKey.ts && pWindow->skey <= pBlock->maxKey.ts) ||
+ (pVerRange->minVer > pBlock->minVersion && pVerRange->minVer <= pBlock->maxVersion) ||
+ (pVerRange->maxVer < pBlock->maxVersion && pVerRange->maxVer >= pBlock->minVersion);
+}
- size_t numOfTables = 0;
- if (pTsdbReadHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) {
- code = loadBlockInfo(pTsdbReadHandle, pTsdbReadHandle->activeIndex, numOfBlocks);
- } else if (pTsdbReadHandle->loadType == BLOCK_LOAD_OFFSET_SEQ_ORDER) {
- numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
+static SFileDataBlockInfo* getCurrentBlockInfo(SDataBlockIter* pBlockIter) {
+ SFileDataBlockInfo* pFBlockInfo = taosArrayGet(pBlockIter->blockList, pBlockIter->index);
+ return pFBlockInfo;
+}
- for (int32_t i = 0; i < numOfTables; ++i) {
- code = loadBlockInfo(pTsdbReadHandle, i, numOfBlocks);
- if (code != TSDB_CODE_SUCCESS) {
- int64_t e = taosGetTimestampUs();
+static SBlock* getNeighborBlockOfSameTable(SFileDataBlockInfo* pFBlockInfo, STableBlockScanInfo* pTableBlockScanInfo,
+ int32_t* nextIndex, int32_t order) {
+ bool asc = ASCENDING_TRAVERSE(order);
+ if (asc && pFBlockInfo->tbBlockIdx >= taosArrayGetSize(pTableBlockScanInfo->pBlockList) - 1) {
+ return NULL;
+ }
- pTsdbReadHandle->cost.headFileLoadTime += (e - s);
- return code;
- }
- }
- } else {
- assert(0);
+ if (!asc && pFBlockInfo->tbBlockIdx == 0) {
+ return NULL;
}
- int64_t e = taosGetTimestampUs();
- pTsdbReadHandle->cost.headFileLoadTime += (e - s);
- return code;
+ int32_t step = asc ? 1 : -1;
+
+ *nextIndex = pFBlockInfo->tbBlockIdx + step;
+ SBlock* pNext = taosArrayGet(pTableBlockScanInfo->pBlockList, *nextIndex);
+ return pNext;
}
-static int32_t doLoadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
- int32_t slotIndex) {
- int64_t st = taosGetTimestampUs();
+static int32_t findFileBlockInfoIndex(SDataBlockIter* pBlockIter, SFileDataBlockInfo* pFBlockInfo) {
+ ASSERT(pBlockIter != NULL && pFBlockInfo != NULL);
- int32_t code = tdInitDataCols(pTsdbReadHandle->pDataCols, pTsdbReadHandle->pSchema);
- if (code != TSDB_CODE_SUCCESS) {
- tsdbError("%p failed to malloc buf for pDataCols, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- goto _error;
+ int32_t step = ASCENDING_TRAVERSE(pBlockIter->order) ? 1 : -1;
+ int32_t index = pBlockIter->index;
+
+ while (index < pBlockIter->numOfBlocks && index >= 0) {
+ SFileDataBlockInfo* pFBlock = taosArrayGet(pBlockIter->blockList, index);
+ if (pFBlock->uid == pFBlockInfo->uid && pFBlock->tbBlockIdx == pFBlockInfo->tbBlockIdx) {
+ return index;
+ }
+
+ index += step;
}
- code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[0], pTsdbReadHandle->pSchema);
- if (code != TSDB_CODE_SUCCESS) {
- tsdbError("%p failed to malloc buf for rhelper.pDataCols[0], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- goto _error;
+ ASSERT(0);
+ return -1;
+}
+
+static int32_t setFileBlockActiveInBlockIter(SDataBlockIter* pBlockIter, int32_t index, int32_t step) {
+ if (index < 0 || index >= pBlockIter->numOfBlocks) {
+ return -1;
}
- code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[1], pTsdbReadHandle->pSchema);
- if (code != TSDB_CODE_SUCCESS) {
- tsdbError("%p failed to malloc buf for rhelper.pDataCols[1], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- goto _error;
+ SFileDataBlockInfo fblock = *(SFileDataBlockInfo*)taosArrayGet(pBlockIter->blockList, index);
+ pBlockIter->index += step;
+
+ if (index != pBlockIter->index) {
+ taosArrayRemove(pBlockIter->blockList, index);
+ taosArrayInsert(pBlockIter->blockList, pBlockIter->index, &fblock);
+
+ SFileDataBlockInfo* pBlockInfo = taosArrayGet(pBlockIter->blockList, pBlockIter->index);
+ ASSERT(pBlockInfo->uid == fblock.uid && pBlockInfo->tbBlockIdx == fblock.tbBlockIdx);
}
- int16_t* colIds = pTsdbReadHandle->suppInfo.defaultLoadColumn->pData;
+ return TSDB_CODE_SUCCESS;
+}
- int32_t ret = tsdbLoadBlockDataCols(&(pTsdbReadHandle->rhelper), pBlock, pCheckInfo->pCompInfo, colIds,
- (int)(QH_GET_NUM_OF_COLS(pTsdbReadHandle)), true);
- if (ret != TSDB_CODE_SUCCESS) {
- int32_t c = terrno;
- assert(c != TSDB_CODE_SUCCESS);
- goto _error;
+static bool overlapWithNeighborBlock(SBlock* pBlock, SBlock* pNeighbor, int32_t order) {
+ // it is the last block in current file, no chance to overlap with neighbor blocks.
+ if (ASCENDING_TRAVERSE(order)) {
+ return pBlock->maxKey.ts == pNeighbor->minKey.ts;
+ } else {
+ return pBlock->minKey.ts == pNeighbor->maxKey.ts;
}
+}
+
+static bool bufferDataInFileBlockGap(int32_t order, TSDBKEY key, SBlock* pBlock) {
+ bool ascScan = ASCENDING_TRAVERSE(order);
+
+ return (ascScan && (key.ts != TSKEY_INITIAL_VAL && key.ts <= pBlock->minKey.ts)) ||
+ (!ascScan && (key.ts != TSKEY_INITIAL_VAL && key.ts >= pBlock->maxKey.ts));
+}
+
+static bool keyOverlapFileBlock(TSDBKEY key, SBlock* pBlock, SVersionRange* pVerRange) {
+ return (key.ts >= pBlock->minKey.ts && key.ts <= pBlock->maxKey.ts) && (pBlock->maxVersion >= pVerRange->minVer) &&
+ (pBlock->minVersion <= pVerRange->maxVer);
+}
- SDataBlockLoadInfo* pBlockLoadInfo = &pTsdbReadHandle->dataBlockLoadInfo;
+static bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBlock* pBlock, int32_t order) {
+ if (pBlockScanInfo->delSkyline == NULL) {
+ return false;
+ }
- pBlockLoadInfo->fileGroup = pTsdbReadHandle->pFileGroup;
- pBlockLoadInfo->slot = pTsdbReadHandle->cur.slot;
- pBlockLoadInfo->uid = pCheckInfo->tableId;
+ TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
+ TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
- SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
- assert(pCols->numOfRows != 0 && pCols->numOfRows <= pBlock->numOfRows);
+ // ts is not overlap
+ if (pBlock->minKey.ts > pLast->ts || pBlock->maxKey.ts < pFirst->ts) {
+ return false;
+ }
- pBlock->numOfRows = pCols->numOfRows;
+ int32_t step = ASCENDING_TRAVERSE(order) ? 1 : -1;
- // Convert from TKEY to TSKEY for primary timestamp column if current block has timestamp before 1970-01-01T00:00:00Z
- if (pBlock->minKey.ts < 0 && colIds[0] == PRIMARYKEY_TIMESTAMP_COL_ID) {
- int64_t* src = pCols->cols[0].pData;
- for (int32_t i = 0; i < pBlock->numOfRows; ++i) {
- src[i] = tdGetKey(src[i]);
+ // version is not overlap
+ size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
+ for (int32_t i = pBlockScanInfo->fileDelIndex; i < num; i += step) {
+ TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
+ if (p->ts >= pBlock->minKey.ts && p->ts <= pBlock->maxKey.ts) {
+ if (p->version >= pBlock->minVersion) {
+ return true;
+ }
+ } else if (p->ts > pBlock->maxKey.ts) {
+ return false;
}
}
- int64_t elapsedTime = (taosGetTimestampUs() - st);
- pTsdbReadHandle->cost.blockLoadTime += elapsedTime;
+ ASSERT(0);
+ return false;
+}
- tsdbDebug("%p load file block into buffer, index:%d, brange:%" PRId64 "-%" PRId64 ", rows:%d, elapsed time:%" PRId64
- " us, %s",
- pTsdbReadHandle, slotIndex, pBlock->minKey.ts, pBlock->maxKey.ts, pBlock->numOfRows, elapsedTime,
- pTsdbReadHandle->idStr);
- return TSDB_CODE_SUCCESS;
+// 1. the version of all rows should be less than the endVersion
+// 2. current block should not overlap with next neighbor block
+// 3. current timestamp should not be overlap with each other
+// 4. output buffer should be large enough to hold all rows in current block
+// 5. delete info should not overlap with current block data
+static bool fileBlockShouldLoad(STsdbReader* pReader, SFileDataBlockInfo* pFBlock, SBlock* pBlock,
+ STableBlockScanInfo* pScanInfo, TSDBKEY key) {
+ int32_t neighborIndex = 0;
+ SBlock* pNeighbor = getNeighborBlockOfSameTable(pFBlock, pScanInfo, &neighborIndex, pReader->order);
-_error:
- pBlock->numOfRows = 0;
+ // overlap with neighbor
+ bool overlapWithNeighbor = false;
+ if (pNeighbor) {
+ overlapWithNeighbor = overlapWithNeighborBlock(pBlock, pNeighbor, pReader->order);
+ }
+
+ // has duplicated ts of different version in this block
+ bool hasDup = (pBlock->nSubBlock == 1) ? pBlock->hasDup : true;
+ bool overlapWithDel = overlapWithDelSkyline(pScanInfo, pBlock, pReader->order);
- tsdbError("%p error occurs in loading file block, index:%d, brange:%" PRId64 "-%" PRId64 ", rows:%d, %s",
- pTsdbReadHandle, slotIndex, pBlock->minKey.ts, pBlock->maxKey.ts, pBlock->numOfRows,
- pTsdbReadHandle->idStr);
- return terrno;
+ return (overlapWithNeighbor || hasDup || dataBlockPartiallyRequired(&pReader->window, &pReader->verRange, pBlock) ||
+ keyOverlapFileBlock(key, pBlock, &pReader->verRange) || (pBlock->nRow > pReader->capacity) || overlapWithDel);
}
-static int32_t getEndPosInDataBlock(STsdbReadHandle* pTsdbReadHandle, SDataBlockInfo* pBlockInfo);
-static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows,
- int32_t start, int32_t end);
-static void doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle);
-static void copyAllRemainRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo,
- SDataBlockInfo* pBlockInfo, int32_t endPos);
+static int32_t buildDataBlockFromBuf(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, int64_t endKey) {
+ if (!(pBlockScanInfo->iiter.hasVal || pBlockScanInfo->iter.hasVal)) {
+ return TSDB_CODE_SUCCESS;
+ }
-static int32_t handleDataMergeIfNeeded(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
- SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
- TSKEY key;
- int32_t code = TSDB_CODE_SUCCESS;
+ SSDataBlock* pBlock = pReader->pResBlock;
- /*bool hasData = */ initTableMemIterator(pTsdbReadHandle, pCheckInfo);
- assert(cur->pos >= 0 && cur->pos <= binfo.rows);
+ int64_t st = taosGetTimestampUs();
+ int32_t code = buildDataBlockFromBufImpl(pBlockScanInfo, endKey, pReader->capacity, pReader);
- key = extractFirstTraverseKey(pCheckInfo, pTsdbReadHandle->order, pCfg->update, TD_VER_MAX);
+ blockDataUpdateTsWindow(pBlock, 0);
+ pBlock->info.uid = pBlockScanInfo->uid;
- if (key != TSKEY_INITIAL_VAL) {
- tsdbDebug("%p key in mem:%" PRId64 ", %s", pTsdbReadHandle, key, pTsdbReadHandle->idStr);
- } else {
- tsdbDebug("%p no data in mem, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
- }
+ setComposedBlockFlag(pReader, true);
- bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+ int64_t elapsedTime = taosGetTimestampUs() - st;
+ tsdbDebug("%p build data block from cache completed, elapsed time:%" PRId64
+ " us, numOfRows:%d, numOfCols:%d, brange: %" PRId64 " - %" PRId64 " %s",
+ pReader, elapsedTime, pBlock->info.rows, (int32_t)blockDataGetNumOfCols(pBlock), pBlock->info.window.skey,
+ pBlock->info.window.ekey, pReader->idStr);
+ return code;
+}
- if ((ascScan && (key != TSKEY_INITIAL_VAL && key <= binfo.window.ekey)) ||
- (!ascScan && (key != TSKEY_INITIAL_VAL && key >= binfo.window.skey))) {
- bool cacheDataInFileBlockHole = (ascScan && (key != TSKEY_INITIAL_VAL && key < binfo.window.skey)) ||
- (!ascScan && (key != TSKEY_INITIAL_VAL && key > binfo.window.ekey));
- if (cacheDataInFileBlockHole) {
- // do not load file block into buffer
- int32_t step = ascScan ? 1 : -1;
+static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, TSDBROW* pRow,
+ STSRow* pTSRow, SIterInfo* pIter, int64_t key) {
+ SRowMerger merge = {0};
+ SBlockData* pBlockData = &pReader->status.fileBlockData;
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
- TSKEY maxKey = ascScan ? (binfo.window.skey - step) : (binfo.window.ekey - step);
- cur->rows =
- tsdbReadRowsFromCache(pCheckInfo, maxKey, pTsdbReadHandle->outputCapacity, &cur->win, pTsdbReadHandle);
- pTsdbReadHandle->realNumOfRows = cur->rows;
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ SArray* pDelList = pBlockScanInfo->delSkyline;
- // update the last key value
- pCheckInfo->lastKey = cur->win.ekey + step;
+ // ascending order traverse
+ if (ASCENDING_TRAVERSE(pReader->order)) {
+ if (key < k.ts) {
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
- if (!ascScan) {
- TSWAP(cur->win.skey, cur->win.ekey);
- }
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ tRowMergerGetRow(&merge, &pTSRow);
+ } else if (k.ts < key) { // k.ts < key
+ doMergeMultiRows(pRow, pBlockScanInfo->uid, pIter, pDelList, &pTSRow, pReader);
+ } else { // k.ts == key, ascending order: file block ----> imem rows -----> mem rows
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
- cur->mixBlock = true;
- cur->blockCompleted = false;
- return code;
- }
+ tRowMerge(&merge, pRow);
+ doMergeRowsInBuf(pIter, k.ts, pBlockScanInfo->delSkyline, &merge, pReader);
- // return error, add test cases
- if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
- return code;
+ tRowMergerGetRow(&merge, &pTSRow);
}
+ } else { // descending order scan
+ if (key < k.ts) {
+ doMergeMultiRows(pRow, pBlockScanInfo->uid, pIter, pDelList, &pTSRow, pReader);
+ } else if (k.ts < key) {
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
- doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
- } else {
- /*
- * no data in cache, only load data from file
- * during the query processing, data in cache will not be checked anymore.
- * Here the buffer is not enough, so only part of file block can be loaded into memory buffer
- */
- int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &binfo);
-
- bool wholeBlockReturned = ((abs(cur->pos - endPos) + 1) == binfo.rows);
- if (wholeBlockReturned) {
- pTsdbReadHandle->realNumOfRows = binfo.rows;
-
- cur->rows = binfo.rows;
- cur->win = binfo.window;
- cur->mixBlock = false;
- cur->blockCompleted = true;
-
- if (ascScan) {
- cur->lastKey = binfo.window.ekey + 1;
- cur->pos = binfo.rows;
- } else {
- cur->lastKey = binfo.window.skey - 1;
- cur->pos = -1;
- }
- } else { // partially copy to dest buffer
- // make sure to only load once
- bool firstTimeExtract = ((cur->pos == 0 && ascScan) || (cur->pos == binfo.rows - 1 && (!ascScan)));
- if (pTsdbReadHandle->outputCapacity < binfo.rows && firstTimeExtract) {
- code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot);
- if (code != TSDB_CODE_SUCCESS) {
- return code;
- }
- }
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ tRowMergerGetRow(&merge, &pTSRow);
+ } else { // descending order: mem rows -----> imem rows ------> file block
+ updateSchema(pRow, pBlockScanInfo->uid, pReader);
- copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &binfo, endPos);
- cur->mixBlock = true;
- }
+ tRowMergerInit(&merge, pRow, pReader->pSchema);
+ doMergeRowsInBuf(pIter, k.ts, pBlockScanInfo->delSkyline, &merge, pReader);
- if (pTsdbReadHandle->outputCapacity >= binfo.rows) {
- ASSERT(cur->blockCompleted || cur->mixBlock);
- }
+ tRowMerge(&merge, &fRow);
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
- if (cur->rows == binfo.rows) {
- tsdbDebug("%p whole file block qualified, brange:%" PRId64 "-%" PRId64 ", rows:%d, lastKey:%" PRId64 ", %s",
- pTsdbReadHandle, cur->win.skey, cur->win.ekey, cur->rows, cur->lastKey, pTsdbReadHandle->idStr);
- } else {
- tsdbDebug("%p create data block from remain file block, brange:%" PRId64 "-%" PRId64
- ", rows:%d, total:%d, lastKey:%" PRId64 ", %s",
- pTsdbReadHandle, cur->win.skey, cur->win.ekey, cur->rows, binfo.rows, cur->lastKey,
- pTsdbReadHandle->idStr);
+ tRowMergerGetRow(&merge, &pTSRow);
}
}
- return code;
+ tRowMergerClear(&merge);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
}
-static int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);
+static int32_t doMergeThreeLevelRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo) {
+ SRowMerger merge = {0};
+ STSRow* pTSRow = NULL;
-static int32_t loadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
- bool* exists) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- int32_t code = TSDB_CODE_SUCCESS;
- bool asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
+ SBlockData* pBlockData = &pReader->status.fileBlockData;
+ SArray* pDelList = pBlockScanInfo->delSkyline;
- if (asc) {
- // query ended in/started from current block
- if (pTsdbReadHandle->window.ekey < pBlock->maxKey.ts || pCheckInfo->lastKey > pBlock->minKey.ts) {
- if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
- *exists = false;
- return code;
- }
+ TSDBROW* pRow = getValidRow(&pBlockScanInfo->iter, pDelList, pReader);
+ TSDBROW* piRow = getValidRow(&pBlockScanInfo->iiter, pDelList, pReader);
+ ASSERT(pRow != NULL && piRow != NULL);
- SDataCols* pTSCol = pTsdbReadHandle->rhelper.pDCols[0];
- assert(pTSCol->cols->type == TSDB_DATA_TYPE_TIMESTAMP && pTSCol->numOfRows == pBlock->numOfRows);
+ int64_t key = pBlockData->aTSKEY[pDumpInfo->rowIndex];
- if (pCheckInfo->lastKey > pBlock->minKey.ts) {
- cur->pos =
- binarySearchForKey(pTSCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
- } else {
- cur->pos = 0;
- }
+ uint64_t uid = pBlockScanInfo->uid;
- assert(pCheckInfo->lastKey <= pBlock->maxKey.ts);
- doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
- } else { // the whole block is loaded in to buffer
- cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
- code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
- }
- } else { // desc order, query ended in current block
- if (pTsdbReadHandle->window.ekey > pBlock->minKey.ts || pCheckInfo->lastKey < pBlock->maxKey.ts) {
- if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
- *exists = false;
- return code;
- }
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ TSDBKEY ik = TSDBROW_KEY(piRow);
- SDataCols* pTsCol = pTsdbReadHandle->rhelper.pDCols[0];
- if (pCheckInfo->lastKey < pBlock->maxKey.ts) {
- cur->pos =
- binarySearchForKey(pTsCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
- } else {
- cur->pos = pBlock->numOfRows - 1;
+ if (ASCENDING_TRAVERSE(pReader->order)) {
+ // [1&2] key <= [k.ts && ik.ts]
+ if (key <= k.ts && key <= ik.ts) {
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
+
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+
+ if (ik.ts == key) {
+ tRowMerge(&merge, piRow);
+ doMergeRowsInBuf(&pBlockScanInfo->iiter, key, pBlockScanInfo->delSkyline, &merge, pReader);
}
- assert(pCheckInfo->lastKey >= pBlock->minKey.ts);
- doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
- } else {
- cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
- code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
- }
- }
+ if (k.ts == key) {
+ tRowMerge(&merge, pRow);
+ doMergeRowsInBuf(&pBlockScanInfo->iter, key, pBlockScanInfo->delSkyline, &merge, pReader);
+ }
- *exists = pTsdbReadHandle->realNumOfRows > 0;
- return code;
-}
+ tRowMergerGetRow(&merge, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
+ } else { // key > ik.ts || key > k.ts
+ ASSERT(key != ik.ts);
+
+ // [3] ik.ts < key <= k.ts
+ // [4] ik.ts < k.ts <= key
+ if (ik.ts < k.ts) {
+ doMergeMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, &pTSRow, pReader);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
+ }
-static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
- int firstPos, lastPos, midPos = -1;
- int numOfRows;
- TSKEY* keyList;
+ // [5] k.ts < key <= ik.ts
+ // [6] k.ts < ik.ts <= key
+ if (k.ts < ik.ts) {
+ doMergeMultiRows(pRow, uid, &pBlockScanInfo->iter, pDelList, &pTSRow, pReader);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
+ }
- assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
+ // [7] k.ts == ik.ts < key
+ if (k.ts == ik.ts) {
+ ASSERT(key > ik.ts && key > k.ts);
- if (num <= 0) return -1;
+ doMergeMemIMemRows(pRow, piRow, pBlockScanInfo, pReader, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+ } else { // descending order scan
+ // [1/2] k.ts >= ik.ts && k.ts >= key
+ if (k.ts >= ik.ts && k.ts >= key) {
+ updateSchema(pRow, uid, pReader);
- keyList = (TSKEY*)pValue;
- firstPos = 0;
- lastPos = num - 1;
+ tRowMergerInit(&merge, pRow, pReader->pSchema);
+ doMergeRowsInBuf(&pBlockScanInfo->iter, key, pBlockScanInfo->delSkyline, &merge, pReader);
- if (order == TSDB_ORDER_DESC) {
- // find the first position which is smaller than the key
- while (1) {
- if (key >= keyList[lastPos]) return lastPos;
- if (key == keyList[firstPos]) return firstPos;
- if (key < keyList[firstPos]) return firstPos - 1;
+ if (ik.ts == k.ts) {
+ tRowMerge(&merge, piRow);
+ doMergeRowsInBuf(&pBlockScanInfo->iiter, key, pBlockScanInfo->delSkyline, &merge, pReader);
+ }
- numOfRows = lastPos - firstPos + 1;
- midPos = (numOfRows >> 1) + firstPos;
+ if (k.ts == key) {
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ tRowMerge(&merge, &fRow);
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ }
- if (key < keyList[midPos]) {
- lastPos = midPos - 1;
- } else if (key > keyList[midPos]) {
- firstPos = midPos + 1;
- } else {
- break;
+ tRowMergerGetRow(&merge, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
+ } else {
+ ASSERT(ik.ts != k.ts); // this case has been included in the previous if branch
+
+ // [3] ik.ts > k.ts >= Key
+ // [4] ik.ts > key >= k.ts
+ if (ik.ts > key) {
+ doMergeMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, &pTSRow, pReader);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
}
- }
- } else {
- // find the first position which is bigger than the key
- while (1) {
- if (key <= keyList[firstPos]) return firstPos;
- if (key == keyList[lastPos]) return lastPos;
-
- if (key > keyList[lastPos]) {
- lastPos = lastPos + 1;
- if (lastPos >= num)
- return -1;
- else
- return lastPos;
+ // [5] key > ik.ts > k.ts
+ // [6] key > k.ts > ik.ts
+ if (key > ik.ts) {
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
+
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ tRowMergerGetRow(&merge, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
}
- numOfRows = lastPos - firstPos + 1;
- midPos = (numOfRows >> 1) + firstPos;
+ //[7] key = ik.ts > k.ts
+ if (key == ik.ts) {
+ doMergeMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, &pTSRow, pReader);
- if (key < keyList[midPos]) {
- lastPos = midPos - 1;
- } else if (key > keyList[midPos]) {
- firstPos = midPos + 1;
- } else {
- break;
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ tRowMerge(&merge, &fRow);
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ tRowMergerGetRow(&merge, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+ return TSDB_CODE_SUCCESS;
}
}
}
- return midPos;
+ ASSERT(0);
+ return -1;
}
-static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows,
- int32_t start, int32_t end) {
- SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
- TSKEY* tsArray = pCols->cols[0].pData;
-
- int32_t num = end - start + 1;
- assert(num >= 0);
+static bool isValidFileBlockRow(SBlockData* pBlockData, SFileBlockDumpInfo* pDumpInfo,
+ STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) {
+ // check for version and time range
+ int64_t ver = pBlockData->aVersion[pDumpInfo->rowIndex];
+ if (ver > pReader->verRange.maxVer || ver < pReader->verRange.minVer) {
+ return false;
+ }
- if (num == 0) {
- return numOfRows;
+ int64_t ts = pBlockData->aTSKEY[pDumpInfo->rowIndex];
+ if (ts > pReader->window.ekey || ts < pReader->window.skey) {
+ return false;
}
- bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
- int32_t trueStart = ascScan ? start : end;
- int32_t trueEnd = ascScan ? end : start;
- int32_t step = ascScan ? 1 : -1;
+ TSDBKEY k = {.ts = ts, .version = ver};
+ if (hasBeenDropped(pBlockScanInfo->delSkyline, &pBlockScanInfo->fileDelIndex, &k, pReader->order)) {
+ return false;
+ }
- int32_t requiredNumOfCols = (int32_t)taosArrayGetSize(pTsdbReadHandle->pColumns);
+ return true;
+}
- // data in buffer has greater timestamp, copy data in file block
- int32_t i = 0, j = 0;
- while (i < requiredNumOfCols && j < pCols->numOfCols) {
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
+static bool outOfTimeWindow(int64_t ts, STimeWindow* pWindow) { return (ts > pWindow->ekey) || (ts < pWindow->skey); }
- SDataCol* src = &pCols->cols[j];
- if (src->colId < pColInfo->info.colId) {
- j++;
- continue;
- }
+static int32_t buildComposedDataBlockImpl(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo) {
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
+ SBlockData* pBlockData = &pReader->status.fileBlockData;
- if (!isAllRowsNull(src) && pColInfo->info.colId == src->colId) {
- if (!IS_VAR_DATA_TYPE(pColInfo->info.type)) { // todo opt performance
- // memmove(pData, (char*)src->pData + bytes * start, bytes * num);
- int32_t rowIndex = numOfRows;
- for (int32_t k = trueStart; ((ascScan && k <= trueEnd) || (!ascScan && k >= trueEnd)); k += step, ++rowIndex) {
- SCellVal sVal = {0};
- if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
- TASSERT(0);
- }
+ SRowMerger merge = {0};
+ STSRow* pTSRow = NULL;
- if (sVal.valType == TD_VTYPE_NORM) {
- colDataAppend(pColInfo, rowIndex, sVal.val, false);
- } else {
- colDataAppendNULL(pColInfo, rowIndex);
- }
- }
- } else { // handle the var-string
- int32_t rowIndex = numOfRows;
-
- // todo refactor, only copy one-by-one
- for (int32_t k = trueStart; ((ascScan && k <= trueEnd) || (!ascScan && k >= trueEnd)); k += step, ++rowIndex) {
- SCellVal sVal = {0};
- if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
- TASSERT(0);
- }
+ int64_t key = pBlockData->aTSKEY[pDumpInfo->rowIndex];
+ TSDBROW* pRow = getValidRow(&pBlockScanInfo->iter, pBlockScanInfo->delSkyline, pReader);
+ TSDBROW* piRow = getValidRow(&pBlockScanInfo->iiter, pBlockScanInfo->delSkyline, pReader);
- if (sVal.valType == TD_VTYPE_NORM) {
- colDataAppend(pColInfo, rowIndex, sVal.val, false);
- } else {
- colDataAppendNULL(pColInfo, rowIndex);
- }
- }
- }
+ if (pBlockScanInfo->iter.hasVal && pBlockScanInfo->iiter.hasVal) {
+ return doMergeThreeLevelRows(pReader, pBlockScanInfo);
+ } else {
+ // imem + file
+ if (pBlockScanInfo->iiter.hasVal) {
+ return doMergeBufAndFileRows(pReader, pBlockScanInfo, piRow, pTSRow, &pBlockScanInfo->iiter, key);
+ }
- j++;
- i++;
- } else { // pColInfo->info.colId < src->colId, it is a NULL data
- colDataAppendNNULL(pColInfo, numOfRows, num);
- i++;
+ // mem + file
+ if (pBlockScanInfo->iter.hasVal) {
+ return doMergeBufAndFileRows(pReader, pBlockScanInfo, pRow, pTSRow, &pBlockScanInfo->iter, key);
}
- }
- while (i < requiredNumOfCols) { // the remain columns are all null data
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
- colDataAppendNNULL(pColInfo, numOfRows, num);
- i++;
+ // imem & mem are all empty, only file exist
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
+ tRowMergerInit(&merge, &fRow, pReader->pSchema);
+ doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge);
+ tRowMergerGetRow(&merge, &pTSRow);
+ doAppendOneRow(pReader->pResBlock, pReader, pTSRow);
+
+ return TSDB_CODE_SUCCESS;
}
+}
- pTsdbReadHandle->cur.win.ekey = tsArray[trueEnd];
- pTsdbReadHandle->cur.lastKey = tsArray[trueEnd] + step;
+static int32_t buildComposedDataBlock(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo) {
+ SSDataBlock* pResBlock = pReader->pResBlock;
- return numOfRows + num;
-}
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
+ SBlockData* pBlockData = &pReader->status.fileBlockData;
+ int32_t step = ASCENDING_TRAVERSE(pReader->order) ? 1 : -1;
-/**
- * @brief // TODO fix bug for reverse copy data problem
- * Note: row1 always has high priority
- *
- * @param pTsdbReadHandle
- * @param capacity
- * @param curRow
- * @param row1
- * @param row2
- * @param numOfCols
- * @param uid
- * @param pSchema1
- * @param pSchema2
- * @param update
- * @param lastRowKey
- * @return int32_t The quantity of rows appended
- */
-static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t* curRow, STSRow* row1,
- STSRow* row2, int32_t numOfCols, uint64_t uid, STSchema* pSchema1, STSchema* pSchema2,
- bool update, TSKEY* lastRowKey) {
-#if 1
- STSchema* pSchema;
- STSRow* row;
- int16_t colId;
- int16_t offset;
-
- bool isRow1DataRow = TD_IS_TP_ROW(row1);
- bool isRow2DataRow;
- bool isChosenRowDataRow;
- int32_t chosen_itr;
- SCellVal sVal = {0};
- TSKEY rowKey = TSKEY_INITIAL_VAL;
- int32_t nResult = 0;
- int32_t mergeOption = 0; // 0 discard 1 overwrite 2 merge
-
- // the schema version info is embeded in STSRow
- int32_t numOfColsOfRow1 = 0;
-
- if (pSchema1 == NULL) {
- pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row1));
- }
-
-#ifdef TD_DEBUG_PRINT_ROW
- char flags[70] = {0};
- STsdb* pTsdb = pTsdbReadHandle->rhelper.pRepo;
- snprintf(flags, 70, "%s:%d vgId:%d dir:%s row1%s=NULL,row2%s=NULL", __func__, __LINE__, TD_VID(pTsdb->pVnode),
- pTsdb->dir, row1 ? "!" : "", row2 ? "!" : "");
- tdSRowPrint(row1, pSchema1, flags);
-#endif
+ while (1) {
+ // todo check the validate of row in file block
+ {
+ if (!isValidFileBlockRow(pBlockData, pDumpInfo, pBlockScanInfo, pReader)) {
+ pDumpInfo->rowIndex += step;
- if (isRow1DataRow) {
- numOfColsOfRow1 = schemaNCols(pSchema1);
- } else {
- numOfColsOfRow1 = tdRowGetNCols(row1);
- }
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pReader->status.blockIter);
+ SBlock* pBlock = taosArrayGet(pBlockScanInfo->pBlockList, pFBlock->tbBlockIdx);
- int32_t numOfColsOfRow2 = 0;
- if (row2) {
- isRow2DataRow = TD_IS_TP_ROW(row2);
- if (pSchema2 == NULL) {
- pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row2));
- }
- if (isRow2DataRow) {
- numOfColsOfRow2 = schemaNCols(pSchema2);
- } else {
- numOfColsOfRow2 = tdRowGetNCols(row2);
+ if (pDumpInfo->rowIndex >= pBlock->nRow || pDumpInfo->rowIndex < 0) {
+ setBlockAllDumped(pDumpInfo, pBlock, pReader->order);
+ break;
+ }
+
+ continue;
+ }
}
- }
- int32_t i = 0, j = 0, k = 0;
- while (i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) {
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
+ buildComposedDataBlockImpl(pReader, pBlockScanInfo);
- int32_t colIdOfRow1;
- if (j >= numOfColsOfRow1) {
- colIdOfRow1 = INT32_MAX;
- } else if (isRow1DataRow) {
- colIdOfRow1 = pSchema1->columns[j].colId;
- } else {
- colIdOfRow1 = tdKvRowColIdAt(row1, j);
- }
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pReader->status.blockIter);
+ SBlock* pBlock = taosArrayGet(pBlockScanInfo->pBlockList, pFBlock->tbBlockIdx);
- int32_t colIdOfRow2;
- if (k >= numOfColsOfRow2) {
- colIdOfRow2 = INT32_MAX;
- } else if (isRow2DataRow) {
- colIdOfRow2 = pSchema2->columns[k].colId;
- } else {
- colIdOfRow2 = tdKvRowColIdAt(row2, k);
+ // currently loaded file data block is consumed
+ if (pDumpInfo->rowIndex >= pBlock->nRow || pDumpInfo->rowIndex < 0) {
+ setBlockAllDumped(pDumpInfo, pBlock, pReader->order);
+ break;
}
- if (colIdOfRow1 < colIdOfRow2) { // the most probability
- if (colIdOfRow1 < pColInfo->info.colId) {
- ++j;
- continue;
- }
- row = row1;
- pSchema = pSchema1;
- isChosenRowDataRow = isRow1DataRow;
- chosen_itr = j;
- } else if (colIdOfRow1 == colIdOfRow2) {
- if (colIdOfRow1 < pColInfo->info.colId) {
- ++j;
- ++k;
- continue;
- }
- row = row1;
- pSchema = pSchema1;
- isChosenRowDataRow = isRow1DataRow;
- chosen_itr = j;
- } else {
- if (colIdOfRow2 < pColInfo->info.colId) {
- ++k;
- continue;
- }
- row = row2;
- pSchema = pSchema2;
- chosen_itr = k;
- isChosenRowDataRow = isRow2DataRow;
- }
-
- if (isChosenRowDataRow) {
- colId = pSchema->columns[chosen_itr].colId;
- offset = pSchema->columns[chosen_itr].offset;
- // TODO: use STSRowIter
- tdSTpRowGetVal(row, colId, pSchema->columns[chosen_itr].type, pSchema->flen, offset, chosen_itr - 1, &sVal);
- if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
- rowKey = *(TSKEY*)sVal.val;
- if (rowKey != *lastRowKey) {
- mergeOption = 1;
- if (*lastRowKey != TSKEY_INITIAL_VAL) {
- ++(*curRow);
- }
- *lastRowKey = rowKey;
- ++nResult;
- } else if (update) {
- mergeOption = 2;
- } else {
- mergeOption = 0;
- break;
- }
- }
- } else {
- // TODO: use STSRowIter
- if (chosen_itr == 0) {
- colId = PRIMARYKEY_TIMESTAMP_COL_ID;
- tdSKvRowGetVal(row, PRIMARYKEY_TIMESTAMP_COL_ID, -1, -1, &sVal);
- rowKey = *(TSKEY*)sVal.val;
- if (rowKey != *lastRowKey) {
- mergeOption = 1;
- if (*lastRowKey != TSKEY_INITIAL_VAL) {
- ++(*curRow);
- }
- *lastRowKey = rowKey;
- ++nResult;
- } else if (update) {
- mergeOption = 2;
- } else {
- mergeOption = 0;
- break;
- }
- } else {
- SKvRowIdx* pColIdx = tdKvRowColIdxAt(row, chosen_itr - 1);
- colId = pColIdx->colId;
- offset = pColIdx->offset;
- tdSKvRowGetVal(row, colId, offset, chosen_itr - 1, &sVal);
- }
+ if (pResBlock->info.rows >= pReader->capacity) {
+ break;
}
+ }
- ASSERT(rowKey != TSKEY_INITIAL_VAL);
-
- if (colId == pColInfo->info.colId) {
- if (tdValTypeIsNorm(sVal.valType)) {
- colDataAppend(pColInfo, *curRow, sVal.val, false);
- } else if (tdValTypeIsNull(sVal.valType)) {
- colDataAppend(pColInfo, *curRow, NULL, true);
- } else if (tdValTypeIsNone(sVal.valType)) {
- // TODO: Set null if nothing append for this row
- if (mergeOption == 1) {
- colDataAppend(pColInfo, *curRow, NULL, true);
- }
- } else {
- ASSERT(0);
- }
-
- ++i;
+ pResBlock->info.uid = pBlockScanInfo->uid;
+ blockDataUpdateTsWindow(pResBlock, 0);
- if (row == row1) {
- ++j;
- } else {
- ++k;
- }
- } else {
- if (mergeOption == 1) {
- colDataAppend(pColInfo, *curRow, NULL, true);
- }
- ++i;
- }
- }
+ setComposedBlockFlag(pReader, true);
- if (mergeOption == 1) {
- while (i < numOfCols) { // the remain columns are all null data
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
- colDataAppend(pColInfo, *curRow, NULL, true);
- ++i;
- }
- }
+ tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s", pReader,
+ pBlockScanInfo->uid, pResBlock->info.window.skey, pResBlock->info.window.ekey, pResBlock->info.rows,
+ pReader->idStr);
- return nResult;
-#endif
+ return TSDB_CODE_SUCCESS;
}
-static void getQualifiedRowsPos(STsdbReadHandle* pTsdbReadHandle, int32_t startPos, int32_t endPos,
- int32_t numOfExisted, int32_t* start, int32_t* end) {
- *start = -1;
+void setComposedBlockFlag(STsdbReader* pReader, bool composed) { pReader->status.composedDataBlock = composed; }
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- int32_t remain = endPos - startPos + 1;
- if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
- *end = (pTsdbReadHandle->outputCapacity - numOfExisted) + startPos - 1;
- } else {
- *end = endPos;
- }
+static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) {
+ if (pBlockScanInfo->iterInit) {
+ return TSDB_CODE_SUCCESS;
+ }
- *start = startPos;
- } else {
- int32_t remain = (startPos - endPos) + 1;
- if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
- *end = startPos + 1 - (pTsdbReadHandle->outputCapacity - numOfExisted);
- } else {
- *end = endPos;
- }
+ int32_t code = TSDB_CODE_SUCCESS;
- *start = *end;
- *end = startPos;
+ TSDBKEY startKey = {0};
+ if (ASCENDING_TRAVERSE(pReader->order)) {
+ startKey = (TSDBKEY){.ts = pReader->window.skey, .version = pReader->verRange.minVer};
+ } else {
+ startKey = (TSDBKEY){.ts = pReader->window.ekey, .version = pReader->verRange.maxVer};
}
-}
-
-static void updateInfoAfterMerge(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, int32_t numOfRows,
- int32_t endPos) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- pCheckInfo->lastKey = cur->lastKey;
- pTsdbReadHandle->realNumOfRows = numOfRows;
- cur->rows = numOfRows;
- cur->pos = endPos;
-}
+ int32_t backward = (!ASCENDING_TRAVERSE(pReader->order));
-static void doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
+ STbData* d = NULL;
+ if (pReader->pTsdb->mem != NULL) {
+ tsdbGetTbDataFromMemTable(pReader->pTsdb->mem, pReader->suid, pBlockScanInfo->uid, &d);
+ if (d != NULL) {
+ code = tsdbTbDataIterCreate(d, &startKey, backward, &pBlockScanInfo->iter.iter);
+ if (code == TSDB_CODE_SUCCESS) {
+ pBlockScanInfo->iter.hasVal = (tsdbTbDataIterGet(pBlockScanInfo->iter.iter) != NULL);
- if (cur->rows > 0) {
- if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
- assert(cur->win.skey >= pTsdbReadHandle->window.skey && cur->win.ekey <= pTsdbReadHandle->window.ekey);
- } else {
- assert(cur->win.skey >= pTsdbReadHandle->window.ekey && cur->win.ekey <= pTsdbReadHandle->window.skey);
+ tsdbDebug("%p uid:%" PRId64 ", check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
+ "-%" PRId64 " %s",
+ pReader, pBlockScanInfo->uid, startKey.ts, pReader->order, d->minKey, d->maxKey, pReader->idStr);
+ } else {
+ tsdbError("%p uid:%" PRId64 ", failed to create iterator for imem, code:%s, %s", pReader, pBlockScanInfo->uid,
+ tstrerror(code), pReader->idStr);
+ return code;
+ }
}
-
- SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, 0);
- assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] &&
- cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows - 1]);
} else {
- cur->win = pTsdbReadHandle->window;
-
- int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
- cur->lastKey = pTsdbReadHandle->window.ekey + step;
+ tsdbDebug("%p uid:%" PRId64 ", no data in mem, %s", pReader, pBlockScanInfo->uid, pReader->idStr);
}
-}
-static void copyAllRemainRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo,
- SDataBlockInfo* pBlockInfo, int32_t endPos) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
+ STbData* di = NULL;
+ if (pReader->pTsdb->imem != NULL) {
+ tsdbGetTbDataFromMemTable(pReader->pTsdb->imem, pReader->suid, pBlockScanInfo->uid, &di);
+ if (di != NULL) {
+ code = tsdbTbDataIterCreate(di, &startKey, backward, &pBlockScanInfo->iiter.iter);
+ if (code == TSDB_CODE_SUCCESS) {
+ pBlockScanInfo->iiter.hasVal = (tsdbTbDataIterGet(pBlockScanInfo->iiter.iter) != NULL);
- SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
- TSKEY* tsArray = pCols->cols[0].pData;
-
- bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
+ tsdbDebug("%p uid:%" PRId64 ", check data in imem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
+ "-%" PRId64 " %s",
+ pReader, pBlockScanInfo->uid, startKey.ts, pReader->order, di->minKey, di->maxKey, pReader->idStr);
+ } else {
+ tsdbError("%p uid:%" PRId64 ", failed to create iterator for mem, code:%s, %s", pReader, pBlockScanInfo->uid,
+ tstrerror(code), pReader->idStr);
+ return code;
+ }
+ }
+ } else {
+ tsdbDebug("%p uid:%" PRId64 ", no data in imem, %s", pReader, pBlockScanInfo->uid, pReader->idStr);
+ }
- int32_t step = ascScan ? 1 : -1;
+ initDelSkylineIterator(pBlockScanInfo, pReader, d, di);
- int32_t start = cur->pos;
- int32_t end = endPos;
+ pBlockScanInfo->iterInit = true;
+ return TSDB_CODE_SUCCESS;
+}
- if (!ascScan) {
- TSWAP(start, end);
+int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, STbData* pMemTbData,
+ STbData* piMemTbData) {
+ if (pBlockScanInfo->delSkyline != NULL) {
+ return TSDB_CODE_SUCCESS;
}
- assert(pTsdbReadHandle->outputCapacity >= (end - start + 1));
- int32_t numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, start, end);
+ int32_t code = 0;
+ STsdb* pTsdb = pReader->pTsdb;
- // the time window should always be ascending order: skey <= ekey
- cur->win = (STimeWindow){.skey = tsArray[start], .ekey = tsArray[end]};
- cur->mixBlock = (numOfRows != pBlockInfo->rows);
- cur->lastKey = tsArray[endPos] + step;
- cur->blockCompleted = (ascScan ? (endPos == pBlockInfo->rows - 1) : (endPos == 0));
+ SArray* pDelData = taosArrayInit(4, sizeof(SDelData));
- // The value of pos may be -1 or pBlockInfo->rows, and it is invalid in both cases.
- int32_t pos = endPos + step;
- updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
- doCheckGeneratedBlockRange(pTsdbReadHandle);
+ SDelFile* pDelFile = tsdbFSStateGetDelFile(pTsdb->fs->cState);
+ if (pDelFile) {
+ SDelFReader* pDelFReader = NULL;
+ code = tsdbDelFReaderOpen(&pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) {
+ goto _err;
+ }
- tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
- pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
- pTsdbReadHandle->idStr);
-}
+ SArray* aDelIdx = taosArrayInit(4, sizeof(SDelIdx));
+ if (aDelIdx == NULL) {
+ goto _err;
+ }
-int32_t getEndPosInDataBlock(STsdbReadHandle* pTsdbReadHandle, SDataBlockInfo* pBlockInfo) {
- // NOTE: reverse the order to find the end position in data block
- int32_t endPos = -1;
- bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
- int32_t order = ascScan ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
+ code = tsdbReadDelIdx(pDelFReader, aDelIdx, NULL);
+ if (code) {
+ goto _err;
+ }
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
+ SDelIdx idx = {.suid = pReader->suid, .uid = pBlockScanInfo->uid};
+ SDelIdx* pIdx = taosArraySearch(aDelIdx, &idx, tCmprDelIdx, TD_EQ);
- if (pTsdbReadHandle->outputCapacity >= pBlockInfo->rows) {
- if (ascScan && pTsdbReadHandle->window.ekey >= pBlockInfo->window.ekey) {
- endPos = pBlockInfo->rows - 1;
- cur->mixBlock = (cur->pos != 0);
- } else if ((!ascScan) && pTsdbReadHandle->window.ekey <= pBlockInfo->window.skey) {
- endPos = 0;
- cur->mixBlock = (cur->pos != pBlockInfo->rows - 1);
- } else {
- assert(pCols->numOfRows > 0);
- endPos = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, pTsdbReadHandle->window.ekey, order);
- cur->mixBlock = true;
- }
- } else {
- if (ascScan && pTsdbReadHandle->window.ekey >= pBlockInfo->window.ekey) {
- endPos = TMIN(cur->pos + pTsdbReadHandle->outputCapacity - 1, pBlockInfo->rows - 1);
- } else if ((!ascScan) && pTsdbReadHandle->window.ekey <= pBlockInfo->window.skey) {
- endPos = TMAX(cur->pos - pTsdbReadHandle->outputCapacity + 1, 0);
- } else {
- ASSERT(pCols->numOfRows > 0);
- endPos = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, pTsdbReadHandle->window.ekey, order);
-
- // current data is more than the capacity
- int32_t size = abs(cur->pos - endPos) + 1;
- if (size > pTsdbReadHandle->outputCapacity) {
- int32_t delta = size - pTsdbReadHandle->outputCapacity;
- if (ascScan) {
- endPos -= delta;
- } else {
- endPos += delta;
- }
- }
+ code = tsdbReadDelData(pDelFReader, pIdx, pDelData, NULL);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _err;
}
- cur->mixBlock = true;
}
- return endPos;
-}
+ SDelData* p = NULL;
+ if (pMemTbData != NULL) {
+ p = pMemTbData->pHead;
+ while (p) {
+ taosArrayPush(pDelData, p);
+ p = p->pNext;
+ }
+ }
-// only return the qualified data to client in terms of query time window, data rows in the same block but do not
-// be included in the query time window will be discarded
-static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock) {
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
- STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
+ if (piMemTbData != NULL) {
+ p = piMemTbData->pHead;
+ while (p) {
+ taosArrayPush(pDelData, p);
+ p = p->pNext;
+ }
+ }
- initTableMemIterator(pTsdbReadHandle, pCheckInfo);
+ if (taosArrayGetSize(pDelData) > 0) {
+ pBlockScanInfo->delSkyline = taosArrayInit(4, sizeof(TSDBKEY));
+ code = tsdbBuildDeleteSkyline(pDelData, 0, (int32_t)(taosArrayGetSize(pDelData) - 1), pBlockScanInfo->delSkyline);
+ }
- SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
- assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_ID &&
- cur->pos >= 0 && cur->pos < pBlock->numOfRows);
- // Even Multi-Version supported, the records with duplicated TSKEY would be merged inside of tsdbLoadData interface.
- TSKEY* tsArray = pCols->cols[0].pData;
- assert(pCols->numOfRows == pBlock->numOfRows && tsArray[0] == pBlock->minKey.ts &&
- tsArray[pBlock->numOfRows - 1] == pBlock->maxKey.ts);
+ taosArrayDestroy(pDelData);
+ pBlockScanInfo->iter.index =
+ ASCENDING_TRAVERSE(pReader->order) ? 0 : taosArrayGetSize(pBlockScanInfo->delSkyline) - 1;
+ pBlockScanInfo->iiter.index = pBlockScanInfo->iter.index;
+ pBlockScanInfo->fileDelIndex = pBlockScanInfo->iter.index;
+ return code;
- bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
- int32_t step = ascScan ? 1 : -1;
+_err:
+ taosArrayDestroy(pDelData);
+ return code;
+}
- // for search the endPos, so the order needs to reverse
- int32_t order = ascScan ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
+static TSDBKEY getCurrentKeyInBuf(SDataBlockIter* pBlockIter, STsdbReader* pReader) {
+ TSDBKEY key = {.ts = TSKEY_INITIAL_VAL};
- int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
- int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &blockInfo);
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ STableBlockScanInfo* pScanInfo = taosHashGet(pReader->status.pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
- STimeWindow* pWin = &blockInfo.window;
- tsdbDebug("%p uid:%" PRIu64 " start merge data block, file block range:%" PRIu64 "-%" PRIu64
- " rows:%d, start:%d, end:%d, %s",
- pTsdbReadHandle, pCheckInfo->tableId, pWin->skey, pWin->ekey, blockInfo.rows, cur->pos, endPos,
- pTsdbReadHandle->idStr);
+ initMemDataIterator(pScanInfo, pReader);
+ TSDBROW* pRow = getValidRow(&pScanInfo->iter, pScanInfo->delSkyline, pReader);
+ if (pRow != NULL) {
+ key = TSDBROW_KEY(pRow);
+ }
- // compared with the data from in-memory buffer, to generate the correct timestamp array list
- int32_t numOfRows = 0;
- int32_t curRow = 0;
+ pRow = getValidRow(&pScanInfo->iiter, pScanInfo->delSkyline, pReader);
+ if (pRow != NULL) {
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ if (key.ts > k.ts) {
+ key = k;
+ }
+ }
- int16_t rv1 = -1;
- int16_t rv2 = -1;
- STSchema* pSchema1 = NULL;
- STSchema* pSchema2 = NULL;
+ return key;
+}
- int32_t pos = cur->pos;
- cur->win = TSWINDOW_INITIALIZER;
- bool adjustPos = false;
+static int32_t moveToNextFile(STsdbReader* pReader, int32_t* numOfBlocks) {
+ SReaderStatus* pStatus = &pReader->status;
+ SArray* pIndexList = taosArrayInit(4, sizeof(SBlockIdx));
- // no data in buffer, load data from file directly
- if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) {
- copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &blockInfo, endPos);
- return;
- } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) {
- SSkipListNode* node = NULL;
- TSKEY lastKeyAppend = TSKEY_INITIAL_VAL;
-
- do {
- STSRow* row2 = NULL;
- STSRow* row1 = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, &row2, TD_VER_MAX);
- if (row1 == NULL) {
- break;
- }
+ while (1) {
+ bool hasNext = filesetIteratorNext(&pStatus->fileIter, pReader);
+ if (!hasNext) { // no data files on disk
+ break;
+ }
- TSKEY key = TD_ROW_KEY(row1);
- if ((key > pTsdbReadHandle->window.ekey && ascScan) || (key < pTsdbReadHandle->window.ekey && !ascScan)) {
- break;
- }
+ taosArrayClear(pIndexList);
+ int32_t code = doLoadBlockIndex(pReader, pReader->pFileReader, pIndexList);
+ if (code != TSDB_CODE_SUCCESS) {
+ taosArrayDestroy(pIndexList);
+ return code;
+ }
- if (adjustPos) {
- if (key == lastKeyAppend) {
- pos -= step;
- }
- adjustPos = false;
+ if (taosArrayGetSize(pIndexList) > 0) {
+ uint32_t numOfValidTable = 0;
+ code = doLoadFileBlock(pReader, pIndexList, &numOfValidTable, numOfBlocks);
+ if (code != TSDB_CODE_SUCCESS) {
+ taosArrayDestroy(pIndexList);
+ return code;
}
- if (((pos > endPos || tsArray[pos] > pTsdbReadHandle->window.ekey) && ascScan) ||
- ((pos < endPos || tsArray[pos] < pTsdbReadHandle->window.ekey) && !ascScan)) {
+ if (numOfValidTable > 0) {
break;
}
+ }
+ // no blocks in current file, try next files
+ }
- if ((key < tsArray[pos] && ascScan) || (key > tsArray[pos] && !ascScan)) {
- if (rv1 != TD_ROW_SVER(row1)) {
- // pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
- rv1 = TD_ROW_SVER(row1);
- }
- if (row2 && rv2 != TD_ROW_SVER(row2)) {
- // pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
- rv2 = TD_ROW_SVER(row2);
- }
-
- numOfRows +=
- mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols,
- pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastKeyAppend);
- if (cur->win.skey == TSKEY_INITIAL_VAL) {
- cur->win.skey = key;
- }
-
- cur->win.ekey = key;
- cur->lastKey = key + step;
- cur->mixBlock = true;
- moveToNextRowInMem(pCheckInfo);
- } else if (key == tsArray[pos]) { // data in buffer has the same timestamp of data in file block, ignore it
-#if 0
- if (pCfg->update) {
- if (pCfg->update == TD_ROW_PARTIAL_UPDATE) {
- doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, pos, pos);
- }
- if (rv1 != TD_ROW_SVER(row1)) {
- // pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
- rv1 = TD_ROW_SVER(row1);
- }
- if (row2 && rv2 != TD_ROW_SVER(row2)) {
- // pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
- rv2 = TD_ROW_SVER(row2);
- }
+ taosArrayDestroy(pIndexList);
+ return TSDB_CODE_SUCCESS;
+}
- bool forceSetNull = pCfg->update != TD_ROW_PARTIAL_UPDATE;
- mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
- pCheckInfo->tableId, pSchema1, pSchema2, forceSetNull, &lastRowKey);
- numOfRows += 1;
- if (cur->win.skey == TSKEY_INITIAL_VAL) {
- cur->win.skey = key;
- }
+static int32_t doBuildDataBlock(STsdbReader* pReader) {
+ int32_t code = TSDB_CODE_SUCCESS;
- cur->win.ekey = key;
- cur->lastKey = key + step;
- cur->mixBlock = true;
+ SReaderStatus* pStatus = &pReader->status;
+ SDataBlockIter* pBlockIter = &pStatus->blockIter;
- moveToNextRowInMem(pCheckInfo);
- pos += step;
- } else {
- moveToNextRowInMem(pCheckInfo);
- }
-#endif
- if (TD_SUPPORT_UPDATE(pCfg->update)) {
- if (lastKeyAppend != key) {
- if (lastKeyAppend != TSKEY_INITIAL_VAL) {
- ++curRow;
- }
- lastKeyAppend = key;
- }
- // load data from file firstly
- numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, curRow, pos, pos);
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ STableBlockScanInfo* pScanInfo = taosHashGet(pStatus->pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
- if (rv1 != TD_ROW_SVER(row1)) {
- rv1 = TD_ROW_SVER(row1);
- }
- if (row2 && rv2 != TD_ROW_SVER(row2)) {
- rv2 = TD_ROW_SVER(row2);
- }
+ SBlock* pBlock = taosArrayGet(pScanInfo->pBlockList, pFBlock->tbBlockIdx);
- // still assign data into current row
- numOfRows +=
- mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols,
- pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastKeyAppend);
+ TSDBKEY key = getCurrentKeyInBuf(pBlockIter, pReader);
+ if (fileBlockShouldLoad(pReader, pFBlock, pBlock, pScanInfo, key)) {
+ tBlockDataInit(&pStatus->fileBlockData);
+ code = doLoadFileBlockData(pReader, pBlockIter, pScanInfo, &pStatus->fileBlockData);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
- if (cur->win.skey == TSKEY_INITIAL_VAL) {
- cur->win.skey = key;
- }
+ // build composed data block
+ code = buildComposedDataBlock(pReader, pScanInfo);
+ } else if (bufferDataInFileBlockGap(pReader->order, key, pBlock)) {
+ // data in memory that are earlier than current file block
+ // todo rows in buffer should be less than the file block in asc, greater than file block in desc
+ int64_t endKey = (ASCENDING_TRAVERSE(pReader->order)) ? pBlock->minKey.ts : pBlock->maxKey.ts;
+ code = buildDataBlockFromBuf(pReader, pScanInfo, endKey);
+ } else { // whole block is required, return it directly
+ SDataBlockInfo* pInfo = &pReader->pResBlock->info;
+ pInfo->rows = pBlock->nRow;
+ pInfo->uid = pScanInfo->uid;
+ pInfo->window = (STimeWindow){.skey = pBlock->minKey.ts, .ekey = pBlock->maxKey.ts};
+ setComposedBlockFlag(pReader, false);
+ setBlockAllDumped(&pStatus->fBlockDumpInfo, pBlock, pReader->order);
+ }
- cur->win.ekey = key;
- cur->lastKey = key + step;
- cur->mixBlock = true;
+ return code;
+}
- moveToNextRowInMem(pCheckInfo);
+static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) {
+ SReaderStatus* pStatus = &pReader->status;
- pos += step;
- adjustPos = true;
- } else {
- // discard the memory record
- moveToNextRowInMem(pCheckInfo);
- }
- } else if ((key > tsArray[pos] && ascScan) || (key < tsArray[pos] && !ascScan)) {
- if (cur->win.skey == TSKEY_INITIAL_VAL) {
- cur->win.skey = tsArray[pos];
- }
+ while (1) {
+ if (pStatus->pTableIter == NULL) {
+ pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, NULL);
+ if (pStatus->pTableIter == NULL) {
+ return TSDB_CODE_SUCCESS;
+ }
+ }
- int32_t end = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, key, order);
- assert(end != -1);
+ STableBlockScanInfo* pBlockScanInfo = pStatus->pTableIter;
+ initMemDataIterator(pBlockScanInfo, pReader);
- if (tsArray[end] == key) { // the value of key in cache equals to the end timestamp value, ignore it
-#if 0
- if (pCfg->update == TD_ROW_DISCARD_UPDATE) {
- moveToNextRowInMem(pCheckInfo);
- } else {
- end -= step;
- }
-#endif
- if (!TD_SUPPORT_UPDATE(pCfg->update)) {
- moveToNextRowInMem(pCheckInfo);
- } else {
- end -= step;
- }
- }
+ int64_t endKey = (ASCENDING_TRAVERSE(pReader->order)) ? INT64_MAX : INT64_MIN;
+ int32_t code = buildDataBlockFromBuf(pReader, pBlockScanInfo, endKey);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
- int32_t qstart = 0, qend = 0;
- getQualifiedRowsPos(pTsdbReadHandle, pos, end, numOfRows, &qstart, &qend);
+ if (pReader->pResBlock->info.rows > 0) {
+ return TSDB_CODE_SUCCESS;
+ }
- if ((lastKeyAppend != TSKEY_INITIAL_VAL) && (lastKeyAppend != (ascScan ? tsArray[qstart] : tsArray[qend]))) {
- ++curRow;
- }
+ // current table is exhausted, let's try the next table
+ pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, pStatus->pTableIter);
+ if (pStatus->pTableIter == NULL) {
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+}
- numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, curRow, qstart, qend);
- pos += (qend - qstart + 1) * step;
- if (numOfRows > 0) {
- curRow = numOfRows - 1;
- }
+// set the correct start position in case of the first/last file block, according to the query time window
+static void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) {
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ STableBlockScanInfo* pScanInfo = taosHashGet(pReader->status.pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
+ SBlock* pBlock = taosArrayGet(pScanInfo->pBlockList, pFBlock->tbBlockIdx);
- cur->win.ekey = ascScan ? tsArray[qend] : tsArray[qstart];
- cur->lastKey = cur->win.ekey + step;
- lastKeyAppend = cur->win.ekey;
- }
- } while (numOfRows < pTsdbReadHandle->outputCapacity);
-
- if (numOfRows < pTsdbReadHandle->outputCapacity) {
- /**
- * if cache is empty, load remain file block data. In contrast, if there are remain data in cache, do NOT
- * copy them all to result buffer, since it may be overlapped with file data block.
- */
- if (node == NULL || ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) > pTsdbReadHandle->window.ekey) && ascScan) ||
- ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) < pTsdbReadHandle->window.ekey) && !ascScan)) {
- // no data in cache or data in cache is greater than the ekey of time window, load data from file block
- if (cur->win.skey == TSKEY_INITIAL_VAL) {
- cur->win.skey = tsArray[pos];
- }
+ SReaderStatus* pStatus = &pReader->status;
- int32_t start = -1, end = -1;
- getQualifiedRowsPos(pTsdbReadHandle, pos, endPos, numOfRows, &start, &end);
+ SFileBlockDumpInfo* pDumpInfo = &pStatus->fBlockDumpInfo;
- numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, start, end);
- pos += (end - start + 1) * step;
+ pDumpInfo->totalRows = pBlock->nRow;
+ pDumpInfo->allDumped = false;
+ pDumpInfo->rowIndex = ASCENDING_TRAVERSE(pReader->order) ? 0 : pBlock->nRow - 1;
+}
- cur->win.ekey = ascScan ? tsArray[end] : tsArray[start];
- cur->lastKey = cur->win.ekey + step;
- cur->mixBlock = true;
- }
- }
+static int32_t initForFirstBlockInFile(STsdbReader* pReader, SDataBlockIter* pBlockIter) {
+ int32_t numOfBlocks = 0;
+ int32_t code = moveToNextFile(pReader, &numOfBlocks);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
}
- cur->blockCompleted = (((pos > endPos || cur->lastKey > pTsdbReadHandle->window.ekey) && ascScan) ||
- ((pos < endPos || cur->lastKey < pTsdbReadHandle->window.ekey) && !ascScan));
-
- if (!ascScan) {
- TSWAP(cur->win.skey, cur->win.ekey);
+ // all data files are consumed, try data in buffer
+ if (numOfBlocks == 0) {
+ pReader->status.loadFromFile = false;
+ return code;
}
- updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
- doCheckGeneratedBlockRange(pTsdbReadHandle);
+ // initialize the block iterator for a new fileset
+ code = initBlockIterator(pReader, pBlockIter, numOfBlocks);
- tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
- pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
- pTsdbReadHandle->idStr);
+ // set the correct start position according to the query time window
+ initBlockDumpInfo(pReader, pBlockIter);
+ return code;
}
-int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
- int firstPos, lastPos, midPos = -1;
- int numOfRows;
- TSKEY* keyList;
+static bool fileBlockPartiallyRead(SFileBlockDumpInfo* pDumpInfo, bool asc) {
+ return (!pDumpInfo->allDumped) &&
+ ((pDumpInfo->rowIndex > 0 && asc) || (pDumpInfo->rowIndex < (pDumpInfo->totalRows - 1) && (!asc)));
+}
- if (num <= 0) return -1;
+static int32_t buildBlockFromFiles(STsdbReader* pReader) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ bool asc = ASCENDING_TRAVERSE(pReader->order);
- keyList = (TSKEY*)pValue;
- firstPos = 0;
- lastPos = num - 1;
+ SDataBlockIter* pBlockIter = &pReader->status.blockIter;
- if (order == TSDB_ORDER_DESC) {
- // find the first position which is smaller than the key
- while (1) {
- if (key >= keyList[lastPos]) return lastPos;
- if (key == keyList[firstPos]) return firstPos;
- if (key < keyList[firstPos]) return firstPos - 1;
+ while (1) {
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pReader->status.blockIter);
+ STableBlockScanInfo* pScanInfo = taosHashGet(pReader->status.pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
- numOfRows = lastPos - firstPos + 1;
- midPos = (numOfRows >> 1) + firstPos;
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
- if (key < keyList[midPos]) {
- lastPos = midPos - 1;
- } else if (key > keyList[midPos]) {
- firstPos = midPos + 1;
- } else {
- break;
+ if (fileBlockPartiallyRead(pDumpInfo, asc)) { // file data block is partially loaded
+ code = buildComposedDataBlock(pReader, pScanInfo);
+ } else {
+ // current block are exhausted, try the next file block
+ if (pDumpInfo->allDumped) {
+ // try next data block in current file
+ bool hasNext = blockIteratorNext(&pReader->status.blockIter);
+ if (hasNext) { // check for the next block in the block accessed order list
+ initBlockDumpInfo(pReader, pBlockIter);
+ } else { // data blocks in current file are exhausted, let's try the next file now
+ code = initForFirstBlockInFile(pReader, pBlockIter);
+
+ // error happens or all the data files are completely checked
+ if ((code != TSDB_CODE_SUCCESS) || (pReader->status.loadFromFile == false)) {
+ return code;
+ }
+ }
}
+
+ // current block is not loaded yet, or data in buffer may overlap with the file block.
+ code = doBuildDataBlock(pReader);
}
- } else {
- // find the first position which is bigger than the key
- while (1) {
- if (key <= keyList[firstPos]) return firstPos;
- if (key == keyList[lastPos]) return lastPos;
-
- if (key > keyList[lastPos]) {
- lastPos = lastPos + 1;
- if (lastPos >= num)
- return -1;
- else
- return lastPos;
- }
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
- numOfRows = lastPos - firstPos + 1;
- midPos = (numOfRows >> 1) + firstPos;
+ if (pReader->pResBlock->info.rows > 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+}
- if (key < keyList[midPos]) {
- lastPos = midPos - 1;
- } else if (key > keyList[midPos]) {
- firstPos = midPos + 1;
- } else {
+static STsdb* getTsdbByRetentions(SVnode* pVnode, TSKEY winSKey, SRetention* retentions, const char* idStr,
+ int8_t* pLevel) {
+ if (VND_IS_RSMA(pVnode)) {
+ int8_t level = 0;
+ int64_t now = taosGetTimestamp(pVnode->config.tsdbCfg.precision);
+
+ for (int8_t i = 0; i < TSDB_RETENTION_MAX; ++i) {
+ SRetention* pRetention = retentions + level;
+ if (pRetention->keep <= 0) {
+ if (level > 0) {
+ --level;
+ }
break;
}
+ if ((now - pRetention->keep) <= winSKey) {
+ break;
+ }
+ ++level;
+ }
+
+ int32_t vgId = TD_VID(pVnode);
+ const char* str = (idStr != NULL) ? idStr : "";
+
+ if (level == TSDB_RETENTION_L0) {
+ *pLevel = TSDB_RETENTION_L0;
+ tsdbDebug("vgId:%d, rsma level %d is selected to query %s", vgId, TSDB_RETENTION_L0, str);
+ return VND_RSMA0(pVnode);
+ } else if (level == TSDB_RETENTION_L1) {
+ *pLevel = TSDB_RETENTION_L1;
+ tsdbDebug("vgId:%d, rsma level %d is selected to query %s", vgId, TSDB_RETENTION_L1, str);
+ return VND_RSMA1(pVnode);
+ } else {
+ *pLevel = TSDB_RETENTION_L2;
+ tsdbDebug("vgId:%d, rsma level %d is selected to query %s", vgId, TSDB_RETENTION_L2, str);
+ return VND_RSMA2(pVnode);
}
}
- return midPos;
+ return VND_TSDB(pVnode);
}
-static void cleanBlockOrderSupporter(SBlockOrderSupporter* pSupporter, int32_t numOfTables) {
- taosMemoryFreeClear(pSupporter->numOfBlocksPerTable);
- taosMemoryFreeClear(pSupporter->blockIndexArray);
+SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level) {
+ int64_t startVer = (pCond->startVersion == -1) ? 0 : pCond->startVersion;
- for (int32_t i = 0; i < numOfTables; ++i) {
- STableBlockInfo* pBlockInfo = pSupporter->pDataBlockInfo[i];
- taosMemoryFreeClear(pBlockInfo);
+ if (VND_IS_RSMA(pVnode)) {
+ return (SVersionRange){.minVer = startVer, .maxVer = tdRSmaGetMaxSubmitVer(pVnode->pSma, level)};
}
- taosMemoryFreeClear(pSupporter->pDataBlockInfo);
-}
+ int64_t endVer = 0;
+ if (pCond->endVersion ==
+ -1) { // user not specified end version, set current maximum version of vnode as the endVersion
+ endVer = pVnode->state.applied;
+ } else {
+ endVer = (pCond->endVersion > pVnode->state.applied) ? pVnode->state.applied : pCond->endVersion;
+ }
-static int32_t dataBlockOrderCompar(const void* pLeft, const void* pRight, void* param) {
- int32_t leftTableIndex = *(int32_t*)pLeft;
- int32_t rightTableIndex = *(int32_t*)pRight;
+ return (SVersionRange){.minVer = startVer, .maxVer = endVer};
+}
- SBlockOrderSupporter* pSupporter = (SBlockOrderSupporter*)param;
+// // todo not unref yet, since it is not support multi-group interpolation query
+// static UNUSED_FUNC void changeQueryHandleForInterpQuery(STsdbReader* pHandle) {
+// // filter the queried time stamp in the first place
+// STsdbReader* pTsdbReadHandle = (STsdbReader*)pHandle;
- int32_t leftTableBlockIndex = pSupporter->blockIndexArray[leftTableIndex];
- int32_t rightTableBlockIndex = pSupporter->blockIndexArray[rightTableIndex];
+// // starts from the buffer in case of descending timestamp order check data blocks
+// size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- if (leftTableBlockIndex > pSupporter->numOfBlocksPerTable[leftTableIndex]) {
- /* left block is empty */
- return 1;
- } else if (rightTableBlockIndex > pSupporter->numOfBlocksPerTable[rightTableIndex]) {
- /* right block is empty */
- return -1;
- }
+// int32_t i = 0;
+// while (i < numOfTables) {
+// STableBlockScanInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
- STableBlockInfo* pLeftBlockInfoEx = &pSupporter->pDataBlockInfo[leftTableIndex][leftTableBlockIndex];
- STableBlockInfo* pRightBlockInfoEx = &pSupporter->pDataBlockInfo[rightTableIndex][rightTableBlockIndex];
+// // the first qualified table for interpolation query
+// // if ((pTsdbReadHandle->window.skey <= pCheckInfo->pTableObj->lastKey) &&
+// // (pCheckInfo->pTableObj->lastKey != TSKEY_INITIAL_VAL)) {
+// // break;
+// // }
- // assert(pLeftBlockInfoEx->compBlock->offset != pRightBlockInfoEx->compBlock->offset);
-#if 0 // TODO: temporarily comment off requested by Dr. Liao
- if (pLeftBlockInfoEx->compBlock->offset == pRightBlockInfoEx->compBlock->offset &&
- pLeftBlockInfoEx->compBlock->last == pRightBlockInfoEx->compBlock->last) {
- tsdbError("error in header file, two block with same offset:%" PRId64, (int64_t)pLeftBlockInfoEx->compBlock->offset);
- }
-#endif
+// i++;
+// }
- return pLeftBlockInfoEx->compBlock->offset > pRightBlockInfoEx->compBlock->offset ? 1 : -1;
-}
+// // there are no data in all the tables
+// if (i == numOfTables) {
+// return;
+// }
-static int32_t createDataBlocksInfo(STsdbReadHandle* pTsdbReadHandle, int32_t numOfBlocks, int32_t* numOfAllocBlocks) {
- size_t size = sizeof(STableBlockInfo) * numOfBlocks;
+// STableBlockScanInfo info = *(STableBlockScanInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
+// taosArrayClear(pTsdbReadHandle->pTableCheckInfo);
- if (pTsdbReadHandle->allocSize < size) {
- pTsdbReadHandle->allocSize = (int32_t)size;
- char* tmp = taosMemoryRealloc(pTsdbReadHandle->pDataBlockInfo, pTsdbReadHandle->allocSize);
- if (tmp == NULL) {
- return TSDB_CODE_TDB_OUT_OF_MEMORY;
- }
+// info.lastKey = pTsdbReadHandle->window.skey;
+// taosArrayPush(pTsdbReadHandle->pTableCheckInfo, &info);
+// }
- pTsdbReadHandle->pDataBlockInfo = (STableBlockInfo*)tmp;
+bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32_t order) {
+ ASSERT(pKey != NULL);
+ if (pDelList == NULL) {
+ return false;
}
+ size_t num = taosArrayGetSize(pDelList);
+ bool asc = ASCENDING_TRAVERSE(order);
+ int32_t step = asc ? 1 : -1;
- memset(pTsdbReadHandle->pDataBlockInfo, 0, size);
- *numOfAllocBlocks = numOfBlocks;
+ if (asc) {
+ if (*index >= num - 1) {
+ TSDBKEY* last = taosArrayGetLast(pDelList);
+ ASSERT(pKey->ts >= last->ts);
- // access data blocks according to the offset of each block in asc/desc order.
- int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
+ if (pKey->ts > last->ts) {
+ return false;
+ } else if (pKey->ts == last->ts) {
+ TSDBKEY* prev = taosArrayGet(pDelList, num - 2);
+ return (prev->version >= pKey->version);
+ }
+ } else {
+ TSDBKEY* pCurrent = taosArrayGet(pDelList, *index);
+ TSDBKEY* pNext = taosArrayGet(pDelList, (*index) + 1);
- SBlockOrderSupporter sup = {0};
- sup.numOfTables = numOfTables;
- sup.numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
- sup.blockIndexArray = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
- sup.pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
+ if (pKey->ts < pCurrent->ts) {
+ return false;
+ }
- if (sup.numOfBlocksPerTable == NULL || sup.blockIndexArray == NULL || sup.pDataBlockInfo == NULL) {
- cleanBlockOrderSupporter(&sup, 0);
- return TSDB_CODE_TDB_OUT_OF_MEMORY;
- }
+ if (pCurrent->ts <= pKey->ts && pNext->ts >= pKey->ts && pCurrent->version >= pKey->version) {
+ return true;
+ }
- int32_t cnt = 0;
- int32_t numOfQualTables = 0;
+ while (pNext->ts <= pKey->ts && (*index) < num - 1) {
+ (*index) += 1;
- for (int32_t j = 0; j < numOfTables; ++j) {
- STableCheckInfo* pTableCheck = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, j);
- if (pTableCheck->numOfBlocks <= 0) {
- continue;
- }
+ if ((*index) < num - 1) {
+ pCurrent = taosArrayGet(pDelList, *index);
+ pNext = taosArrayGet(pDelList, (*index) + 1);
- SBlock* pBlock = pTableCheck->pCompInfo->blocks;
- sup.numOfBlocksPerTable[numOfQualTables] = pTableCheck->numOfBlocks;
+ // it is not a consecutive deletion range, ignore it
+ if (pCurrent->version == 0 && pNext->version > 0) {
+ continue;
+ }
- char* buf = taosMemoryMalloc(sizeof(STableBlockInfo) * pTableCheck->numOfBlocks);
- if (buf == NULL) {
- cleanBlockOrderSupporter(&sup, numOfQualTables);
- return TSDB_CODE_TDB_OUT_OF_MEMORY;
+ if (pCurrent->ts <= pKey->ts && pNext->ts >= pKey->ts && pCurrent->version >= pKey->version) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
+ } else {
+ if (*index <= 0) {
+ TSDBKEY* pFirst = taosArrayGet(pDelList, 0);
- sup.pDataBlockInfo[numOfQualTables] = (STableBlockInfo*)buf;
+ if (pKey->ts < pFirst->ts) {
+ return false;
+ } else if (pKey->ts == pFirst->ts) {
+ return pFirst->version >= pKey->version;
+ } else {
+ ASSERT(0);
+ }
+ } else {
+ TSDBKEY* pCurrent = taosArrayGet(pDelList, *index);
+ TSDBKEY* pPrev = taosArrayGet(pDelList, (*index) - 1);
- for (int32_t k = 0; k < pTableCheck->numOfBlocks; ++k) {
- STableBlockInfo* pBlockInfo = &sup.pDataBlockInfo[numOfQualTables][k];
+ if (pKey->ts > pCurrent->ts) {
+ return false;
+ }
- pBlockInfo->compBlock = &pBlock[k];
- pBlockInfo->pTableCheckInfo = pTableCheck;
- cnt++;
- }
+ if (pPrev->ts <= pKey->ts && pCurrent->ts >= pKey->ts && pPrev->version >= pKey->version) {
+ return true;
+ }
- numOfQualTables++;
- }
+ while (pPrev->ts >= pKey->ts && (*index) > 1) {
+ (*index) += step;
- assert(numOfBlocks == cnt);
+ if ((*index) >= 1) {
+ pCurrent = taosArrayGet(pDelList, *index);
+ pPrev = taosArrayGet(pDelList, (*index) - 1);
- // since there is only one table qualified, blocks are not sorted
- if (numOfQualTables == 1) {
- memcpy(pTsdbReadHandle->pDataBlockInfo, sup.pDataBlockInfo[0], sizeof(STableBlockInfo) * numOfBlocks);
- cleanBlockOrderSupporter(&sup, numOfQualTables);
-
- tsdbDebug("%p create data blocks info struct completed for 1 table, %d blocks not sorted %s", pTsdbReadHandle, cnt,
- pTsdbReadHandle->idStr);
- return TSDB_CODE_SUCCESS;
- }
-
- tsdbDebug("%p create data blocks info struct completed, %d blocks in %d tables %s", pTsdbReadHandle, cnt,
- numOfQualTables, pTsdbReadHandle->idStr);
-
- assert(cnt <= numOfBlocks && numOfQualTables <= numOfTables); // the pTableQueryInfo[j]->numOfBlocks may be 0
- sup.numOfTables = numOfQualTables;
-
- SMultiwayMergeTreeInfo* pTree = NULL;
- uint8_t ret = tMergeTreeCreate(&pTree, sup.numOfTables, &sup, dataBlockOrderCompar);
- if (ret != TSDB_CODE_SUCCESS) {
- cleanBlockOrderSupporter(&sup, numOfTables);
- return TSDB_CODE_TDB_OUT_OF_MEMORY;
- }
-
- int32_t numOfTotal = 0;
-
- while (numOfTotal < cnt) {
- int32_t pos = tMergeTreeGetChosenIndex(pTree);
- int32_t index = sup.blockIndexArray[pos]++;
+ // it is not a consecutive deletion range, ignore it
+ if (pCurrent->version > 0 && pPrev->version == 0) {
+ continue;
+ }
- STableBlockInfo* pBlocksInfo = sup.pDataBlockInfo[pos];
- pTsdbReadHandle->pDataBlockInfo[numOfTotal++] = pBlocksInfo[index];
+ if (pPrev->ts <= pKey->ts && pCurrent->ts >= pKey->ts && pPrev->version >= pKey->version) {
+ return true;
+ }
+ }
+ }
- // set data block index overflow, in order to disable the offset comparator
- if (sup.blockIndexArray[pos] >= sup.numOfBlocksPerTable[pos]) {
- sup.blockIndexArray[pos] = sup.numOfBlocksPerTable[pos] + 1;
+ return false;
}
-
- tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
}
- /*
- * available when no import exists
- * for(int32_t i = 0; i < cnt - 1; ++i) {
- * assert((*pDataBlockInfo)[i].compBlock->offset < (*pDataBlockInfo)[i+1].compBlock->offset);
- * }
- */
-
- tsdbDebug("%p %d data blocks sort completed, %s", pTsdbReadHandle, cnt, pTsdbReadHandle->idStr);
- cleanBlockOrderSupporter(&sup, numOfTables);
- taosMemoryFree(pTree);
-
- return TSDB_CODE_SUCCESS;
+ return false;
}
-static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists);
-
-static int32_t getDataBlock(STsdbReadHandle* pTsdbReadHandle, STableBlockInfo* pNext, bool* exists) {
- int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
-
- while (1) {
- int32_t code = loadFileDataBlock(pTsdbReadHandle, pNext->compBlock, pNext->pTableCheckInfo, exists);
- if (code != TSDB_CODE_SUCCESS || *exists) {
- return code;
- }
-
- if ((cur->slot == pTsdbReadHandle->numOfBlocks - 1 && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
- (cur->slot == 0 && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
- // all data blocks in current file has been checked already, try next file if exists
- return getFirstFileDataBlock(pTsdbReadHandle, exists);
- } else { // next block of the same file
- cur->slot += step;
- cur->mixBlock = false;
- cur->blockCompleted = false;
- pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
- }
+TSDBROW* getValidRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* pReader) {
+ if (!pIter->hasVal) {
+ return NULL;
}
-}
-
-static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
- pTsdbReadHandle->numOfBlocks = 0;
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- int32_t code = TSDB_CODE_SUCCESS;
-
- int32_t numOfBlocks = 0;
- int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
-
- STsdbKeepCfg* pCfg = REPO_KEEP_CFG(pTsdbReadHandle->pTsdb);
- STimeWindow win = TSWINDOW_INITIALIZER;
+ TSDBROW* pRow = tsdbTbDataIterGet(pIter->iter);
+ TSDBKEY key = TSDBROW_KEY(pRow);
+ if (outOfTimeWindow(key.ts, &pReader->window)) {
+ pIter->hasVal = false;
+ return NULL;
+ }
- while (true) {
- tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
+ // it is a valid data version
+ if ((key.version <= pReader->verRange.maxVer && key.version >= pReader->verRange.minVer) &&
+ (!hasBeenDropped(pDelList, &pIter->index, &key, pReader->order))) {
+ return pRow;
+ }
- if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- break;
+ while (1) {
+ pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
+ if (!pIter->hasVal) {
+ return NULL;
}
- tsdbGetFidKeyRange(pCfg->days, pCfg->precision, pTsdbReadHandle->pFileGroup->fid, &win.skey, &win.ekey);
+ pRow = tsdbTbDataIterGet(pIter->iter);
- // current file are not overlapped with query time window, ignore remain files
- if ((ASCENDING_TRAVERSE(pTsdbReadHandle->order) && win.skey > pTsdbReadHandle->window.ekey) ||
- (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && win.ekey < pTsdbReadHandle->window.ekey)) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
- pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
- pTsdbReadHandle->pFileGroup = NULL;
- assert(pTsdbReadHandle->numOfBlocks == 0);
- break;
+ key = TSDBROW_KEY(pRow);
+ if (outOfTimeWindow(key.ts, &pReader->window)) {
+ pIter->hasVal = false;
+ return NULL;
}
- if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- code = terrno;
- break;
+ if (key.version <= pReader->verRange.maxVer && key.version >= pReader->verRange.minVer &&
+ (!hasBeenDropped(pDelList, &pIter->index, &key, pReader->order))) {
+ return pRow;
}
+ }
+}
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
-
- if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
- code = terrno;
+int32_t doMergeRowsInBuf(SIterInfo* pIter, int64_t ts, SArray* pDelList, SRowMerger* pMerger, STsdbReader* pReader) {
+ while (1) {
+ pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
+ if (!pIter->hasVal) {
break;
}
- if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
+ // data exists but not valid
+ TSDBROW* pRow = getValidRow(pIter, pDelList, pReader);
+ if (pRow == NULL) {
break;
}
- tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pTsdbReadHandle, numOfBlocks, numOfTables,
- pTsdbReadHandle->pFileGroup->fid, pTsdbReadHandle->idStr);
-
- assert(numOfBlocks >= 0);
- if (numOfBlocks == 0) {
- continue;
- }
-
- // todo return error code to query engine
- if ((code = createDataBlocksInfo(pTsdbReadHandle, numOfBlocks, &pTsdbReadHandle->numOfBlocks)) !=
- TSDB_CODE_SUCCESS) {
+ // ts is not identical, quit
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ if (k.ts != ts) {
break;
}
- assert(numOfBlocks >= pTsdbReadHandle->numOfBlocks);
- if (pTsdbReadHandle->numOfBlocks > 0) {
- break;
- }
+ tRowMerge(pMerger, pRow);
}
- // no data in file anymore
- if (pTsdbReadHandle->numOfBlocks <= 0 || code != TSDB_CODE_SUCCESS) {
- if (code == TSDB_CODE_SUCCESS) {
- assert(pTsdbReadHandle->pFileGroup == NULL);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t doMergeRowsInFileBlockImpl(SBlockData* pBlockData, int32_t rowIndex, int64_t key, SRowMerger* pMerger,
+ SVersionRange* pVerRange, int32_t step) {
+ while (pBlockData->aTSKEY[rowIndex] == key && rowIndex < pBlockData->nRow && rowIndex >= 0) {
+ if (pBlockData->aVersion[rowIndex] > pVerRange->maxVer || pBlockData->aVersion[rowIndex] < pVerRange->minVer) {
+ rowIndex += step;
+ continue;
}
- cur->fid = INT32_MIN; // denote that there are no data in file anymore
- *exists = false;
- return code;
+ TSDBROW fRow = tsdbRowFromBlockData(pBlockData, rowIndex);
+ tRowMerge(pMerger, &fRow);
+ rowIndex += step;
}
- assert(pTsdbReadHandle->pFileGroup != NULL && pTsdbReadHandle->numOfBlocks > 0);
- cur->slot = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 0 : pTsdbReadHandle->numOfBlocks - 1;
- cur->fid = pTsdbReadHandle->pFileGroup->fid;
-
- STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
- return getDataBlock(pTsdbReadHandle, pBlockInfo, exists);
+ return rowIndex;
}
-static bool isEndFileDataBlock(SQueryFilePos* cur, int32_t numOfBlocks, bool ascTrav) {
- assert(cur != NULL && numOfBlocks > 0);
- return (cur->slot == numOfBlocks - 1 && ascTrav) || (cur->slot == 0 && !ascTrav);
-}
-
-static void moveToNextDataBlockInCurrentFile(STsdbReadHandle* pTsdbReadHandle) {
- int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
+typedef enum {
+ CHECK_FILEBLOCK_CONT = 0x1,
+ CHECK_FILEBLOCK_QUIT = 0x2,
+} CHECK_FILEBLOCK_STATE;
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
- assert(cur->slot < pTsdbReadHandle->numOfBlocks && cur->slot >= 0);
-
- cur->slot += step;
- cur->mixBlock = false;
- cur->blockCompleted = false;
-}
+static int32_t checkForNeighborFileBlock(STsdbReader* pReader, STableBlockScanInfo* pScanInfo, SBlock* pBlock,
+ SFileDataBlockInfo* pFBlock, SRowMerger* pMerger, int64_t key,
+ CHECK_FILEBLOCK_STATE* state) {
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
+ SBlockData* pBlockData = &pReader->status.fileBlockData;
-static int32_t getBucketIndex(int32_t startRow, int32_t bucketRange, int32_t numOfRows) {
- return (numOfRows - startRow) / bucketRange;
-}
+ *state = CHECK_FILEBLOCK_QUIT;
+ int32_t step = ASCENDING_TRAVERSE(pReader->order) ? 1 : -1;
-int32_t tsdbGetFileBlocksDistInfo(tsdbReaderT* queryHandle, STableBlockDistInfo* pTableBlockInfo) {
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
+ int32_t nextIndex = -1;
+ SBlock* pNeighborBlock = getNeighborBlockOfSameTable(pFBlock, pScanInfo, &nextIndex, pReader->order);
+ if (pNeighborBlock == NULL) { // do nothing
+ return 0;
+ }
- pTableBlockInfo->totalSize = 0;
- pTableBlockInfo->totalRows = 0;
+ bool overlap = overlapWithNeighborBlock(pBlock, pNeighborBlock, pReader->order);
+ if (overlap) { // load next block
+ SReaderStatus* pStatus = &pReader->status;
+ SDataBlockIter* pBlockIter = &pStatus->blockIter;
- STsdbFS* pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
+ // 1. find the next neighbor block in the scan block list
+ SFileDataBlockInfo fb = {.uid = pFBlock->uid, .tbBlockIdx = nextIndex};
+ int32_t neighborIndex = findFileBlockInfoIndex(pBlockIter, &fb);
- // find the start data block in file
- pTsdbReadHandle->locateStart = true;
- STsdbKeepCfg* pCfg = REPO_KEEP_CFG(pTsdbReadHandle->pTsdb);
- int32_t fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
+ // 2. remove it from the scan block list
+ setFileBlockActiveInBlockIter(pBlockIter, neighborIndex, step);
- tsdbRLockFS(pFileHandle);
- tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
- tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
- tsdbUnLockFS(pFileHandle);
+ // 3. load the neighbor block, and set it to be the currently accessed file data block
+ int32_t code = doLoadFileBlockData(pReader, pBlockIter, pScanInfo, &pStatus->fileBlockData);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
- STsdbCfg* pc = REPO_CFG(pTsdbReadHandle->pTsdb);
- pTableBlockInfo->defMinRows = pc->minRows;
- pTableBlockInfo->defMaxRows = pc->maxRows;
+ // 4. check the data values
+ initBlockDumpInfo(pReader, pBlockIter);
- int32_t bucketRange = ceil((pc->maxRows - pc->minRows) / 20.0);
+ pDumpInfo->rowIndex =
+ doMergeRowsInFileBlockImpl(pBlockData, pDumpInfo->rowIndex, key, pMerger, &pReader->verRange, step);
- pTableBlockInfo->numOfFiles += 1;
+ if (pDumpInfo->rowIndex >= pBlock->nRow) {
+ *state = CHECK_FILEBLOCK_CONT;
+ }
+ }
- int32_t code = TSDB_CODE_SUCCESS;
- int32_t numOfBlocks = 0;
- int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- int defaultRows = 4096;
- STimeWindow win = TSWINDOW_INITIALIZER;
+ return TSDB_CODE_SUCCESS;
+}
- while (true) {
- numOfBlocks = 0;
- tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
+int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader,
+ SRowMerger* pMerger) {
+ SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
- if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- break;
- }
+ bool asc = ASCENDING_TRAVERSE(pReader->order);
+ int64_t key = pBlockData->aTSKEY[pDumpInfo->rowIndex];
+ int32_t step = asc ? 1 : -1;
- tsdbGetFidKeyRange(pCfg->days, pCfg->precision, pTsdbReadHandle->pFileGroup->fid, &win.skey, &win.ekey);
+ pDumpInfo->rowIndex += step;
+ if (pDumpInfo->rowIndex <= pBlockData->nRow - 1) {
+ pDumpInfo->rowIndex =
+ doMergeRowsInFileBlockImpl(pBlockData, pDumpInfo->rowIndex, key, pMerger, &pReader->verRange, step);
+ }
- // current file are not overlapped with query time window, ignore remain files
- if ((win.skey > pTsdbReadHandle->window.ekey)/* || (!ascTraverse && win.ekey < pTsdbReadHandle->window.ekey)*/) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
- pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
- pTsdbReadHandle->pFileGroup = NULL;
- break;
- }
+ // all rows are consumed, let's try next file block
+ if ((pDumpInfo->rowIndex >= pBlockData->nRow && asc) || (pDumpInfo->rowIndex < 0 && !asc)) {
+ while (1) {
+ CHECK_FILEBLOCK_STATE st;
- pTableBlockInfo->numOfFiles += 1;
- if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
- code = terrno;
- break;
+ SFileDataBlockInfo* pFileBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter);
+ SBlock* pCurrentBlock = taosArrayGet(pScanInfo->pBlockList, pFileBlockInfo->tbBlockIdx);
+ checkForNeighborFileBlock(pReader, pScanInfo, pCurrentBlock, pFileBlockInfo, pMerger, key, &st);
+ if (st == CHECK_FILEBLOCK_QUIT) {
+ break;
+ }
}
+ }
- tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
-
- if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
- code = terrno;
- break;
- }
+ return TSDB_CODE_SUCCESS;
+}
- if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
- break;
- }
+void updateSchema(TSDBROW* pRow, uint64_t uid, STsdbReader* pReader) {
+ int32_t sversion = TSDBROW_SVERSION(pRow);
- tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pTsdbReadHandle, numOfBlocks, numOfTables,
- pTsdbReadHandle->pFileGroup->fid, pTsdbReadHandle->idStr);
+ if (pReader->pSchema == NULL) {
+ pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, sversion);
+ } else if (pReader->pSchema->version != sversion) {
+ taosMemoryFreeClear(pReader->pSchema);
+ pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, sversion);
+ }
+}
- if (numOfBlocks == 0) {
- continue;
- }
+void doMergeMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, SArray* pDelList, STSRow** pTSRow,
+ STsdbReader* pReader) {
+ SRowMerger merge = {0};
- pTableBlockInfo->numOfBlocks += numOfBlocks;
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ updateSchema(pRow, uid, pReader);
- for (int32_t i = 0; i < numOfTables; ++i) {
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
+ tRowMergerInit(&merge, pRow, pReader->pSchema);
+ doMergeRowsInBuf(pIter, k.ts, pDelList, &merge, pReader);
+ tRowMergerGetRow(&merge, pTSRow);
+ tRowMergerClear(&merge);
+}
- SBlock* pBlock = pCheckInfo->pCompInfo->blocks;
+void doMergeMemIMemRows(TSDBROW* pRow, TSDBROW* piRow, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader,
+ STSRow** pTSRow) {
+ SRowMerger merge = {0};
- for (int32_t j = 0; j < pCheckInfo->numOfBlocks; ++j) {
- pTableBlockInfo->totalSize += pBlock[j].len;
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ TSDBKEY ik = TSDBROW_KEY(piRow);
- int32_t numOfRows = pBlock[j].numOfRows;
- pTableBlockInfo->totalRows += numOfRows;
+ if (ASCENDING_TRAVERSE(pReader->order)) { // ascending order imem --> mem
+ updateSchema(piRow, pBlockScanInfo->uid, pReader);
- if (numOfRows > pTableBlockInfo->maxRows) {
- pTableBlockInfo->maxRows = numOfRows;
- }
+ tRowMergerInit(&merge, piRow, pReader->pSchema);
+ doMergeRowsInBuf(&pBlockScanInfo->iiter, ik.ts, pBlockScanInfo->delSkyline, &merge, pReader);
- if (numOfRows < pTableBlockInfo->minRows) {
- pTableBlockInfo->minRows = numOfRows;
- }
+ tRowMerge(&merge, pRow);
+ doMergeRowsInBuf(&pBlockScanInfo->iter, k.ts, pBlockScanInfo->delSkyline, &merge, pReader);
+ } else {
+ updateSchema(pRow, pBlockScanInfo->uid, pReader);
- if (numOfRows < defaultRows) {
- pTableBlockInfo->numOfSmallBlocks += 1;
- }
+ tRowMergerInit(&merge, pRow, pReader->pSchema);
+ doMergeRowsInBuf(&pBlockScanInfo->iter, k.ts, pBlockScanInfo->delSkyline, &merge, pReader);
- int32_t bucketIndex = getBucketIndex(pTableBlockInfo->defMinRows, bucketRange, numOfRows);
- pTableBlockInfo->blockRowsHisto[bucketIndex]++;
- }
- }
+ tRowMerge(&merge, piRow);
+ doMergeRowsInBuf(&pBlockScanInfo->iiter, k.ts, pBlockScanInfo->delSkyline, &merge, pReader);
}
- pTableBlockInfo->numOfTables = numOfTables;
- return code;
+ tRowMergerGetRow(&merge, pTSRow);
}
-static int32_t getDataBlocksInFiles(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
- STsdbFS* pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
+int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, STSRow** pTSRow,
+ int64_t endKey) {
+ TSDBROW* pRow = getValidRow(&pBlockScanInfo->iter, pBlockScanInfo->delSkyline, pReader);
+ TSDBROW* piRow = getValidRow(&pBlockScanInfo->iiter, pBlockScanInfo->delSkyline, pReader);
+ SArray* pDelList = pBlockScanInfo->delSkyline;
- // find the start data block in file
- if (!pTsdbReadHandle->locateStart) {
- pTsdbReadHandle->locateStart = true;
- STsdbKeepCfg* pCfg = REPO_KEEP_CFG(pTsdbReadHandle->pTsdb);
- int32_t fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
-
- tsdbRLockFS(pFileHandle);
- tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
- tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
- tsdbUnLockFS(pFileHandle);
-
- return getFirstFileDataBlock(pTsdbReadHandle, exists);
- } else {
- // check if current file block is all consumed
- STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
- STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
-
- // current block is done, try next
- if ((!cur->mixBlock) || cur->blockCompleted) {
- // all data blocks in current file has been checked already, try next file if exists
- } else {
- tsdbDebug("%p continue in current data block, index:%d, pos:%d, %s", pTsdbReadHandle, cur->slot, cur->pos,
- pTsdbReadHandle->idStr);
- int32_t code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlockInfo->compBlock, pCheckInfo);
- *exists = (pTsdbReadHandle->realNumOfRows > 0);
-
- if (code != TSDB_CODE_SUCCESS || *exists) {
- return code;
- }
+ // todo refactor
+ bool asc = ASCENDING_TRAVERSE(pReader->order);
+ if (pBlockScanInfo->iter.hasVal) {
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ if ((k.ts >= endKey && asc) || (k.ts <= endKey && !asc)) {
+ pRow = NULL;
}
+ }
- // current block is empty, try next block in file
- // all data blocks in current file has been checked already, try next file if exists
- if (isEndFileDataBlock(cur, pTsdbReadHandle->numOfBlocks, ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
- return getFirstFileDataBlock(pTsdbReadHandle, exists);
- } else {
- moveToNextDataBlockInCurrentFile(pTsdbReadHandle);
- STableBlockInfo* pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
- return getDataBlock(pTsdbReadHandle, pNext, exists);
+ if (pBlockScanInfo->iiter.hasVal) {
+ TSDBKEY k = TSDBROW_KEY(piRow);
+ if ((k.ts >= endKey && asc) || (k.ts <= endKey && !asc)) {
+ piRow = NULL;
}
}
-}
-static bool doHasDataInBuffer(STsdbReadHandle* pTsdbReadHandle) {
- size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
+ if (pBlockScanInfo->iter.hasVal && pBlockScanInfo->iiter.hasVal && pRow != NULL && piRow != NULL) {
+ TSDBKEY k = TSDBROW_KEY(pRow);
+ TSDBKEY ik = TSDBROW_KEY(piRow);
- while (pTsdbReadHandle->activeIndex < numOfTables) {
- if (hasMoreDataInCache(pTsdbReadHandle)) {
- return true;
+ if (ik.ts < k.ts) { // ik.ts < k.ts
+ doMergeMultiRows(piRow, pBlockScanInfo->uid, &pBlockScanInfo->iiter, pDelList, pTSRow, pReader);
+ } else if (k.ts < ik.ts) {
+ doMergeMultiRows(pRow, pBlockScanInfo->uid, &pBlockScanInfo->iter, pDelList, pTSRow, pReader);
+ } else { // ik.ts == k.ts
+ doMergeMemIMemRows(pRow, piRow, pBlockScanInfo, pReader, pTSRow);
}
- pTsdbReadHandle->activeIndex += 1;
+ return TSDB_CODE_SUCCESS;
}
- return false;
-}
+ if (pBlockScanInfo->iter.hasVal && pRow != NULL) {
+ doMergeMultiRows(pRow, pBlockScanInfo->uid, &pBlockScanInfo->iter, pDelList, pTSRow, pReader);
+ return TSDB_CODE_SUCCESS;
+ }
-// todo not unref yet, since it is not support multi-group interpolation query
-static UNUSED_FUNC void changeQueryHandleForInterpQuery(tsdbReaderT pHandle) {
- // filter the queried time stamp in the first place
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
+ if (pBlockScanInfo->iiter.hasVal && piRow != NULL) {
+ doMergeMultiRows(piRow, pBlockScanInfo->uid, &pBlockScanInfo->iiter, pDelList, pTSRow, pReader);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
- // starts from the buffer in case of descending timestamp order check data blocks
- size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
+int32_t doAppendOneRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* pTSRow) {
+ int32_t numOfRows = pBlock->info.rows;
+ int32_t numOfCols = (int32_t)taosArrayGetSize(pBlock->pDataBlock);
- int32_t i = 0;
- while (i < numOfTables) {
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
+ SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
+ STSchema* pSchema = pReader->pSchema;
- // the first qualified table for interpolation query
- // if ((pTsdbReadHandle->window.skey <= pCheckInfo->pTableObj->lastKey) &&
- // (pCheckInfo->pTableObj->lastKey != TSKEY_INITIAL_VAL)) {
- // break;
- // }
+ SColVal colVal = {0};
+ int32_t i = 0, j = 0;
- i++;
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ if (pColInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
+ colDataAppend(pColInfoData, numOfRows, (const char*)&pTSRow->ts, false);
+ i += 1;
}
- // there are no data in all the tables
- if (i == numOfTables) {
- return;
+ while (i < numOfCols && j < pSchema->numOfCols) {
+ pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ col_id_t colId = pColInfoData->info.colId;
+
+ if (colId == pSchema->columns[j].colId) {
+ tTSRowGetVal(pTSRow, pReader->pSchema, j, &colVal);
+ doCopyColVal(pColInfoData, numOfRows, i, &colVal, pSupInfo);
+ i += 1;
+ j += 1;
+ } else if (colId < pSchema->columns[j].colId) {
+ colDataAppendNULL(pColInfoData, numOfRows);
+ i += 1;
+ } else if (colId > pSchema->columns[j].colId) {
+ j += 1;
+ }
}
- STableCheckInfo info = *(STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
- taosArrayClear(pTsdbReadHandle->pTableCheckInfo);
+ // set null value since current column does not exist in the "pSchema"
+ while (i < numOfCols) {
+ pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ colDataAppendNULL(pColInfoData, numOfRows);
+ i += 1;
+ }
- info.lastKey = pTsdbReadHandle->window.skey;
- taosArrayPush(pTsdbReadHandle->pTableCheckInfo, &info);
+ pBlock->info.rows += 1;
+ return TSDB_CODE_SUCCESS;
}
-static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
- STsdbReadHandle* pTsdbReadHandle) {
- int numOfRows = 0;
- int curRows = 0;
- int32_t numOfCols = (int32_t)taosArrayGetSize(pTsdbReadHandle->pColumns);
- STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
- win->skey = TSKEY_INITIAL_VAL;
-
- int64_t st = taosGetTimestampUs();
- int16_t rv = -1;
- STSchema* pSchema = NULL;
- TSKEY lastRowKey = TSKEY_INITIAL_VAL;
+int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity,
+ STsdbReader* pReader) {
+ SSDataBlock* pBlock = pReader->pResBlock;
do {
- STSRow* row = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, NULL, TD_VER_MAX);
- if (row == NULL) {
+ STSRow* pTSRow = NULL;
+ tsdbGetNextRowInMem(pBlockScanInfo, pReader, &pTSRow, endKey);
+ if (pTSRow == NULL) {
break;
}
- TSKEY key = TD_ROW_KEY(row);
- if ((key > maxKey && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
- (key < maxKey && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
- tsdbDebug("%p key:%" PRIu64 " beyond qrange:%" PRId64 " - %" PRId64 ", no more data in buffer", pTsdbReadHandle,
- key, pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey);
+ doAppendOneRow(pBlock, pReader, pTSRow);
+ taosMemoryFree(pTSRow);
+ // no data in buffer, return immediately
+ if (!(pBlockScanInfo->iter.hasVal || pBlockScanInfo->iiter.hasVal)) {
break;
}
- if (win->skey == INT64_MIN) {
- win->skey = key;
- }
-
- win->ekey = key;
- if (rv != TD_ROW_SVER(row)) {
- pSchema = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), pCheckInfo->tableId, TD_ROW_SVER(row));
- rv = TD_ROW_SVER(row);
- }
- numOfRows += mergeTwoRowFromMem(pTsdbReadHandle, maxRowsToRead, &curRows, row, NULL, numOfCols, pCheckInfo->tableId,
- pSchema, NULL, pCfg->update, &lastRowKey);
-
- if (numOfRows >= maxRowsToRead) {
- moveToNextRowInMem(pCheckInfo);
+ if (pBlock->info.rows >= capacity) {
break;
}
+ } while (1);
- } while (moveToNextRowInMem(pCheckInfo));
-
- taosMemoryFreeClear(pSchema); // free the STSChema
- assert(numOfRows <= maxRowsToRead);
+ ASSERT(pBlock->info.rows <= capacity);
+ return TSDB_CODE_SUCCESS;
+}
- int64_t elapsedTime = taosGetTimestampUs() - st;
- tsdbDebug("%p build data block from cache completed, elapsed time:%" PRId64 " us, numOfRows:%d, numOfCols:%d, %s",
- pTsdbReadHandle, elapsedTime, numOfRows, numOfCols, pTsdbReadHandle->idStr);
+// todo refactor, use arraylist instead
+int32_t tsdbSetTableId(STsdbReader* pReader, int64_t uid) {
+ ASSERT(pReader != NULL);
+ taosHashClear(pReader->status.pTableMap);
- return numOfRows;
+ STableBlockScanInfo info = {.lastKey = 0, .uid = uid};
+ taosHashPut(pReader->status.pTableMap, &info.uid, sizeof(uint64_t), &info, sizeof(info));
+ return TDB_CODE_SUCCESS;
}
void* tsdbGetIdx(SMeta* pMeta) {
@@ -2830,34 +2727,30 @@ void* tsdbGetIdx(SMeta* pMeta) {
}
return metaGetIdx(pMeta);
}
+
void* tsdbGetIvtIdx(SMeta* pMeta) {
if (pMeta == NULL) {
return NULL;
}
return metaGetIvtIdx(pMeta);
}
-int32_t tsdbGetAllTableList(SMeta* pMeta, uint64_t uid, SArray* list) {
- SMCtbCursor* pCur = metaOpenCtbCursor(pMeta, uid);
- while (1) {
- tb_uid_t id = metaCtbCursorNext(pCur);
- if (id == 0) {
- break;
- }
-
- STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, uid = id};
- taosArrayPush(list, &info);
+/**
+ * @brief Get all suids since suid
+ *
+ * @param pMeta
+ * @param suid return all suids in one vnode if suid is 0
+ * @param list
+ * @return int32_t
+ */
+int32_t tsdbGetStbIdList(SMeta* pMeta, int64_t suid, SArray* list) {
+ SMStbCursor* pCur = metaOpenStbCursor(pMeta, suid);
+ if (!pCur) {
+ return TSDB_CODE_FAILED;
}
- metaCloseCtbCursor(pCur);
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t tsdbGetCtbIdList(SMeta* pMeta, int64_t suid, SArray* list) {
- SMCtbCursor* pCur = metaOpenCtbCursor(pMeta, suid);
-
while (1) {
- tb_uid_t id = metaCtbCursorNext(pCur);
+ tb_uid_t id = metaStbCursorNext(pCur);
if (id == 0) {
break;
}
@@ -2865,867 +2758,451 @@ int32_t tsdbGetCtbIdList(SMeta* pMeta, int64_t suid, SArray* list) {
taosArrayPush(list, &id);
}
- metaCloseCtbCursor(pCur);
+ metaCloseStbCursor(pCur);
return TSDB_CODE_SUCCESS;
}
-static void destroyHelper(void* param) {
- if (param == NULL) {
- return;
+// ====================================== EXPOSED APIs ======================================
+int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, SArray* pTableList, STsdbReader** ppReader,
+ const char* idstr) {
+ int32_t code = tsdbReaderCreate(pVnode, pCond, ppReader, idstr);
+ if (code) {
+ goto _err;
}
- // tQueryInfo* pInfo = (tQueryInfo*)param;
- // if (pInfo->optr != TSDB_RELATION_IN) {
- // taosMemoryFreeClear(pInfo->q);
- // } else {
- // taosHashCleanup((SHashObj *)(pInfo->q));
- // }
+ if (pCond->suid != 0) {
+ (*ppReader)->pSchema = metaGetTbTSchema((*ppReader)->pTsdb->pVnode->pMeta, (*ppReader)->suid, -1);
+ ASSERT((*ppReader)->pSchema);
+ } else if (taosArrayGetSize(pTableList) > 0) {
+ STableKeyInfo* pKey = taosArrayGet(pTableList, 0);
+ (*ppReader)->pSchema = metaGetTbTSchema((*ppReader)->pTsdb->pVnode->pMeta, pKey->uid, -1);
+ }
- taosMemoryFree(param);
-}
+ STsdbReader* pReader = *ppReader;
+ if (isEmptyQueryTimeWindow(&pReader->window)) {
+ tsdbDebug("%p query window not overlaps with the data set, no result returned, %s", pReader, pReader->idStr);
+ return TSDB_CODE_SUCCESS;
+ }
-#define TSDB_PREV_ROW 0x1
-#define TSDB_NEXT_ROW 0x2
+ int32_t numOfTables = taosArrayGetSize(pTableList);
+ pReader->status.pTableMap = createDataBlockScanInfo(pReader, pTableList->pData, numOfTables);
+ if (pReader->status.pTableMap == NULL) {
+ tsdbReaderClose(pReader);
+ *ppReader = NULL;
-static bool loadBlockOfActiveTable(STsdbReadHandle* pTsdbReadHandle) {
- if (pTsdbReadHandle->checkFiles) {
- // check if the query range overlaps with the file data block
- bool exists = true;
+ code = TSDB_CODE_TDB_OUT_OF_MEMORY;
+ goto _err;
+ }
- int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
- if (code != TSDB_CODE_SUCCESS) {
- pTsdbReadHandle->checkFiles = false;
- return false;
- }
+ SDataBlockIter* pBlockIter = &pReader->status.blockIter;
- if (exists) {
- tsdbRetrieveDataBlock((tsdbReaderT*)pTsdbReadHandle, NULL);
- if (pTsdbReadHandle->currentLoadExternalRows && pTsdbReadHandle->window.skey == pTsdbReadHandle->window.ekey) {
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, 0);
- assert(*(int64_t*)pColInfo->pData == pTsdbReadHandle->window.skey);
- }
+ STsdbFSState* pFState = pReader->pTsdb->fs->cState;
+ initFilesetIterator(&pReader->status.fileIter, pFState, pReader->order, pReader->idStr);
+ resetDataBlockIterator(&pReader->status.blockIter, pReader->order);
- pTsdbReadHandle->currentLoadExternalRows = false; // clear the flag, since the exact matched row is found.
- return exists;
+ // no data in files, let's try buffer in memory
+ if (pReader->status.fileIter.numOfFiles == 0) {
+ pReader->status.loadFromFile = false;
+ } else {
+ code = initForFirstBlockInFile(pReader, pBlockIter);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
}
-
- pTsdbReadHandle->checkFiles = false;
}
- if (hasMoreDataInCache(pTsdbReadHandle)) {
- pTsdbReadHandle->currentLoadExternalRows = false;
- return true;
- }
+ tsdbDebug("%p total numOfTable:%d in this query %s", pReader, numOfTables, pReader->idStr);
+ return code;
- // current result is empty
- if (pTsdbReadHandle->currentLoadExternalRows && pTsdbReadHandle->window.skey == pTsdbReadHandle->window.ekey &&
- pTsdbReadHandle->cur.rows == 0) {
- // SMemTable* pMemRef = pTsdbReadHandle->pMemTable;
+_err:
+ tsdbError("failed to create data reader, code: %s %s", tstrerror(code), pReader->idStr);
+ return code;
+}
- // doGetExternalRow(pTsdbReadHandle, TSDB_PREV_ROW, pMemRef);
- // doGetExternalRow(pTsdbReadHandle, TSDB_NEXT_ROW, pMemRef);
+void tsdbReaderClose(STsdbReader* pReader) {
+ if (pReader == NULL) {
+ return;
+ }
- bool result = tsdbGetExternalRow(pTsdbReadHandle);
+ SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
- // pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
- // pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
- pTsdbReadHandle->currentLoadExternalRows = false;
+ taosMemoryFreeClear(pSupInfo->plist);
+ taosMemoryFree(pSupInfo->colIds);
- return result;
+ taosArrayDestroy(pSupInfo->pColAgg);
+ for (int32_t i = 0; i < blockDataGetNumOfCols(pReader->pResBlock); ++i) {
+ if (pSupInfo->buildBuf[i] != NULL) {
+ taosMemoryFreeClear(pSupInfo->buildBuf[i]);
+ }
}
+ taosMemoryFree(pSupInfo->buildBuf);
- return false;
-}
-
-static bool loadCachedLastRow(STsdbReadHandle* pTsdbReadHandle) {
- // the last row is cached in buffer, return it directly.
- // here note that the pTsdbReadHandle->window must be the TS_INITIALIZER
- int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
- size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- assert(numOfTables > 0 && numOfCols > 0);
+ cleanupFilesetIterator(&pReader->status.fileIter);
+ cleanupDataBlockIterator(&pReader->status.blockIter);
+ destroyBlockScanInfo(pReader->status.pTableMap);
+ blockDataDestroy(pReader->pResBlock);
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
+ if (pReader->pFileReader != NULL) {
+ tsdbDataFReaderClose(&pReader->pFileReader);
+ }
- STSRow* pRow = NULL;
- TSKEY key = TSKEY_INITIAL_VAL;
- int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
- TSKEY lastRowKey = TSKEY_INITIAL_VAL;
- int32_t curRow = 0;
+#if 0
+// if (pReader->status.pTableScanInfo != NULL) {
+// pReader->status.pTableScanInfo = destroyTableCheckInfo(pReader->status.pTableScanInfo);
+// }
- if (++pTsdbReadHandle->activeIndex < numOfTables) {
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
- // int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key);
- // if (ret != TSDB_CODE_SUCCESS) {
- // return false;
- // }
- mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, pRow, NULL, numOfCols,
- pCheckInfo->tableId, NULL, NULL, true, &lastRowKey);
- taosMemoryFreeClear(pRow);
+// tsdbDestroyReadH(&pReader->rhelper);
- // update the last key value
- pCheckInfo->lastKey = key + step;
+// tdFreeDataCols(pReader->pDataCols);
+// pReader->pDataCols = NULL;
+//
+// pReader->prev = doFreeColumnInfoData(pReader->prev);
+// pReader->next = doFreeColumnInfoData(pReader->next);
+#endif
- cur->rows = 1; // only one row
- cur->lastKey = key + step;
- cur->mixBlock = true;
- cur->win.skey = key;
- cur->win.ekey = key;
+ SIOCostSummary* pCost = &pReader->cost;
- return true;
- }
+ tsdbDebug("%p :io-cost summary: head-file read cnt:%" PRIu64 ", head-file time:%" PRIu64 " us, statis-info:%" PRId64
+ " us, datablock:%" PRId64 " us, check data:%" PRId64 " us, %s",
+ pReader, pCost->headFileLoad, pCost->headFileLoadTime, pCost->smaLoadTime, pCost->blockLoadTime,
+ pCost->checkForNextTime, pReader->idStr);
- return false;
+ taosMemoryFree(pReader->idStr);
+ taosMemoryFree(pReader->pSchema);
+ taosMemoryFreeClear(pReader);
}
-// static bool loadCachedLast(STsdbReadHandle* pTsdbReadHandle) {
-// // the last row is cached in buffer, return it directly.
-// // here note that the pTsdbReadHandle->window must be the TS_INITIALIZER
-// int32_t tgNumOfCols = (int32_t)QH_GET_NUM_OF_COLS(pTsdbReadHandle);
-// size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
-// int32_t numOfRows = 0;
-// assert(numOfTables > 0 && tgNumOfCols > 0);
-// SQueryFilePos* cur = &pTsdbReadHandle->cur;
-// TSKEY priKey = TSKEY_INITIAL_VAL;
-// int32_t priIdx = -1;
-// SColumnInfoData* pColInfo = NULL;
-//
-// while (++pTsdbReadHandle->activeIndex < numOfTables) {
-// STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
-// STable* pTable = pCheckInfo->pTableObj;
-// char* pData = NULL;
-//
-// int32_t numOfCols = pTable->maxColNum;
-//
-// if (pTable->lastCols == NULL || pTable->maxColNum <= 0) {
-// tsdbWarn("no last cached for table %s, uid:%" PRIu64 ",tid:%d", pTable->name->data, pTable->uid,
-// pTable->tableId); continue;
-// }
-//
-// int32_t i = 0, j = 0;
-// while(i < tgNumOfCols && j < numOfCols) {
-// pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
-// if (pTable->lastCols[j].colId < pColInfo->info.colId) {
-// j++;
-// continue;
-// } else if (pTable->lastCols[j].colId > pColInfo->info.colId) {
-// i++;
-// continue;
-// }
-//
-// pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
-//
-// if (pTable->lastCols[j].bytes > 0) {
-// void* value = pTable->lastCols[j].pData;
-// switch (pColInfo->info.type) {
-// case TSDB_DATA_TYPE_BINARY:
-// case TSDB_DATA_TYPE_NCHAR:
-// memcpy(pData, value, varDataTLen(value));
-// break;
-// case TSDB_DATA_TYPE_NULL:
-// case TSDB_DATA_TYPE_BOOL:
-// case TSDB_DATA_TYPE_TINYINT:
-// case TSDB_DATA_TYPE_UTINYINT:
-// *(uint8_t *)pData = *(uint8_t *)value;
-// break;
-// case TSDB_DATA_TYPE_SMALLINT:
-// case TSDB_DATA_TYPE_USMALLINT:
-// *(uint16_t *)pData = *(uint16_t *)value;
-// break;
-// case TSDB_DATA_TYPE_INT:
-// case TSDB_DATA_TYPE_UINT:
-// *(uint32_t *)pData = *(uint32_t *)value;
-// break;
-// case TSDB_DATA_TYPE_BIGINT:
-// case TSDB_DATA_TYPE_UBIGINT:
-// *(uint64_t *)pData = *(uint64_t *)value;
-// break;
-// case TSDB_DATA_TYPE_FLOAT:
-// SET_FLOAT_PTR(pData, value);
-// break;
-// case TSDB_DATA_TYPE_DOUBLE:
-// SET_DOUBLE_PTR(pData, value);
-// break;
-// case TSDB_DATA_TYPE_TIMESTAMP:
-// if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
-// priKey = tdGetKey(*(TKEY *)value);
-// priIdx = i;
-//
-// i++;
-// j++;
-// continue;
-// } else {
-// *(TSKEY *)pData = *(TSKEY *)value;
-// }
-// break;
-// default:
-// memcpy(pData, value, pColInfo->info.bytes);
-// }
-//
-// for (int32_t n = 0; n < tgNumOfCols; ++n) {
-// if (n == i) {
-// continue;
-// }
-//
-// pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, n);
-// pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;;
-//
-// if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
-//// *(TSKEY *)pData = pTable->lastCols[j].ts;
-// continue;
-// }
-//
-// if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
-// setVardataNull(pData, pColInfo->info.type);
-// } else {
-// setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
-// }
-// }
-//
-// numOfRows++;
-// assert(numOfRows < pTsdbReadHandle->outputCapacity);
-// }
-//
-// i++;
-// j++;
-// }
-//
-// // leave the real ts column as the last row, because last function only (not stable) use the last row as res
-// if (priKey != TSKEY_INITIAL_VAL) {
-// pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, priIdx);
-// pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
-//
-// *(TSKEY *)pData = priKey;
-//
-// for (int32_t n = 0; n < tgNumOfCols; ++n) {
-// if (n == priIdx) {
-// continue;
-// }
-//
-// pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, n);
-// pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;;
-//
-// assert (pColInfo->info.colId != PRIMARYKEY_TIMESTAMP_COL_ID);
-//
-// if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
-// setVardataNull(pData, pColInfo->info.type);
-// } else {
-// setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
-// }
-// }
-//
-// numOfRows++;
-// }
-//
-// if (numOfRows > 0) {
-// cur->rows = numOfRows;
-// cur->mixBlock = true;
-//
-// return true;
-// }
-// }
-//
-// return false;
-//}
-
-static bool loadDataBlockFromTableSeq(STsdbReadHandle* pTsdbReadHandle) {
- size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
- assert(numOfTables > 0);
-
- int64_t stime = taosGetTimestampUs();
-
- while (pTsdbReadHandle->activeIndex < numOfTables) {
- if (loadBlockOfActiveTable(pTsdbReadHandle)) {
- return true;
- }
+bool tsdbNextDataBlock(STsdbReader* pReader) {
+ if (isEmptyQueryTimeWindow(&pReader->window)) {
+ return false;
+ }
- STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
- pCheckInfo->numOfBlocks = 0;
+ // cleanup the data that belongs to the previous data block
+ SSDataBlock* pBlock = pReader->pResBlock;
+ blockDataCleanup(pBlock);
- pTsdbReadHandle->activeIndex += 1;
- pTsdbReadHandle->locateStart = false;
- pTsdbReadHandle->checkFiles = true;
- pTsdbReadHandle->cur.rows = 0;
- pTsdbReadHandle->currentLoadExternalRows = pTsdbReadHandle->loadExternalRow;
+ int64_t stime = taosGetTimestampUs();
+ int64_t elapsedTime = stime;
+ SReaderStatus* pStatus = &pReader->status;
- terrno = TSDB_CODE_SUCCESS;
+ if (pReader->type == BLOCK_LOAD_OFFSET_ORDER) {
+ if (pStatus->loadFromFile) {
+ int32_t code = buildBlockFromFiles(pReader);
+ if (code != TSDB_CODE_SUCCESS) {
+ return false;
+ }
- int64_t elapsedTime = taosGetTimestampUs() - stime;
- pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
+ if (pBlock->info.rows > 0) {
+ return true;
+ } else {
+ buildBlockFromBufferSequentially(pReader);
+ return pBlock->info.rows > 0;
+ }
+ } else { // no data in files, let's try the buffer
+ buildBlockFromBufferSequentially(pReader);
+ return pBlock->info.rows > 0;
+ }
+ } else if (pReader->type == BLOCK_LOAD_TABLESEQ_ORDER) {
+ } else if (pReader->type == BLOCK_LOAD_EXTERN_ORDER) {
+ } else {
+ ASSERT(0);
}
-
return false;
}
-// handle data in cache situation
-// bool tsdbNextDataBlock(tsdbReaderT pHandle, uint64_t uid)
-bool tsdbNextDataBlock(tsdbReaderT pHandle) {
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
+void tsdbRetrieveDataBlockInfo(STsdbReader* pReader, SDataBlockInfo* pDataBlockInfo) {
+ ASSERT(pDataBlockInfo != NULL && pReader != NULL);
+ pDataBlockInfo->rows = pReader->pResBlock->info.rows;
+ pDataBlockInfo->uid = pReader->pResBlock->info.uid;
+ pDataBlockInfo->window = pReader->pResBlock->info.window;
+}
- size_t numOfCols = taosArrayGetSize(pTsdbReadHandle->pColumns);
- for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
- colInfoDataCleanup(pColInfo, pTsdbReadHandle->outputCapacity);
- }
+int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SColumnDataAgg*** pBlockStatis, bool* allHave) {
+ int32_t code = 0;
+ *allHave = false;
- if (emptyQueryTimewindow(pTsdbReadHandle)) {
- tsdbDebug("%p query window not overlaps with the data set, no result returned, %s", pTsdbReadHandle,
- pTsdbReadHandle->idStr);
- return false;
+ // there is no statistics data for composed block
+ if (pReader->status.composedDataBlock) {
+ *pBlockStatis = NULL;
+ return TSDB_CODE_SUCCESS;
}
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pReader->status.blockIter);
+ STableBlockScanInfo* pBlockScanInfo = taosHashGet(pReader->status.pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
+ SBlock* pBlock = taosArrayGet(pBlockScanInfo->pBlockList, pFBlock->tbBlockIdx);
+
int64_t stime = taosGetTimestampUs();
- int64_t elapsedTime = stime;
- // TODO refactor: remove "type"
- if (pTsdbReadHandle->type == TSDB_QUERY_TYPE_LAST) {
- if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LASTROW) {
- // return loadCachedLastRow(pTsdbReadHandle);
- } else if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LAST) {
- // return loadCachedLast(pTsdbReadHandle);
+ SBlockLoadSuppInfo* pSup = &pReader->suppInfo;
+
+ if (tBlockHasSma(pBlock)) {
+ code = tsdbReadBlockSma(pReader->pFileReader, pBlock, pSup->pColAgg, NULL);
+ if (code != TSDB_CODE_SUCCESS) {
+ tsdbDebug("vgId:%d, failed to load block SMA for uid %" PRIu64 ", code:%s, %s", 0, pFBlock->uid, tstrerror(code),
+ pReader->idStr);
+ return code;
}
+ } else {
+ *pBlockStatis = NULL;
+ return TSDB_CODE_SUCCESS;
}
- if (pTsdbReadHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) {
- return loadDataBlockFromTableSeq(pTsdbReadHandle);
- } else { // loadType == RR and Offset Order
- if (pTsdbReadHandle->checkFiles) {
- // check if the query range overlaps with the file data block
- bool exists = true;
+ *allHave = true;
- int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
- if (code != TSDB_CODE_SUCCESS) {
- pTsdbReadHandle->activeIndex = 0;
- pTsdbReadHandle->checkFiles = false;
+ // always load the first primary timestamp column data
+ SColumnDataAgg* pTsAgg = &pSup->tsColAgg;
- return false;
- }
+ pTsAgg->numOfNull = 0;
+ pTsAgg->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
+ pTsAgg->min = pReader->pResBlock->info.window.skey;
+ pTsAgg->max = pReader->pResBlock->info.window.ekey;
+ pSup->plist[0] = pTsAgg;
- if (exists) {
- pTsdbReadHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime);
- return exists;
- }
+ // update the number of NULL data rows
+ size_t numOfCols = blockDataGetNumOfCols(pReader->pResBlock);
- pTsdbReadHandle->activeIndex = 0;
- pTsdbReadHandle->checkFiles = false;
+ int32_t i = 0, j = 0;
+ while (j < numOfCols && i < taosArrayGetSize(pSup->pColAgg)) {
+ SColumnDataAgg* pAgg = taosArrayGet(pSup->pColAgg, i);
+ if (pAgg->colId == pSup->colIds[j]) {
+ if (IS_BSMA_ON(&(pReader->pSchema->columns[i]))) {
+ pSup->plist[j] = pAgg;
+ } else {
+ *allHave = false;
+ }
+ i += 1;
+ j += 1;
+ } else if (pAgg->colId < pSup->colIds[j]) {
+ i += 1;
+ } else if (pSup->colIds[j] < pAgg->colId) {
+ j += 1;
}
+ }
+
+ int64_t elapsed = taosGetTimestampUs() - stime;
+ pReader->cost.smaLoadTime += elapsed;
- // TODO: opt by consider the scan order
- bool ret = doHasDataInBuffer(pTsdbReadHandle);
- terrno = TSDB_CODE_SUCCESS;
+ *pBlockStatis = pSup->plist;
- elapsedTime = taosGetTimestampUs() - stime;
- pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
- return ret;
- }
+ tsdbDebug("vgId:%d, succeed to load block SMA for uid %" PRIu64 ", elapsed time:%" PRId64 "us, %s", 0, pFBlock->uid,
+ elapsed, pReader->idStr);
+
+ return code;
}
-// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, SMemTable* pMemRef) {
-// STsdbReadHandle* pSecQueryHandle = NULL;
-//
-// if (type == TSDB_PREV_ROW && pTsdbReadHandle->prev) {
-// return TSDB_CODE_SUCCESS;
-// }
-//
-// if (type == TSDB_NEXT_ROW && pTsdbReadHandle->next) {
-// return TSDB_CODE_SUCCESS;
-// }
-//
-// // prepare the structure
-// int32_t numOfCols = (int32_t) QH_GET_NUM_OF_COLS(pTsdbReadHandle);
-//
-// if (type == TSDB_PREV_ROW) {
-// pTsdbReadHandle->prev = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
-// if (pTsdbReadHandle->prev == NULL) {
-// terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
-// goto out_of_memory;
-// }
-// } else {
-// pTsdbReadHandle->next = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
-// if (pTsdbReadHandle->next == NULL) {
-// terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
-// goto out_of_memory;
-// }
-// }
-//
-// SArray* row = (type == TSDB_PREV_ROW)? pTsdbReadHandle->prev : pTsdbReadHandle->next;
-//
-// for (int32_t i = 0; i < numOfCols; ++i) {
-// SColumnInfoData* pCol = taosArrayGet(pTsdbReadHandle->pColumns, i);
-//
-// SColumnInfoData colInfo = {{0}, 0};
-// colInfo.info = pCol->info;
-// colInfo.pData = taosMemoryCalloc(1, pCol->info.bytes);
-// if (colInfo.pData == NULL) {
-// terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
-// goto out_of_memory;
-// }
-//
-// taosArrayPush(row, &colInfo);
-// }
-//
-// // load the previous row
-// SQueryTableDataCond cond = {.numOfCols = numOfCols, .loadExternalRows = false, .type = BLOCK_LOAD_OFFSET_SEQ_ORDER};
-// if (type == TSDB_PREV_ROW) {
-// cond.order = TSDB_ORDER_DESC;
-// cond.twindow = (STimeWindow){pTsdbReadHandle->window.skey, INT64_MIN};
-// } else {
-// cond.order = TSDB_ORDER_ASC;
-// cond.twindow = (STimeWindow){pTsdbReadHandle->window.skey, INT64_MAX};
-// }
-//
-// cond.colList = taosMemoryCalloc(cond.numOfCols, sizeof(SColumnInfo));
-// if (cond.colList == NULL) {
-// terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
-// goto out_of_memory;
-// }
-//
-// for (int32_t i = 0; i < cond.numOfCols; ++i) {
-// SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, i);
-// memcpy(&cond.colList[i], &pColInfoData->info, sizeof(SColumnInfo));
-// }
-//
-// pSecQueryHandle = tsdbQueryTablesImpl(pTsdbReadHandle->pTsdb, &cond, pTsdbReadHandle->idStr, pMemRef);
-// taosMemoryFreeClear(cond.colList);
-//
-// // current table, only one table
-// STableCheckInfo* pCurrent = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
-//
-// SArray* psTable = NULL;
-// pSecQueryHandle->pTableCheckInfo = createCheckInfoFromCheckInfo(pCurrent, pSecQueryHandle->window.skey, &psTable);
-// if (pSecQueryHandle->pTableCheckInfo == NULL) {
-// taosArrayDestroy(psTable);
-// terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
-// goto out_of_memory;
-// }
-//
-//
-// tsdbMayTakeMemSnapshot(pSecQueryHandle, psTable);
-// if (!tsdbNextDataBlock((void*)pSecQueryHandle)) {
-// // no result in current query, free the corresponding result rows structure
-// if (type == TSDB_PREV_ROW) {
-// pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
-// } else {
-// pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
-// }
-//
-// goto out_of_memory;
-// }
-//
-// SDataBlockInfo blockInfo = {{0}, 0};
-// tsdbRetrieveDataBlockInfo((void*)pSecQueryHandle, &blockInfo);
-// tsdbRetrieveDataBlock((void*)pSecQueryHandle, pSecQueryHandle->defaultLoadColumn);
-//
-// row = (type == TSDB_PREV_ROW)? pTsdbReadHandle->prev:pTsdbReadHandle->next;
-// int32_t pos = (type == TSDB_PREV_ROW)?pSecQueryHandle->cur.rows - 1:0;
-//
-// for (int32_t i = 0; i < numOfCols; ++i) {
-// SColumnInfoData* pCol = taosArrayGet(row, i);
-// SColumnInfoData* s = taosArrayGet(pSecQueryHandle->pColumns, i);
-// memcpy((char*)pCol->pData, (char*)s->pData + s->info.bytes * pos, pCol->info.bytes);
-// }
-//
-// out_of_memory:
-// tsdbCleanupReadHandle(pSecQueryHandle);
-// return terrno;
-//}
-
-bool tsdbGetExternalRow(tsdbReaderT pHandle) {
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
- SQueryFilePos* cur = &pTsdbReadHandle->cur;
-
- cur->fid = INT32_MIN;
- cur->mixBlock = true;
- if (pTsdbReadHandle->prev == NULL || pTsdbReadHandle->next == NULL) {
- cur->rows = 0;
- return false;
- }
+SArray* tsdbRetrieveDataBlock(STsdbReader* pReader, SArray* pIdList) {
+ SReaderStatus* pStatus = &pReader->status;
- int32_t numOfCols = (int32_t)QH_GET_NUM_OF_COLS(pTsdbReadHandle);
- for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, i);
- SColumnInfoData* first = taosArrayGet(pTsdbReadHandle->prev, i);
+ if (pStatus->composedDataBlock) {
+ return pReader->pResBlock->pDataBlock;
+ }
- memcpy(pColInfoData->pData, first->pData, pColInfoData->info.bytes);
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pStatus->blockIter);
+ STableBlockScanInfo* pBlockScanInfo = taosHashGet(pStatus->pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
- SColumnInfoData* sec = taosArrayGet(pTsdbReadHandle->next, i);
- memcpy(((char*)pColInfoData->pData) + pColInfoData->info.bytes, sec->pData, pColInfoData->info.bytes);
+ int32_t code = tBlockDataInit(&pStatus->fileBlockData);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return NULL;
+ }
- if (i == 0 && pColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
- cur->win.skey = *(TSKEY*)pColInfoData->pData;
- cur->win.ekey = *(TSKEY*)(((char*)pColInfoData->pData) + TSDB_KEYSIZE);
- }
+ code = doLoadFileBlockData(pReader, &pStatus->blockIter, pBlockScanInfo, &pStatus->fileBlockData);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return NULL;
}
- cur->rows = 2;
- return true;
+ copyBlockDataToSDataBlock(pReader, pBlockScanInfo);
+ return pReader->pResBlock->pDataBlock;
}
-/*
- * if lastRow == NULL, return TSDB_CODE_TDB_NO_CACHE_LAST_ROW
- * else set pRes and return TSDB_CODE_SUCCESS and save lastKey
- */
-// int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey) {
-// int32_t code = TSDB_CODE_SUCCESS;
-//
-// TSDB_RLOCK_TABLE(pTable);
-//
-// if (!pTable->lastRow) {
-// code = TSDB_CODE_TDB_NO_CACHE_LAST_ROW;
-// goto out;
-// }
-//
-// if (pRes) {
-// *pRes = tdMemRowDup(pTable->lastRow);
-// if (*pRes == NULL) {
-// code = TSDB_CODE_TDB_OUT_OF_MEMORY;
-// }
-// }
-//
-// out:
-// TSDB_RUNLOCK_TABLE(pTable);
-// return code;
-//}
-
-bool isTsdbCacheLastRow(tsdbReaderT* pReader) {
- return ((STsdbReadHandle*)pReader)->cachelastrow > TSDB_CACHED_TYPE_NONE;
-}
-
-int32_t checkForCachedLastRow(STsdbReadHandle* pTsdbReadHandle, STableListInfo* tableList) {
- assert(pTsdbReadHandle != NULL && tableList != NULL);
-
- // TSKEY key = TSKEY_INITIAL_VAL;
- //
- // SArray* group = taosArrayGetP(groupList->pGroupList, 0);
- // assert(group != NULL);
- //
- // STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(group, 0);
- //
- // int32_t code = 0;
- //
- // if (((STable*)pInfo->pTable)->lastRow) {
- // code = tsdbGetCachedLastRow(pInfo->pTable, NULL, &key);
- // if (code != TSDB_CODE_SUCCESS) {
- // pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_NONE;
- // } else {
- // pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LASTROW;
- // }
- // }
- //
- // // update the tsdb query time range
- // if (pTsdbReadHandle->cachelastrow != TSDB_CACHED_TYPE_NONE) {
- // pTsdbReadHandle->window = TSWINDOW_INITIALIZER;
- // pTsdbReadHandle->checkFiles = false;
- // pTsdbReadHandle->activeIndex = -1; // start from -1
- // }
+int32_t tsdbReaderReset(STsdbReader* pReader, SQueryTableDataCond* pCond) {
+ if (isEmptyQueryTimeWindow(&pReader->window)) {
+ return TSDB_CODE_SUCCESS;
+ }
- return TSDB_CODE_SUCCESS;
-}
+ pReader->order = pCond->order;
+ pReader->type = BLOCK_LOAD_OFFSET_ORDER;
+ pReader->status.loadFromFile = true;
+ pReader->status.pTableIter = NULL;
-int32_t checkForCachedLast(STsdbReadHandle* pTsdbReadHandle) {
- assert(pTsdbReadHandle != NULL);
+ pReader->window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows);
- int32_t code = 0;
- // if (pTsdbReadHandle->pTsdb && atomic_load_8(&pTsdbReadHandle->pTsdb->hasCachedLastColumn)){
- // pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LAST;
- // }
+ // allocate buffer in order to load data blocks from file
+ memset(&pReader->suppInfo.tsColAgg, 0, sizeof(SColumnDataAgg));
+ memset(pReader->suppInfo.plist, 0, POINTER_BYTES);
- // update the tsdb query time range
- if (pTsdbReadHandle->cachelastrow) {
- pTsdbReadHandle->checkFiles = false;
- pTsdbReadHandle->activeIndex = -1; // start from -1
- }
+ pReader->suppInfo.tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID;
+ tsdbDataFReaderClose(&pReader->pFileReader);
- return code;
-}
-
-STimeWindow updateLastrowForEachGroup(STableListInfo* pList) {
- STimeWindow window = {INT64_MAX, INT64_MIN};
-
- // int32_t totalNumOfTable = 0;
- // SArray* emptyGroup = taosArrayInit(16, sizeof(int32_t));
- //
- // // NOTE: starts from the buffer in case of descending timestamp order check data blocks
- // size_t numOfGroups = taosArrayGetSize(groupList->pGroupList);
- // for (int32_t j = 0; j < numOfGroups; ++j) {
- // SArray* pGroup = taosArrayGetP(groupList->pGroupList, j);
- // TSKEY key = TSKEY_INITIAL_VAL;
- //
- // STableKeyInfo keyInfo = {0};
- //
- // size_t numOfTables = taosArrayGetSize(pGroup);
- // for (int32_t i = 0; i < numOfTables; ++i) {
- // STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i);
- //
- // // if the lastKey equals to INT64_MIN, there is no data in this table
- // TSKEY lastKey = 0; //((STable*)(pInfo->pTable))->lastKey;
- // if (key < lastKey) {
- // key = lastKey;
- //
- // // keyInfo.pTable = pInfo->pTable;
- // keyInfo.lastKey = key;
- // pInfo->lastKey = key;
- //
- // if (key < window.skey) {
- // window.skey = key;
- // }
- //
- // if (key > window.ekey) {
- // window.ekey = key;
- // }
- // }
- // }
- //
- // // more than one table in each group, only one table left for each group
- // // if (keyInfo.pTable != NULL) {
- // // totalNumOfTable++;
- // // if (taosArrayGetSize(pGroup) == 1) {
- // // // do nothing
- // // } else {
- // // taosArrayClear(pGroup);
- // // taosArrayPush(pGroup, &keyInfo);
- // // }
- // // } else { // mark all the empty groups, and remove it later
- // // taosArrayDestroy(pGroup);
- // // taosArrayPush(emptyGroup, &j);
- // // }
- // }
- //
- // // window does not being updated, so set the original
- // if (window.skey == INT64_MAX && window.ekey == INT64_MIN) {
- // window = TSWINDOW_INITIALIZER;
- // assert(totalNumOfTable == 0 && taosArrayGetSize(groupList->pGroupList) == numOfGroups);
- // }
- //
- // taosArrayRemoveBatch(groupList->pGroupList, TARRAY_GET_START(emptyGroup), (int32_t)taosArrayGetSize(emptyGroup));
- // taosArrayDestroy(emptyGroup);
- //
- // groupList->numOfTables = totalNumOfTable;
- return window;
-}
-
-void tsdbRetrieveDataBlockInfo(tsdbReaderT* pTsdbReadHandle, SDataBlockInfo* pDataBlockInfo) {
- STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
- SQueryFilePos* cur = &pHandle->cur;
-
- uint64_t uid = 0;
-
- // there are data in file
- if (pHandle->cur.fid != INT32_MIN) {
- STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[cur->slot];
- uid = pBlockInfo->pTableCheckInfo->tableId;
- } else {
- STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
- uid = pCheckInfo->tableId;
- }
+ // todo set the correct numOfTables
+ int32_t numOfTables = 1;
+ SDataBlockIter* pBlockIter = &pReader->status.blockIter;
- tsdbDebug("data block generated, uid:%" PRIu64 " numOfRows:%d, tsrange:%" PRId64 " - %" PRId64 " %s", uid, cur->rows,
- cur->win.skey, cur->win.ekey, pHandle->idStr);
+ tsdbDataFReaderClose(&pReader->pFileReader);
- pDataBlockInfo->uid = uid;
+ STsdbFSState* pFState = pReader->pTsdb->fs->cState;
+ initFilesetIterator(&pReader->status.fileIter, pFState, pReader->order, pReader->idStr);
+ resetDataBlockIterator(&pReader->status.blockIter, pReader->order);
+ resetDataBlockScanInfo(pReader->status.pTableMap);
-#if 0
- // for multi-group data query processing test purpose
- pDataBlockInfo->groupId = uid;
-#endif
+ int32_t code = 0;
+ // no data in files, let's try buffer in memory
+ if (pReader->status.fileIter.numOfFiles == 0) {
+ pReader->status.loadFromFile = false;
+ } else {
+ code = initForFirstBlockInFile(pReader, pBlockIter);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+ }
- pDataBlockInfo->rows = cur->rows;
- pDataBlockInfo->window = cur->win;
+ tsdbDebug("%p reset reader, suid:%" PRIu64 ", numOfTables:%d, query range:%" PRId64 " - %" PRId64 " in query %s",
+ pReader, pReader->suid, numOfTables, pReader->window.skey, pReader->window.ekey, pReader->idStr);
+ return code;
}
-/*
- * return null for mixed data block, if not a complete file data block, the statistics value will always return NULL
- */
-int32_t tsdbRetrieveDataBlockStatisInfo(tsdbReaderT* pTsdbReadHandle, SColumnDataAgg*** pBlockStatis, bool* allHave) {
- STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
- *allHave = false;
+static int32_t getBucketIndex(int32_t startRow, int32_t bucketRange, int32_t numOfRows) {
+ return (numOfRows - startRow) / bucketRange;
+}
- SQueryFilePos* c = &pHandle->cur;
- if (c->mixBlock) {
- *pBlockStatis = NULL;
- return TSDB_CODE_SUCCESS;
- }
+int32_t tsdbGetFileBlocksDistInfo(STsdbReader* pReader, STableBlockDistInfo* pTableBlockInfo) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ pTableBlockInfo->totalSize = 0;
+ pTableBlockInfo->totalRows = 0;
- STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[c->slot];
- assert((c->slot >= 0 && c->slot < pHandle->numOfBlocks) || ((c->slot == pHandle->numOfBlocks) && (c->slot == 0)));
+ // find the start data block in file
+ SReaderStatus* pStatus = &pReader->status;
- // file block with sub-blocks has no statistics data
- if (pBlockInfo->compBlock->numOfSubBlocks > 1) {
- *pBlockStatis = NULL;
- return TSDB_CODE_SUCCESS;
- }
+ STsdbCfg* pc = &pReader->pTsdb->pVnode->config.tsdbCfg;
+ pTableBlockInfo->defMinRows = pc->minRows;
+ pTableBlockInfo->defMaxRows = pc->maxRows;
- int64_t stime = taosGetTimestampUs();
- int statisStatus = tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock);
- if (statisStatus < TSDB_STATIS_OK) {
- return terrno;
- } else if (statisStatus > TSDB_STATIS_OK) {
- *pBlockStatis = NULL;
- return TSDB_CODE_SUCCESS;
- }
+ int32_t bucketRange = ceil((pc->maxRows - pc->minRows) / 20.0);
- tsdbDebug("vgId:%d, succeed to load block statis part for uid %" PRIu64, REPO_ID(pHandle->pTsdb),
- TSDB_READ_TABLE_UID(&pHandle->rhelper));
+ pTableBlockInfo->numOfFiles += 1;
- int16_t* colIds = pHandle->suppInfo.defaultLoadColumn->pData;
+ int32_t numOfTables = (int32_t)taosHashGetSize(pStatus->pTableMap);
+ int defaultRows = 4096;
- size_t numOfCols = QH_GET_NUM_OF_COLS(pHandle);
- memset(pHandle->suppInfo.plist, 0, numOfCols * POINTER_BYTES);
- memset(pHandle->suppInfo.pstatis, 0, numOfCols * sizeof(SColumnDataAgg));
+ SDataBlockIter* pBlockIter = &pStatus->blockIter;
+ pTableBlockInfo->numOfFiles += pStatus->fileIter.numOfFiles;
- for (int32_t i = 0; i < numOfCols; ++i) {
- pHandle->suppInfo.pstatis[i].colId = colIds[i];
+ if (pBlockIter->numOfBlocks > 0) {
+ pTableBlockInfo->numOfBlocks += pBlockIter->numOfBlocks;
}
- *allHave = true;
- tsdbGetBlockStatis(&pHandle->rhelper, pHandle->suppInfo.pstatis, (int)numOfCols, pBlockInfo->compBlock);
+ pTableBlockInfo->numOfTables = numOfTables;
+ bool hasNext = (pBlockIter->numOfBlocks > 0);
- // always load the first primary timestamp column data
- SColumnDataAgg* pPrimaryColStatis = &pHandle->suppInfo.pstatis[0];
- assert(pPrimaryColStatis->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
+ while (true) {
+ if (hasNext) {
+ SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(pBlockIter);
+ STableBlockScanInfo* pScanInfo = taosHashGet(pStatus->pTableMap, &pFBlock->uid, sizeof(pFBlock->uid));
+ SBlock* pBlock = taosArrayGet(pScanInfo->pBlockList, pFBlock->tbBlockIdx);
- pPrimaryColStatis->numOfNull = 0;
- pPrimaryColStatis->min = pBlockInfo->compBlock->minKey.ts;
- pPrimaryColStatis->max = pBlockInfo->compBlock->maxKey.ts;
- pHandle->suppInfo.plist[0] = &pHandle->suppInfo.pstatis[0];
+ int32_t numOfRows = pBlock->nRow;
+ pTableBlockInfo->totalRows += numOfRows;
- // update the number of NULL data rows
- int32_t* slotIds = pHandle->suppInfo.slotIds;
- for (int32_t i = 1; i < numOfCols; ++i) {
- ASSERT(colIds[i] == pHandle->pSchema->columns[slotIds[i]].colId);
- if (IS_BSMA_ON(&(pHandle->pSchema->columns[slotIds[i]]))) {
- if (pHandle->suppInfo.pstatis[i].numOfNull == -1) { // set the column data are all NULL
- pHandle->suppInfo.pstatis[i].numOfNull = pBlockInfo->compBlock->numOfRows;
+ if (numOfRows > pTableBlockInfo->maxRows) {
+ pTableBlockInfo->maxRows = numOfRows;
}
- pHandle->suppInfo.plist[i] = &pHandle->suppInfo.pstatis[i];
- } else {
- *allHave = false;
- }
- }
+ if (numOfRows < pTableBlockInfo->minRows) {
+ pTableBlockInfo->minRows = numOfRows;
+ }
- int64_t elapsed = taosGetTimestampUs() - stime;
- pHandle->cost.statisInfoLoadTime += elapsed;
+ if (numOfRows < defaultRows) {
+ pTableBlockInfo->numOfSmallBlocks += 1;
+ }
- *pBlockStatis = pHandle->suppInfo.plist;
- return TSDB_CODE_SUCCESS;
-}
+ int32_t bucketIndex = getBucketIndex(pTableBlockInfo->defMinRows, bucketRange, numOfRows);
+ pTableBlockInfo->blockRowsHisto[bucketIndex]++;
-SArray* tsdbRetrieveDataBlock(tsdbReaderT* pTsdbReadHandle, SArray* pIdList) {
- /**
- * In the following two cases, the data has been loaded to SColumnInfoData.
- * 1. data is from cache, 2. data block is not completed qualified to query time range
- */
- STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
- if (pHandle->cur.fid == INT32_MIN) {
- return pHandle->pColumns;
- } else {
- STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[pHandle->cur.slot];
- STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
+ hasNext = blockIteratorNext(&pStatus->blockIter);
- if (pHandle->cur.mixBlock) {
- return pHandle->pColumns;
} else {
- SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlockInfo->compBlock);
- assert(pHandle->realNumOfRows <= binfo.rows);
-
- // data block has been loaded, todo extract method
- SDataBlockLoadInfo* pBlockLoadInfo = &pHandle->dataBlockLoadInfo;
-
- if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fid == pHandle->cur.fid &&
- pBlockLoadInfo->uid == pCheckInfo->tableId) {
- return pHandle->pColumns;
- } else { // only load the file block
- SBlock* pBlock = pBlockInfo->compBlock;
- if (doLoadFileDataBlock(pHandle, pBlock, pCheckInfo, pHandle->cur.slot) != TSDB_CODE_SUCCESS) {
- return NULL;
- }
-
- int32_t numOfRows = doCopyRowsFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfRows - 1);
- return pHandle->pColumns;
+ code = initForFirstBlockInFile(pReader, pBlockIter);
+ if ((code != TSDB_CODE_SUCCESS) || (pReader->status.loadFromFile == false)) {
+ break;
}
- }
- }
-}
-static int tsdbCheckInfoCompar(const void* key1, const void* key2) {
- if (((STableCheckInfo*)key1)->tableId < ((STableCheckInfo*)key2)->tableId) {
- return -1;
- } else if (((STableCheckInfo*)key1)->tableId > ((STableCheckInfo*)key2)->tableId) {
- return 1;
- } else {
- ASSERT(false);
- return 0;
- }
-}
+ pTableBlockInfo->numOfBlocks += pBlockIter->numOfBlocks;
+ }
-static void* doFreeColumnInfoData(SArray* pColumnInfoData) {
- if (pColumnInfoData == NULL) {
- return NULL;
- }
+ /*
+ hasNext = blockIteratorNext(&pStatus->blockIter);
+ */
- size_t cols = taosArrayGetSize(pColumnInfoData);
- for (int32_t i = 0; i < cols; ++i) {
- SColumnInfoData* pColInfo = taosArrayGet(pColumnInfoData, i);
- colDataDestroy(pColInfo);
+ // tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pReader, numOfBlocks, numOfTables,
+ // pReader->pFileGroup->fid, pReader->idStr);
}
- taosArrayDestroy(pColumnInfoData);
- return NULL;
+ return code;
}
-static void* destroyTableCheckInfo(SArray* pTableCheckInfo) {
- size_t size = taosArrayGetSize(pTableCheckInfo);
- for (int32_t i = 0; i < size; ++i) {
- STableCheckInfo* p = taosArrayGet(pTableCheckInfo, i);
- destroyTableMemIterator(p);
+int64_t tsdbGetNumOfRowsInMemTable(STsdbReader* pReader) {
+ int64_t rows = 0;
- taosMemoryFreeClear(p->pCompInfo);
- }
+ SReaderStatus* pStatus = &pReader->status;
+ pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, NULL);
- taosArrayDestroy(pTableCheckInfo);
- return NULL;
-}
+ while (pStatus->pTableIter != NULL) {
+ STableBlockScanInfo* pBlockScanInfo = pStatus->pTableIter;
-void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
- STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
- if (pTsdbReadHandle == NULL) {
- return;
- }
-
- pTsdbReadHandle->pColumns = doFreeColumnInfoData(pTsdbReadHandle->pColumns);
+ STbData* d = NULL;
+ if (pReader->pTsdb->mem != NULL) {
+ tsdbGetTbDataFromMemTable(pReader->pTsdb->mem, pReader->suid, pBlockScanInfo->uid, &d);
+ if (d != NULL) {
+ rows += tsdbGetNRowsInTbData(d);
+ }
+ }
- taosArrayDestroy(pTsdbReadHandle->suppInfo.defaultLoadColumn);
- taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
- taosMemoryFreeClear(pTsdbReadHandle->suppInfo.pstatis);
- taosMemoryFreeClear(pTsdbReadHandle->suppInfo.plist);
- taosMemoryFree(pTsdbReadHandle->suppInfo.slotIds);
+ STbData* di = NULL;
+ if (pReader->pTsdb->imem != NULL) {
+ tsdbGetTbDataFromMemTable(pReader->pTsdb->imem, pReader->suid, pBlockScanInfo->uid, &di);
+ if (di != NULL) {
+ rows += tsdbGetNRowsInTbData(di);
+ }
+ }
- if (!emptyQueryTimewindow(pTsdbReadHandle)) {
- // tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
- } else {
- assert(pTsdbReadHandle->pTableCheckInfo == NULL);
+ // current table is exhausted, let's try the next table
+ pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, pStatus->pTableIter);
}
- if (pTsdbReadHandle->pTableCheckInfo != NULL) {
- pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
- }
+ return rows;
+}
- tsdbDestroyReadH(&pTsdbReadHandle->rhelper);
+int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int64_t* suid) {
+ int32_t sversion = 1;
- tdFreeDataCols(pTsdbReadHandle->pDataCols);
- pTsdbReadHandle->pDataCols = NULL;
+ SMetaReader mr = {0};
+ metaReaderInit(&mr, pVnode->pMeta, 0);
+ int32_t code = metaGetTableEntryByUid(&mr, uid);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
+ metaReaderClear(&mr);
+ return terrno;
+ }
- pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
- pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
+ *suid = 0;
- SIOCostSummary* pCost = &pTsdbReadHandle->cost;
+ if (mr.me.type == TSDB_CHILD_TABLE) {
+ *suid = mr.me.ctbEntry.suid;
+ code = metaGetTableEntryByUid(&mr, *suid);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
+ metaReaderClear(&mr);
+ return terrno;
+ }
+ sversion = mr.me.stbEntry.schemaRow.version;
+ } else {
+ ASSERT(mr.me.type == TSDB_NORMAL_TABLE);
+ sversion = mr.me.ntbEntry.schemaRow.version;
+ }
- tsdbDebug("%p :io-cost summary: head-file read cnt:%" PRIu64 ", head-file time:%" PRIu64 " us, statis-info:%" PRId64
- " us, datablock:%" PRId64 " us, check data:%" PRId64 " us, %s",
- pTsdbReadHandle, pCost->headFileLoad, pCost->headFileLoadTime, pCost->statisInfoLoadTime,
- pCost->blockLoadTime, pCost->checkForNextTime, pTsdbReadHandle->idStr);
+ metaReaderClear(&mr);
+ *pSchema = metaGetTbTSchema(pVnode->pMeta, uid, sversion);
- taosMemoryFree(pTsdbReadHandle->idStr);
- taosMemoryFree(pTsdbReadHandle->pSchema);
- taosMemoryFreeClear(pTsdbReadHandle);
+ return TSDB_CODE_SUCCESS;
}
+
diff --git a/source/dnode/vnode/src/tsdb/tsdbReadImpl.c b/source/dnode/vnode/src/tsdb/tsdbReadImpl.c
deleted file mode 100644
index 1c2514d46f2c04125b2d763ca5ffa2fb68d307cb..0000000000000000000000000000000000000000
--- a/source/dnode/vnode/src/tsdb/tsdbReadImpl.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#include "tsdb.h"
-
-#define TSDB_KEY_COL_OFFSET 0
-
-static void tsdbResetReadTable(SReadH *pReadh);
-static void tsdbResetReadFile(SReadH *pReadh);
-static int tsdbLoadBlockOffset(SReadH *pReadh, SBlock *pBlock);
-static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, int8_t bitmapMode);
-static int tsdbCheckAndDecodeColumnData(SDataCol *pDataCol, void *content, int32_t len, int32_t bitmapLen, int8_t comp,
- int numOfRows, int numOfBitmaps, int maxPoints, char *buffer, int bufferSize);
-static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, const int16_t *colIds,
- int numOfColIds, int8_t bitmapMode);
-static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBlockCol *pBlockCol, SDataCol *pDataCol);
-
-int tsdbInitReadH(SReadH *pReadh, STsdb *pRepo) {
- ASSERT(pReadh != NULL && pRepo != NULL);
-
- STsdbCfg *pCfg = REPO_CFG(pRepo);
-
- memset((void *)pReadh, 0, sizeof(*pReadh));
- pReadh->pRepo = pRepo;
-
- TSDB_FSET_SET_CLOSED(TSDB_READ_FSET(pReadh));
-
- pReadh->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
- if (pReadh->aBlkIdx == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
-
- pReadh->pDCols[0] = tdNewDataCols(0, pCfg->maxRows);
- if (pReadh->pDCols[0] == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyReadH(pReadh);
- return -1;
- }
-
- pReadh->pDCols[1] = tdNewDataCols(0, pCfg->maxRows);
- if (pReadh->pDCols[1] == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- tsdbDestroyReadH(pReadh);
- return -1;
- }
-
- return 0;
-}
-
-void tsdbDestroyReadH(SReadH *pReadh) {
- if (pReadh == NULL) return;
-
- pReadh->pExBuf = taosTZfree(pReadh->pExBuf);
- pReadh->pCBuf = taosTZfree(pReadh->pCBuf);
- pReadh->pBuf = taosTZfree(pReadh->pBuf);
- pReadh->pDCols[0] = tdFreeDataCols(pReadh->pDCols[0]);
- pReadh->pDCols[1] = tdFreeDataCols(pReadh->pDCols[1]);
- pReadh->pAggrBlkData = taosTZfree(pReadh->pAggrBlkData);
- pReadh->pBlkData = taosTZfree(pReadh->pBlkData);
- pReadh->pBlkInfo = taosTZfree(pReadh->pBlkInfo);
- pReadh->cidx = 0;
- pReadh->pBlkIdx = NULL;
- pReadh->pTable = NULL;
- pReadh->aBlkIdx = taosArrayDestroy(pReadh->aBlkIdx);
- tsdbCloseDFileSet(TSDB_READ_FSET(pReadh));
- pReadh->pRepo = NULL;
-}
-
-int tsdbSetAndOpenReadFSet(SReadH *pReadh, SDFileSet *pSet) {
- ASSERT(pSet != NULL);
- tsdbResetReadFile(pReadh);
-
- pReadh->rSet = *pSet;
- TSDB_FSET_SET_CLOSED(TSDB_READ_FSET(pReadh));
- // if (tsdbOpenDFileSet(TSDB_READ_FSET(pReadh), O_RDONLY) < 0) {
- if (tsdbOpenDFileSet(TSDB_READ_FSET(pReadh), TD_FILE_READ) < 0) {
- tsdbError("vgId:%d, failed to open file set %d since %s", TSDB_READ_REPO_ID(pReadh), TSDB_FSET_FID(pSet),
- tstrerror(terrno));
- return -1;
- }
-
- return 0;
-}
-
-void tsdbCloseAndUnsetFSet(SReadH *pReadh) { tsdbResetReadFile(pReadh); }
-
-int tsdbLoadBlockIdx(SReadH *pReadh) {
- SDFile *pHeadf = TSDB_READ_HEAD_FILE(pReadh);
- SBlockIdx blkIdx;
-
- ASSERT(taosArrayGetSize(pReadh->aBlkIdx) == 0);
-
- // No data at all, just return
- if (pHeadf->info.offset <= 0) return 0;
-
- if (tsdbSeekDFile(pHeadf, pHeadf->info.offset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load SBlockIdx part while seek file %s since %s, offset:%u len :%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pHeadf->info.offset,
- pHeadf->info.len);
- return -1;
- }
-
- if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pHeadf->info.len) < 0) return -1;
-
- int64_t nread = tsdbReadDFile(pHeadf, TSDB_READ_BUF(pReadh), pHeadf->info.len);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to load SBlockIdx part while read file %s since %s, offset:%u len :%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pHeadf->info.offset,
- pHeadf->info.len);
- return -1;
- }
-
- if (nread < pHeadf->info.len) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, SBlockIdx part in file %s is corrupted, offset:%u expected bytes:%u read bytes: %" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pHeadf->info.offset, pHeadf->info.len, nread);
- return -1;
- }
-
- if (!taosCheckChecksumWhole((uint8_t *)TSDB_READ_BUF(pReadh), pHeadf->info.len)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, SBlockIdx part in file %s is corrupted since wrong checksum, offset:%u len :%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pHeadf->info.offset, pHeadf->info.len);
- return -1;
- }
-
- void *ptr = TSDB_READ_BUF(pReadh);
- int tsize = 0;
- while (POINTER_DISTANCE(ptr, TSDB_READ_BUF(pReadh)) < (pHeadf->info.len - sizeof(TSCKSUM))) {
- ptr = tsdbDecodeSBlockIdx(ptr, &blkIdx);
- ASSERT(ptr != NULL);
-
- if (taosArrayPush(pReadh->aBlkIdx, (void *)(&blkIdx)) == NULL) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
-
- tsize++;
- // ASSERT(tsize == 1 || ((SBlockIdx *)taosArrayGet(pReadh->aBlkIdx, tsize - 2))->tid <
- // ((SBlockIdx *)taosArrayGet(pReadh->aBlkIdx, tsize - 1))->tid);
- }
-
- return 0;
-}
-
-static int32_t tsdbBlockIdxCmprFn(const void *p1, const void *p2) {
- SBlockIdx *pBlockIdx1 = (SBlockIdx *)p1;
- SBlockIdx *pBlockIdx2 = (SBlockIdx *)p2;
-
- if (pBlockIdx1->suid < pBlockIdx2->suid) {
- return -1;
- } else if (pBlockIdx1->suid > pBlockIdx2->suid) {
- return 1;
- }
-
- if (pBlockIdx1->uid < pBlockIdx2->uid) {
- return -1;
- } else if (pBlockIdx1->uid > pBlockIdx2->uid) {
- return 1;
- }
-
- return 0;
-}
-int tsdbSetReadTable(SReadH *pReadh, STable *pTable) {
- STSchema *pSchema = tsdbGetTableSchemaImpl(TSDB_READ_REPO(pReadh), pTable, false, false, -1);
-
- pReadh->pTable = pTable;
-
- if (tdInitDataCols(pReadh->pDCols[0], pSchema) < 0) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
-
- if (tdInitDataCols(pReadh->pDCols[1], pSchema) < 0) {
- terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
- return -1;
- }
-
- uint8_t *p = taosArraySearch(pReadh->aBlkIdx, &(SBlockIdx){.suid = pTable->suid, .uid = pTable->uid},
- tsdbBlockIdxCmprFn, TD_EQ);
- if (p == NULL) {
- pReadh->pBlkIdx = NULL;
- } else {
- pReadh->pBlkIdx = (SBlockIdx *)p;
- }
-
- return 0;
-}
-
-int tsdbLoadBlockInfo(SReadH *pReadh, void *pTarget) {
- ASSERT(pReadh->pBlkIdx != NULL);
-
- SDFile *pHeadf = TSDB_READ_HEAD_FILE(pReadh);
- SBlockIdx *pBlkIdx = pReadh->pBlkIdx;
-
- if (tsdbSeekDFile(pHeadf, pBlkIdx->offset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load SBlockInfo part while seek file %s since %s, offset:%u len:%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
- return -1;
- }
-
- if (tsdbMakeRoom((void **)(&(pReadh->pBlkInfo)), pBlkIdx->len) < 0) return -1;
-
- int64_t nread = tsdbReadDFile(pHeadf, (void *)(pReadh->pBlkInfo), pBlkIdx->len);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to load SBlockInfo part while read file %s since %s, offset:%u len :%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
- return -1;
- }
-
- if (nread < pBlkIdx->len) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, SBlockInfo part in file %s is corrupted, offset:%u expected bytes:%u read bytes:%" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len, nread);
- return -1;
- }
-
- if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pBlkInfo), pBlkIdx->len)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, SBlockInfo part in file %s is corrupted since wrong checksum, offset:%u len :%u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len);
- return -1;
- }
-
- // ASSERT(pBlkIdx->tid == pReadh->pBlkInfo->tid && pBlkIdx->uid == pReadh->pBlkInfo->uid);
-
- if (pTarget) {
- memcpy(pTarget, (void *)(pReadh->pBlkInfo), pBlkIdx->len);
- }
-
- return 0;
-}
-
-static FORCE_INLINE void tsdbSwapDataCols(SDataCols *pDest, SDataCols *pSrc) {
- SDataCol *pCols = pDest->cols;
- memcpy(pDest, pSrc, sizeof(SDataCols));
- pSrc->cols = pCols;
-}
-
-static void printTsdbLoadBlkData(SReadH *readh, SDataCols *pDCols, SBlock *pBlock, const char *tag, int32_t ln) {
- printf("%s:%d:%" PRIi64 " ================\n", tag, ln, taosGetSelfPthreadId());
- if (pBlock) {
- SDFile *pHeadf = TSDB_READ_HEAD_FILE(readh);
- printf("%s:%d:%" PRIi64 ":%p:%d %s\n", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- pHeadf->f.aname);
- SDFile *pDFile = pBlock->last ? TSDB_READ_LAST_FILE(readh) : TSDB_READ_DATA_FILE(readh);
- printf("%s:%d:%" PRIi64 ":%p:%d %s\n", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- pDFile->f.aname);
- }
- SDataCol *pDCol = pDCols->cols + 0;
- if (TSKEY_MIN == *(int64_t *)pDCol->pData) {
- ASSERT(0);
- }
-
- int rows = pDCols->numOfRows;
- for (int r = 0; r < rows; ++r) {
- if (pBlock) {
- printf("%s:%d:%" PRIi64 ":%p:%d rows[%d][%d] ", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- rows, r);
- } else {
- printf("%s:%d:%" PRIi64 ":%s rows[%d][%d] ", tag, ln, taosGetSelfPthreadId(), "=== merge === ", rows, r);
- }
-
- int nDataCols = pDCols->numOfCols;
- int j = 0;
- SCellVal sVal = {0};
- while (j < nDataCols) {
- SDataCol *pDataCol = pDCols->cols + j;
- tdGetColDataOfRow(&sVal, pDataCol, r, pDCols->bitmapMode);
- tdSCellValPrint(&sVal, pDataCol->type);
- ++j;
- }
- printf("\n");
- }
-
- fflush(stdout);
-}
-
-int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo) {
- ASSERT(pBlock->numOfSubBlocks > 0);
- STsdbCfg *pCfg = REPO_CFG(pReadh->pRepo);
- int8_t update = pCfg->update;
-
- SBlock *iBlock = pBlock;
- if (pBlock->numOfSubBlocks > 1) {
- if (pBlkInfo) {
- iBlock = (SBlock *)POINTER_SHIFT(pBlkInfo, pBlock->offset);
- } else {
- iBlock = (SBlock *)POINTER_SHIFT(pReadh->pBlkInfo, pBlock->offset);
- }
- }
-
- if (tsdbLoadBlockDataImpl(pReadh, iBlock, pReadh->pDCols[0], TSDB_BITMODE_ONE_BIT) < 0) return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkData(pReadh, pReadh->pDCols[0], iBlock, __func__, __LINE__);
-#endif
- for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
- iBlock++;
- if (tsdbLoadBlockDataImpl(pReadh, iBlock, pReadh->pDCols[1], TSDB_BITMODE_DEFAULT) < 0) return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkData(pReadh, pReadh->pDCols[1], iBlock, __func__, __LINE__);
-#endif
- // TODO: use the real maxVersion to replace the UINT64_MAX to support Multi-Version
- if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL,
- TD_SUPPORT_UPDATE(update), TD_VER_MAX) < 0)
- return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkData(pReadh, pReadh->pDCols[0], iBlock, " === MERGE === ", __LINE__);
-#endif
- }
- // if ((pBlock->numOfSubBlocks == 1) && (iBlock->hasDupKey)) { // TODO: use this line
- if (pBlock->numOfSubBlocks == 1) {
- tdResetDataCols(pReadh->pDCols[1]);
- pReadh->pDCols[1]->bitmapMode = pReadh->pDCols[0]->bitmapMode;
- if (tdMergeDataCols(pReadh->pDCols[1], pReadh->pDCols[0], pReadh->pDCols[0]->numOfRows, NULL,
- TD_SUPPORT_UPDATE(update), TD_VER_MAX) < 0) {
- return -1;
- }
- tsdbSwapDataCols(pReadh->pDCols[0], pReadh->pDCols[1]);
- ASSERT(pReadh->pDCols[0]->bitmapMode != 0);
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkData(pReadh, pReadh->pDCols[0], iBlock, " === UPDATE FILTER === ", __LINE__);
-#endif
- }
-
- ASSERT(pReadh->pDCols[0]->numOfRows <= pBlock->numOfRows);
- ASSERT(dataColsKeyFirst(pReadh->pDCols[0]) == pBlock->minKey.ts);
- ASSERT(dataColsKeyLast(pReadh->pDCols[0]) == pBlock->maxKey.ts);
-
- return 0;
-}
-
-static void printTsdbLoadBlkDataCols(SReadH *readh, SDataCols *pDCols, SBlock *pBlock, const int16_t *colIds,
- int numOfColsIds, const char *tag, int32_t ln) {
- printf("%s:%d:%" PRIi64 " ================\n", tag, ln, taosGetSelfPthreadId());
- if (pBlock) {
- SDFile *pHeadf = TSDB_READ_HEAD_FILE(readh);
- printf("%s:%d:%" PRIi64 ":%p:%d %s\n", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- pHeadf->f.aname);
- SDFile *pDFile = pBlock->last ? TSDB_READ_LAST_FILE(readh) : TSDB_READ_DATA_FILE(readh);
- printf("%s:%d:%" PRIi64 ":%p:%d %s\n", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- pDFile->f.aname);
- }
-
- int rows = pDCols->numOfRows;
- for (int r = 0; r < rows; ++r) {
- if (pBlock) {
- printf("%s:%d:%" PRIi64 ":%p:%d rows[%d][%d] ", tag, ln, taosGetSelfPthreadId(), pBlock, (int32_t)pBlock->len,
- rows, r);
- } else {
- printf("%s:%d:%" PRIi64 ":%s rows[%d][%d] ", tag, ln, taosGetSelfPthreadId(), "=== merge === ", rows, r);
- }
-
- int nDataCols = pDCols->numOfCols;
- int j = 0, k = 0;
- SCellVal sVal = {0};
- while (j < nDataCols) {
- if (k >= numOfColsIds) break;
- SDataCol *pDataCol = pDCols->cols + j;
- int16_t colId1 = pDataCol->colId;
- int16_t colId2 = *(colIds + k);
- if (colId1 < colId2) {
- ++j;
- } else if (colId1 > colId2) {
- ++k; // colId2 not exists in SDataCols
- printf("NotExists ");
- } else {
- tdGetColDataOfRow(&sVal, pDataCol, r, pDCols->bitmapMode);
- tdSCellValPrint(&sVal, pDataCol->type);
- ++j;
- ++k;
- }
- }
- printf("\n");
- }
-
- fflush(stdout);
-}
-
-// TODO: filter by Multi-Version
-int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo, const int16_t *colIds, int numOfColsIds,
- bool mergeBitmap) {
- ASSERT(pBlock->numOfSubBlocks > 0);
- int8_t update = pReadh->pRepo->pVnode->config.tsdbCfg.update;
-
- SBlock *iBlock = pBlock;
- if (pBlock->numOfSubBlocks > 1) {
- if (pBlkInfo) {
- iBlock = POINTER_SHIFT(pBlkInfo, pBlock->offset);
- } else {
- iBlock = POINTER_SHIFT(pReadh->pBlkInfo, pBlock->offset);
- }
- }
-
- if (tsdbLoadBlockDataColsImpl(pReadh, iBlock, pReadh->pDCols[0], colIds, numOfColsIds, TSDB_BITMODE_ONE_BIT) < 0)
- return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkDataCols(pReadh, pReadh->pDCols[0], iBlock, colIds, numOfColsIds, __func__, __LINE__);
-#endif
- for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
- iBlock++;
- if (tsdbLoadBlockDataColsImpl(pReadh, iBlock, pReadh->pDCols[1], colIds, numOfColsIds, TSDB_BITMODE_DEFAULT) < 0)
- return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkDataCols(pReadh, pReadh->pDCols[1], iBlock, colIds, numOfColsIds, __func__, __LINE__);
-#endif
- // TODO: use the real maxVersion to replace the UINT64_MAX to support Multi-Version
- if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL,
- TD_SUPPORT_UPDATE(update), TD_VER_MAX) < 0)
- return -1;
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkDataCols(pReadh, pReadh->pDCols[0], NULL, colIds, numOfColsIds, __func__, __LINE__);
-#endif
- }
- // if ((pBlock->numOfSubBlocks == 1) && (iBlock->hasDupKey)) { // TODO: use this line
- if (pBlock->numOfSubBlocks == 1) {
- tdResetDataCols(pReadh->pDCols[1]);
- pReadh->pDCols[1]->bitmapMode = pReadh->pDCols[0]->bitmapMode;
- if (tdMergeDataCols(pReadh->pDCols[1], pReadh->pDCols[0], pReadh->pDCols[0]->numOfRows, NULL,
- TD_SUPPORT_UPDATE(update), TD_VER_MAX) < 0) {
- return -1;
- }
- tsdbSwapDataCols(pReadh->pDCols[0], pReadh->pDCols[1]);
- ASSERT(pReadh->pDCols[0]->bitmapMode != 0);
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkDataCols(pReadh, pReadh->pDCols[0], NULL, colIds, numOfColsIds,
- " === update filter === ", __LINE__);
-#endif
- }
-
- if (mergeBitmap && !tdDataColsIsBitmapI(pReadh->pDCols[0])) {
- for (int i = 0; i < numOfColsIds; ++i) {
- SDataCol *pDataCol = pReadh->pDCols[0]->cols + i;
- if (pDataCol->len > 0 && pDataCol->bitmap) {
- tdMergeBitmap(pDataCol->pBitmap, pReadh->pDCols[0]->numOfRows, pDataCol->pBitmap);
- tdDataColsSetBitmapI(pReadh->pDCols[0]);
- }
- }
-#ifdef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
- printTsdbLoadBlkDataCols(pReadh, pReadh->pDCols[0], NULL, colIds, numOfColsIds, " === merge bitmap === ", __LINE__);
-#endif
- }
-
- ASSERT(pReadh->pDCols[0]->numOfRows <= pBlock->numOfRows);
- ASSERT(dataColsKeyFirst(pReadh->pDCols[0]) == pBlock->minKey.ts);
- ASSERT(dataColsKeyLast(pReadh->pDCols[0]) == pBlock->maxKey.ts);
-
- return 0;
-}
-
-int tsdbLoadBlockStatis(SReadH *pReadh, SBlock *pBlock) {
- ASSERT(pBlock->numOfSubBlocks <= 1);
-
- if (!pBlock->aggrStat) {
- tsdbDebug("vgId:%d, no need to load block statis part for uid %" PRIu64 " since not exist", REPO_ID(pReadh->pRepo),
- TSDB_READ_TABLE_UID(pReadh));
- return TSDB_STATIS_NONE;
- }
-
- SDFile *pDFileAggr = pBlock->last ? TSDB_READ_SMAL_FILE(pReadh) : TSDB_READ_SMAD_FILE(pReadh);
-
- if (tsdbSeekDFile(pDFileAggr, pBlock->aggrOffset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load block statis part for uid %" PRIu64 " while seek file %s to offset %" PRIu64
- " since %s",
- TSDB_READ_REPO_ID(pReadh), TSDB_READ_TABLE_UID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr),
- (uint64_t)pBlock->aggrOffset, tstrerror(terrno));
- return -1;
- }
-
- size_t sizeAggr = tsdbBlockAggrSize(pBlock->numOfBSma, (uint32_t)pBlock->blkVer);
- if (tsdbMakeRoom((void **)(&(pReadh->pAggrBlkData)), sizeAggr) < 0) return -1;
-
- int64_t nreadAggr = tsdbReadDFile(pDFileAggr, (void *)(pReadh->pAggrBlkData), sizeAggr);
- if (nreadAggr < 0) {
- tsdbError("vgId:%d, failed to load block statis part for uid %" PRIu64
- " while read file %s since %s, offset:%" PRIu64 " len :%" PRIzu,
- TSDB_READ_REPO_ID(pReadh), TSDB_READ_TABLE_UID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr),
- tstrerror(terrno), (uint64_t)pBlock->aggrOffset, sizeAggr);
- return -1;
- }
-
- if (nreadAggr < sizeAggr) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block statis part for uid %" PRIu64 " in file %s is corrupted, offset:%" PRIu64
- " expected bytes:%" PRIzu " read bytes: %" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_READ_TABLE_UID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr),
- (uint64_t)pBlock->aggrOffset, sizeAggr, nreadAggr);
- return -1;
- }
-
- if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pAggrBlkData), (uint32_t)sizeAggr)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block statis part for uid %" PRIu64
- "in file %s is corrupted since wrong checksum, offset:%" PRIu64 " len :%" PRIzu,
- TSDB_READ_REPO_ID(pReadh), TSDB_READ_TABLE_UID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr),
- (uint64_t)pBlock->aggrOffset, sizeAggr);
- return -1;
- }
- return 0;
-}
-
-static int tsdbLoadBlockOffset(SReadH *pReadh, SBlock *pBlock) {
- ASSERT(pBlock->numOfSubBlocks <= 1);
- SDFile *pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
- if (tsdbSeekDFile(pDFile, pBlock->offset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load block head part while seek file %s to offset %" PRId64 " since %s",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tstrerror(terrno));
- return -1;
- }
-
- size_t size = tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer);
- if (tsdbMakeRoom((void **)(&(pReadh->pBlkData)), size) < 0) return -1;
-
- int64_t nread = tsdbReadDFile(pDFile, (void *)(pReadh->pBlkData), size);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to load block head part while read file %s since %s, offset:%" PRId64 " len :%" PRIzu,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), (int64_t)pBlock->offset, size);
- return -1;
- }
-
- if (nread < size) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block head part in file %s is corrupted, offset:%" PRId64 " expected bytes:%" PRIzu
- " read bytes: %" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, size, nread);
- return -1;
- }
-
- if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pBlkData), (uint32_t)size)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block head part in file %s is corrupted since wrong checksum, offset:%" PRId64 " len :%" PRIzu,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, size);
- return -1;
- }
- return 0;
-}
-
-int tsdbEncodeSBlockIdx(void **buf, SBlockIdx *pIdx) {
- int tlen = 0;
-
- tlen += taosEncodeFixedU64(buf, pIdx->suid);
- tlen += taosEncodeFixedU64(buf, pIdx->uid);
- tlen += taosEncodeVariantU32(buf, pIdx->len);
- tlen += taosEncodeVariantU32(buf, pIdx->offset);
- tlen += taosEncodeFixedU8(buf, pIdx->hasLast);
- tlen += taosEncodeVariantU32(buf, pIdx->numOfBlocks);
- tlen += taosEncodeFixedU64(buf, pIdx->maxKey.ts);
-
- return tlen;
-}
-
-void *tsdbDecodeSBlockIdx(void *buf, SBlockIdx *pIdx) {
- uint8_t hasLast = 0;
- uint32_t numOfBlocks = 0;
- uint64_t value = 0;
-
- // if ((buf = taosDecodeVariantI32(buf, &(pIdx->tid))) == NULL) return NULL;
- if ((buf = taosDecodeFixedU64(buf, &value)) == NULL) return NULL;
- pIdx->suid = (int64_t)value;
- if ((buf = taosDecodeFixedU64(buf, &value)) == NULL) return NULL;
- pIdx->uid = (int64_t)value;
- if ((buf = taosDecodeVariantU32(buf, &(pIdx->len))) == NULL) return NULL;
- if ((buf = taosDecodeVariantU32(buf, &(pIdx->offset))) == NULL) return NULL;
- if ((buf = taosDecodeFixedU8(buf, &(hasLast))) == NULL) return NULL;
- pIdx->hasLast = hasLast;
- if ((buf = taosDecodeVariantU32(buf, &(numOfBlocks))) == NULL) return NULL;
- pIdx->numOfBlocks = numOfBlocks;
- if ((buf = taosDecodeFixedU64(buf, &value)) == NULL) return NULL;
- pIdx->maxKey.ts = (TSKEY)value;
-
- return buf;
-}
-
-void tsdbGetBlockStatis(SReadH *pReadh, SColumnDataAgg *pStatis, int numOfCols, SBlock *pBlock) {
-#ifdef TD_REFACTOR_3
- SBlockData *pBlockData = pReadh->pBlkData;
-
- for (int i = 0, j = 0; i < numOfCols;) {
- if (j >= pBlockData->numOfCols) {
- pStatis[i].numOfNull = -1;
- ++i;
- continue;
- }
-
- if (pStatis[i].colId == pBlockData->cols[j].colId) {
- pStatis[i].sum = pBlockData->cols[j].sum;
- pStatis[i].max = pBlockData->cols[j].max;
- pStatis[i].min = pBlockData->cols[j].min;
- pStatis[i].maxIndex = pBlockData->cols[j].maxIndex;
- pStatis[i].minIndex = pBlockData->cols[j].minIndex;
- pStatis[i].numOfNull = pBlockData->cols[j].numOfNull;
- ++i;
- ++j;
- } else if (pStatis[i].colId < pBlockData->cols[j].colId) {
- pStatis[i].numOfNull = -1;
- ++i;
- } else {
- ++j;
- }
- }
-#else
- if (pBlock->aggrStat) {
- SAggrBlkData *pAggrBlkData = pReadh->pAggrBlkData;
-
- for (int i = 0, j = 0; i < numOfCols;) {
- if (j >= pBlock->numOfBSma) {
- pStatis[i].numOfNull = -1;
- ++i;
- continue;
- }
- SAggrBlkCol *pAggrBlkCol = ((SAggrBlkCol *)(pAggrBlkData)) + j;
- if (pStatis[i].colId == pAggrBlkCol->colId) {
- pStatis[i].sum = pAggrBlkCol->sum;
- pStatis[i].max = pAggrBlkCol->max;
- pStatis[i].min = pAggrBlkCol->min;
- pStatis[i].maxIndex = pAggrBlkCol->maxIndex;
- pStatis[i].minIndex = pAggrBlkCol->minIndex;
- pStatis[i].numOfNull = pAggrBlkCol->numOfNull;
- ++i;
- ++j;
- } else if (pStatis[i].colId < pAggrBlkCol->colId) {
- pStatis[i].numOfNull = -1;
- ++i;
- } else {
- ++j;
- }
- }
- }
-
-#endif
-}
-
-static void tsdbResetReadTable(SReadH *pReadh) {
- tdResetDataCols(pReadh->pDCols[0]);
- tdResetDataCols(pReadh->pDCols[1]);
- pReadh->cidx = 0;
- pReadh->pBlkIdx = NULL;
- pReadh->pTable = NULL;
-}
-
-static void tsdbResetReadFile(SReadH *pReadh) {
- tsdbResetReadTable(pReadh);
- taosArrayClear(pReadh->aBlkIdx);
- tsdbCloseDFileSet(TSDB_READ_FSET(pReadh));
-}
-
-static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, int8_t bitmapMode) {
- ASSERT(pBlock->numOfSubBlocks == 0 || pBlock->numOfSubBlocks == 1);
-
- SDFile *pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
-
- tdResetDataCols(pDataCols);
-
- pDataCols->bitmapMode = bitmapMode;
-
- if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pBlock->len) < 0) return -1;
-
- SBlockData *pBlockData = (SBlockData *)TSDB_READ_BUF(pReadh);
-
- if (tsdbSeekDFile(pDFile, pBlock->offset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load block data part while seek file %s to offset %" PRId64 " since %s",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tstrerror(terrno));
- return -1;
- }
-
- int64_t nread = tsdbReadDFile(pDFile, TSDB_READ_BUF(pReadh), pBlock->len);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to load block data part while read file %s since %s, offset:%" PRId64 " len :%d",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), (int64_t)pBlock->offset,
- pBlock->len);
- return -1;
- }
-
- if (nread < pBlock->len) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block data part in file %s is corrupted, offset:%" PRId64
- " expected bytes:%d read bytes: %" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, pBlock->len, nread);
- return -1;
- }
-
- int32_t tsize = (int32_t)tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer);
- if (!taosCheckChecksumWhole((uint8_t *)TSDB_READ_BUF(pReadh), tsize)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block head part in file %s is corrupted since wrong checksum, offset:%" PRId64 " len :%d",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tsize);
- return -1;
- }
-
- ASSERT(tsize < pBlock->len);
- ASSERT(pBlockData->numOfCols == pBlock->numOfCols);
-
- pDataCols->numOfRows = pBlock->numOfRows;
-
- // Recover the data
- int ccol = 0; // loop iter for SBlockCol object
- int dcol = 0; // loop iter for SDataCols object
- int nBitmaps = (int)TD_BITMAP_BYTES(pBlock->numOfRows);
- SBlockCol *pBlockCol = NULL;
- while (dcol < pDataCols->numOfCols) {
- SDataCol *pDataCol = &(pDataCols->cols[dcol]);
- if (dcol != 0 && ccol >= pBlockData->numOfCols) {
- // Set current column as NULL and forward
- dataColReset(pDataCol);
- ++dcol;
- continue;
- }
-
- int16_t tcolId = PRIMARYKEY_TIMESTAMP_COL_ID;
- uint32_t toffset = TSDB_KEY_COL_OFFSET;
- int32_t tlen = pBlock->keyLen;
-
- if (dcol != 0) {
- pBlockCol = &(pBlockData->cols[ccol]);
- tcolId = pBlockCol->colId;
- toffset = pBlockCol->offset;
- tlen = pBlockCol->len;
- pDataCol->bitmap = pBlockCol->blen > 0 ? 1 : 0;
- } else {
- ASSERT(pDataCol->colId == tcolId);
- TD_SET_COL_ROWS_NORM(pDataCol);
- }
-
- // int32_t tBitmaps = 0;
- int32_t tLenBitmap = 0;
- if ((dcol != 0) && (pBlockCol->blen > 0)) {
- tLenBitmap = nBitmaps;
- }
-
- if (tcolId == pDataCol->colId) {
- if (pBlock->algorithm == TWO_STAGE_COMP) {
- int zsize = pDataCol->bytes * pBlock->numOfRows + tLenBitmap + 2 * COMP_OVERFLOW_BYTES;
- if (tsdbMakeRoom((void **)(&TSDB_READ_COMP_BUF(pReadh)), zsize) < 0) return -1;
- }
-
- if (tsdbCheckAndDecodeColumnData(pDataCol, POINTER_SHIFT(pBlockData, tsize + toffset), tlen,
- pBlockCol ? pBlockCol->blen : 0, pBlock->algorithm, pBlock->numOfRows,
- tLenBitmap, pDataCols->maxPoints, TSDB_READ_COMP_BUF(pReadh),
- (int)taosTSizeof(TSDB_READ_COMP_BUF(pReadh))) < 0) {
- tsdbError("vgId:%d, file %s is broken at column %d block offset %" PRId64 " column offset %u",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tcolId, (int64_t)pBlock->offset, toffset);
- return -1;
- }
-
- if (dcol != 0) {
- ++ccol;
- }
- ++dcol;
- } else if (tcolId < pDataCol->colId) {
- ++ccol;
- } else {
- // Set current column as NULL and forward
- dataColReset(pDataCol);
- ++dcol;
- }
- }
-
- return 0;
-}
-
-static int tsdbCheckAndDecodeColumnData(SDataCol *pDataCol, void *content, int32_t len, int32_t bitmapLen, int8_t comp,
- int numOfRows, int numOfBitmaps, int maxPoints, char *buffer, int bufferSize) {
- if (!taosCheckChecksumWhole((uint8_t *)content, len)) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- return -1;
- }
-
- tdAllocMemForCol(pDataCol, maxPoints);
-
- // Decode the data
- if (comp) {
- // Need to decompress
- int tlen =
- (*(tDataTypes[pDataCol->type].decompFunc))(content, len - bitmapLen - sizeof(TSCKSUM), numOfRows,
- pDataCol->pData, pDataCol->spaceSize, comp, buffer, bufferSize);
- if (tlen <= 0) {
- tsdbError(
- "Failed to decompress column data, file corrupted, len:%d comp:%d numOfRows:%d maxPoints:%d bufferSize:%d",
- (int32_t)(len - bitmapLen - sizeof(TSCKSUM)), comp, numOfRows, maxPoints, bufferSize);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- return -1;
- }
- pDataCol->len = tlen;
-
- if (numOfBitmaps > 0) {
- tlen = tsDecompressTinyint(POINTER_SHIFT(content, len - bitmapLen - sizeof(TSCKSUM)), bitmapLen, numOfBitmaps,
- pDataCol->pBitmap, pDataCol->spaceSize, comp, buffer, bufferSize);
- if (tlen <= 0) {
- tsdbError(
- "Failed to decompress column bitmap, file corrupted, len:%d comp:%d numOfRows:%d maxPoints:%d "
- "bufferSize:%d",
- bitmapLen, comp, numOfBitmaps, maxPoints, bufferSize);
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- return -1;
- }
- // pDataCol->blen = tlen;
- }
- } else {
- // No need to decompress, just memcpy it
- pDataCol->len = len - bitmapLen - sizeof(TSCKSUM);
- memcpy(pDataCol->pData, content, pDataCol->len);
- if (numOfBitmaps > 0) {
- // pDataCol->blen = bitmapLen;
- memcpy(pDataCol->pBitmap, POINTER_SHIFT(content, len - bitmapLen - sizeof(TSCKSUM)), bitmapLen);
- }
- }
-
-#if 0
- if (lenOfBitmaps > 0) {
- pDataCol->len -= lenOfBitmaps;
-
- void *pSrcBitmap = NULL;
- if (IS_VAR_DATA_TYPE(pDataCol->type)) {
- pSrcBitmap = dataColSetOffset(pDataCol, numOfRows);
- } else {
- pSrcBitmap = POINTER_SHIFT(pDataCol->pData, numOfRows * TYPE_BYTES[pDataCol->type]);
- }
- void *pDestBitmap = POINTER_SHIFT(pDataCol->pData, pDataCol->bytes * maxPoints);
- // restore the bitmap parts
- memcpy(pDestBitmap, pSrcBitmap, lenOfBitmaps);
- } else if (IS_VAR_DATA_TYPE(pDataCol->type)) {
- dataColSetOffset(pDataCol, numOfRows);
- }
-#endif
- if (IS_VAR_DATA_TYPE(pDataCol->type)) {
- dataColSetOffset(pDataCol, numOfRows);
- }
- return 0;
-}
-
-static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, const int16_t *colIds,
- int numOfColIds, int8_t bitmapMode) {
- ASSERT(pBlock->numOfSubBlocks == 0 || pBlock->numOfSubBlocks == 1);
- ASSERT(colIds[0] == PRIMARYKEY_TIMESTAMP_COL_ID);
-
- SDFile *pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
- SBlockCol blockCol = {0};
-
- tdResetDataCols(pDataCols);
-
- pDataCols->bitmapMode = bitmapMode;
-
- // If only load timestamp column, no need to load SBlockData part
- if (numOfColIds > 1 && tsdbLoadBlockOffset(pReadh, pBlock) < 0) return -1;
-
- pDataCols->numOfRows = pBlock->numOfRows;
-
- int dcol = 0;
- int ccol = 0;
- for (int i = 0; i < numOfColIds; i++) {
- int16_t colId = colIds[i];
- SDataCol *pDataCol = NULL;
- SBlockCol *pBlockCol = NULL;
-
- while (true) {
- if (dcol >= pDataCols->numOfCols) {
- pDataCol = NULL;
- break;
- }
- pDataCol = &pDataCols->cols[dcol];
- if (pDataCol->colId > colId) {
- pDataCol = NULL;
- break;
- } else {
- dcol++;
- if (pDataCol->colId == colId) break;
- }
- }
-
- if (pDataCol == NULL) continue;
- ASSERT(pDataCol->colId == colId);
-
- if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) { // load the key row
- blockCol.colId = colId;
- blockCol.blen = 0; // default is NORM for the primary key column
- blockCol.len = pBlock->keyLen;
- blockCol.type = pDataCol->type;
- blockCol.offset = TSDB_KEY_COL_OFFSET;
- pBlockCol = &blockCol;
- } else { // load non-key rows
- while (true) {
- if (ccol >= pBlock->numOfCols) {
- pBlockCol = NULL;
- break;
- }
-
- pBlockCol = &(pReadh->pBlkData->cols[ccol]);
- if (pBlockCol->colId > colId) {
- pBlockCol = NULL;
- break;
- } else {
- ccol++;
- if (pBlockCol->colId == colId) break;
- }
- }
-
- if (pBlockCol == NULL) {
- dataColReset(pDataCol);
- continue;
- }
-
- ASSERT(pBlockCol->colId == pDataCol->colId);
- }
- // set the bitmap
- pDataCol->bitmap = pBlockCol->blen > 0 ? 1 : 0;
-
- if (tsdbLoadColData(pReadh, pDFile, pBlock, pBlockCol, pDataCol) < 0) return -1;
- }
-
- return 0;
-}
-
-static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBlockCol *pBlockCol, SDataCol *pDataCol) {
- ASSERT(pDataCol->colId == pBlockCol->colId);
-
- STsdb *pRepo = TSDB_READ_REPO(pReadh);
- STsdbCfg *pCfg = REPO_CFG(pRepo);
-
- int nBitmaps = (int)TD_BITMAP_BYTES(pBlock->numOfRows);
- // int32_t tBitmaps = 0;
- int32_t tLenBitmap = 0;
-
- if (pBlockCol->blen) {
- tLenBitmap = nBitmaps;
- }
-
- int tsize = pDataCol->bytes * pBlock->numOfRows + tLenBitmap + 2 * COMP_OVERFLOW_BYTES;
-
- if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pBlockCol->len) < 0) return -1;
- if (tsdbMakeRoom((void **)(&TSDB_READ_COMP_BUF(pReadh)), tsize) < 0) return -1;
-
- int64_t offset =
- pBlock->offset + tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer) + pBlockCol->offset;
- if (tsdbSeekDFile(pDFile, offset, SEEK_SET) < 0) {
- tsdbError("vgId:%d, failed to load block column data while seek file %s to offset %" PRId64 " since %s",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), offset, tstrerror(terrno));
- return -1;
- }
-
- int64_t nread = tsdbReadDFile(pDFile, TSDB_READ_BUF(pReadh), pBlockCol->len);
- if (nread < 0) {
- tsdbError("vgId:%d, failed to load block column data while read file %s since %s, offset:%" PRId64 " len :%d",
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), offset, pBlockCol->len);
- return -1;
- }
-
- if (nread < pBlockCol->len) {
- terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
- tsdbError("vgId:%d, block column data in file %s is corrupted, offset:%" PRId64 " expected bytes:%d" PRIzu
- " read bytes: %" PRId64,
- TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), offset, pBlockCol->len, nread);
- return -1;
- }
-
- if (tsdbCheckAndDecodeColumnData(pDataCol, pReadh->pBuf, pBlockCol->len, pBlockCol->blen, pBlock->algorithm,
- pBlock->numOfRows, tLenBitmap, pCfg->maxRows, pReadh->pCBuf,
- (int32_t)taosTSizeof(pReadh->pCBuf)) < 0) {
- tsdbError("vgId:%d, file %s is broken at column %d offset %" PRId64, REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
- pBlockCol->colId, offset);
- return -1;
- }
-
- return 0;
-}
diff --git a/source/dnode/vnode/src/tsdb/tsdbReaderWriter.c b/source/dnode/vnode/src/tsdb/tsdbReaderWriter.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e7a9d3b040157f503d351c4fe74f70f72e1c860
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbReaderWriter.c
@@ -0,0 +1,2026 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdb.h"
+
+#define TSDB_FILE_DLMT ((uint32_t)0xF00AFA0F)
+
+// SDelFWriter ====================================================
+int32_t tsdbDelFWriterOpen(SDelFWriter **ppWriter, SDelFile *pFile, STsdb *pTsdb) {
+ int32_t code = 0;
+ char fname[TSDB_FILENAME_LEN];
+ char hdr[TSDB_FHDR_SIZE] = {0};
+ SDelFWriter *pDelFWriter;
+ int64_t n;
+
+ // alloc
+ pDelFWriter = (SDelFWriter *)taosMemoryCalloc(1, sizeof(*pDelFWriter));
+ if (pDelFWriter == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pDelFWriter->pTsdb = pTsdb;
+ pDelFWriter->fDel = *pFile;
+
+ tsdbDelFileName(pTsdb, pFile, fname);
+ pDelFWriter->pWriteH = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE);
+ if (pDelFWriter->pWriteH == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // update header
+ n = taosWriteFile(pDelFWriter->pWriteH, &hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ pDelFWriter->fDel.size = TSDB_FHDR_SIZE;
+ pDelFWriter->fDel.offset = 0;
+
+ *ppWriter = pDelFWriter;
+ return code;
+
+_err:
+ tsdbError("vgId:%d failed to open del file writer since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppWriter = NULL;
+ return code;
+}
+
+int32_t tsdbDelFWriterClose(SDelFWriter **ppWriter, int8_t sync) {
+ int32_t code = 0;
+ SDelFWriter *pWriter = *ppWriter;
+
+ // sync
+ if (sync && taosFsyncFile(pWriter->pWriteH) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // close
+ if (taosCloseFile(&pWriter->pWriteH) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ *ppWriter = NULL;
+ return code;
+
+_err:
+ tsdbError("vgId:%d failed to close del file writer since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbWriteDelData(SDelFWriter *pWriter, SArray *aDelData, uint8_t **ppBuf, SDelIdx *pDelIdx) {
+ int32_t code = 0;
+ uint8_t *pBuf = NULL;
+ int64_t size;
+ int64_t n;
+ SBlockDataHdr hdr = {.delimiter = TSDB_FILE_DLMT, .suid = pDelIdx->suid, .uid = pDelIdx->uid};
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // prepare
+ size = sizeof(hdr);
+ for (int32_t iDelData = 0; iDelData < taosArrayGetSize(aDelData); iDelData++) {
+ size += tPutDelData(NULL, taosArrayGet(aDelData, iDelData));
+ }
+ size += sizeof(TSCKSUM);
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // build
+ n = 0;
+ *(SBlockDataHdr *)(*ppBuf) = hdr;
+ n += sizeof(hdr);
+ for (int32_t iDelData = 0; iDelData < taosArrayGetSize(aDelData); iDelData++) {
+ n += tPutDelData(*ppBuf + n, taosArrayGet(aDelData, iDelData));
+ }
+ taosCalcChecksumAppend(0, *ppBuf, size);
+
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ // write
+ n = taosWriteFile(pWriter->pWriteH, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ ASSERT(n == size);
+
+ // update
+ pDelIdx->offset = pWriter->fDel.size;
+ pDelIdx->size = size;
+ pWriter->fDel.size += size;
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d failed to write del data since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+int32_t tsdbWriteDelIdx(SDelFWriter *pWriter, SArray *aDelIdx, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t size;
+ int64_t n;
+ uint8_t *pBuf = NULL;
+ SDelIdx *pDelIdx;
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // prepare
+ size = 0;
+ size += tPutU32(NULL, TSDB_FILE_DLMT);
+ for (int32_t iDelIdx = 0; iDelIdx < taosArrayGetSize(aDelIdx); iDelIdx++) {
+ size += tPutDelIdx(NULL, taosArrayGet(aDelIdx, iDelIdx));
+ }
+ size += sizeof(TSCKSUM);
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // build
+ n = 0;
+ n += tPutU32(*ppBuf + n, TSDB_FILE_DLMT);
+ for (int32_t iDelIdx = 0; iDelIdx < taosArrayGetSize(aDelIdx); iDelIdx++) {
+ n += tPutDelIdx(*ppBuf + n, taosArrayGet(aDelIdx, iDelIdx));
+ }
+ taosCalcChecksumAppend(0, *ppBuf, size);
+
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ // write
+ n = taosWriteFile(pWriter->pWriteH, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // update
+ pWriter->fDel.offset = pWriter->fDel.size;
+ pWriter->fDel.size += size;
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d write del idx failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+int32_t tsdbUpdateDelFileHdr(SDelFWriter *pWriter) {
+ int32_t code = 0;
+ char hdr[TSDB_FHDR_SIZE];
+ int64_t size = TSDB_FHDR_SIZE;
+ int64_t n;
+
+ // build
+ memset(hdr, 0, size);
+ tPutDelFile(hdr, &pWriter->fDel);
+ taosCalcChecksumAppend(0, hdr, size);
+
+ // seek
+ if (taosLSeekFile(pWriter->pWriteH, 0, SEEK_SET) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // write
+ n = taosWriteFile(pWriter->pWriteH, hdr, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d update del file hdr failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+// SDelFReader ====================================================
+struct SDelFReader {
+ STsdb *pTsdb;
+ SDelFile fDel;
+ TdFilePtr pReadH;
+};
+
+int32_t tsdbDelFReaderOpen(SDelFReader **ppReader, SDelFile *pFile, STsdb *pTsdb, uint8_t **ppBuf) {
+ int32_t code = 0;
+ char fname[TSDB_FILENAME_LEN];
+ SDelFReader *pDelFReader;
+ int64_t n;
+
+ // alloc
+ pDelFReader = (SDelFReader *)taosMemoryCalloc(1, sizeof(*pDelFReader));
+ if (pDelFReader == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ // open impl
+ pDelFReader->pTsdb = pTsdb;
+ pDelFReader->fDel = *pFile;
+
+ tsdbDelFileName(pTsdb, pFile, fname);
+ pDelFReader->pReadH = taosOpenFile(fname, TD_FILE_READ);
+ if (pDelFReader == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ taosMemoryFree(pDelFReader);
+ goto _err;
+ }
+
+#if 0
+ // load and check hdr if buffer is given
+ if (ppBuf) {
+ code = tRealloc(ppBuf, TSDB_FHDR_SIZE);
+ if (code) {
+ goto _err;
+ }
+
+ n = taosReadFile(pDelFReader->pReadH, *ppBuf, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < TSDB_FHDR_SIZE) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ if (!taosCheckChecksumWhole(*ppBuf, TSDB_FHDR_SIZE)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // TODO: check the content
+ }
+#endif
+
+_exit:
+ *ppReader = pDelFReader;
+ return code;
+
+_err:
+ tsdbError("vgId:%d del file reader open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppReader = NULL;
+ return code;
+}
+
+int32_t tsdbDelFReaderClose(SDelFReader **ppReader) {
+ int32_t code = 0;
+ SDelFReader *pReader = *ppReader;
+
+ if (pReader) {
+ if (taosCloseFile(&pReader->pReadH) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _exit;
+ }
+ taosMemoryFree(pReader);
+ }
+ *ppReader = NULL;
+
+_exit:
+ return code;
+}
+
+int32_t tsdbReadDelData(SDelFReader *pReader, SDelIdx *pDelIdx, SArray *aDelData, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t offset = pDelIdx->offset;
+ int64_t size = pDelIdx->size;
+ int64_t n;
+ uint8_t *pBuf = NULL;
+ SBlockDataHdr *pHdr;
+ SDelData *pDelData = &(SDelData){0};
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // seek
+ if (taosLSeekFile(pReader->pReadH, offset, SEEK_SET) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // read
+ n = taosReadFile(pReader->pReadH, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // check
+ if (!taosCheckChecksumWhole(*ppBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // // decode
+ n = 0;
+ pHdr = (SBlockDataHdr *)(*ppBuf + n);
+ ASSERT(pHdr->delimiter == TSDB_FILE_DLMT);
+ ASSERT(pHdr->suid == pDelIdx->suid);
+ ASSERT(pHdr->uid == pDelIdx->uid);
+ n += sizeof(*pHdr);
+ taosArrayClear(aDelData);
+ while (n < size - sizeof(TSCKSUM)) {
+ n += tGetDelData(*ppBuf + n, pDelData);
+
+ if (taosArrayPush(aDelData, pDelData) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ ASSERT(n == size - sizeof(TSCKSUM));
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d read del data failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+int32_t tsdbReadDelIdx(SDelFReader *pReader, SArray *aDelIdx, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int32_t n;
+ int64_t offset = pReader->fDel.offset;
+ int64_t size = pReader->fDel.size - offset;
+ uint32_t delimiter;
+ uint8_t *pBuf = NULL;
+ SDelIdx *pDelIdx = &(SDelIdx){0};
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // seek
+ if (taosLSeekFile(pReader->pReadH, offset, SEEK_SET) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // read
+ n = taosReadFile(pReader->pReadH, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // check
+ if (!taosCheckChecksumWhole(*ppBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // decode
+ n = 0;
+ n += tGetU32(*ppBuf + n, &delimiter);
+ ASSERT(delimiter == TSDB_FILE_DLMT);
+
+ taosArrayClear(aDelIdx);
+ while (n < size - sizeof(TSCKSUM)) {
+ n += tGetDelIdx(*ppBuf + n, pDelIdx);
+
+ if (taosArrayPush(aDelIdx, pDelIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ ASSERT(n == size - sizeof(TSCKSUM));
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d read del idx failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+// SDataFReader ====================================================
+struct SDataFReader {
+ STsdb *pTsdb;
+ SDFileSet *pSet;
+ TdFilePtr pHeadFD;
+ TdFilePtr pDataFD;
+ TdFilePtr pLastFD;
+ TdFilePtr pSmaFD;
+};
+
+int32_t tsdbDataFReaderOpen(SDataFReader **ppReader, STsdb *pTsdb, SDFileSet *pSet) {
+ int32_t code = 0;
+ SDataFReader *pReader;
+ char fname[TSDB_FILENAME_LEN];
+
+ // alloc
+ pReader = (SDataFReader *)taosMemoryCalloc(1, sizeof(*pReader));
+ if (pReader == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pReader->pTsdb = pTsdb;
+ pReader->pSet = pSet;
+
+ // open impl
+ // head
+ tsdbDataFileName(pTsdb, pSet, TSDB_HEAD_FILE, fname);
+ pReader->pHeadFD = taosOpenFile(fname, TD_FILE_READ);
+ if (pReader->pHeadFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // data
+ tsdbDataFileName(pTsdb, pSet, TSDB_DATA_FILE, fname);
+ pReader->pDataFD = taosOpenFile(fname, TD_FILE_READ);
+ if (pReader->pDataFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // last
+ tsdbDataFileName(pTsdb, pSet, TSDB_LAST_FILE, fname);
+ pReader->pLastFD = taosOpenFile(fname, TD_FILE_READ);
+ if (pReader->pLastFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // sma
+ tsdbDataFileName(pTsdb, pSet, TSDB_SMA_FILE, fname);
+ pReader->pSmaFD = taosOpenFile(fname, TD_FILE_READ);
+ if (pReader->pSmaFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ *ppReader = pReader;
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb data file reader open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppReader = NULL;
+ return code;
+}
+
+int32_t tsdbDataFReaderClose(SDataFReader **ppReader) {
+ int32_t code = 0;
+ if (*ppReader == NULL) goto _exit;
+
+ if (taosCloseFile(&(*ppReader)->pHeadFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppReader)->pDataFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppReader)->pLastFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppReader)->pSmaFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ taosMemoryFree(*ppReader);
+
+_exit:
+ *ppReader = NULL;
+ return code;
+
+_err:
+ tsdbError("vgId:%d data file reader close failed since %s", TD_VID((*ppReader)->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbReadBlockIdx(SDataFReader *pReader, SArray *aBlockIdx, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t offset = pReader->pSet->fHead.offset;
+ int64_t size = pReader->pSet->fHead.size - offset;
+ uint8_t *pBuf = NULL;
+ int64_t n;
+ uint32_t delimiter;
+ SBlockIdx blockIdx;
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // seek
+ if (taosLSeekFile(pReader->pHeadFD, offset, SEEK_SET) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // read
+ n = taosReadFile(pReader->pHeadFD, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // check
+ if (!taosCheckChecksumWhole(*ppBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // decode
+ n = 0;
+ n = tGetU32(*ppBuf + n, &delimiter);
+ ASSERT(delimiter == TSDB_FILE_DLMT);
+
+ taosArrayClear(aBlockIdx);
+ while (n < size - sizeof(TSCKSUM)) {
+ n += tGetBlockIdx(*ppBuf + n, &blockIdx);
+
+ if (taosArrayPush(aBlockIdx, &blockIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d read block idx failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+int32_t tsdbReadBlock(SDataFReader *pReader, SBlockIdx *pBlockIdx, SMapData *mBlock, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t offset = pBlockIdx->offset;
+ int64_t size = pBlockIdx->size;
+ uint8_t *pBuf = NULL;
+ int64_t n;
+ int64_t tn;
+ SBlockDataHdr hdr;
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // seek
+ if (taosLSeekFile(pReader->pHeadFD, offset, SEEK_SET) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // read
+ n = taosReadFile(pReader->pHeadFD, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // check
+ if (!taosCheckChecksumWhole(*ppBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // decode
+ hdr = *(SBlockDataHdr *)(*ppBuf);
+ ASSERT(hdr.delimiter == TSDB_FILE_DLMT);
+ ASSERT(hdr.suid == pBlockIdx->suid);
+ ASSERT(hdr.uid == pBlockIdx->uid);
+
+ n = sizeof(hdr);
+ tn = tGetMapData(*ppBuf + n, mBlock);
+ if (tn < 0) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ n += tn;
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d read block failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+static int32_t tsdbReadBlockDataKey(SBlockData *pBlockData, SSubBlock *pSubBlock, uint8_t *pBuf, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t size = pSubBlock->szVersion + pSubBlock->szTSKEY + sizeof(TSCKSUM);
+ int64_t n;
+
+ if (!taosCheckChecksumWhole(pBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ code = tRealloc((uint8_t **)&pBlockData->aVersion, sizeof(int64_t) * pSubBlock->nRow);
+ if (code) goto _err;
+ code = tRealloc((uint8_t **)&pBlockData->aTSKEY, sizeof(TSKEY) * pSubBlock->nRow);
+ if (code) goto _err;
+
+ if (pSubBlock->cmprAlg == NO_COMPRESSION) {
+ ASSERT(pSubBlock->szVersion == sizeof(int64_t) * pSubBlock->nRow);
+ ASSERT(pSubBlock->szTSKEY == sizeof(TSKEY) * pSubBlock->nRow);
+
+ // VERSION
+ memcpy(pBlockData->aVersion, pBuf, pSubBlock->szVersion);
+
+ // TSKEY
+ memcpy(pBlockData->aTSKEY, pBuf + pSubBlock->szVersion, pSubBlock->szTSKEY);
+ } else {
+ size = sizeof(int64_t) * pSubBlock->nRow + COMP_OVERFLOW_BYTES;
+ if (pSubBlock->cmprAlg == TWO_STAGE_COMP) {
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+ }
+
+ // VERSION
+ n = tsDecompressBigint(pBuf, pSubBlock->szVersion, pSubBlock->nRow, (char *)pBlockData->aVersion,
+ sizeof(int64_t) * pSubBlock->nRow, pSubBlock->cmprAlg, *ppBuf, size);
+ if (n < 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ // TSKEY
+ n = tsDecompressTimestamp(pBuf + pSubBlock->szVersion, pSubBlock->szTSKEY, pSubBlock->nRow,
+ (char *)pBlockData->aTSKEY, sizeof(TSKEY) * pSubBlock->nRow, pSubBlock->cmprAlg, *ppBuf,
+ size);
+ if (n < 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+ }
+
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbReadColDataImpl(SSubBlock *pSubBlock, SBlockCol *pBlockCol, SColData *pColData, uint8_t *pBuf,
+ uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t size;
+ int64_t n;
+
+ if (!taosCheckChecksumWhole(pBuf, pBlockCol->szBitmap + pBlockCol->szOffset + pBlockCol->szValue + sizeof(TSCKSUM))) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ pColData->nVal = pSubBlock->nRow;
+ pColData->flag = pBlockCol->flag;
+
+ // BITMAP
+ if (pBlockCol->flag != HAS_VALUE) {
+ ASSERT(pBlockCol->szBitmap);
+
+ size = BIT2_SIZE(pColData->nVal);
+ code = tRealloc(&pColData->pBitMap, size);
+ if (code) goto _err;
+
+ code = tRealloc(ppBuf, size + COMP_OVERFLOW_BYTES);
+ if (code) goto _err;
+
+ n = tsDecompressTinyint(pBuf, pBlockCol->szBitmap, size, pColData->pBitMap, size, TWO_STAGE_COMP, *ppBuf,
+ size + COMP_OVERFLOW_BYTES);
+ if (n <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ ASSERT(n == size);
+ } else {
+ ASSERT(pBlockCol->szBitmap == 0);
+ }
+ pBuf = pBuf + pBlockCol->szBitmap;
+
+ // OFFSET
+ if (IS_VAR_DATA_TYPE(pColData->type)) {
+ ASSERT(pBlockCol->szOffset);
+
+ size = sizeof(int32_t) * pColData->nVal;
+ code = tRealloc((uint8_t **)&pColData->aOffset, size);
+ if (code) goto _err;
+
+ code = tRealloc(ppBuf, size + COMP_OVERFLOW_BYTES);
+ if (code) goto _err;
+
+ n = tsDecompressInt(pBuf, pBlockCol->szOffset, pColData->nVal, (char *)pColData->aOffset, size, TWO_STAGE_COMP,
+ *ppBuf, size + COMP_OVERFLOW_BYTES);
+ if (n <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ ASSERT(n == size);
+ } else {
+ ASSERT(pBlockCol->szOffset == 0);
+ }
+ pBuf = pBuf + pBlockCol->szOffset;
+
+ // VALUE
+ pColData->nData = pBlockCol->szOrigin;
+
+ code = tRealloc(&pColData->pData, pColData->nData);
+ if (code) goto _err;
+
+ if (pSubBlock->cmprAlg == NO_COMPRESSION) {
+ memcpy(pColData->pData, pBuf, pColData->nData);
+ } else {
+ if (pSubBlock->cmprAlg == TWO_STAGE_COMP) {
+ code = tRealloc(ppBuf, pColData->nData + COMP_OVERFLOW_BYTES);
+ if (code) goto _err;
+ }
+
+ n = tDataTypes[pBlockCol->type].decompFunc(pBuf, pBlockCol->szValue, pSubBlock->nRow, pColData->pData,
+ pColData->nData, pSubBlock->cmprAlg, *ppBuf,
+ pColData->nData + COMP_OVERFLOW_BYTES);
+ if (n < 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ ASSERT(n == pColData->nData);
+ }
+
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbReadBlockCol(SSubBlock *pSubBlock, uint8_t *p, SArray *aBlockCol) {
+ int32_t code = 0;
+ int32_t n = 0;
+ SBlockCol blockCol;
+ SBlockCol *pBlockCol = &blockCol;
+
+ if (!taosCheckChecksumWhole(p, pSubBlock->szBlockCol + sizeof(TSCKSUM))) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ n += sizeof(SBlockDataHdr);
+ while (n < pSubBlock->szBlockCol) {
+ n += tGetBlockCol(p + n, pBlockCol);
+
+ if (taosArrayPush(aBlockCol, pBlockCol) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ ASSERT(n == pSubBlock->szBlockCol);
+
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbReadSubColData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, int32_t iSubBlock,
+ int16_t *aColId, int32_t nCol, SBlockData *pBlockData, uint8_t **ppBuf1,
+ uint8_t **ppBuf2) {
+ TdFilePtr pFD = pBlock->last ? pReader->pLastFD : pReader->pDataFD;
+ SSubBlock *pSubBlock = &pBlock->aSubBlock[iSubBlock];
+ SArray *aBlockCol = NULL;
+ int32_t code = 0;
+ int64_t offset;
+ int64_t size;
+ int64_t n;
+
+ tBlockDataReset(pBlockData);
+ pBlockData->nRow = pSubBlock->nRow;
+
+ // TSDBKEY and SBlockCol
+ if (nCol == 1) {
+ offset = pSubBlock->offset + pSubBlock->szBlockCol + sizeof(TSCKSUM);
+ size = pSubBlock->szVersion + pSubBlock->szTSKEY + sizeof(TSCKSUM);
+ } else {
+ offset = pSubBlock->offset;
+ size = pSubBlock->szBlockCol + sizeof(TSCKSUM) + pSubBlock->szVersion + pSubBlock->szTSKEY + sizeof(TSCKSUM);
+ }
+
+ code = tRealloc(ppBuf1, size);
+ if (code) goto _err;
+
+ n = taosLSeekFile(pFD, offset, SEEK_SET);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosReadFile(pFD, *ppBuf1, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ if (nCol == 1) {
+ code = tsdbReadBlockDataKey(pBlockData, pSubBlock, *ppBuf1, ppBuf2);
+ if (code) goto _err;
+
+ goto _exit;
+ } else {
+ aBlockCol = taosArrayInit(0, sizeof(SBlockCol));
+ if (aBlockCol == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ code = tsdbReadBlockCol(pSubBlock, *ppBuf1, aBlockCol);
+ if (code) goto _err;
+
+ code = tsdbReadBlockDataKey(pBlockData, pSubBlock, *ppBuf1 + pSubBlock->szBlockCol + sizeof(TSCKSUM), ppBuf2);
+ if (code) goto _err;
+ }
+
+ for (int32_t iCol = 1; iCol < nCol; iCol++) {
+ void *p = taosArraySearch(aBlockCol, &(SBlockCol){.cid = aColId[iCol]}, tBlockColCmprFn, TD_EQ);
+
+ if (p) {
+ SBlockCol *pBlockCol = (SBlockCol *)p;
+ SColData *pColData;
+
+ ASSERT(pBlockCol->flag && pBlockCol->flag != HAS_NONE);
+
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _err;
+
+ tColDataInit(pColData, pBlockCol->cid, pBlockCol->type, pBlockCol->smaOn);
+ if (pBlockCol->flag == HAS_NULL) {
+ for (int32_t iRow = 0; iRow < pSubBlock->nRow; iRow++) {
+ code = tColDataAppendValue(pColData, &COL_VAL_NULL(pBlockCol->cid, pBlockCol->type));
+ if (code) goto _err;
+ }
+ } else {
+ offset = pSubBlock->offset + pSubBlock->szBlockCol + sizeof(TSCKSUM) + pSubBlock->szVersion +
+ pSubBlock->szTSKEY + sizeof(TSCKSUM) + pBlockCol->offset;
+ size = pBlockCol->szBitmap + pBlockCol->szOffset + pBlockCol->szValue + sizeof(TSCKSUM);
+
+ code = tRealloc(ppBuf1, size);
+ if (code) goto _err;
+
+ // seek
+ n = taosLSeekFile(pFD, offset, SEEK_SET);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // read
+ n = taosReadFile(pFD, *ppBuf1, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ code = tsdbReadColDataImpl(pSubBlock, pBlockCol, pColData, *ppBuf1, ppBuf2);
+ if (code) goto _err;
+ }
+ }
+ }
+
+_exit:
+ taosArrayDestroy(aBlockCol);
+ return code;
+
+_err:
+ taosArrayDestroy(aBlockCol);
+ return code;
+}
+
+int32_t tsdbReadColData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, int16_t *aColId, int32_t nCol,
+ SBlockData *pBlockData, uint8_t **ppBuf1, uint8_t **ppBuf2) {
+ int32_t code = 0;
+ uint8_t *pBuf1 = NULL;
+ uint8_t *pBuf2 = NULL;
+
+ ASSERT(aColId[0] == PRIMARYKEY_TIMESTAMP_COL_ID);
+
+ if (!ppBuf1) ppBuf1 = &pBuf1;
+ if (!ppBuf2) ppBuf2 = &pBuf2;
+
+ code = tsdbReadSubColData(pReader, pBlockIdx, pBlock, 0, aColId, nCol, pBlockData, ppBuf1, ppBuf2);
+ if (code) goto _err;
+
+ if (pBlock->nSubBlock > 1) {
+ SBlockData *pBlockData1 = &(SBlockData){0};
+ SBlockData *pBlockData2 = &(SBlockData){0};
+
+ tBlockDataInit(pBlockData1);
+ tBlockDataInit(pBlockData2);
+ for (int32_t iSubBlock = 1; iSubBlock < pBlock->nSubBlock; iSubBlock++) {
+ code = tsdbReadSubColData(pReader, pBlockIdx, pBlock, iSubBlock, aColId, nCol, pBlockData1, ppBuf1, ppBuf2);
+ if (code) goto _err;
+
+ code = tBlockDataCopy(pBlockData, pBlockData2);
+ if (code) {
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ goto _err;
+ }
+
+ code = tBlockDataMerge(pBlockData1, pBlockData2, pBlockData);
+ if (code) {
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ goto _err;
+ }
+ }
+
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ }
+
+ tFree(pBuf1);
+ tFree(pBuf2);
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb read col data failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf1);
+ tFree(pBuf2);
+ return code;
+}
+
+static int32_t tsdbReadSubBlockData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, int32_t iSubBlock,
+ SBlockData *pBlockData, uint8_t **ppBuf1, uint8_t **ppBuf2) {
+ int32_t code = 0;
+ uint8_t *p;
+ int64_t size;
+ int64_t n;
+ TdFilePtr pFD = pBlock->last ? pReader->pLastFD : pReader->pDataFD;
+ SSubBlock *pSubBlock = &pBlock->aSubBlock[iSubBlock];
+ SArray *aBlockCol = NULL;
+
+ tBlockDataReset(pBlockData);
+
+ // realloc
+ code = tRealloc(ppBuf1, pSubBlock->szBlock);
+ if (code) goto _err;
+
+ // seek
+ n = taosLSeekFile(pFD, pSubBlock->offset, SEEK_SET);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // read
+ n = taosReadFile(pFD, *ppBuf1, pSubBlock->szBlock);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < pSubBlock->szBlock) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ pBlockData->nRow = pSubBlock->nRow;
+
+ // TSDBKEY
+ p = *ppBuf1 + pSubBlock->szBlockCol + sizeof(TSCKSUM);
+ code = tsdbReadBlockDataKey(pBlockData, pSubBlock, p, ppBuf2);
+ if (code) goto _err;
+
+ // COLUMNS
+ aBlockCol = taosArrayInit(0, sizeof(SBlockCol));
+ if (aBlockCol == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ code = tsdbReadBlockCol(pSubBlock, *ppBuf1, aBlockCol);
+ if (code) goto _err;
+
+ for (int32_t iBlockCol = 0; iBlockCol < taosArrayGetSize(aBlockCol); iBlockCol++) {
+ SColData *pColData;
+ SBlockCol *pBlockCol = (SBlockCol *)taosArrayGet(aBlockCol, iBlockCol);
+
+ ASSERT(pBlockCol->flag && pBlockCol->flag != HAS_NONE);
+
+ code = tBlockDataAddColData(pBlockData, iBlockCol, &pColData);
+ if (code) goto _err;
+
+ tColDataInit(pColData, pBlockCol->cid, pBlockCol->type, pBlockCol->smaOn);
+ if (pBlockCol->flag == HAS_NULL) {
+ for (int32_t iRow = 0; iRow < pSubBlock->nRow; iRow++) {
+ code = tColDataAppendValue(pColData, &COL_VAL_NULL(pBlockCol->cid, pBlockCol->type));
+ if (code) goto _err;
+ }
+ } else {
+ p = *ppBuf1 + pSubBlock->szBlockCol + sizeof(TSCKSUM) + pSubBlock->szVersion + pSubBlock->szTSKEY +
+ sizeof(TSCKSUM) + pBlockCol->offset;
+ code = tsdbReadColDataImpl(pSubBlock, pBlockCol, pColData, p, ppBuf2);
+ if (code) goto _err;
+ }
+ }
+
+ taosArrayDestroy(aBlockCol);
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb read sub block data failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ taosArrayDestroy(aBlockCol);
+ return code;
+}
+
+int32_t tsdbReadBlockData(SDataFReader *pReader, SBlockIdx *pBlockIdx, SBlock *pBlock, SBlockData *pBlockData,
+ uint8_t **ppBuf1, uint8_t **ppBuf2) {
+ int32_t code = 0;
+ TdFilePtr pFD = pBlock->last ? pReader->pLastFD : pReader->pDataFD;
+ uint8_t *pBuf1 = NULL;
+ uint8_t *pBuf2 = NULL;
+ int32_t iSubBlock;
+
+ if (!ppBuf1) ppBuf1 = &pBuf1;
+ if (!ppBuf2) ppBuf2 = &pBuf2;
+
+ // read the first sub-block
+ iSubBlock = 0;
+ code = tsdbReadSubBlockData(pReader, pBlockIdx, pBlock, iSubBlock, pBlockData, ppBuf1, ppBuf2);
+ if (code) goto _err;
+
+ // read remain block data and do merg
+ if (pBlock->nSubBlock > 1) {
+ SBlockData *pBlockData1 = &(SBlockData){0};
+ SBlockData *pBlockData2 = &(SBlockData){0};
+
+ tBlockDataInit(pBlockData1);
+ tBlockDataInit(pBlockData2);
+ for (iSubBlock = 1; iSubBlock < pBlock->nSubBlock; iSubBlock++) {
+ code = tsdbReadSubBlockData(pReader, pBlockIdx, pBlock, iSubBlock, pBlockData1, ppBuf1, ppBuf2);
+ if (code) {
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ goto _err;
+ }
+
+ code = tBlockDataCopy(pBlockData, pBlockData2);
+ if (code) {
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ goto _err;
+ }
+
+ // merge two block data
+ code = tBlockDataMerge(pBlockData1, pBlockData2, pBlockData);
+ if (code) {
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ goto _err;
+ }
+ }
+
+ tBlockDataClear(pBlockData1);
+ tBlockDataClear(pBlockData2);
+ }
+
+ ASSERT(pBlock->nRow == pBlockData->nRow);
+ ASSERT(tsdbKeyCmprFn(&pBlock->minKey, &TSDBROW_KEY(&tBlockDataFirstRow(pBlockData))) == 0);
+ ASSERT(tsdbKeyCmprFn(&pBlock->maxKey, &TSDBROW_KEY(&tBlockDataLastRow(pBlockData))) == 0);
+
+ if (pBuf1) tFree(pBuf1);
+ if (pBuf2) tFree(pBuf2);
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb read block data failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ if (pBuf1) tFree(pBuf1);
+ if (pBuf2) tFree(pBuf2);
+ return code;
+}
+
+int32_t tsdbReadBlockSma(SDataFReader *pReader, SBlock *pBlock, SArray *aColumnDataAgg, uint8_t **ppBuf) {
+ int32_t code = 0;
+ TdFilePtr pFD = pReader->pSmaFD;
+ int64_t offset = pBlock->aSubBlock[0].sOffset;
+ int64_t size = pBlock->aSubBlock[0].nSma * sizeof(SColumnDataAgg) + sizeof(TSCKSUM);
+ uint8_t *pBuf = NULL;
+ int64_t n;
+
+ ASSERT(tBlockHasSma(pBlock));
+
+ if (!ppBuf) ppBuf = &pBuf;
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // lseek
+ n = taosLSeekFile(pFD, offset, SEEK_SET);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // read
+ n = taosReadFile(pFD, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ } else if (n < size) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // check
+ if (!taosCheckChecksumWhole(*ppBuf, size)) {
+ code = TSDB_CODE_FILE_CORRUPTED;
+ goto _err;
+ }
+
+ // decode
+ taosArrayClear(aColumnDataAgg);
+ for (int32_t iSma = 0; iSma < pBlock->aSubBlock[0].nSma; iSma++) {
+ if (taosArrayPush(aColumnDataAgg, &((SColumnDataAgg *)(*ppBuf))[iSma]) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d read block sma failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+// SDataFWriter ====================================================
+struct SDataFWriter {
+ STsdb *pTsdb;
+ SDFileSet wSet;
+ TdFilePtr pHeadFD;
+ TdFilePtr pDataFD;
+ TdFilePtr pLastFD;
+ TdFilePtr pSmaFD;
+};
+
+SDFileSet *tsdbDataFWriterGetWSet(SDataFWriter *pWriter) { return &pWriter->wSet; }
+
+int32_t tsdbDataFWriterOpen(SDataFWriter **ppWriter, STsdb *pTsdb, SDFileSet *pSet) {
+ int32_t code = 0;
+ int32_t flag;
+ int64_t n;
+ SDataFWriter *pWriter = NULL;
+ char fname[TSDB_FILENAME_LEN];
+ char hdr[TSDB_FHDR_SIZE] = {0};
+
+ // alloc
+ pWriter = taosMemoryCalloc(1, sizeof(*pWriter));
+ if (pWriter == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pWriter->pTsdb = pTsdb;
+ pWriter->wSet = *pSet;
+ pSet = &pWriter->wSet;
+
+ // head
+ flag = TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC;
+ tsdbDataFileName(pTsdb, pSet, TSDB_HEAD_FILE, fname);
+ pWriter->pHeadFD = taosOpenFile(fname, flag);
+ if (pWriter->pHeadFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosWriteFile(pWriter->pHeadFD, hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ ASSERT(n == TSDB_FHDR_SIZE);
+
+ pSet->fHead.size += TSDB_FHDR_SIZE;
+
+ // data
+ if (pSet->fData.size == 0) {
+ flag = TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC;
+ } else {
+ flag = TD_FILE_WRITE;
+ }
+ tsdbDataFileName(pTsdb, pSet, TSDB_DATA_FILE, fname);
+ pWriter->pDataFD = taosOpenFile(fname, flag);
+ if (pWriter->pDataFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ if (pSet->fData.size == 0) {
+ n = taosWriteFile(pWriter->pDataFD, hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ pSet->fData.size += TSDB_FHDR_SIZE;
+ } else {
+ n = taosLSeekFile(pWriter->pDataFD, 0, SEEK_END);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ ASSERT(n == pSet->fData.size);
+ }
+
+ // last
+ if (pSet->fLast.size == 0) {
+ flag = TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC;
+ } else {
+ flag = TD_FILE_WRITE;
+ }
+ tsdbDataFileName(pTsdb, pSet, TSDB_LAST_FILE, fname);
+ pWriter->pLastFD = taosOpenFile(fname, flag);
+ if (pWriter->pLastFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ if (pSet->fLast.size == 0) {
+ n = taosWriteFile(pWriter->pLastFD, hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ pSet->fLast.size += TSDB_FHDR_SIZE;
+ } else {
+ n = taosLSeekFile(pWriter->pLastFD, 0, SEEK_END);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ ASSERT(n == pSet->fLast.size);
+ }
+
+ // sma
+ if (pSet->fSma.size == 0) {
+ flag = TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC;
+ } else {
+ flag = TD_FILE_WRITE;
+ }
+ tsdbDataFileName(pTsdb, pSet, TSDB_SMA_FILE, fname);
+ pWriter->pSmaFD = taosOpenFile(fname, flag);
+ if (pWriter->pSmaFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ if (pSet->fSma.size == 0) {
+ n = taosWriteFile(pWriter->pSmaFD, hdr, TSDB_FHDR_SIZE);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ pSet->fSma.size += TSDB_FHDR_SIZE;
+ } else {
+ n = taosLSeekFile(pWriter->pSmaFD, 0, SEEK_END);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ ASSERT(n == pSet->fSma.size);
+ }
+
+ *ppWriter = pWriter;
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb data file writer open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppWriter = NULL;
+ return code;
+}
+
+int32_t tsdbDataFWriterClose(SDataFWriter **ppWriter, int8_t sync) {
+ int32_t code = 0;
+ STsdb *pTsdb = (*ppWriter)->pTsdb;
+
+ if (*ppWriter == NULL) goto _exit;
+
+ if (sync) {
+ if (taosFsyncFile((*ppWriter)->pHeadFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosFsyncFile((*ppWriter)->pDataFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosFsyncFile((*ppWriter)->pLastFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosFsyncFile((*ppWriter)->pSmaFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ }
+
+ if (taosCloseFile(&(*ppWriter)->pHeadFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppWriter)->pDataFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppWriter)->pLastFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ if (taosCloseFile(&(*ppWriter)->pSmaFD) < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ taosMemoryFree(*ppWriter);
+_exit:
+ *ppWriter = NULL;
+ return code;
+
+_err:
+ tsdbError("vgId:%d data file writer close failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbUpdateDFileSetHeader(SDataFWriter *pWriter) {
+ int32_t code = 0;
+
+ // head ==============
+ code = tsdbUpdateDFileHdr(pWriter->pHeadFD, &pWriter->wSet, TSDB_HEAD_FILE);
+ if (code) goto _err;
+
+ // data ==============
+ code = tsdbUpdateDFileHdr(pWriter->pHeadFD, &pWriter->wSet, TSDB_DATA_FILE);
+ if (code) goto _err;
+
+ // last ==============
+ code = tsdbUpdateDFileHdr(pWriter->pHeadFD, &pWriter->wSet, TSDB_LAST_FILE);
+ if (code) goto _err;
+
+ // sma ==============
+ code = tsdbUpdateDFileHdr(pWriter->pHeadFD, &pWriter->wSet, TSDB_SMA_FILE);
+ if (code) goto _err;
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d update DFileSet header failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbWriteBlockIdx(SDataFWriter *pWriter, SArray *aBlockIdx, uint8_t **ppBuf) {
+ int32_t code = 0;
+ SHeadFile *pHeadFile = &pWriter->wSet.fHead;
+ uint8_t *pBuf = NULL;
+ int64_t size;
+ int64_t n;
+
+ if (!ppBuf) ppBuf = &pBuf;
+
+ // prepare
+ size = tPutU32(NULL, TSDB_FILE_DLMT);
+ for (int32_t iBlockIdx = 0; iBlockIdx < taosArrayGetSize(aBlockIdx); iBlockIdx++) {
+ size += tPutBlockIdx(NULL, taosArrayGet(aBlockIdx, iBlockIdx));
+ }
+ size += sizeof(TSCKSUM);
+
+ // alloc
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // build
+ n = 0;
+ n = tPutU32(*ppBuf + n, TSDB_FILE_DLMT);
+ for (int32_t iBlockIdx = 0; iBlockIdx < taosArrayGetSize(aBlockIdx); iBlockIdx++) {
+ n += tPutBlockIdx(*ppBuf + n, taosArrayGet(aBlockIdx, iBlockIdx));
+ }
+ taosCalcChecksumAppend(0, *ppBuf, size);
+
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ // write
+ n = taosWriteFile(pWriter->pHeadFD, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // update
+ pHeadFile->offset = pHeadFile->size;
+ pHeadFile->size += size;
+
+ tFree(pBuf);
+ return code;
+
+_err:
+ tsdbError("vgId:%d write block idx failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf);
+ return code;
+}
+
+int32_t tsdbWriteBlock(SDataFWriter *pWriter, SMapData *mBlock, uint8_t **ppBuf, SBlockIdx *pBlockIdx) {
+ int32_t code = 0;
+ SHeadFile *pHeadFile = &pWriter->wSet.fHead;
+ SBlockDataHdr hdr = {.delimiter = TSDB_FILE_DLMT, .suid = pBlockIdx->suid, .uid = pBlockIdx->uid};
+ uint8_t *pBuf = NULL;
+ int64_t size;
+ int64_t n;
+
+ ASSERT(mBlock->nItem > 0);
+
+ // prepare
+ size = sizeof(SBlockDataHdr) + tPutMapData(NULL, mBlock) + sizeof(TSCKSUM);
+
+ // alloc
+ if (!ppBuf) ppBuf = &pBuf;
+ code = tRealloc(ppBuf, size);
+ if (code) goto _err;
+
+ // build
+ n = 0;
+ *(SBlockDataHdr *)(*ppBuf) = hdr;
+ n += sizeof(hdr);
+ n += tPutMapData(*ppBuf + n, mBlock);
+ taosCalcChecksumAppend(0, *ppBuf, size);
+
+ ASSERT(n + sizeof(TSCKSUM) == size);
+
+ // write
+ n = taosWriteFile(pWriter->pHeadFD, *ppBuf, size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // update
+ pBlockIdx->offset = pHeadFile->size;
+ pBlockIdx->size = size;
+ pHeadFile->size += size;
+
+ tFree(pBuf);
+ tsdbTrace("vgId:%d write block, offset:%" PRId64 " size:%" PRId64, TD_VID(pWriter->pTsdb->pVnode), pBlockIdx->offset,
+ pBlockIdx->size);
+ return code;
+
+_err:
+ tFree(pBuf);
+ tsdbError("vgId:%d write block failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static void tsdbUpdateBlockInfo(SBlockData *pBlockData, SBlock *pBlock) {
+ for (int32_t iRow = 0; iRow < pBlockData->nRow; iRow++) {
+ TSDBKEY key = {.ts = pBlockData->aTSKEY[iRow], .version = pBlockData->aVersion[iRow]};
+
+ if (iRow == 0) {
+ if (tsdbKeyCmprFn(&pBlock->minKey, &key) > 0) {
+ pBlock->minKey = key;
+ }
+ } else {
+ if (pBlockData->aTSKEY[iRow] == pBlockData->aTSKEY[iRow - 1]) {
+ pBlock->hasDup = 1;
+ }
+ }
+
+ if (iRow == pBlockData->nRow - 1 && tsdbKeyCmprFn(&pBlock->maxKey, &key) < 0) {
+ pBlock->maxKey = key;
+ }
+
+ pBlock->minVersion = TMIN(pBlock->minVersion, key.version);
+ pBlock->maxVersion = TMAX(pBlock->maxVersion, key.version);
+ }
+ pBlock->nRow += pBlockData->nRow;
+}
+
+static int32_t tsdbWriteBlockDataKey(SSubBlock *pSubBlock, SBlockData *pBlockData, uint8_t **ppBuf1, int64_t *nDataP,
+ uint8_t **ppBuf2) {
+ int32_t code = 0;
+ int64_t size;
+ int64_t tsize;
+
+ if (pSubBlock->cmprAlg == NO_COMPRESSION) {
+ pSubBlock->szVersion = sizeof(int64_t) * pSubBlock->nRow;
+ pSubBlock->szTSKEY = sizeof(TSKEY) * pSubBlock->nRow;
+
+ code = tRealloc(ppBuf1, *nDataP + pSubBlock->szVersion + pSubBlock->szTSKEY + sizeof(TSCKSUM));
+ if (code) goto _err;
+
+ // VERSION
+ memcpy(*ppBuf1 + *nDataP, pBlockData->aVersion, pSubBlock->szVersion);
+
+ // TSKEY
+ memcpy(*ppBuf1 + *nDataP + pSubBlock->szVersion, pBlockData->aTSKEY, pSubBlock->szTSKEY);
+ } else {
+ size = (sizeof(int64_t) + sizeof(TSKEY)) * pSubBlock->nRow + COMP_OVERFLOW_BYTES * 2;
+
+ code = tRealloc(ppBuf1, *nDataP + size + sizeof(TSCKSUM));
+ if (code) goto _err;
+
+ tsize = sizeof(int64_t) * pSubBlock->nRow + COMP_OVERFLOW_BYTES;
+ if (pSubBlock->cmprAlg == TWO_STAGE_COMP) {
+ code = tRealloc(ppBuf2, tsize);
+ if (code) goto _err;
+ }
+
+ // VERSION
+ pSubBlock->szVersion =
+ tsCompressBigint((char *)pBlockData->aVersion, sizeof(int64_t) * pBlockData->nRow, pBlockData->nRow,
+ *ppBuf1 + *nDataP, size, pSubBlock->cmprAlg, *ppBuf2, tsize);
+ if (pSubBlock->szVersion <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ // TSKEY
+ pSubBlock->szTSKEY = tsCompressTimestamp((char *)pBlockData->aTSKEY, sizeof(TSKEY) * pBlockData->nRow,
+ pBlockData->nRow, *ppBuf1 + *nDataP + pSubBlock->szVersion,
+ size - pSubBlock->szVersion, pSubBlock->cmprAlg, *ppBuf2, tsize);
+ if (pSubBlock->szTSKEY <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+
+ ASSERT(pSubBlock->szVersion + pSubBlock->szTSKEY <= size);
+ }
+
+ // checksum
+ size = pSubBlock->szVersion + pSubBlock->szTSKEY + sizeof(TSCKSUM);
+ taosCalcChecksumAppend(0, *ppBuf1 + *nDataP, size);
+
+ *nDataP += size;
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbWriteColData(SColData *pColData, SBlockCol *pBlockCol, SSubBlock *pSubBlock, uint8_t **ppBuf1,
+ int64_t *nDataP, uint8_t **ppBuf2) {
+ int32_t code = 0;
+ int64_t size;
+ int64_t n = 0;
+
+ // BITMAP
+ if (pColData->flag != HAS_VALUE) {
+ size = BIT2_SIZE(pColData->nVal) + COMP_OVERFLOW_BYTES;
+
+ code = tRealloc(ppBuf1, *nDataP + n + size);
+ if (code) goto _err;
+
+ code = tRealloc(ppBuf2, size);
+ if (code) goto _err;
+
+ pBlockCol->szBitmap =
+ tsCompressTinyint((char *)pColData->pBitMap, BIT2_SIZE(pColData->nVal), BIT2_SIZE(pColData->nVal),
+ *ppBuf1 + *nDataP + n, size, TWO_STAGE_COMP, *ppBuf2, size);
+ if (pBlockCol->szBitmap <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+ } else {
+ pBlockCol->szBitmap = 0;
+ }
+ n += pBlockCol->szBitmap;
+
+ // OFFSET
+ if (IS_VAR_DATA_TYPE(pColData->type)) {
+ size = sizeof(int32_t) * pColData->nVal + COMP_OVERFLOW_BYTES;
+
+ code = tRealloc(ppBuf1, *nDataP + n + size);
+ if (code) goto _err;
+
+ code = tRealloc(ppBuf2, size);
+ if (code) goto _err;
+
+ pBlockCol->szOffset = tsCompressInt((char *)pColData->aOffset, sizeof(int32_t) * pColData->nVal, pColData->nVal,
+ *ppBuf1 + *nDataP + n, size, TWO_STAGE_COMP, *ppBuf2, size);
+ if (pBlockCol->szOffset <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+ } else {
+ pBlockCol->szOffset = 0;
+ }
+ n += pBlockCol->szOffset;
+
+ // VALUE
+ if (pSubBlock->cmprAlg == NO_COMPRESSION) {
+ pBlockCol->szValue = pColData->nData;
+
+ code = tRealloc(ppBuf1, *nDataP + n + pBlockCol->szValue + sizeof(TSCKSUM));
+ if (code) goto _err;
+
+ memcpy(*ppBuf1 + *nDataP + n, pColData->pData, pBlockCol->szValue);
+ } else {
+ size = pColData->nData + COMP_OVERFLOW_BYTES;
+
+ code = tRealloc(ppBuf1, *nDataP + n + size + sizeof(TSCKSUM));
+ if (code) goto _err;
+
+ if (pSubBlock->cmprAlg == TWO_STAGE_COMP) {
+ code = tRealloc(ppBuf2, size);
+ if (code) goto _err;
+ }
+
+ pBlockCol->szValue =
+ tDataTypes[pColData->type].compFunc((char *)pColData->pData, pColData->nData, pColData->nVal,
+ *ppBuf1 + *nDataP + n, size, pSubBlock->cmprAlg, *ppBuf2, size);
+ if (pBlockCol->szValue <= 0) {
+ code = TSDB_CODE_COMPRESS_ERROR;
+ goto _err;
+ }
+ }
+ n += pBlockCol->szValue;
+ pBlockCol->szOrigin = pColData->nData;
+
+ // checksum
+ n += sizeof(TSCKSUM);
+ taosCalcChecksumAppend(0, *ppBuf1 + *nDataP, n);
+
+ *nDataP += n;
+
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbWriteBlockDataImpl(TdFilePtr pFD, SSubBlock *pSubBlock, SBlockDataHdr hdr, SArray *aBlockCol,
+ uint8_t *pData, int64_t nData, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int32_t nBlockCol = taosArrayGetSize(aBlockCol);
+ int64_t size;
+ int64_t n;
+
+ // HDR + SArray
+ pSubBlock->szBlockCol = sizeof(hdr);
+ for (int32_t iBlockCol = 0; iBlockCol < nBlockCol; iBlockCol++) {
+ pSubBlock->szBlockCol += tPutBlockCol(NULL, taosArrayGet(aBlockCol, iBlockCol));
+ }
+
+ code = tRealloc(ppBuf, pSubBlock->szBlockCol + sizeof(TSCKSUM));
+ if (code) goto _err;
+
+ n = 0;
+ memcpy(*ppBuf, &hdr, sizeof(hdr));
+ n += sizeof(hdr);
+ for (int32_t iBlockCol = 0; iBlockCol < nBlockCol; iBlockCol++) {
+ n += tPutBlockCol(*ppBuf + n, taosArrayGet(aBlockCol, iBlockCol));
+ }
+ taosCalcChecksumAppend(0, *ppBuf, pSubBlock->szBlockCol + sizeof(TSCKSUM));
+
+ ASSERT(n == pSubBlock->szBlockCol);
+
+ n = taosWriteFile(pFD, *ppBuf, pSubBlock->szBlockCol + sizeof(TSCKSUM));
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ // SBlockData
+ n = taosWriteFile(pFD, pData, nData);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ return code;
+
+_err:
+ return code;
+}
+
+static int32_t tsdbWriteBlockSma(TdFilePtr pFD, SBlockData *pBlockData, SSubBlock *pSubBlock, uint8_t **ppBuf) {
+ int32_t code = 0;
+ int64_t n;
+ SColData *pColData;
+
+ // prepare
+ pSubBlock->nSma = 0;
+ for (int32_t iColData = 0; iColData < taosArrayGetSize(pBlockData->aIdx); iColData++) {
+ pColData = tBlockDataGetColDataByIdx(pBlockData, iColData);
+
+ if (IS_VAR_DATA_TYPE(pColData->type) || (!pColData->smaOn)) continue;
+
+ pSubBlock->nSma++;
+ }
+ if (pSubBlock->nSma == 0) goto _exit;
+
+ // calc
+ code = tRealloc(ppBuf, sizeof(SColumnDataAgg) * pSubBlock->nSma + sizeof(TSCKSUM));
+ if (code) goto _err;
+ n = 0;
+ for (int32_t iColData = 0; iColData < taosArrayGetSize(pBlockData->aIdx); iColData++) {
+ pColData = tBlockDataGetColDataByIdx(pBlockData, iColData);
+
+ if (IS_VAR_DATA_TYPE(pColData->type) || (!pColData->smaOn)) continue;
+
+ tsdbCalcColDataSMA(pColData, &((SColumnDataAgg *)(*ppBuf))[n]);
+ n++;
+ }
+ taosCalcChecksumAppend(0, *ppBuf, sizeof(SColumnDataAgg) * pSubBlock->nSma + sizeof(TSCKSUM));
+
+ // write
+ n = taosWriteFile(pFD, *ppBuf, sizeof(SColumnDataAgg) * pSubBlock->nSma + sizeof(TSCKSUM));
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+_exit:
+ return code;
+
+_err:
+ return code;
+}
+
+int32_t tsdbWriteBlockData(SDataFWriter *pWriter, SBlockData *pBlockData, uint8_t **ppBuf1, uint8_t **ppBuf2,
+ SBlockIdx *pBlockIdx, SBlock *pBlock, int8_t cmprAlg) {
+ int32_t code = 0;
+ SSubBlock *pSubBlock = &pBlock->aSubBlock[pBlock->nSubBlock++];
+ SBlockCol blockCol;
+ SBlockCol *pBlockCol = &blockCol;
+ int64_t n;
+ TdFilePtr pFileFD = pBlock->last ? pWriter->pLastFD : pWriter->pDataFD;
+ SBlockDataHdr hdr = {.delimiter = TSDB_FILE_DLMT, .suid = pBlockIdx->suid, .uid = pBlockIdx->uid};
+ uint8_t *p;
+ int64_t nData;
+ uint8_t *pBuf1 = NULL;
+ uint8_t *pBuf2 = NULL;
+ SArray *aBlockCol = NULL;
+
+ if (!ppBuf1) ppBuf1 = &pBuf1;
+ if (!ppBuf2) ppBuf2 = &pBuf2;
+
+ tsdbUpdateBlockInfo(pBlockData, pBlock);
+
+ pSubBlock->nRow = pBlockData->nRow;
+ pSubBlock->cmprAlg = cmprAlg;
+ if (pBlock->last) {
+ pSubBlock->offset = pWriter->wSet.fLast.size;
+ } else {
+ pSubBlock->offset = pWriter->wSet.fData.size;
+ }
+
+ // ======================= BLOCK DATA =======================
+ // TSDBKEY
+ nData = 0;
+ code = tsdbWriteBlockDataKey(pSubBlock, pBlockData, ppBuf1, &nData, ppBuf2);
+ if (code) goto _err;
+
+ // COLUMNS
+ aBlockCol = taosArrayInit(taosArrayGetSize(pBlockData->aIdx), sizeof(SBlockCol));
+ if (aBlockCol == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ int32_t offset = 0;
+ for (int32_t iCol = 0; iCol < taosArrayGetSize(pBlockData->aIdx); iCol++) {
+ SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, iCol);
+
+ ASSERT(pColData->flag);
+
+ if (pColData->flag == HAS_NONE) continue;
+
+ pBlockCol->cid = pColData->cid;
+ pBlockCol->type = pColData->type;
+ pBlockCol->smaOn = pColData->smaOn;
+ pBlockCol->flag = pColData->flag;
+
+ if (pColData->flag != HAS_NULL) {
+ code = tsdbWriteColData(pColData, pBlockCol, pSubBlock, ppBuf1, &nData, ppBuf2);
+ if (code) goto _err;
+
+ pBlockCol->offset = offset;
+ offset = offset + pBlockCol->szBitmap + pBlockCol->szOffset + pBlockCol->szValue + sizeof(TSCKSUM);
+ }
+
+ if (taosArrayPush(aBlockCol, pBlockCol) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ // write
+ code = tsdbWriteBlockDataImpl(pFileFD, pSubBlock, hdr, aBlockCol, *ppBuf1, nData, ppBuf2);
+ if (code) goto _err;
+
+ pSubBlock->szBlock = pSubBlock->szBlockCol + sizeof(TSCKSUM) + nData;
+ if (pBlock->last) {
+ pWriter->wSet.fLast.size += pSubBlock->szBlock;
+ } else {
+ pWriter->wSet.fData.size += pSubBlock->szBlock;
+ }
+
+ // ======================= BLOCK SMA =======================
+ pSubBlock->sOffset = 0;
+ pSubBlock->nSma = 0;
+
+ if (pBlock->nSubBlock > 1 || pBlock->last || pBlock->hasDup) goto _exit;
+
+ code = tsdbWriteBlockSma(pWriter->pSmaFD, pBlockData, pSubBlock, ppBuf1);
+ if (code) goto _err;
+
+ if (pSubBlock->nSma > 0) {
+ pSubBlock->sOffset = pWriter->wSet.fSma.size;
+ pWriter->wSet.fSma.size += (sizeof(SColumnDataAgg) * pSubBlock->nSma + sizeof(TSCKSUM));
+ }
+
+_exit:
+ tFree(pBuf1);
+ tFree(pBuf2);
+ taosArrayDestroy(aBlockCol);
+ return code;
+
+_err:
+ tsdbError("vgId:%d write block data failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ tFree(pBuf1);
+ tFree(pBuf2);
+ taosArrayDestroy(aBlockCol);
+ return code;
+}
+
+int32_t tsdbDFileSetCopy(STsdb *pTsdb, SDFileSet *pSetFrom, SDFileSet *pSetTo) {
+ int32_t code = 0;
+ int64_t n;
+ int64_t size;
+ TdFilePtr pOutFD = NULL; // TODO
+ TdFilePtr PInFD = NULL; // TODO
+ char fNameFrom[TSDB_FILENAME_LEN];
+ char fNameTo[TSDB_FILENAME_LEN];
+
+ // head
+ tsdbDataFileName(pTsdb, pSetFrom, TSDB_HEAD_FILE, fNameFrom);
+ tsdbDataFileName(pTsdb, pSetTo, TSDB_HEAD_FILE, fNameTo);
+
+ pOutFD = taosOpenFile(fNameTo, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
+ if (pOutFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ PInFD = taosOpenFile(fNameFrom, TD_FILE_READ);
+ if (PInFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosFSendFile(pOutFD, PInFD, 0, pSetFrom->fHead.size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ taosCloseFile(&pOutFD);
+ taosCloseFile(&PInFD);
+
+ // data
+ tsdbDataFileName(pTsdb, pSetFrom, TSDB_DATA_FILE, fNameFrom);
+ tsdbDataFileName(pTsdb, pSetTo, TSDB_DATA_FILE, fNameTo);
+
+ pOutFD = taosOpenFile(fNameTo, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
+ if (pOutFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ PInFD = taosOpenFile(fNameFrom, TD_FILE_READ);
+ if (PInFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosFSendFile(pOutFD, PInFD, 0, pSetFrom->fData.size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ taosCloseFile(&pOutFD);
+ taosCloseFile(&PInFD);
+
+ // last
+ tsdbDataFileName(pTsdb, pSetFrom, TSDB_LAST_FILE, fNameFrom);
+ tsdbDataFileName(pTsdb, pSetTo, TSDB_LAST_FILE, fNameTo);
+ pOutFD = taosOpenFile(fNameTo, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
+ if (pOutFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ PInFD = taosOpenFile(fNameFrom, TD_FILE_READ);
+ if (PInFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosFSendFile(pOutFD, PInFD, 0, pSetFrom->fLast.size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ taosCloseFile(&pOutFD);
+ taosCloseFile(&PInFD);
+
+ // sma
+ tsdbDataFileName(pTsdb, pSetFrom, TSDB_SMA_FILE, fNameFrom);
+ tsdbDataFileName(pTsdb, pSetTo, TSDB_SMA_FILE, fNameTo);
+
+ pOutFD = taosOpenFile(fNameTo, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
+ if (pOutFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ PInFD = taosOpenFile(fNameFrom, TD_FILE_READ);
+ if (PInFD == NULL) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+
+ n = taosFSendFile(pOutFD, PInFD, 0, pSetFrom->fSma.size);
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ goto _err;
+ }
+ taosCloseFile(&pOutFD);
+ taosCloseFile(&PInFD);
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb DFileSet copy failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbRetention.c b/source/dnode/vnode/src/tsdb/tsdbRetention.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ae646a571250e321e2ead6cefef2e6c6068a5f4
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbRetention.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdb.h"
+
+static int32_t tsdbDoRetentionImpl(STsdb *pTsdb, int64_t now, int8_t try, int8_t *canDo) {
+ int32_t code = 0;
+ STsdbFSState *pState;
+
+ if (try) {
+ pState = pTsdb->fs->cState;
+ *canDo = 0;
+ } else {
+ pState = pTsdb->fs->nState;
+ }
+
+ for (int32_t iSet = 0; iSet < taosArrayGetSize(pState->aDFileSet); iSet++) {
+ SDFileSet *pDFileSet = (SDFileSet *)taosArrayGet(pState->aDFileSet, iSet);
+ int32_t expLevel = tsdbFidLevel(pDFileSet->fid, &pTsdb->keepCfg, now);
+ SDiskID did;
+
+ // check
+ if (expLevel == pDFileSet->diskId.id) continue;
+
+ // delete or move
+ if (expLevel < 0) {
+ if (try) {
+ *canDo = 1;
+ } else {
+ tsdbFSStateDeleteDFileSet(pState, pDFileSet->fid);
+ iSet--;
+ }
+ } else {
+ // alloc
+ if (tfsAllocDisk(pTsdb->pVnode->pTfs, expLevel, &did) < 0) {
+ code = terrno;
+ goto _exit;
+ }
+
+ if (did.level == pDFileSet->diskId.level) continue;
+
+ if (try) {
+ *canDo = 1;
+ } else {
+ // copy the file to new disk
+
+ SDFileSet nDFileSet = *pDFileSet;
+ nDFileSet.diskId = did;
+
+ tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, did);
+
+ code = tsdbDFileSetCopy(pTsdb, pDFileSet, &nDFileSet);
+ if (code) goto _exit;
+
+ code = tsdbFSStateUpsertDFileSet(pState, &nDFileSet);
+ if (code) goto _exit;
+ }
+ }
+ }
+
+_exit:
+ return code;
+}
+
+int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) {
+ int32_t code = 0;
+ int8_t canDo;
+
+ // try
+ tsdbDoRetentionImpl(pTsdb, now, 1, &canDo);
+ if (!canDo) goto _exit;
+
+ // begin
+ code = tsdbFSBegin(pTsdb->fs);
+ if (code) goto _err;
+
+ // do retention
+ code = tsdbDoRetentionImpl(pTsdb, now, 0, NULL);
+ if (code) goto _err;
+
+ // commit
+ code = tsdbFSCommit(pTsdb->fs);
+ if (code) goto _err;
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb do retention failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ tsdbFSRollback(pTsdb->fs);
+ return code;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
index 79989a55601b99e681c573cae1f5c26e38cd7421..06d4a861162575e97adc54f13829761651efcd85 100644
--- a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
+++ b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
@@ -15,22 +15,755 @@
#include "tsdb.h"
-struct STsdbSnapshotReader {
- STsdb* pTsdb;
- // TODO
+// STsdbSnapReader ========================================
+struct STsdbSnapReader {
+ STsdb* pTsdb;
+ int64_t sver;
+ int64_t ever;
+ // for data file
+ int8_t dataDone;
+ int32_t fid;
+ SDataFReader* pDataFReader;
+ SArray* aBlockIdx; // SArray
+ int32_t iBlockIdx;
+ SBlockIdx* pBlockIdx;
+ SMapData mBlock; // SMapData
+ int32_t iBlock;
+ SBlockData blkData;
+ // for del file
+ int8_t delDone;
+ SDelFReader* pDelFReader;
+ int32_t iDelIdx;
+ SArray* aDelIdx; // SArray
+ SArray* aDelData; // SArray
};
-int32_t tsdbSnapshotReaderOpen(STsdb* pTsdb, STsdbSnapshotReader** ppReader, int64_t sver, int64_t ever) {
+static int32_t tsdbSnapReadData(STsdbSnapReader* pReader, uint8_t** ppData) {
+ int32_t code = 0;
+
+ while (true) {
+ if (pReader->pDataFReader == NULL) {
+ SDFileSet* pSet = NULL;
+
+ // search the next data file set to read (todo)
+ if (0 /* TODO */) {
+ code = TSDB_CODE_VND_READ_END;
+ goto _exit;
+ }
+
+ // open
+ code = tsdbDataFReaderOpen(&pReader->pDataFReader, pReader->pTsdb, pSet);
+ if (code) goto _err;
+
+ // SBlockIdx
+ code = tsdbReadBlockIdx(pReader->pDataFReader, pReader->aBlockIdx, NULL);
+ if (code) goto _err;
+
+ pReader->iBlockIdx = 0;
+ pReader->pBlockIdx = NULL;
+ }
+
+ while (true) {
+ if (pReader->pBlockIdx == NULL) {
+ if (pReader->iBlockIdx >= taosArrayGetSize(pReader->aBlockIdx)) {
+ tsdbDataFReaderClose(&pReader->pDataFReader);
+ break;
+ }
+
+ pReader->pBlockIdx = (SBlockIdx*)taosArrayGet(pReader->aBlockIdx, pReader->iBlockIdx);
+ pReader->iBlockIdx++;
+
+ // SBlock
+ code = tsdbReadBlock(pReader->pDataFReader, pReader->pBlockIdx, &pReader->mBlock, NULL);
+ if (code) goto _err;
+
+ pReader->iBlock = 0;
+ }
+
+ while (true) {
+ SBlock block;
+ SBlock* pBlock = █
+
+ if (pReader->iBlock >= pReader->mBlock.nItem) {
+ pReader->pBlockIdx = NULL;
+ break;
+ }
+
+ tMapDataGetItemByIdx(&pReader->mBlock, pReader->iBlock, pBlock, tGetBlock);
+ pReader->iBlock++;
+
+ if ((pBlock->minVersion >= pReader->sver && pBlock->minVersion <= pReader->ever) ||
+ (pBlock->maxVersion >= pReader->sver && pBlock->maxVersion <= pReader->ever)) {
+ // overlap (todo)
+
+ code = tsdbReadBlockData(pReader->pDataFReader, pReader->pBlockIdx, pBlock, &pReader->blkData, NULL, NULL);
+ if (code) goto _err;
+
+ goto _exit;
+ }
+ }
+ }
+ }
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d snap read data failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapReadDel(STsdbSnapReader* pReader, uint8_t** ppData) {
+ int32_t code = 0;
+ STsdb* pTsdb = pReader->pTsdb;
+ SDelFile* pDelFile = pTsdb->fs->cState->pDelFile;
+
+ if (pReader->pDelFReader == NULL) {
+ if (pDelFile == NULL) {
+ code = TSDB_CODE_VND_READ_END;
+ goto _exit;
+ }
+
+ // open
+ code = tsdbDelFReaderOpen(&pReader->pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) goto _err;
+
+ // read index
+ code = tsdbReadDelIdx(pReader->pDelFReader, pReader->aDelIdx, NULL);
+ if (code) goto _err;
+
+ pReader->iDelIdx = 0;
+ }
+
+ while (pReader->iDelIdx < taosArrayGetSize(pReader->aDelIdx)) {
+ SDelIdx* pDelIdx = (SDelIdx*)taosArrayGet(pReader->aDelIdx, pReader->iDelIdx);
+ int32_t size = 0;
+
+ pReader->iDelIdx++;
+
+ code = tsdbReadDelData(pReader->pDelFReader, pDelIdx, pReader->aDelData, NULL);
+ if (code) goto _err;
+
+ for (int32_t iDelData = 0; iDelData < taosArrayGetSize(pReader->aDelData); iDelData++) {
+ SDelData* pDelData = (SDelData*)taosArrayGet(pReader->aDelData, iDelData);
+
+ if (pDelData->version >= pReader->sver && pDelData->version <= pReader->ever) {
+ size += tPutDelData(NULL, pDelData);
+ }
+ }
+
+ if (size > 0) {
+ int64_t n = 0;
+
+ size = size + sizeof(SSnapDataHdr) + sizeof(TABLEID);
+ code = tRealloc(ppData, size);
+ if (code) goto _err;
+
+ // SSnapDataHdr
+ SSnapDataHdr* pSnapDataHdr = (SSnapDataHdr*)(*ppData + n);
+ pSnapDataHdr->type = 1;
+ pSnapDataHdr->size = size; // TODO: size here may incorrect
+ n += sizeof(SSnapDataHdr);
+
+ // TABLEID
+ TABLEID* pId = (TABLEID*)(*ppData + n);
+ pId->suid = pDelIdx->suid;
+ pId->uid = pDelIdx->uid;
+ n += sizeof(*pId);
+
+ // DATA
+ for (int32_t iDelData = 0; iDelData < taosArrayGetSize(pReader->aDelData); iDelData++) {
+ SDelData* pDelData = (SDelData*)taosArrayGet(pReader->aDelData, iDelData);
+
+ if (pDelData->version >= pReader->sver && pDelData->version <= pReader->ever) {
+ n += tPutDelData(*ppData + n, pDelData);
+ }
+ }
+
+ goto _exit;
+ }
+ }
+
+ code = TSDB_CODE_VND_READ_END;
+ tsdbDelFReaderClose(&pReader->pDelFReader);
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d snap read del failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbSnapReaderOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapReader** ppReader) {
+ int32_t code = 0;
+ STsdbSnapReader* pReader = NULL;
+
+ // alloc
+ pReader = (STsdbSnapReader*)taosMemoryCalloc(1, sizeof(*pReader));
+ if (pReader == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pReader->pTsdb = pTsdb;
+ pReader->sver = sver;
+ pReader->ever = ever;
+
+ pReader->aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx));
+ if (pReader->aBlockIdx == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ pReader->mBlock = tMapDataInit();
+
+ code = tBlockDataInit(&pReader->blkData);
+ if (code) goto _err;
+
+ pReader->aDelIdx = taosArrayInit(0, sizeof(SDelIdx));
+ if (pReader->aDelIdx == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ pReader->aDelData = taosArrayInit(0, sizeof(SDelData));
+ if (pReader->aDelData == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ *ppReader = pReader;
+ return code;
+
+_err:
+ tsdbError("vgId:%d snapshot reader open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppReader = NULL;
+ return code;
+}
+
+int32_t tsdbSnapReaderClose(STsdbSnapReader** ppReader) {
+ int32_t code = 0;
+ STsdbSnapReader* pReader = *ppReader;
+
+ taosArrayDestroy(pReader->aDelData);
+ taosArrayDestroy(pReader->aDelIdx);
+ if (pReader->pDelFReader) {
+ tsdbDelFReaderClose(&pReader->pDelFReader);
+ }
+ tBlockDataClear(&pReader->blkData);
+ tMapDataClear(&pReader->mBlock);
+ taosArrayDestroy(pReader->aBlockIdx);
+ if (pReader->pDataFReader) {
+ tsdbDataFReaderClose(&pReader->pDataFReader);
+ }
+ taosMemoryFree(pReader);
+ *ppReader = NULL;
+
+ return code;
+}
+
+int32_t tsdbSnapRead(STsdbSnapReader* pReader, uint8_t** ppData) {
+ int32_t code = 0;
+
+ // read data file
+ if (!pReader->dataDone) {
+ code = tsdbSnapReadData(pReader, ppData);
+ if (code) {
+ if (code == TSDB_CODE_VND_READ_END) {
+ pReader->dataDone = 1;
+ } else {
+ goto _err;
+ }
+ } else {
+ goto _exit;
+ }
+ }
+
+ // read del file
+ if (!pReader->delDone) {
+ code = tsdbSnapReadDel(pReader, ppData);
+ if (code) {
+ if (code == TSDB_CODE_VND_READ_END) {
+ pReader->delDone = 1;
+ } else {
+ goto _err;
+ }
+ } else {
+ goto _exit;
+ }
+ }
+
+ code = TSDB_CODE_VND_READ_END;
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d snapshot read failed since %s", TD_VID(pReader->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+// STsdbSnapWriter ========================================
+struct STsdbSnapWriter {
+ STsdb* pTsdb;
+ int64_t sver;
+ int64_t ever;
+
+ // config
+ int32_t minutes;
+ int8_t precision;
+ int32_t minRow;
+ int32_t maxRow;
+ int8_t cmprAlg;
+
+ // for data file
+ int32_t fid;
+ SDataFReader* pDataFReader;
+ SArray* aBlockIdx;
+ int32_t iBlockIdx;
+ SBlockIdx* pBlockIdx;
+ SMapData mBlock;
+ int32_t iBlock;
+ SBlock* pBlock;
+ SBlock block;
+ SBlockData blockData;
+ int32_t iRow;
+
+ SDataFWriter* pDataFWriter;
+ SArray* aBlockIdxN;
+ SBlockIdx* pBlockIdxN;
+ SBlockIdx blockIdx;
+ SMapData mBlockN;
+ SBlock* pBlockN;
+ SBlock blockN;
+ SBlockData nBlockData;
+
+ // for del file
+ SDelFReader* pDelFReader;
+ SDelFWriter* pDelFWriter;
+ int32_t iDelIdx;
+ SArray* aDelIdx;
+ SArray* aDelData;
+ SArray* aDelIdxN;
+};
+
+static int32_t tsdbSnapRollback(STsdbSnapWriter* pWriter) {
+ int32_t code = 0;
// TODO
- return 0;
+ return code;
}
-int32_t tsdbSnapshotReaderClose(STsdbSnapshotReader* pReader) {
+static int32_t tsdbSnapCommit(STsdbSnapWriter* pWriter) {
+ int32_t code = 0;
// TODO
- return 0;
+ return code;
}
-int32_t tsdbSnapshotRead(STsdbSnapshotReader* pReader, void** ppData, uint32_t* nData) {
+static int32_t tsdbSnapWriteDataEnd(STsdbSnapWriter* pWriter) {
+ int32_t code = 0;
+ STsdb* pTsdb = pWriter->pTsdb;
+
+ if (pWriter->pDataFWriter == NULL) goto _exit;
+
// TODO
- return 0;
+
+ code = tsdbDataFWriterClose(&pWriter->pDataFWriter, 0);
+ if (code) goto _err;
+
+ if (pWriter->pDataFReader) {
+ code = tsdbDataFReaderClose(&pWriter->pDataFReader);
+ if (code) goto _err;
+ }
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot writer data end failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapWriteAppendData(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ int32_t iRow = 0; // todo
+ int32_t nRow = 0; // todo
+ SBlockData* pBlockData = NULL; // todo
+
+ while (iRow < nRow) {
+ code = tBlockDataAppendRow(&pWriter->nBlockData, &tsdbRowFromBlockData(pBlockData, iRow), NULL);
+ if (code) goto _err;
+ }
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot write append data failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapWriteTableDataEnd(STsdbSnapWriter* pWrite) {
+ int32_t code = 0;
+ // TODO
+ return code;
+}
+
+static int32_t tsdbSnapWriteTableData(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ TABLEID id = {0}; // TODO
+
+ // skip
+ while (pWriter->pBlockIdx && tTABLEIDCmprFn(&id, pWriter->pBlockIdx) < 0) {
+ code = tsdbSnapWriteTableDataEnd(pWriter);
+ if (code) goto _err;
+
+ pWriter->iBlockIdx++;
+ if (pWriter->iBlockIdx < taosArrayGetSize(pWriter->aBlockIdx)) {
+ pWriter->pBlockIdx = (SBlockIdx*)taosArrayGet(pWriter->aBlockIdx, pWriter->iBlockIdx);
+ } else {
+ pWriter->pBlockIdx = NULL;
+ }
+ }
+
+ // new or merge
+ if (pWriter->pBlockIdx == NULL || tTABLEIDCmprFn(&id, pWriter->pBlockIdx) < 0) {
+ int32_t c;
+
+ if (pWriter->pBlockIdxN && ((c = tTABLEIDCmprFn(&id, pWriter->pBlockIdxN)) != 0)) {
+ ASSERT(c > 0);
+
+ code = tsdbSnapWriteTableDataEnd(pWriter);
+ if (code) goto _err;
+ }
+
+ if (pWriter->pBlockIdxN == NULL) {
+ pWriter->pBlockIdx = &pWriter->blockIdx;
+ pWriter->pBlockIdx->suid = id.suid;
+ pWriter->pBlockIdx->uid = id.uid;
+ }
+
+ // loop to write the data
+ TSDBROW* pRow = NULL; // todo
+ int32_t nRow = 0; // todo
+ SBlockData* pBlockData = NULL; // todo
+ for (int32_t iRow = 0; iRow < nRow; iRow++) {
+ code = tBlockDataAppendRow(&pWriter->nBlockData, &tsdbRowFromBlockData(pBlockData, iRow), NULL);
+ if (code) goto _err;
+
+ if (pWriter->nBlockData.nRow > pWriter->maxRow * 4 / 5) {
+ code = tsdbWriteBlockData(pWriter->pDataFWriter, &pWriter->nBlockData, NULL, NULL, pWriter->pBlockIdxN,
+ pWriter->pBlockN, pWriter->cmprAlg);
+ if (code) goto _err;
+ }
+ }
+ } else {
+ // skip
+ while (true) {
+ if (pWriter->pBlock == NULL) break;
+ if (pWriter->pBlock->last) break;
+ if (tBlockCmprFn(&(SBlock){.minKey = {0}, .maxKey = {0}}, pWriter->pBlock) >= 0) break;
+
+ code = tMapDataPutItem(&pWriter->mBlockN, pWriter->pBlock, tPutBlock);
+ if (code) goto _err;
+ }
+
+ if (pWriter->pBlock) {
+ if (pWriter->pBlock->last) {
+ // load the last block and merge with the data (todo)
+ } else {
+ int32_t c = tBlockCmprFn(&(SBlock){0 /*TODO*/}, pWriter->pBlock);
+
+ if (c > 0) {
+ // commit until pWriter->pBlock (todo)
+ } else {
+ // load the block and merge with the data (todo)
+ }
+ }
+ } else {
+ int32_t nRow = 0;
+ SBlockData* pBlockData = NULL;
+
+ for (int32_t iRow = 0; iRow < nRow; iRow++) {
+ code = tBlockDataAppendRow(&pWriter->nBlockData, &tsdbRowFromBlockData(pBlockData, iRow), NULL);
+ if (code) goto _err;
+
+ if (pWriter->nBlockData.nRow >= pWriter->maxRow * 4 / 5) {
+ code = tsdbWriteBlockData(pWriter->pDataFWriter, &pWriter->nBlockData, NULL, NULL, pWriter->pBlockIdxN,
+ pWriter->pBlockN, pWriter->cmprAlg);
+ if (code) goto _err;
+
+ tBlockDataClearData(&pWriter->nBlockData);
+ }
+ }
+ }
+ }
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot write table data failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapWriteData(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ STsdb* pTsdb = pWriter->pTsdb;
+ int64_t skey; // todo
+ int64_t ekey; // todo
+
+ int32_t fid = tsdbKeyFid(skey, pWriter->minutes, pWriter->precision);
+ ASSERT(fid == tsdbKeyFid(ekey, pWriter->minutes, pWriter->precision));
+
+ // begin
+ if (pWriter->pDataFWriter == NULL || pWriter->fid != fid) {
+ code = tsdbSnapWriteDataEnd(pWriter);
+ if (code) goto _err;
+
+ pWriter->fid = fid;
+ SDFileSet* pSet = tsdbFSStateGetDFileSet(pTsdb->fs->nState, fid);
+ // reader
+ if (pSet) {
+ // open
+ code = tsdbDataFReaderOpen(&pWriter->pDataFReader, pTsdb, pSet);
+ if (code) goto _err;
+
+ // SBlockIdx
+ code = tsdbReadBlockIdx(pWriter->pDataFReader, pWriter->aBlockIdx, NULL);
+ if (code) goto _err;
+ } else {
+ taosArrayClear(pWriter->aBlockIdx);
+ }
+ pWriter->iBlockIdx = 0;
+
+ // writer
+ SDFileSet wSet = {0};
+ if (pSet == NULL) {
+ wSet = (SDFileSet){0}; // todo
+ } else {
+ wSet = (SDFileSet){0}; // todo
+ }
+
+ code = tsdbDataFWriterOpen(&pWriter->pDataFWriter, pTsdb, &wSet);
+ if (code) goto _err;
+
+ taosArrayClear(pWriter->aBlockIdxN);
+ }
+
+ code = tsdbSnapWriteTableData(pWriter, pData, nData);
+ if (code) goto _err;
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot write data failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapWriteDel(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ STsdb* pTsdb = pWriter->pTsdb;
+
+ if (pWriter->pDelFWriter == NULL) {
+ SDelFile* pDelFile = tsdbFSStateGetDelFile(pTsdb->fs->nState);
+
+ // reader
+ if (pDelFile) {
+ code = tsdbDelFReaderOpen(&pWriter->pDelFReader, pDelFile, pTsdb, NULL);
+ if (code) goto _err;
+
+ code = tsdbReadDelIdx(pWriter->pDelFReader, pWriter->aDelIdx, NULL);
+ if (code) goto _err;
+ }
+
+ // writer
+ SDelFile delFile = {.commitID = pTsdb->pVnode->state.commitID, .offset = 0, .size = 0};
+ code = tsdbDelFWriterOpen(&pWriter->pDelFWriter, &delFile, pTsdb);
+ if (code) goto _err;
+ }
+
+ // process the del data
+ TABLEID id = {0}; // todo
+
+ while (true) {
+ SDelIdx* pDelIdx = NULL;
+ int64_t n = 0;
+ SDelData delData;
+ SDelIdx delIdx;
+ int8_t toBreak = 0;
+
+ if (pWriter->iDelIdx < taosArrayGetSize(pWriter->aDelIdx)) {
+ pDelIdx = taosArrayGet(pWriter->aDelIdx, pWriter->iDelIdx);
+ }
+
+ if (pDelIdx) {
+ int32_t c = tTABLEIDCmprFn(&id, pDelIdx);
+ if (c < 0) {
+ goto _new_del;
+ } else {
+ code = tsdbReadDelData(pWriter->pDelFReader, pDelIdx, pWriter->aDelData, NULL);
+ if (code) goto _err;
+
+ pWriter->iDelIdx++;
+ if (c == 0) {
+ toBreak = 1;
+ delIdx = (SDelIdx){.suid = id.suid, .uid = id.uid};
+ goto _merge_del;
+ } else {
+ delIdx = (SDelIdx){.suid = pDelIdx->suid, .uid = pDelIdx->uid};
+ goto _write_del;
+ }
+ }
+ }
+
+ _new_del:
+ toBreak = 1;
+ delIdx = (SDelIdx){.suid = id.suid, .uid = id.uid};
+ taosArrayClear(pWriter->aDelData);
+
+ _merge_del:
+ while (n < nData) {
+ n += tGetDelData(pData + n, &delData);
+ if (taosArrayPush(pWriter->aDelData, &delData) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ _write_del:
+ code = tsdbWriteDelData(pWriter->pDelFWriter, pWriter->aDelData, NULL, &delIdx);
+ if (code) goto _err;
+
+ if (taosArrayPush(pWriter->aDelIdxN, &delIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ if (toBreak) break;
+ }
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot write del failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+static int32_t tsdbSnapWriteDelEnd(STsdbSnapWriter* pWriter) {
+ int32_t code = 0;
+ STsdb* pTsdb = pWriter->pTsdb;
+
+ if (pWriter->pDelFWriter == NULL) goto _exit;
+ for (; pWriter->iDelIdx < taosArrayGetSize(pWriter->aDelIdx); pWriter->iDelIdx++) {
+ SDelIdx* pDelIdx = (SDelIdx*)taosArrayGet(pWriter->aDelIdx, pWriter->iDelIdx);
+
+ code = tsdbReadDelData(pWriter->pDelFReader, pDelIdx, pWriter->aDelData, NULL);
+ if (code) goto _err;
+
+ SDelIdx delIdx = (SDelIdx){.suid = pDelIdx->suid, .uid = pDelIdx->uid};
+ code = tsdbWriteDelData(pWriter->pDelFWriter, pWriter->aDelData, NULL, &delIdx);
+ if (code) goto _err;
+
+ if (taosArrayPush(pWriter->aDelIdx, &delIdx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+
+ code = tsdbUpdateDelFileHdr(pWriter->pDelFWriter);
+ if (code) goto _err;
+
+ code = tsdbFSStateUpsertDelFile(pTsdb->fs->nState, &pWriter->pDelFWriter->fDel);
+ if (code) goto _err;
+
+ code = tsdbDelFWriterClose(&pWriter->pDelFWriter, 1);
+ if (code) goto _err;
+
+ if (pWriter->pDelFReader) {
+ code = tsdbDelFReaderClose(&pWriter->pDelFReader);
+ if (code) goto _err;
+ }
+
+_exit:
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshow write del end failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapWriter** ppWriter) {
+ int32_t code = 0;
+ STsdbSnapWriter* pWriter = NULL;
+
+ // alloc
+ pWriter = (STsdbSnapWriter*)taosMemoryCalloc(1, sizeof(*pWriter));
+ if (pWriter == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pWriter->pTsdb = pTsdb;
+ pWriter->sver = sver;
+ pWriter->ever = ever;
+
+ *ppWriter = pWriter;
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot writer open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
+ *ppWriter = NULL;
+ return code;
+}
+
+int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback) {
+ int32_t code = 0;
+ STsdbSnapWriter* pWriter = *ppWriter;
+
+ if (rollback) {
+ code = tsdbSnapRollback(pWriter);
+ if (code) goto _err;
+ } else {
+ code = tsdbSnapWriteDataEnd(pWriter);
+ if (code) goto _err;
+
+ code = tsdbSnapWriteDelEnd(pWriter);
+ if (code) goto _err;
+
+ code = tsdbSnapCommit(pWriter);
+ if (code) goto _err;
+ }
+
+ taosMemoryFree(pWriter);
+ *ppWriter = NULL;
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshot writer close failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
+ int32_t code = 0;
+ int8_t type = pData[0];
+
+ // ts data
+ if (type == 0) {
+ code = tsdbSnapWriteData(pWriter, pData + 1, nData - 1);
+ if (code) goto _err;
+ } else {
+ code = tsdbSnapWriteDataEnd(pWriter);
+ if (code) goto _err;
+ }
+
+ // del data
+ if (type == 1) {
+ code = tsdbSnapWriteDel(pWriter, pData + 1, nData - 1);
+ if (code) goto _err;
+ }
+
+ return code;
+
+_err:
+ tsdbError("vgId:%d tsdb snapshow write failed since %s", TD_VID(pWriter->pTsdb->pVnode), tstrerror(code));
+ return code;
}
diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c
new file mode 100644
index 0000000000000000000000000000000000000000..dc6c823368d65fd774b54ef6ac0798207e4464c9
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c
@@ -0,0 +1,1316 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdb.h"
+
+// SMapData =======================================================================
+void tMapDataReset(SMapData *pMapData) {
+ pMapData->nItem = 0;
+ pMapData->nData = 0;
+}
+
+void tMapDataClear(SMapData *pMapData) {
+ tFree((uint8_t *)pMapData->aOffset);
+ tFree(pMapData->pData);
+}
+
+int32_t tMapDataPutItem(SMapData *pMapData, void *pItem, int32_t (*tPutItemFn)(uint8_t *, void *)) {
+ int32_t code = 0;
+ int32_t offset = pMapData->nData;
+ int32_t nItem = pMapData->nItem;
+
+ pMapData->nItem++;
+ pMapData->nData += tPutItemFn(NULL, pItem);
+
+ // alloc
+ code = tRealloc((uint8_t **)&pMapData->aOffset, sizeof(int32_t) * pMapData->nItem);
+ if (code) goto _err;
+ code = tRealloc(&pMapData->pData, pMapData->nData);
+ if (code) goto _err;
+
+ // put
+ pMapData->aOffset[nItem] = offset;
+ tPutItemFn(pMapData->pData + offset, pItem);
+
+_err:
+ return code;
+}
+
+int32_t tMapDataSearch(SMapData *pMapData, void *pSearchItem, int32_t (*tGetItemFn)(uint8_t *, void *),
+ int32_t (*tItemCmprFn)(const void *, const void *), void *pItem) {
+ int32_t code = 0;
+ int32_t lidx = 0;
+ int32_t ridx = pMapData->nItem - 1;
+ int32_t midx;
+ int32_t c;
+
+ while (lidx <= ridx) {
+ midx = (lidx + ridx) / 2;
+
+ tMapDataGetItemByIdx(pMapData, midx, pItem, tGetItemFn);
+
+ c = tItemCmprFn(pSearchItem, pItem);
+ if (c == 0) {
+ goto _exit;
+ } else if (c < 0) {
+ ridx = midx - 1;
+ } else {
+ lidx = midx + 1;
+ }
+ }
+
+ code = TSDB_CODE_NOT_FOUND;
+
+_exit:
+ return code;
+}
+
+void tMapDataGetItemByIdx(SMapData *pMapData, int32_t idx, void *pItem, int32_t (*tGetItemFn)(uint8_t *, void *)) {
+ ASSERT(idx >= 0 && idx < pMapData->nItem);
+ tGetItemFn(pMapData->pData + pMapData->aOffset[idx], pItem);
+}
+
+int32_t tPutMapData(uint8_t *p, SMapData *pMapData) {
+ int32_t n = 0;
+
+ n += tPutI32v(p ? p + n : p, pMapData->nItem);
+ if (pMapData->nItem) {
+ int32_t lOffset = 0;
+ for (int32_t iItem = 0; iItem < pMapData->nItem; iItem++) {
+ n += tPutI32v(p ? p + n : p, pMapData->aOffset[iItem] - lOffset);
+ lOffset = pMapData->aOffset[iItem];
+ }
+
+ n += tPutI32v(p ? p + n : p, pMapData->nData);
+ if (p) {
+ memcpy(p + n, pMapData->pData, pMapData->nData);
+ }
+ n += pMapData->nData;
+ }
+
+ return n;
+}
+
+int32_t tGetMapData(uint8_t *p, SMapData *pMapData) {
+ int32_t n = 0;
+ int32_t offset;
+
+ tMapDataReset(pMapData);
+
+ n += tGetI32v(p + n, &pMapData->nItem);
+ if (pMapData->nItem) {
+ if (tRealloc((uint8_t **)&pMapData->aOffset, sizeof(int32_t) * pMapData->nItem)) return -1;
+
+ int32_t lOffset = 0;
+ for (int32_t iItem = 0; iItem < pMapData->nItem; iItem++) {
+ n += tGetI32v(p + n, &pMapData->aOffset[iItem]);
+ pMapData->aOffset[iItem] += lOffset;
+ lOffset = pMapData->aOffset[iItem];
+ }
+
+ n += tGetI32v(p + n, &pMapData->nData);
+ if (tRealloc(&pMapData->pData, pMapData->nData)) return -1;
+ memcpy(pMapData->pData, p + n, pMapData->nData);
+ n += pMapData->nData;
+ }
+
+ return n;
+}
+
+// TABLEID =======================================================================
+int32_t tTABLEIDCmprFn(const void *p1, const void *p2) {
+ TABLEID *pId1 = (TABLEID *)p1;
+ TABLEID *pId2 = (TABLEID *)p2;
+
+ if (pId1->suid < pId2->suid) {
+ return -1;
+ } else if (pId1->suid > pId2->suid) {
+ return 1;
+ }
+
+ if (pId1->uid < pId2->uid) {
+ return -1;
+ } else if (pId1->uid > pId2->uid) {
+ return 1;
+ }
+
+ return 0;
+}
+
+// TSDBKEY =======================================================================
+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;
+}
+
+// TSDBKEY ======================================================
+static FORCE_INLINE int32_t tPutTSDBKEY(uint8_t *p, TSDBKEY *pKey) {
+ int32_t n = 0;
+
+ n += tPutI64v(p ? p + n : p, pKey->version);
+ n += tPutI64(p ? p + n : p, pKey->ts);
+
+ return n;
+}
+
+static FORCE_INLINE int32_t tGetTSDBKEY(uint8_t *p, TSDBKEY *pKey) {
+ int32_t n = 0;
+
+ n += tGetI64v(p + n, &pKey->version);
+ n += tGetI64(p + n, &pKey->ts);
+
+ return n;
+}
+
+// SBlockIdx ======================================================
+void tBlockIdxReset(SBlockIdx *pBlockIdx) {
+ pBlockIdx->minKey = TSKEY_MAX;
+ pBlockIdx->maxKey = TSKEY_MIN;
+ pBlockIdx->minVersion = VERSION_MAX;
+ pBlockIdx->maxVersion = VERSION_MIN;
+ pBlockIdx->offset = -1;
+ pBlockIdx->size = -1;
+}
+
+int32_t tPutBlockIdx(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlockIdx *pBlockIdx = (SBlockIdx *)ph;
+
+ n += tPutI64(p ? p + n : p, pBlockIdx->suid);
+ n += tPutI64(p ? p + n : p, pBlockIdx->uid);
+ n += tPutI64(p ? p + n : p, pBlockIdx->minKey);
+ n += tPutI64(p ? p + n : p, pBlockIdx->maxKey);
+ n += tPutI64v(p ? p + n : p, pBlockIdx->minVersion);
+ n += tPutI64v(p ? p + n : p, pBlockIdx->maxVersion);
+ n += tPutI64v(p ? p + n : p, pBlockIdx->offset);
+ n += tPutI64v(p ? p + n : p, pBlockIdx->size);
+
+ return n;
+}
+
+int32_t tGetBlockIdx(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlockIdx *pBlockIdx = (SBlockIdx *)ph;
+
+ n += tGetI64(p + n, &pBlockIdx->suid);
+ n += tGetI64(p + n, &pBlockIdx->uid);
+ n += tGetI64(p + n, &pBlockIdx->minKey);
+ n += tGetI64(p + n, &pBlockIdx->maxKey);
+ n += tGetI64v(p + n, &pBlockIdx->minVersion);
+ n += tGetI64v(p + n, &pBlockIdx->maxVersion);
+ n += tGetI64v(p + n, &pBlockIdx->offset);
+ n += tGetI64v(p + n, &pBlockIdx->size);
+
+ return n;
+}
+
+int32_t tCmprBlockIdx(void const *lhs, void const *rhs) {
+ SBlockIdx *lBlockIdx = (SBlockIdx *)lhs;
+ SBlockIdx *rBlockIdx = (SBlockIdx *)rhs;
+
+ if (lBlockIdx->suid < rBlockIdx->suid) {
+ return -1;
+ } else if (lBlockIdx->suid > rBlockIdx->suid) {
+ return 1;
+ }
+
+ if (lBlockIdx->uid < rBlockIdx->uid) {
+ return -1;
+ } else if (lBlockIdx->uid > rBlockIdx->uid) {
+ return 1;
+ }
+
+ return 0;
+}
+
+// SBlock ======================================================
+void tBlockReset(SBlock *pBlock) {
+ *pBlock =
+ (SBlock){.minKey = TSDBKEY_MAX, .maxKey = TSDBKEY_MIN, .minVersion = VERSION_MAX, .maxVersion = VERSION_MIN};
+}
+
+int32_t tPutBlock(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlock *pBlock = (SBlock *)ph;
+
+ n += tPutTSDBKEY(p ? p + n : p, &pBlock->minKey);
+ n += tPutTSDBKEY(p ? p + n : p, &pBlock->maxKey);
+ n += tPutI64v(p ? p + n : p, pBlock->minVersion);
+ n += tPutI64v(p ? p + n : p, pBlock->maxVersion);
+ n += tPutI32v(p ? p + n : p, pBlock->nRow);
+ n += tPutI8(p ? p + n : p, pBlock->last);
+ n += tPutI8(p ? p + n : p, pBlock->hasDup);
+ n += tPutI8(p ? p + n : p, pBlock->nSubBlock);
+ for (int8_t iSubBlock = 0; iSubBlock < pBlock->nSubBlock; iSubBlock++) {
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].nRow);
+ n += tPutI8(p ? p + n : p, pBlock->aSubBlock[iSubBlock].cmprAlg);
+ n += tPutI64v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].offset);
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].szBlockCol);
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].szVersion);
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].szTSKEY);
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].szBlock);
+ n += tPutI64v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].sOffset);
+ n += tPutI32v(p ? p + n : p, pBlock->aSubBlock[iSubBlock].nSma);
+ }
+
+ return n;
+}
+
+int32_t tGetBlock(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlock *pBlock = (SBlock *)ph;
+
+ n += tGetTSDBKEY(p + n, &pBlock->minKey);
+ n += tGetTSDBKEY(p + n, &pBlock->maxKey);
+ n += tGetI64v(p + n, &pBlock->minVersion);
+ n += tGetI64v(p + n, &pBlock->maxVersion);
+ n += tGetI32v(p + n, &pBlock->nRow);
+ n += tGetI8(p + n, &pBlock->last);
+ n += tGetI8(p + n, &pBlock->hasDup);
+ n += tGetI8(p + n, &pBlock->nSubBlock);
+ for (int8_t iSubBlock = 0; iSubBlock < pBlock->nSubBlock; iSubBlock++) {
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].nRow);
+ n += tGetI8(p + n, &pBlock->aSubBlock[iSubBlock].cmprAlg);
+ n += tGetI64v(p + n, &pBlock->aSubBlock[iSubBlock].offset);
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].szBlockCol);
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].szVersion);
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].szTSKEY);
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].szBlock);
+ n += tGetI64v(p + n, &pBlock->aSubBlock[iSubBlock].sOffset);
+ n += tGetI32v(p + n, &pBlock->aSubBlock[iSubBlock].nSma);
+ }
+
+ return n;
+}
+
+int32_t tBlockCmprFn(const void *p1, const void *p2) {
+ SBlock *pBlock1 = (SBlock *)p1;
+ SBlock *pBlock2 = (SBlock *)p2;
+
+ if (tsdbKeyCmprFn(&pBlock1->maxKey, &pBlock2->minKey) < 0) {
+ return -1;
+ } else if (tsdbKeyCmprFn(&pBlock1->minKey, &pBlock2->maxKey) > 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+bool tBlockHasSma(SBlock *pBlock) {
+ if (pBlock->nSubBlock > 1) return false;
+ if (pBlock->last) return false;
+ if (pBlock->hasDup) return false;
+
+ return pBlock->aSubBlock[0].nSma > 0;
+}
+
+// SBlockCol ======================================================
+int32_t tPutBlockCol(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlockCol *pBlockCol = (SBlockCol *)ph;
+
+ ASSERT(pBlockCol->flag && (pBlockCol->flag != HAS_NONE));
+
+ n += tPutI16v(p ? p + n : p, pBlockCol->cid);
+ n += tPutI8(p ? p + n : p, pBlockCol->type);
+ n += tPutI8(p ? p + n : p, pBlockCol->smaOn);
+ n += tPutI8(p ? p + n : p, pBlockCol->flag);
+
+ if (pBlockCol->flag != HAS_NULL) {
+ n += tPutI32v(p ? p + n : p, pBlockCol->offset);
+ n += tPutI32v(p ? p + n : p, pBlockCol->szBitmap);
+ n += tPutI32v(p ? p + n : p, pBlockCol->szOffset);
+ n += tPutI32v(p ? p + n : p, pBlockCol->szValue);
+ n += tPutI32v(p ? p + n : p, pBlockCol->szOrigin);
+ }
+
+ return n;
+}
+
+int32_t tGetBlockCol(uint8_t *p, void *ph) {
+ int32_t n = 0;
+ SBlockCol *pBlockCol = (SBlockCol *)ph;
+
+ n += tGetI16v(p + n, &pBlockCol->cid);
+ n += tGetI8(p + n, &pBlockCol->type);
+ n += tGetI8(p + n, &pBlockCol->smaOn);
+ n += tGetI8(p + n, &pBlockCol->flag);
+
+ ASSERT(pBlockCol->flag && (pBlockCol->flag != HAS_NONE));
+
+ if (pBlockCol->flag != HAS_NULL) {
+ n += tGetI32v(p + n, &pBlockCol->offset);
+ n += tGetI32v(p + n, &pBlockCol->szBitmap);
+ n += tGetI32v(p + n, &pBlockCol->szOffset);
+ n += tGetI32v(p + n, &pBlockCol->szValue);
+ n += tGetI32v(p + n, &pBlockCol->szOrigin);
+ }
+
+ return n;
+}
+
+int32_t tBlockColCmprFn(const void *p1, const void *p2) {
+ if (((SBlockCol *)p1)->cid < ((SBlockCol *)p2)->cid) {
+ return -1;
+ } else if (((SBlockCol *)p1)->cid > ((SBlockCol *)p2)->cid) {
+ return 1;
+ }
+
+ return 0;
+}
+
+// SDelIdx ======================================================
+int32_t tCmprDelIdx(void const *lhs, void const *rhs) {
+ SDelIdx *lDelIdx = (SDelIdx *)lhs;
+ SDelIdx *rDelIdx = (SDelIdx *)rhs;
+
+ if (lDelIdx->suid < rDelIdx->suid) {
+ return -1;
+ } else if (lDelIdx->suid > rDelIdx->suid) {
+ return 1;
+ }
+
+ if (lDelIdx->uid < rDelIdx->uid) {
+ return -1;
+ } else if (lDelIdx->uid > rDelIdx->uid) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int32_t tPutDelIdx(uint8_t *p, void *ph) {
+ SDelIdx *pDelIdx = (SDelIdx *)ph;
+ int32_t n = 0;
+
+ n += tPutI64(p ? p + n : p, pDelIdx->suid);
+ n += tPutI64(p ? p + n : p, pDelIdx->uid);
+ n += tPutI64v(p ? p + n : p, pDelIdx->offset);
+ n += tPutI64v(p ? p + n : p, pDelIdx->size);
+
+ return n;
+}
+
+int32_t tGetDelIdx(uint8_t *p, void *ph) {
+ SDelIdx *pDelIdx = (SDelIdx *)ph;
+ int32_t n = 0;
+
+ n += tGetI64(p + n, &pDelIdx->suid);
+ n += tGetI64(p + n, &pDelIdx->uid);
+ n += tGetI64v(p + n, &pDelIdx->offset);
+ n += tGetI64v(p + n, &pDelIdx->size);
+
+ return n;
+}
+
+// SDelData ======================================================
+int32_t tPutDelData(uint8_t *p, void *ph) {
+ SDelData *pDelData = (SDelData *)ph;
+ int32_t n = 0;
+
+ n += tPutI64v(p ? p + n : p, pDelData->version);
+ n += tPutI64(p ? p + n : p, pDelData->sKey);
+ n += tPutI64(p ? p + n : p, pDelData->eKey);
+
+ return n;
+}
+
+int32_t tGetDelData(uint8_t *p, void *ph) {
+ SDelData *pDelData = (SDelData *)ph;
+ int32_t n = 0;
+
+ n += tGetI64v(p + n, &pDelData->version);
+ n += tGetI64(p + n, &pDelData->sKey);
+ n += tGetI64(p + n, &pDelData->eKey);
+
+ return n;
+}
+
+int32_t tsdbKeyFid(TSKEY key, int32_t minutes, int8_t precision) {
+ if (key < 0) {
+ return (int)((key + 1) / tsTickPerMin[precision] / minutes - 1);
+ } else {
+ return (int)((key / tsTickPerMin[precision] / minutes));
+ }
+}
+
+void tsdbFidKeyRange(int32_t fid, int32_t minutes, int8_t precision, TSKEY *minKey, TSKEY *maxKey) {
+ *minKey = fid * minutes * tsTickPerMin[precision];
+ *maxKey = *minKey + minutes * tsTickPerMin[precision] - 1;
+}
+
+int32_t tsdbFidLevel(int32_t fid, STsdbKeepCfg *pKeepCfg, int64_t now) {
+ int32_t aFid[3];
+ TSKEY key;
+
+ if (pKeepCfg->precision == TSDB_TIME_PRECISION_MILLI) {
+ now = now * 1000;
+ } else if (pKeepCfg->precision == TSDB_TIME_PRECISION_MICRO) {
+ now = now * 1000000l;
+ } else if (pKeepCfg->precision == TSDB_TIME_PRECISION_NANO) {
+ now = now * 1000000000l;
+ } else {
+ ASSERT(0);
+ }
+
+ key = now - pKeepCfg->keep0 * tsTickPerMin[pKeepCfg->precision];
+ aFid[0] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
+ key = now - pKeepCfg->keep1 * tsTickPerMin[pKeepCfg->precision];
+ aFid[1] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
+ key = now - pKeepCfg->keep2 * tsTickPerMin[pKeepCfg->precision];
+ aFid[2] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
+
+ if (fid >= aFid[0]) {
+ return 0;
+ } else if (fid >= aFid[1]) {
+ return 1;
+ } else if (fid >= aFid[2]) {
+ return 2;
+ } else {
+ return -1;
+ }
+}
+
+// TSDBROW ======================================================
+void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) {
+ STColumn *pTColumn = &pTSchema->columns[iCol];
+ SValue value;
+
+ ASSERT(iCol > 0);
+
+ if (pRow->type == 0) {
+ tTSRowGetVal(pRow->pTSRow, pTSchema, iCol, pColVal);
+ } else if (pRow->type == 1) {
+ SColData *pColData;
+
+ tBlockDataGetColData(pRow->pBlockData, pTColumn->colId, &pColData);
+
+ if (pColData) {
+ tColDataGetValue(pColData, pRow->iRow, pColVal);
+ } else {
+ *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type);
+ }
+ } else {
+ ASSERT(0);
+ }
+}
+
+int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow) {
+ int32_t n = 0;
+
+ n += tPutI64(p, pRow->version);
+ if (p) memcpy(p + n, pRow->pTSRow, pRow->pTSRow->len);
+ n += pRow->pTSRow->len;
+
+ return n;
+}
+
+int32_t tGetTSDBRow(uint8_t *p, TSDBROW *pRow) {
+ int32_t n = 0;
+
+ n += tGetI64(p, &pRow->version);
+ pRow->pTSRow = (STSRow *)(p + n);
+ n += pRow->pTSRow->len;
+
+ return n;
+}
+
+int32_t tsdbRowCmprFn(const void *p1, const void *p2) {
+ return tsdbKeyCmprFn(&TSDBROW_KEY((TSDBROW *)p1), &TSDBROW_KEY((TSDBROW *)p2));
+}
+
+// SRowIter ======================================================
+void tRowIterInit(SRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema) {
+ pIter->pRow = pRow;
+ if (pRow->type == 0) {
+ ASSERT(pTSchema);
+ pIter->pTSchema = pTSchema;
+ pIter->i = 1;
+ } else if (pRow->type == 1) {
+ pIter->pTSchema = NULL;
+ pIter->i = 0;
+ } else {
+ ASSERT(0);
+ }
+}
+
+SColVal *tRowIterNext(SRowIter *pIter) {
+ if (pIter->pRow->type == 0) {
+ if (pIter->i < pIter->pTSchema->numOfCols) {
+ tsdbRowGetColVal(pIter->pRow, pIter->pTSchema, pIter->i, &pIter->colVal);
+ pIter->i++;
+
+ return &pIter->colVal;
+ }
+ } else {
+ if (pIter->i < taosArrayGetSize(pIter->pRow->pBlockData->aIdx)) {
+ SColData *pColData = tBlockDataGetColDataByIdx(pIter->pRow->pBlockData, pIter->i);
+
+ tColDataGetValue(pColData, pIter->pRow->iRow, &pIter->colVal);
+ pIter->i++;
+
+ return &pIter->colVal;
+ }
+ }
+
+ return NULL;
+}
+
+// SRowMerger ======================================================
+int32_t tRowMergerInit(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema) {
+ int32_t code = 0;
+ TSDBKEY key = TSDBROW_KEY(pRow);
+ SColVal *pColVal = &(SColVal){0};
+ STColumn *pTColumn;
+
+ pMerger->pTSchema = pTSchema;
+ pMerger->version = key.version;
+
+ pMerger->pArray = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal));
+ if (pMerger->pArray == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+ // ts
+ pTColumn = &pTSchema->columns[0];
+
+ ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP);
+
+ *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.ts = key.ts});
+ if (taosArrayPush(pMerger->pArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+ // other
+ for (int16_t iCol = 1; iCol < pTSchema->numOfCols; iCol++) {
+ tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal);
+ if (taosArrayPush(pMerger->pArray, pColVal) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ }
+
+_exit:
+ return code;
+}
+
+void tRowMergerClear(SRowMerger *pMerger) { taosArrayDestroy(pMerger->pArray); }
+
+int32_t tRowMerge(SRowMerger *pMerger, TSDBROW *pRow) {
+ int32_t code = 0;
+ TSDBKEY key = TSDBROW_KEY(pRow);
+ SColVal *pColVal = &(SColVal){0};
+
+ ASSERT(((SColVal *)pMerger->pArray->pData)->value.ts == key.ts);
+
+ for (int32_t iCol = 1; iCol < pMerger->pTSchema->numOfCols; iCol++) {
+ tsdbRowGetColVal(pRow, pMerger->pTSchema, iCol, pColVal);
+
+ if (key.version > pMerger->version) {
+ if (!pColVal->isNone) {
+ taosArraySet(pMerger->pArray, iCol, pColVal);
+ }
+ } else if (key.version < pMerger->version) {
+ SColVal *tColVal = (SColVal *)taosArrayGet(pMerger->pArray, iCol);
+ if (tColVal->isNone && !pColVal->isNone) {
+ taosArraySet(pMerger->pArray, iCol, pColVal);
+ }
+ } else {
+ ASSERT(0);
+ }
+ }
+
+ pMerger->version = key.version;
+
+_exit:
+ return code;
+}
+
+int32_t tRowMergerGetRow(SRowMerger *pMerger, STSRow **ppRow) {
+ int32_t code = 0;
+
+ code = tdSTSRowNew(pMerger->pArray, pMerger->pTSchema, ppRow);
+
+ return code;
+}
+
+// delete skyline ======================================================
+static int32_t tsdbMergeSkyline(SArray *aSkyline1, SArray *aSkyline2, SArray *aSkyline) {
+ int32_t code = 0;
+ int32_t i1 = 0;
+ int32_t n1 = taosArrayGetSize(aSkyline1);
+ int32_t i2 = 0;
+ int32_t n2 = taosArrayGetSize(aSkyline2);
+ TSDBKEY *pSkyline1;
+ TSDBKEY *pSkyline2;
+ TSDBKEY item;
+ int64_t version1 = 0;
+ int64_t version2 = 0;
+
+ ASSERT(n1 > 0 && n2 > 0);
+
+ taosArrayClear(aSkyline);
+
+ while (i1 < n1 && i2 < n2) {
+ pSkyline1 = (TSDBKEY *)taosArrayGet(aSkyline1, i1);
+ pSkyline2 = (TSDBKEY *)taosArrayGet(aSkyline2, i2);
+
+ if (pSkyline1->ts < pSkyline2->ts) {
+ version1 = pSkyline1->version;
+ i1++;
+ } else if (pSkyline1->ts > pSkyline2->ts) {
+ version2 = pSkyline2->version;
+ i2++;
+ } else {
+ version1 = pSkyline1->version;
+ version2 = pSkyline2->version;
+ i1++;
+ i2++;
+ }
+
+ item.ts = TMIN(pSkyline1->ts, pSkyline2->ts);
+ item.version = TMAX(version1, version2);
+ if (taosArrayPush(aSkyline, &item) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ }
+
+ while (i1 < n1) {
+ pSkyline1 = (TSDBKEY *)taosArrayGet(aSkyline1, i1);
+ item.ts = pSkyline1->ts;
+ item.version = pSkyline1->version;
+ if (taosArrayPush(aSkyline, &item) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ i1++;
+ }
+
+ while (i2 < n2) {
+ pSkyline2 = (TSDBKEY *)taosArrayGet(aSkyline2, i2);
+ item.ts = pSkyline2->ts;
+ item.version = pSkyline2->version;
+ if (taosArrayPush(aSkyline, &item) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ i2++;
+ }
+
+_exit:
+ return code;
+}
+int32_t tsdbBuildDeleteSkyline(SArray *aDelData, int32_t sidx, int32_t eidx, SArray *aSkyline) {
+ int32_t code = 0;
+ SDelData *pDelData;
+ int32_t midx;
+
+ taosArrayClear(aSkyline);
+ if (sidx == eidx) {
+ pDelData = (SDelData *)taosArrayGet(aDelData, sidx);
+ taosArrayPush(aSkyline, &(TSDBKEY){.ts = pDelData->sKey, .version = pDelData->version});
+ taosArrayPush(aSkyline, &(TSDBKEY){.ts = pDelData->eKey, .version = 0});
+ } else {
+ SArray *aSkyline1 = NULL;
+ SArray *aSkyline2 = NULL;
+
+ aSkyline1 = taosArrayInit(0, sizeof(TSDBKEY));
+ aSkyline2 = taosArrayInit(0, sizeof(TSDBKEY));
+ if (aSkyline1 == NULL || aSkyline2 == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _clear;
+ }
+
+ midx = (sidx + eidx) / 2;
+
+ code = tsdbBuildDeleteSkyline(aDelData, sidx, midx, aSkyline1);
+ if (code) goto _clear;
+
+ code = tsdbBuildDeleteSkyline(aDelData, midx + 1, eidx, aSkyline2);
+ if (code) goto _clear;
+
+ code = tsdbMergeSkyline(aSkyline1, aSkyline2, aSkyline);
+
+ _clear:
+ taosArrayDestroy(aSkyline1);
+ taosArrayDestroy(aSkyline2);
+ }
+
+ return code;
+}
+
+// SColData ========================================
+void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) {
+ pColData->cid = cid;
+ pColData->type = type;
+ pColData->smaOn = smaOn;
+ tColDataReset(pColData);
+}
+
+void tColDataReset(SColData *pColData) {
+ pColData->nVal = 0;
+ pColData->flag = 0;
+ pColData->nData = 0;
+}
+
+void tColDataClear(void *ph) {
+ SColData *pColData = (SColData *)ph;
+
+ tFree(pColData->pBitMap);
+ tFree((uint8_t *)pColData->aOffset);
+ tFree(pColData->pData);
+}
+
+int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) {
+ int32_t code = 0;
+ int64_t size;
+ SValue value = {0};
+ SValue *pValue = &value;
+
+ ASSERT(pColVal->cid == pColData->cid);
+ ASSERT(pColVal->type == pColData->type);
+
+ // realloc bitmap
+ size = BIT2_SIZE(pColData->nVal + 1);
+ code = tRealloc(&pColData->pBitMap, size);
+ if (code) goto _exit;
+
+ // put value
+ if (pColVal->isNone) {
+ pColData->flag |= HAS_NONE;
+ SET_BIT2(pColData->pBitMap, pColData->nVal, 0);
+ } else if (pColVal->isNull) {
+ pColData->flag |= HAS_NULL;
+ SET_BIT2(pColData->pBitMap, pColData->nVal, 1);
+ } else {
+ pColData->flag |= HAS_VALUE;
+ SET_BIT2(pColData->pBitMap, pColData->nVal, 2);
+ pValue = &pColVal->value;
+ }
+
+ if (IS_VAR_DATA_TYPE(pColData->type)) {
+ // offset
+ code = tRealloc((uint8_t **)&pColData->aOffset, sizeof(int32_t) * (pColData->nVal + 1));
+ if (code) goto _exit;
+ pColData->aOffset[pColData->nVal] = pColData->nData;
+
+ // value
+ if ((!pColVal->isNone) && (!pColVal->isNull)) {
+ code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData);
+ if (code) goto _exit;
+ memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData);
+ pColData->nData += pColVal->value.nData;
+ }
+ } else {
+ code = tRealloc(&pColData->pData, pColData->nData + tPutValue(NULL, pValue, pColVal->type));
+ if (code) goto _exit;
+ pColData->nData += tPutValue(pColData->pData + pColData->nData, pValue, pColVal->type);
+ }
+
+ pColData->nVal++;
+
+_exit:
+ return code;
+}
+
+int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) {
+ int32_t code = 0;
+ int32_t size;
+
+ ASSERT(pColDataSrc->nVal > 0);
+
+ pColDataDest->cid = pColDataSrc->cid;
+ pColDataDest->type = pColDataSrc->type;
+ pColDataDest->smaOn = pColDataSrc->smaOn;
+ pColDataDest->nVal = pColDataSrc->nVal;
+ pColDataDest->flag = pColDataSrc->flag;
+
+ if (pColDataSrc->flag != HAS_NONE && pColDataSrc->flag != HAS_NULL && pColDataSrc->flag != HAS_VALUE) {
+ size = BIT2_SIZE(pColDataSrc->nVal);
+ code = tRealloc(&pColDataDest->pBitMap, size);
+ if (code) goto _exit;
+ memcpy(pColDataDest->pBitMap, pColDataSrc->pBitMap, size);
+ }
+
+ if (IS_VAR_DATA_TYPE(pColDataDest->type)) {
+ size = sizeof(int32_t) * pColDataSrc->nVal;
+
+ code = tRealloc((uint8_t **)&pColDataDest->aOffset, size);
+ if (code) goto _exit;
+
+ memcpy(pColDataDest->aOffset, pColDataSrc->aOffset, size);
+ }
+
+ code = tRealloc(&pColDataDest->pData, pColDataSrc->nData);
+ if (code) goto _exit;
+ pColDataDest->nData = pColDataSrc->nData;
+ memcpy(pColDataDest->pData, pColDataSrc->pData, pColDataDest->nData);
+
+_exit:
+ return code;
+}
+
+int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) {
+ int32_t code = 0;
+
+ ASSERT(iVal < pColData->nVal);
+ ASSERT(pColData->flag);
+
+ if (pColData->flag == HAS_NONE) {
+ *pColVal = COL_VAL_NONE(pColData->cid, pColData->type);
+ goto _exit;
+ } else if (pColData->flag == HAS_NULL) {
+ *pColVal = COL_VAL_NULL(pColData->cid, pColData->type);
+ goto _exit;
+ } else if (pColData->flag != HAS_VALUE) {
+ uint8_t v = GET_BIT2(pColData->pBitMap, iVal);
+ if (v == 0) {
+ *pColVal = COL_VAL_NONE(pColData->cid, pColData->type);
+ goto _exit;
+ } else if (v == 1) {
+ *pColVal = COL_VAL_NULL(pColData->cid, pColData->type);
+ goto _exit;
+ }
+ }
+
+ // get value
+ SValue value;
+ if (IS_VAR_DATA_TYPE(pColData->type)) {
+ if (iVal + 1 < pColData->nVal) {
+ value.nData = pColData->aOffset[iVal + 1] - pColData->aOffset[iVal];
+ } else {
+ value.nData = pColData->nData - pColData->aOffset[iVal];
+ }
+
+ value.pData = pColData->pData + pColData->aOffset[iVal];
+ } else {
+ tGetValue(pColData->pData + tDataTypes[pColData->type].bytes * iVal, &value, pColData->type);
+ }
+ *pColVal = COL_VAL_VALUE(pColData->cid, pColData->type, value);
+
+_exit:
+ return code;
+}
+
+static FORCE_INLINE int32_t tColDataCmprFn(const void *p1, const void *p2) {
+ SColData *pColData1 = (SColData *)p1;
+ SColData *pColData2 = (SColData *)p2;
+
+ if (pColData1->cid < pColData2->cid) {
+ return -1;
+ } else if (pColData1->cid > pColData2->cid) {
+ return 1;
+ }
+
+ return 0;
+}
+
+// SBlockData ======================================================
+int32_t tBlockDataInit(SBlockData *pBlockData) {
+ int32_t code = 0;
+
+ pBlockData->nRow = 0;
+ pBlockData->aVersion = NULL;
+ pBlockData->aTSKEY = NULL;
+ pBlockData->aIdx = taosArrayInit(0, sizeof(int32_t));
+ if (pBlockData->aIdx == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ pBlockData->aColData = taosArrayInit(0, sizeof(SColData));
+ if (pBlockData->aColData == NULL) {
+ taosArrayDestroy(pBlockData->aIdx);
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+
+_exit:
+ return code;
+}
+
+void tBlockDataReset(SBlockData *pBlockData) {
+ pBlockData->nRow = 0;
+ taosArrayClear(pBlockData->aIdx);
+}
+
+void tBlockDataClear(SBlockData *pBlockData) {
+ tFree((uint8_t *)pBlockData->aVersion);
+ tFree((uint8_t *)pBlockData->aTSKEY);
+ taosArrayDestroy(pBlockData->aIdx);
+ taosArrayDestroyEx(pBlockData->aColData, tColDataClear);
+}
+
+int32_t tBlockDataSetSchema(SBlockData *pBlockData, STSchema *pTSchema) {
+ int32_t code = 0;
+ SColData *pColData;
+ STColumn *pTColumn;
+
+ tBlockDataReset(pBlockData);
+ for (int32_t iColumn = 1; iColumn < pTSchema->numOfCols; iColumn++) {
+ pTColumn = &pTSchema->columns[iColumn];
+
+ code = tBlockDataAddColData(pBlockData, iColumn - 1, &pColData);
+ if (code) goto _exit;
+
+ tColDataInit(pColData, pTColumn->colId, pTColumn->type, (pTColumn->flags & COL_SMA_ON) != 0);
+ }
+
+_exit:
+ return code;
+}
+
+void tBlockDataClearData(SBlockData *pBlockData) {
+ pBlockData->nRow = 0;
+ for (int32_t iColData = 0; iColData < taosArrayGetSize(pBlockData->aIdx); iColData++) {
+ SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, iColData);
+ tColDataReset(pColData);
+ }
+}
+
+int32_t tBlockDataAddColData(SBlockData *pBlockData, int32_t iColData, SColData **ppColData) {
+ int32_t code = 0;
+ SColData *pColData = NULL;
+ int32_t idx = taosArrayGetSize(pBlockData->aIdx);
+
+ if (idx >= taosArrayGetSize(pBlockData->aColData)) {
+ if (taosArrayPush(pBlockData->aColData, &((SColData){0})) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ }
+ pColData = (SColData *)taosArrayGet(pBlockData->aColData, idx);
+
+ if (taosArrayInsert(pBlockData->aIdx, iColData, &idx) == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ *ppColData = pColData;
+ return code;
+
+_err:
+ *ppColData = NULL;
+ return code;
+}
+
+int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema) {
+ int32_t code = 0;
+
+ // TSDBKEY
+ code = tRealloc((uint8_t **)&pBlockData->aVersion, sizeof(int64_t) * (pBlockData->nRow + 1));
+ if (code) goto _err;
+ code = tRealloc((uint8_t **)&pBlockData->aTSKEY, sizeof(TSKEY) * (pBlockData->nRow + 1));
+ if (code) goto _err;
+ pBlockData->aVersion[pBlockData->nRow] = TSDBROW_VERSION(pRow);
+ pBlockData->aTSKEY[pBlockData->nRow] = TSDBROW_TS(pRow);
+
+ // OTHER
+ int32_t iColData = 0;
+ int32_t nColData = taosArrayGetSize(pBlockData->aIdx);
+ SRowIter iter = {0};
+ SRowIter *pIter = &iter;
+ SColData *pColData;
+ SColVal *pColVal;
+
+ if (nColData == 0) goto _exit;
+
+ tRowIterInit(pIter, pRow, pTSchema);
+ pColData = tBlockDataGetColDataByIdx(pBlockData, iColData);
+ pColVal = tRowIterNext(pIter);
+
+ while (pColData) {
+ if (pColVal) {
+ if (pColData->cid == pColVal->cid) {
+ code = tColDataAppendValue(pColData, pColVal);
+ if (code) goto _err;
+
+ pColVal = tRowIterNext(pIter);
+ pColData = ((++iColData) < nColData) ? tBlockDataGetColDataByIdx(pBlockData, iColData) : NULL;
+ } else if (pColData->cid < pColVal->cid) {
+ code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type));
+ if (code) goto _err;
+
+ pColData = ((++iColData) < nColData) ? tBlockDataGetColDataByIdx(pBlockData, iColData) : NULL;
+ } else {
+ pColVal = tRowIterNext(pIter);
+ }
+ } else {
+ code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type));
+ if (code) goto _err;
+
+ pColData = ((++iColData) < nColData) ? tBlockDataGetColDataByIdx(pBlockData, iColData) : NULL;
+ }
+ }
+
+_exit:
+ pBlockData->nRow++;
+ return code;
+
+_err:
+ return code;
+}
+
+int32_t tBlockDataMerge(SBlockData *pBlockData1, SBlockData *pBlockData2, SBlockData *pBlockData) {
+ int32_t code = 0;
+
+ // set target
+ int32_t iColData1 = 0;
+ int32_t nColData1 = taosArrayGetSize(pBlockData1->aIdx);
+ int32_t iColData2 = 0;
+ int32_t nColData2 = taosArrayGetSize(pBlockData2->aIdx);
+ SColData *pColData1;
+ SColData *pColData2;
+ SColData *pColData;
+
+ tBlockDataReset(pBlockData);
+ while (iColData1 < nColData1 && iColData2 < nColData2) {
+ pColData1 = tBlockDataGetColDataByIdx(pBlockData1, iColData1);
+ pColData2 = tBlockDataGetColDataByIdx(pBlockData2, iColData2);
+
+ if (pColData1->cid == pColData2->cid) {
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _exit;
+ tColDataInit(pColData, pColData2->cid, pColData2->type, pColData2->smaOn);
+
+ iColData1++;
+ iColData2++;
+ } else if (pColData1->cid < pColData2->cid) {
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _exit;
+ tColDataInit(pColData, pColData1->cid, pColData1->type, pColData1->smaOn);
+
+ iColData1++;
+ } else {
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _exit;
+ tColDataInit(pColData, pColData2->cid, pColData2->type, pColData2->smaOn);
+
+ iColData2++;
+ }
+ }
+
+ while (iColData1 < nColData1) {
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _exit;
+ tColDataInit(pColData, pColData1->cid, pColData1->type, pColData1->smaOn);
+
+ iColData1++;
+ }
+
+ while (iColData2 < nColData2) {
+ code = tBlockDataAddColData(pBlockData, taosArrayGetSize(pBlockData->aIdx), &pColData);
+ if (code) goto _exit;
+ tColDataInit(pColData, pColData2->cid, pColData2->type, pColData2->smaOn);
+
+ iColData2++;
+ }
+
+ // loop to merge
+ int32_t iRow1 = 0;
+ int32_t nRow1 = pBlockData1->nRow;
+ int32_t iRow2 = 0;
+ int32_t nRow2 = pBlockData2->nRow;
+ TSDBROW row1;
+ TSDBROW row2;
+ int32_t c;
+
+ while (iRow1 < nRow1 && iRow2 < nRow2) {
+ row1 = tsdbRowFromBlockData(pBlockData1, iRow1);
+ row2 = tsdbRowFromBlockData(pBlockData2, iRow2);
+
+ c = tsdbKeyCmprFn(&TSDBROW_KEY(&row1), &TSDBROW_KEY(&row2));
+ if (c < 0) {
+ code = tBlockDataAppendRow(pBlockData, &row1, NULL);
+ if (code) goto _exit;
+ iRow1++;
+ } else if (c > 0) {
+ code = tBlockDataAppendRow(pBlockData, &row2, NULL);
+ if (code) goto _exit;
+ iRow2++;
+ } else {
+ ASSERT(0);
+ }
+ }
+
+ while (iRow1 < nRow1) {
+ row1 = tsdbRowFromBlockData(pBlockData1, iRow1);
+ code = tBlockDataAppendRow(pBlockData, &row1, NULL);
+ if (code) goto _exit;
+ iRow1++;
+ }
+
+ while (iRow2 < nRow2) {
+ row2 = tsdbRowFromBlockData(pBlockData2, iRow2);
+ code = tBlockDataAppendRow(pBlockData, &row2, NULL);
+ if (code) goto _exit;
+ iRow2++;
+ }
+
+_exit:
+ return code;
+}
+
+int32_t tBlockDataCopy(SBlockData *pBlockDataSrc, SBlockData *pBlockDataDest) {
+ int32_t code = 0;
+ SColData *pColDataSrc;
+ SColData *pColDataDest;
+
+ ASSERT(pBlockDataSrc->nRow > 0);
+
+ tBlockDataReset(pBlockDataDest);
+
+ pBlockDataDest->nRow = pBlockDataSrc->nRow;
+ // TSDBKEY
+ code = tRealloc((uint8_t **)&pBlockDataDest->aVersion, sizeof(int64_t) * pBlockDataSrc->nRow);
+ if (code) goto _exit;
+ code = tRealloc((uint8_t **)&pBlockDataDest->aTSKEY, sizeof(TSKEY) * pBlockDataSrc->nRow);
+ if (code) goto _exit;
+ memcpy(pBlockDataDest->aVersion, pBlockDataSrc->aVersion, sizeof(int64_t) * pBlockDataSrc->nRow);
+ memcpy(pBlockDataDest->aTSKEY, pBlockDataSrc->aTSKEY, sizeof(TSKEY) * pBlockDataSrc->nRow);
+
+ // other
+ for (size_t iColData = 0; iColData < taosArrayGetSize(pBlockDataSrc->aIdx); iColData++) {
+ pColDataSrc = tBlockDataGetColDataByIdx(pBlockDataSrc, iColData);
+ code = tBlockDataAddColData(pBlockDataDest, iColData, &pColDataDest);
+ if (code) goto _exit;
+
+ code = tColDataCopy(pColDataSrc, pColDataDest);
+ if (code) goto _exit;
+ }
+
+_exit:
+ return code;
+}
+
+SColData *tBlockDataGetColDataByIdx(SBlockData *pBlockData, int32_t idx) {
+ ASSERT(idx >= 0 && idx < taosArrayGetSize(pBlockData->aIdx));
+ return (SColData *)taosArrayGet(pBlockData->aColData, *(int32_t *)taosArrayGet(pBlockData->aIdx, idx));
+}
+
+void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColData) {
+ ASSERT(cid != PRIMARYKEY_TIMESTAMP_COL_ID);
+ int32_t lidx = 0;
+ int32_t ridx = taosArrayGetSize(pBlockData->aIdx) - 1;
+
+ while (lidx <= ridx) {
+ int32_t midx = (lidx + ridx) / 2;
+ SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, midx);
+ int32_t c = tColDataCmprFn(pColData, &(SColData){.cid = cid});
+
+ if (c == 0) {
+ *ppColData = pColData;
+ return;
+ } else if (c < 0) {
+ lidx = midx + 1;
+ } else {
+ ridx = midx - 1;
+ }
+ }
+
+ *ppColData = NULL;
+}
+
+// ALGORITHM ==============================
+void tsdbCalcColDataSMA(SColData *pColData, SColumnDataAgg *pColAgg) {
+ SColVal colVal;
+ SColVal *pColVal = &colVal;
+
+ *pColAgg = (SColumnDataAgg){.colId = pColData->cid};
+ for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) {
+ tColDataGetValue(pColData, iVal, pColVal);
+
+ if (pColVal->isNone || pColVal->isNull) {
+ pColAgg->numOfNull++;
+ } else {
+ switch (pColData->type) {
+ case TSDB_DATA_TYPE_NULL:
+ break;
+ case TSDB_DATA_TYPE_BOOL:
+ break;
+ case TSDB_DATA_TYPE_TINYINT:
+ break;
+ case TSDB_DATA_TYPE_SMALLINT:
+ break;
+ case TSDB_DATA_TYPE_INT: {
+ pColAgg->sum += colVal.value.i32;
+ if (pColAgg->min > colVal.value.i32) {
+ pColAgg->min = colVal.value.i32;
+ }
+ if (pColAgg->max < colVal.value.i32) {
+ pColAgg->max = colVal.value.i32;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_BIGINT: {
+ pColAgg->sum += colVal.value.i64;
+ if (pColAgg->min > colVal.value.i64) {
+ pColAgg->min = colVal.value.i64;
+ }
+ if (pColAgg->max < colVal.value.i64) {
+ pColAgg->max = colVal.value.i64;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_FLOAT:
+ break;
+ case TSDB_DATA_TYPE_DOUBLE:
+ break;
+ case TSDB_DATA_TYPE_VARCHAR:
+ break;
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ break;
+ case TSDB_DATA_TYPE_NCHAR:
+ break;
+ case TSDB_DATA_TYPE_UTINYINT:
+ break;
+ case TSDB_DATA_TYPE_USMALLINT:
+ break;
+ case TSDB_DATA_TYPE_UINT:
+ break;
+ case TSDB_DATA_TYPE_UBIGINT:
+ break;
+ case TSDB_DATA_TYPE_JSON:
+ break;
+ case TSDB_DATA_TYPE_VARBINARY:
+ break;
+ case TSDB_DATA_TYPE_DECIMAL:
+ break;
+ case TSDB_DATA_TYPE_BLOB:
+ break;
+ case TSDB_DATA_TYPE_MEDIUMBLOB:
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+ }
+}
diff --git a/source/dnode/vnode/src/tsdb/tsdbWrite.c b/source/dnode/vnode/src/tsdb/tsdbWrite.c
index e184763bc812c7a9ca11db2e9a0432073c1df07c..a221bc17957b36a43e3847a33346ae1b05f8794c 100644
--- a/source/dnode/vnode/src/tsdb/tsdbWrite.c
+++ b/source/dnode/vnode/src/tsdb/tsdbWrite.c
@@ -28,7 +28,7 @@ int tsdbInsertData(STsdb *pTsdb, int64_t version, SSubmitReq *pMsg, SSubmitRsp *
// scan and convert
if (tsdbScanAndConvertSubmitMsg(pTsdb, pMsg) < 0) {
if (terrno != TSDB_CODE_TDB_TABLE_RECONFIGURE) {
- tsdbError("vgId:%d, failed to insert data since %s", REPO_ID(pTsdb), tstrerror(terrno));
+ tsdbError("vgId:%d, failed to insert data since %s", TD_VID(pTsdb->pVnode), tstrerror(terrno));
}
return -1;
}
@@ -77,7 +77,7 @@ static FORCE_INLINE int tsdbCheckRowRange(STsdb *pTsdb, tb_uid_t uid, STSRow *ro
if (rowKey < minKey || rowKey > maxKey) {
tsdbError("vgId:%d, table uid %" PRIu64 " timestamp is out of range! now %" PRId64 " minKey %" PRId64
" maxKey %" PRId64 " row key %" PRId64,
- REPO_ID(pTsdb), uid, now, minKey, maxKey, rowKey);
+ TD_VID(pTsdb->pVnode), uid, now, minKey, maxKey, rowKey);
terrno = TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE;
return -1;
}
@@ -92,7 +92,7 @@ int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitReq *pMsg) {
SSubmitBlk *pBlock = NULL;
SSubmitBlkIter blkIter = {0};
STSRow *row = NULL;
- STsdbKeepCfg *pCfg = REPO_KEEP_CFG(pTsdb);
+ STsdbKeepCfg *pCfg = &pTsdb->keepCfg;
TSKEY now = taosGetTimestamp(pCfg->precision);
TSKEY minKey = now - tsTickPerMin[pCfg->precision] * pCfg->keep2;
TSKEY maxKey = now + tsTickPerMin[pCfg->precision] * pCfg->days;
diff --git a/source/dnode/vnode/src/vnd/vnodeCfg.c b/source/dnode/vnode/src/vnd/vnodeCfg.c
index 79e63d5abc2a8947e7e8de3feeea267829c5f2f8..eac1fd1a74dc9f83a15492c4e686b08d572734aa 100644
--- a/source/dnode/vnode/src/vnd/vnodeCfg.c
+++ b/source/dnode/vnode/src/vnd/vnodeCfg.c
@@ -15,30 +15,39 @@
#include "vnd.h"
-const SVnodeCfg vnodeCfgDefault = {
- .vgId = -1,
- .dbname = "",
- .dbId = 0,
- .szPage = 4096,
- .szCache = 256,
- .szBuf = 96 * 1024 * 1024,
- .isHeap = false,
- .isWeak = 0,
- .tsdbCfg = {.precision = TSDB_TIME_PRECISION_MILLI,
- .update = 1,
- .compression = 2,
- .slLevel = 5,
- .days = 10,
- .minRows = 100,
- .maxRows = 4096,
- .keep2 = 3650,
- .keep0 = 3650,
- .keep1 = 3650},
- .walCfg =
- {.vgId = -1, .fsyncPeriod = 0, .retentionPeriod = 0, .rollPeriod = 0, .segSize = 0, .level = TAOS_WAL_WRITE},
- .hashBegin = 0,
- .hashEnd = 0,
- .hashMethod = 0};
+const SVnodeCfg vnodeCfgDefault = {.vgId = -1,
+ .dbname = "",
+ .dbId = 0,
+ .szPage = 4096,
+ .szCache = 256,
+ .cacheLast = 3,
+ .cacheLastSize = 8,
+ .szBuf = 96 * 1024 * 1024,
+ .isHeap = false,
+ .isWeak = 0,
+ .tsdbCfg = {.precision = TSDB_TIME_PRECISION_MILLI,
+ .update = 1,
+ .compression = 2,
+ .slLevel = 5,
+ .days = 14400,
+ .minRows = 100,
+ .maxRows = 4096,
+ .keep2 = 5256000,
+ .keep0 = 5256000,
+ .keep1 = 5256000},
+ .walCfg =
+ {
+ .vgId = -1,
+ .fsyncPeriod = 0,
+ .retentionPeriod = -1,
+ .rollPeriod = -1,
+ .segSize = -1,
+ .retentionSize = -1,
+ .level = TAOS_WAL_WRITE,
+ },
+ .hashBegin = 0,
+ .hashEnd = 0,
+ .hashMethod = 0};
int vnodeCheckCfg(const SVnodeCfg *pCfg) {
// TODO
@@ -53,6 +62,8 @@ int vnodeEncodeConfig(const void *pObj, SJson *pJson) {
if (tjsonAddIntegerToObject(pJson, "dbId", pCfg->dbId) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "szPage", pCfg->szPage) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "szCache", pCfg->szCache) < 0) return -1;
+ if (tjsonAddIntegerToObject(pJson, "cacheLast", pCfg->cacheLast) < 0) return -1;
+ if (tjsonAddIntegerToObject(pJson, "cacheLastSize", pCfg->cacheLastSize) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "szBuf", pCfg->szBuf) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "isHeap", pCfg->isHeap) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "isWeak", pCfg->isWeak) < 0) return -1;
@@ -79,7 +90,7 @@ int vnodeEncodeConfig(const void *pObj, SJson *pJson) {
SJson *pNodeRetentions = tjsonCreateArray();
tjsonAddItemToObject(pJson, "retentions", pNodeRetentions);
for (int32_t i = 0; i < nRetention; ++i) {
- SJson *pNodeRetention = tjsonCreateObject();
+ SJson *pNodeRetention = tjsonCreateObject();
const SRetention *pRetention = pCfg->tsdbCfg.retentions + i;
tjsonAddIntegerToObject(pNodeRetention, "freq", pRetention->freq);
tjsonAddIntegerToObject(pNodeRetention, "freqUnit", pRetention->freqUnit);
@@ -118,45 +129,49 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) {
int32_t code;
tjsonGetNumberValue(pJson, "vgId", pCfg->vgId, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
if (tjsonGetStringValue(pJson, "dbname", pCfg->dbname) < 0) return -1;
tjsonGetNumberValue(pJson, "dbId", pCfg->dbId, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "szPage", pCfg->szPage, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "szCache", pCfg->szCache, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
+ tjsonGetNumberValue(pJson, "cacheLast", pCfg->cacheLast, code);
+ if (code < 0) return -1;
+ tjsonGetNumberValue(pJson, "cacheLastSize", pCfg->cacheLastSize, code);
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "szBuf", pCfg->szBuf, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "isHeap", pCfg->isHeap, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "isWeak", pCfg->isWeak, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "isTsma", pCfg->isTsma, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "isRsma", pCfg->isRsma, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "precision", pCfg->tsdbCfg.precision, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "update", pCfg->tsdbCfg.update, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "compression", pCfg->tsdbCfg.compression, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "slLevel", pCfg->tsdbCfg.slLevel, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "daysPerFile", pCfg->tsdbCfg.days, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "minRows", pCfg->tsdbCfg.minRows, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "maxRows", pCfg->tsdbCfg.maxRows, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "keep0", pCfg->tsdbCfg.keep0, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "keep1", pCfg->tsdbCfg.keep1, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "keep2", pCfg->tsdbCfg.keep2, code);
- if(code < 0) return -1;
- SJson *pNodeRetentions = tjsonGetObjectItem(pJson, "retentions");
+ if (code < 0) return -1;
+ SJson *pNodeRetentions = tjsonGetObjectItem(pJson, "retentions");
int32_t nRetention = tjsonGetArraySize(pNodeRetentions);
if (nRetention > TSDB_RETENTION_MAX) {
nRetention = TSDB_RETENTION_MAX;
@@ -170,30 +185,30 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) {
tjsonGetNumberValue(pNodeRetention, "keepUnit", (pCfg->tsdbCfg.retentions)[i].keepUnit, code);
}
tjsonGetNumberValue(pJson, "wal.vgId", pCfg->walCfg.vgId, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.fsyncPeriod", pCfg->walCfg.fsyncPeriod, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.retentionPeriod", pCfg->walCfg.retentionPeriod, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.rollPeriod", pCfg->walCfg.rollPeriod, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.retentionSize", pCfg->walCfg.retentionSize, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.segSize", pCfg->walCfg.segSize, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "wal.level", pCfg->walCfg.level, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "hashBegin", pCfg->hashBegin, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "hashEnd", pCfg->hashEnd, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "hashMethod", pCfg->hashMethod, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "syncCfg.replicaNum", pCfg->syncCfg.replicaNum, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
tjsonGetNumberValue(pJson, "syncCfg.myIndex", pCfg->syncCfg.myIndex, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
SJson *pNodeInfoArr = tjsonGetObjectItem(pJson, "syncCfg.nodeInfo");
int arraySize = tjsonGetArraySize(pNodeInfoArr);
diff --git a/source/dnode/vnode/src/vnd/vnodeCommit.c b/source/dnode/vnode/src/vnd/vnodeCommit.c
index 3715866bb88f3ae030d5f65c7ce938e69120f466..ebbb691e288d13626bc56964b6f2b444836d7685 100644
--- a/source/dnode/vnode/src/vnd/vnodeCommit.c
+++ b/source/dnode/vnode/src/vnd/vnodeCommit.c
@@ -15,7 +15,7 @@
#include "vnd.h"
-#define VND_INFO_FNAME "vnode.json"
+#define VND_INFO_FNAME "vnode.json"
#define VND_INFO_FNAME_TMP "vnode_tmp.json"
static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData);
@@ -40,6 +40,7 @@ int vnodeBegin(SVnode *pVnode) {
/* pthread_mutex_unlock(); */
+ pVnode->state.commitID++;
// begin meta
if (metaBegin(pVnode->pMeta) < 0) {
vError("vgId:%d, failed to begin meta since %s", TD_VID(pVnode), tstrerror(terrno));
@@ -47,32 +48,35 @@ int vnodeBegin(SVnode *pVnode) {
}
// begin tsdb
- if (pVnode->pSma) {
- if (tsdbBegin(VND_RSMA0(pVnode)) < 0) {
- vError("vgId:%d, failed to begin rsma0 since %s", TD_VID(pVnode), tstrerror(terrno));
- return -1;
- }
+ if (tsdbBegin(pVnode->pTsdb) < 0) {
+ vError("vgId:%d, failed to begin tsdb since %s", TD_VID(pVnode), tstrerror(terrno));
+ return -1;
+ }
- if (tsdbBegin(VND_RSMA1(pVnode)) < 0) {
+ if (pVnode->pSma) {
+ if (VND_RSMA1(pVnode) && tsdbBegin(VND_RSMA1(pVnode)) < 0) {
vError("vgId:%d, failed to begin rsma1 since %s", TD_VID(pVnode), tstrerror(terrno));
return -1;
}
- if (tsdbBegin(VND_RSMA2(pVnode)) < 0) {
+ if (VND_RSMA2(pVnode) && tsdbBegin(VND_RSMA2(pVnode)) < 0) {
vError("vgId:%d, failed to begin rsma2 since %s", TD_VID(pVnode), tstrerror(terrno));
return -1;
}
- } else {
- if (tsdbBegin(pVnode->pTsdb) < 0) {
- vError("vgId:%d, failed to begin tsdb since %s", TD_VID(pVnode), tstrerror(terrno));
- return -1;
- }
}
+ // begin sma
+ smaBegin(pVnode->pSma); // TODO: refactor to include the rsma1/rsma2 tsdbBegin() after tsdb_refact branch merged
+
return 0;
}
-int vnodeShouldCommit(SVnode *pVnode) { return pVnode->inUse->size > pVnode->config.szBuf / 3; }
+int vnodeShouldCommit(SVnode *pVnode) {
+ if (pVnode->inUse) {
+ return pVnode->inUse->size > pVnode->config.szBuf / 3;
+ }
+ return false;
+}
int vnodeSaveInfo(const char *dir, const SVnodeInfo *pInfo) {
char fname[TSDB_FILENAME_LEN];
@@ -210,7 +214,8 @@ int vnodeCommit(SVnode *pVnode) {
SVnodeInfo info = {0};
char dir[TSDB_FILENAME_LEN];
- vInfo("vgId:%d, start to commit, version: %" PRId64, TD_VID(pVnode), pVnode->state.applied);
+ vInfo("vgId:%d, start to commit, commit ID:%" PRId64 " version:%" PRId64, TD_VID(pVnode), pVnode->state.commitID,
+ pVnode->state.applied);
pVnode->onCommit = pVnode->inUse;
pVnode->inUse = NULL;
@@ -218,11 +223,17 @@ int vnodeCommit(SVnode *pVnode) {
// save info
info.config = pVnode->config;
info.state.committed = pVnode->state.applied;
+ info.state.commitTerm = pVnode->state.applyTerm;
+ info.state.commitID = pVnode->state.commitID;
snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path);
if (vnodeSaveInfo(dir, &info) < 0) {
ASSERT(0);
return -1;
}
+ walBeginSnapshot(pVnode->pWal, pVnode->state.applied);
+
+ // preCommit
+ smaPreCommit(pVnode->pSma);
// commit each sub-system
if (metaCommit(pVnode->pMeta) < 0) {
@@ -262,7 +273,13 @@ int vnodeCommit(SVnode *pVnode) {
return -1;
}
+ pVnode->state.committed = info.state.committed;
+
+ // postCommit
+ smaPostCommit(pVnode->pSma);
+
// apply the commit (TODO)
+ walEndSnapshot(pVnode->pWal);
vnodeBufPoolReset(pVnode->onCommit);
pVnode->onCommit->next = pVnode->pPool;
pVnode->pPool = pVnode->onCommit;
@@ -278,7 +295,7 @@ static int vnodeCommitImpl(void *arg) {
// metaCommit(pVnode->pMeta);
tqCommit(pVnode->pTq);
- tsdbCommit(pVnode->pTsdb);
+ // tsdbCommit(pVnode->pTsdb, );
// vnodeBufPoolRecycle(pVnode);
tsem_post(&(pVnode->canCommit));
@@ -301,7 +318,8 @@ static int vnodeEncodeState(const void *pObj, SJson *pJson) {
const SVState *pState = (SVState *)pObj;
if (tjsonAddIntegerToObject(pJson, "commit version", pState->committed) < 0) return -1;
- if (tjsonAddIntegerToObject(pJson, "applied version", pState->applied) < 0) return -1;
+ if (tjsonAddIntegerToObject(pJson, "commit ID", pState->commitID) < 0) return -1;
+ if (tjsonAddIntegerToObject(pJson, "commit term", pState->commitTerm) < 0) return -1;
return 0;
}
@@ -311,9 +329,11 @@ static int vnodeDecodeState(const SJson *pJson, void *pObj) {
int32_t code;
tjsonGetNumberValue(pJson, "commit version", pState->committed, code);
- if(code < 0) return -1;
- tjsonGetNumberValue(pJson, "applied version", pState->applied, code);
- if(code < 0) return -1;
+ if (code < 0) return -1;
+ tjsonGetNumberValue(pJson, "commit ID", pState->commitID, code);
+ if (code < 0) return -1;
+ tjsonGetNumberValue(pJson, "commit term", pState->commitTerm, code);
+ if (code < 0) return -1;
return 0;
}
diff --git a/source/dnode/vnode/src/vnd/vnodeModule.c b/source/dnode/vnode/src/vnd/vnodeModule.c
index d0aede145eb8640e1e9031160d5ab7573d4a74e8..69f87a2c1a72c28cb64371b421bfc59219adc60c 100644
--- a/source/dnode/vnode/src/vnd/vnodeModule.c
+++ b/source/dnode/vnode/src/vnd/vnodeModule.c
@@ -100,6 +100,7 @@ void vnodeCleanup() {
walCleanUp();
tqCleanUp();
+ smaCleanUp();
}
int vnodeScheduleTask(int (*execute)(void*), void* arg) {
diff --git a/source/dnode/vnode/src/vnd/vnodeOpen.c b/source/dnode/vnode/src/vnd/vnodeOpen.c
index dfc258b42b75bb3b5da4012a4f44ed0c7d337f05..0914827950e5f5c81f8ac8ec87b5e4d3d3b548f4 100644
--- a/source/dnode/vnode/src/vnd/vnodeOpen.c
+++ b/source/dnode/vnode/src/vnd/vnodeOpen.c
@@ -28,7 +28,7 @@ int vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs) {
}
// create vnode env
- if (tfsMkdir(pTfs, path) < 0) {
+ if (tfsMkdirAt(pTfs, path, (SDiskID){0}) < 0) {
vError("vgId:%d, failed to create vnode since: %s", pCfg->vgId, tstrerror(terrno));
return -1;
}
@@ -37,6 +37,7 @@ int vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs) {
info.config = *pCfg;
info.state.committed = -1;
info.state.applied = -1;
+ info.state.commitID = 0;
if (vnodeSaveInfo(dir, &info) < 0 || vnodeCommitInfo(dir, &info) < 0) {
vError("vgId:%d, failed to save vnode config since %s", pCfg->vgId, tstrerror(terrno));
@@ -78,10 +79,13 @@ SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb) {
strcpy(pVnode->path, path);
pVnode->config = info.config;
pVnode->state.committed = info.state.committed;
+ pVnode->state.commitTerm = info.state.commitTerm;
pVnode->state.applied = info.state.committed;
+ pVnode->state.commitID = info.state.commitID;
+ pVnode->state.commitTerm = info.state.commitTerm;
pVnode->pTfs = pTfs;
pVnode->msgCb = msgCb;
- pVnode->syncCount = 0;
+ pVnode->blockCount = 0;
tsem_init(&pVnode->syncSem, 0, 0);
tsem_init(&(pVnode->canCommit), 0, 1);
@@ -113,6 +117,13 @@ SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb) {
// open wal
sprintf(tdir, "%s%s%s", dir, TD_DIRSEP, VNODE_WAL_DIR);
taosRealPath(tdir, NULL, sizeof(tdir));
+
+// for test tsdb snapshot
+#if 0
+ pVnode->config.walCfg.segSize = 200;
+ pVnode->config.walCfg.retentionSize = 2000;
+#endif
+
pVnode->pWal = walOpen(tdir, &(pVnode->config.walCfg));
if (pVnode->pWal == NULL) {
vError("vgId:%d, failed to open vnode wal since %s", TD_VID(pVnode), tstrerror(terrno));
@@ -156,14 +167,20 @@ _err:
if (pVnode->pTq) tqClose(pVnode->pTq);
if (pVnode->pWal) walClose(pVnode->pWal);
if (pVnode->pTsdb) tsdbClose(&pVnode->pTsdb);
- if (pVnode->pMeta) metaClose(pVnode->pMeta);
if (pVnode->pSma) smaClose(pVnode->pSma);
+ if (pVnode->pMeta) metaClose(pVnode->pMeta);
tsem_destroy(&(pVnode->canCommit));
taosMemoryFree(pVnode);
return NULL;
}
+void vnodePreClose(SVnode *pVnode) {
+ if (pVnode) {
+ syncLeaderTransfer(pVnode->sync);
+ }
+}
+
void vnodeClose(SVnode *pVnode) {
if (pVnode) {
vnodeCommit(pVnode);
@@ -192,4 +209,9 @@ void vnodeStop(SVnode *pVnode) {}
int64_t vnodeGetSyncHandle(SVnode *pVnode) { return pVnode->sync; }
-void vnodeGetSnapshot(SVnode *pVnode, SSnapshot *pSnapshot) { pSnapshot->lastApplyIndex = pVnode->state.committed; }
+void vnodeGetSnapshot(SVnode *pVnode, SSnapshot *pSnapshot) {
+ pSnapshot->data = NULL;
+ pSnapshot->lastApplyIndex = pVnode->state.committed;
+ pSnapshot->lastApplyTerm = pVnode->state.commitTerm;
+ pSnapshot->lastConfigIndex = -1;
+}
diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c
index 2333a93ce094e000b725e4df917d7b088f4cc4e3..5b807d60e30b2ec20d70520a992a4e5c55dcff9f 100644
--- a/source/dnode/vnode/src/vnd/vnodeQuery.c
+++ b/source/dnode/vnode/src/vnd/vnodeQuery.c
@@ -27,10 +27,10 @@ int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg) {
SMetaReader mer1 = {0};
SMetaReader mer2 = {0};
char tableFName[TSDB_TABLE_FNAME_LEN];
- SRpcMsg rpcMsg;
+ SRpcMsg rpcMsg = {0};
int32_t code = 0;
int32_t rspLen = 0;
- void *pRsp = NULL;
+ void * pRsp = NULL;
SSchemaWrapper schema = {0};
SSchemaWrapper schemaTag = {0};
@@ -111,6 +111,7 @@ _exit:
rpcMsg.pCont = pRsp;
rpcMsg.contLen = rspLen;
rpcMsg.code = code;
+ rpcMsg.msgType = pMsg->msgType;
if (code) {
qError("get table %s meta failed cause of %s", infoReq.tbName, tstrerror(code));
@@ -124,6 +125,116 @@ _exit:
return TSDB_CODE_SUCCESS;
}
+int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg) {
+ STableCfgReq cfgReq = {0};
+ STableCfgRsp cfgRsp = {0};
+ SMetaReader mer1 = {0};
+ SMetaReader mer2 = {0};
+ char tableFName[TSDB_TABLE_FNAME_LEN];
+ SRpcMsg rpcMsg = {0};
+ int32_t code = 0;
+ int32_t rspLen = 0;
+ void * pRsp = NULL;
+ SSchemaWrapper schema = {0};
+ SSchemaWrapper schemaTag = {0};
+
+ // decode req
+ if (tDeserializeSTableCfgReq(pMsg->pCont, pMsg->contLen, &cfgReq) != 0) {
+ code = TSDB_CODE_INVALID_MSG;
+ goto _exit;
+ }
+
+ strcpy(cfgRsp.tbName, cfgReq.tbName);
+ memcpy(cfgRsp.dbFName, cfgReq.dbFName, sizeof(cfgRsp.dbFName));
+
+ sprintf(tableFName, "%s.%s", cfgReq.dbFName, cfgReq.tbName);
+ code = vnodeValidateTableHash(pVnode, tableFName);
+ if (code) {
+ goto _exit;
+ }
+
+ // query meta
+ metaReaderInit(&mer1, pVnode->pMeta, 0);
+
+ if (metaGetTableEntryByName(&mer1, cfgReq.tbName) < 0) {
+ code = terrno;
+ goto _exit;
+ }
+
+ cfgRsp.tableType = mer1.me.type;
+
+ if (mer1.me.type == TSDB_SUPER_TABLE) {
+ code = TSDB_CODE_VND_HASH_MISMATCH;
+ goto _exit;
+ } else if (mer1.me.type == TSDB_CHILD_TABLE) {
+ metaReaderInit(&mer2, pVnode->pMeta, 0);
+ if (metaGetTableEntryByUid(&mer2, mer1.me.ctbEntry.suid) < 0) goto _exit;
+
+ strcpy(cfgRsp.stbName, mer2.me.name);
+ schema = mer2.me.stbEntry.schemaRow;
+ schemaTag = mer2.me.stbEntry.schemaTag;
+ cfgRsp.ttl = mer1.me.ctbEntry.ttlDays;
+ cfgRsp.commentLen = mer1.me.ctbEntry.commentLen;
+ if (mer1.me.ctbEntry.commentLen > 0) {
+ cfgRsp.pComment = strdup(mer1.me.ctbEntry.comment);
+ }
+ STag *pTag = (STag *)mer1.me.ctbEntry.pTags;
+ cfgRsp.tagsLen = pTag->len;
+ cfgRsp.pTags = taosMemoryMalloc(cfgRsp.tagsLen);
+ memcpy(cfgRsp.pTags, pTag, cfgRsp.tagsLen);
+ } else if (mer1.me.type == TSDB_NORMAL_TABLE) {
+ schema = mer1.me.ntbEntry.schemaRow;
+ cfgRsp.ttl = mer1.me.ntbEntry.ttlDays;
+ cfgRsp.commentLen = mer1.me.ntbEntry.commentLen;
+ if (mer1.me.ntbEntry.commentLen > 0) {
+ cfgRsp.pComment = strdup(mer1.me.ntbEntry.comment);
+ }
+ } else {
+ ASSERT(0);
+ }
+
+ cfgRsp.numOfTags = schemaTag.nCols;
+ cfgRsp.numOfColumns = schema.nCols;
+ cfgRsp.pSchemas = (SSchema *)taosMemoryMalloc(sizeof(SSchema) * (cfgRsp.numOfColumns + cfgRsp.numOfTags));
+
+ memcpy(cfgRsp.pSchemas, schema.pSchema, sizeof(SSchema) * schema.nCols);
+ if (schemaTag.nCols) {
+ memcpy(cfgRsp.pSchemas + schema.nCols, schemaTag.pSchema, sizeof(SSchema) * schemaTag.nCols);
+ }
+
+ // encode and send response
+ rspLen = tSerializeSTableCfgRsp(NULL, 0, &cfgRsp);
+ if (rspLen < 0) {
+ code = TSDB_CODE_INVALID_MSG;
+ goto _exit;
+ }
+
+ pRsp = rpcMallocCont(rspLen);
+ if (pRsp == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _exit;
+ }
+ tSerializeSTableCfgRsp(pRsp, rspLen, &cfgRsp);
+
+_exit:
+ rpcMsg.info = pMsg->info;
+ rpcMsg.pCont = pRsp;
+ rpcMsg.contLen = rspLen;
+ rpcMsg.code = code;
+ rpcMsg.msgType = pMsg->msgType;
+
+ if (code) {
+ qError("get table %s cfg failed cause of %s", cfgReq.tbName, tstrerror(code));
+ }
+
+ tmsgSendRsp(&rpcMsg);
+
+ tFreeSTableCfgRsp(&cfgRsp);
+ metaReaderClear(&mer2);
+ metaReaderClear(&mer1);
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t vnodeGetLoad(SVnode *pVnode, SVnodeLoad *pLoad) {
pLoad->vgId = TD_VID(pVnode);
pLoad->syncState = syncGetMyRole(pVnode->sync);
@@ -150,11 +261,49 @@ void vnodeGetInfo(SVnode *pVnode, const char **dbname, int32_t *vgId) {
}
}
-// wrapper of tsdb read interface
-tsdbReaderT tsdbQueryCacheLast(SVnode *pVnode, SQueryTableDataCond *pCond, STableListInfo* tableList, uint64_t qId,
- void *pMemRef) {
-#if 0
- return tsdbQueryCacheLastT(pVnode->pTsdb, pCond, groupList, qId, pMemRef);
-#endif
- return 0;
-}
\ No newline at end of file
+int32_t vnodeGetAllTableList(SVnode *pVnode, uint64_t uid, SArray *list) {
+ SMCtbCursor *pCur = metaOpenCtbCursor(pVnode->pMeta, uid);
+
+ while (1) {
+ tb_uid_t id = metaCtbCursorNext(pCur);
+ if (id == 0) {
+ break;
+ }
+
+ STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, uid = id};
+ taosArrayPush(list, &info);
+ }
+
+ metaCloseCtbCursor(pCur);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t vnodeGetCtbIdList(SVnode *pVnode, int64_t suid, SArray *list) {
+ SMCtbCursor *pCur = metaOpenCtbCursor(pVnode->pMeta, suid);
+
+ while (1) {
+ tb_uid_t id = metaCtbCursorNext(pCur);
+ if (id == 0) {
+ break;
+ }
+
+ taosArrayPush(list, &id);
+ }
+
+ metaCloseCtbCursor(pCur);
+ return TSDB_CODE_SUCCESS;
+}
+
+void *vnodeGetIdx(SVnode *pVnode) {
+ if (pVnode == NULL) {
+ return NULL;
+ }
+ return metaGetIdx(pVnode->pMeta);
+}
+
+void *vnodeGetIvtIdx(SVnode *pVnode) {
+ if (pVnode == NULL) {
+ return NULL;
+ }
+ return metaGetIvtIdx(pVnode->pMeta);
+}
diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c
index baa8422307dd7785201bcc4b8b632bb3c05a37cb..27f30ec7878351f4e0a2d78d21da5a1fdc960873 100644
--- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c
+++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c
@@ -13,24 +13,27 @@
* along with this program. If not, see .
*/
-#include "vnodeInt.h"
-
-struct SVSnapshotReader {
- SVnode *pVnode;
- int64_t sver;
- int64_t ever;
- int8_t isMetaEnd;
- int8_t isTsdbEnd;
- SMetaSnapshotReader *pMetaReader;
- STsdbSnapshotReader *pTsdbReader;
- void *pData;
- int32_t nData;
+#include "vnd.h"
+
+// SVSnapReader ========================================================
+struct SVSnapReader {
+ SVnode *pVnode;
+ int64_t sver;
+ int64_t ever;
+ // meta
+ int8_t metaDone;
+ SMetaSnapReader *pMetaReader;
+ // tsdb
+ int8_t tsdbDone;
+ STsdbSnapReader *pTsdbReader;
+ uint8_t *pData;
};
-int32_t vnodeSnapshotReaderOpen(SVnode *pVnode, SVSnapshotReader **ppReader, int64_t sver, int64_t ever) {
- SVSnapshotReader *pReader = NULL;
+int32_t vnodeSnapReaderOpen(SVnode *pVnode, int64_t sver, int64_t ever, SVSnapReader **ppReader) {
+ int32_t code = 0;
+ SVSnapReader *pReader = NULL;
- pReader = (SVSnapshotReader *)taosMemoryCalloc(1, sizeof(*pReader));
+ pReader = (SVSnapReader *)taosMemoryCalloc(1, sizeof(*pReader));
if (pReader == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
@@ -38,72 +41,169 @@ int32_t vnodeSnapshotReaderOpen(SVnode *pVnode, SVSnapshotReader **ppReader, int
pReader->pVnode = pVnode;
pReader->sver = sver;
pReader->ever = ever;
- pReader->isMetaEnd = 0;
- pReader->isTsdbEnd = 0;
- if (metaSnapshotReaderOpen(pVnode->pMeta, &pReader->pMetaReader, sver, ever) < 0) {
- taosMemoryFree(pReader);
- goto _err;
- }
+ code = metaSnapReaderOpen(pVnode->pMeta, sver, ever, &pReader->pMetaReader);
+ if (code) goto _err;
- if (tsdbSnapshotReaderOpen(pVnode->pTsdb, &pReader->pTsdbReader, sver, ever) < 0) {
- metaSnapshotReaderClose(pReader->pMetaReader);
- taosMemoryFree(pReader);
- goto _err;
- }
+ code = tsdbSnapReaderOpen(pVnode->pTsdb, sver, ever, &pReader->pTsdbReader);
+ if (code) goto _err;
-_exit:
*ppReader = pReader;
- return 0;
+ return code;
_err:
+ vError("vgId:%d vnode snapshot reader open failed since %s", TD_VID(pVnode), tstrerror(code));
*ppReader = NULL;
- return -1;
+ return code;
}
-int32_t vnodeSnapshotReaderClose(SVSnapshotReader *pReader) {
- if (pReader) {
- vnodeFree(pReader->pData);
- tsdbSnapshotReaderClose(pReader->pTsdbReader);
- metaSnapshotReaderClose(pReader->pMetaReader);
- taosMemoryFree(pReader);
- }
- return 0;
+int32_t vnodeSnapReaderClose(SVSnapReader *pReader) {
+ int32_t code = 0;
+
+ tFree(pReader->pData);
+ if (pReader->pTsdbReader) tsdbSnapReaderClose(&pReader->pTsdbReader);
+ if (pReader->pMetaReader) metaSnapReaderClose(&pReader->pMetaReader);
+ taosMemoryFree(pReader);
+
+ return code;
}
-int32_t vnodeSnapshotRead(SVSnapshotReader *pReader, const void **ppData, uint32_t *nData) {
+int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) {
int32_t code = 0;
- if (!pReader->isMetaEnd) {
- code = metaSnapshotRead(pReader->pMetaReader, &pReader->pData, &pReader->nData);
+ if (!pReader->metaDone) {
+ code = metaSnapRead(pReader->pMetaReader, &pReader->pData);
if (code) {
if (code == TSDB_CODE_VND_READ_END) {
- pReader->isMetaEnd = 1;
+ pReader->metaDone = 1;
} else {
- return code;
+ goto _err;
}
} else {
*ppData = pReader->pData;
- *nData = pReader->nData;
- return code;
+ *nData = sizeof(SSnapDataHdr) + ((SSnapDataHdr *)pReader->pData)->size;
+ goto _exit;
}
}
- if (!pReader->isTsdbEnd) {
- code = tsdbSnapshotRead(pReader->pTsdbReader, &pReader->pData, &pReader->nData);
+ if (!pReader->tsdbDone) {
+ code = tsdbSnapRead(pReader->pTsdbReader, &pReader->pData);
if (code) {
if (code == TSDB_CODE_VND_READ_END) {
- pReader->isTsdbEnd = 1;
+ pReader->tsdbDone = 1;
} else {
- return code;
+ goto _err;
}
} else {
*ppData = pReader->pData;
- *nData = pReader->nData;
- return code;
+ *nData = sizeof(SSnapDataHdr) + ((SSnapDataHdr *)pReader->pData)->size;
+ goto _exit;
}
}
code = TSDB_CODE_VND_READ_END;
+
+_exit:
+ return code;
+
+_err:
+ vError("vgId:% snapshot read failed since %s", TD_VID(pReader->pVnode), tstrerror(code));
+ return code;
+}
+
+// SVSnapWriter ========================================================
+struct SVSnapWriter {
+ SVnode *pVnode;
+ int64_t sver;
+ int64_t ever;
+ // meta
+ SMetaSnapWriter *pMetaSnapWriter;
+ // tsdb
+ STsdbSnapWriter *pTsdbSnapWriter;
+};
+
+static int32_t vnodeSnapRollback(SVSnapWriter *pWriter) {
+ int32_t code = 0;
+ // TODO
+ return code;
+}
+
+static int32_t vnodeSnapCommit(SVSnapWriter *pWriter) {
+ int32_t code = 0;
+ // TODO
+ return code;
+}
+
+int32_t vnodeSnapWriterOpen(SVnode *pVnode, int64_t sver, int64_t ever, SVSnapWriter **ppWriter) {
+ int32_t code = 0;
+ SVSnapWriter *pWriter = NULL;
+
+ // alloc
+ pWriter = (SVSnapWriter *)taosMemoryCalloc(1, sizeof(*pWriter));
+ if (pWriter == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+ pWriter->pVnode = pVnode;
+ pWriter->sver = sver;
+ pWriter->ever = ever;
+
+ return code;
+
+_err:
+ vError("vgId:%d vnode snapshot writer open failed since %s", TD_VID(pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback) {
+ int32_t code = 0;
+
+ if (rollback) {
+ code = vnodeSnapRollback(pWriter);
+ if (code) goto _err;
+ } else {
+ code = vnodeSnapCommit(pWriter);
+ if (code) goto _err;
+ }
+
+ taosMemoryFree(pWriter);
+ return code;
+
+_err:
+ vError("vgId:%d vnode snapshow writer close failed since %s", TD_VID(pWriter->pVnode), tstrerror(code));
+ return code;
+}
+
+int32_t vnodeSnapWrite(SVSnapWriter *pWriter, uint8_t *pData, uint32_t nData) {
+ int32_t code = 0;
+ SSnapDataHdr *pSnapDataHdr = (SSnapDataHdr *)pData;
+ SVnode *pVnode = pWriter->pVnode;
+
+ ASSERT(pSnapDataHdr->size + sizeof(SSnapDataHdr) == nData);
+
+ if (pSnapDataHdr->type == 0) {
+ // meta
+ if (pWriter->pMetaSnapWriter == NULL) {
+ code = metaSnapWriterOpen(pVnode->pMeta, pWriter->sver, pWriter->ever, &pWriter->pMetaSnapWriter);
+ if (code) goto _err;
+ }
+
+ code = metaSnapWrite(pWriter->pMetaSnapWriter, pData + sizeof(SSnapDataHdr), nData - sizeof(SSnapDataHdr));
+ if (code) goto _err;
+ } else {
+ // tsdb
+ if (pWriter->pTsdbSnapWriter == NULL) {
+ code = tsdbSnapWriterOpen(pVnode->pTsdb, pWriter->sver, pWriter->ever, &pWriter->pTsdbSnapWriter);
+ if (code) goto _err;
+ }
+
+ code = tsdbSnapWrite(pWriter->pTsdbSnapWriter, pData + sizeof(SSnapDataHdr), nData - sizeof(SSnapDataHdr));
+ if (code) goto _err;
+ }
+
+ return code;
+
+_err:
+ vError("vgId:%d vnode snapshot write failed since %s", TD_VID(pVnode), tstrerror(code));
return code;
}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/vnd/vnodeStateMgr.c b/source/dnode/vnode/src/vnd/vnodeStateMgr.c
deleted file mode 100644
index 6dea4a4e57392be988126c579648f39a8270b9bf..0000000000000000000000000000000000000000
--- a/source/dnode/vnode/src/vnd/vnodeStateMgr.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
\ No newline at end of file
diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c
index f3595ebfb0972b0d6c1ad9e03fd3902d200fb41d..cca212a4e405dddedb9175677395ece6326bc5d8 100644
--- a/source/dnode/vnode/src/vnd/vnodeSvr.c
+++ b/source/dnode/vnode/src/vnd/vnodeSvr.c
@@ -24,11 +24,13 @@ static int32_t vnodeProcessDropTbReq(SVnode *pVnode, int64_t version, void *pReq
static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
static int32_t vnodeProcessCreateTSmaReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
static int32_t vnodeProcessAlterConfirmReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
-static int32_t vnodeProcessAlterHasnRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
-static int32_t vnodeProcessWriteMsg(SVnode *pVnode, int64_t version, SRpcMsg *pMsg, SRpcMsg *pRsp);
+static int32_t vnodeProcessAlterHashRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
+static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
static int32_t vnodeProcessDropTtlTbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
+static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
+static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp);
-int32_t vnodePreprocessReq(SVnode *pVnode, SRpcMsg *pMsg) {
+int32_t vnodePreProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg) {
int32_t code = 0;
SDecoder dc = {0};
@@ -93,14 +95,47 @@ int32_t vnodePreprocessReq(SVnode *pVnode, SRpcMsg *pMsg) {
}
} break;
+ case TDMT_VND_DELETE: {
+ int32_t size;
+ int32_t ret;
+ uint8_t *pCont;
+ SEncoder *pCoder = &(SEncoder){0};
+ SDeleteRes res = {0};
+ SReadHandle handle = {
+ .meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb};
+
+ code = qWorkerProcessDeleteMsg(&handle, pVnode->pQuery, pMsg, &res);
+ if (code) goto _err;
+
+ // malloc and encode
+ tEncodeSize(tEncodeDeleteRes, &res, size, ret);
+ pCont = rpcMallocCont(size + sizeof(SMsgHead));
+
+ ((SMsgHead *)pCont)->contLen = htonl(size + sizeof(SMsgHead));
+ ((SMsgHead *)pCont)->vgId = htonl(TD_VID(pVnode));
+
+ tEncoderInit(pCoder, pCont + sizeof(SMsgHead), size);
+ tEncodeDeleteRes(pCoder, &res);
+ tEncoderClear(pCoder);
+
+ rpcFreeCont(pMsg->pCont);
+ pMsg->pCont = pCont;
+ pMsg->contLen = size + sizeof(SMsgHead);
+
+ taosArrayDestroy(res.uidList);
+ } break;
default:
break;
}
return code;
+
+_err:
+ vError("vgId%d, preprocess request failed since %s", TD_VID(pVnode), tstrerror(code));
+ return code;
}
-int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRpcMsg *pRsp) {
+int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRpcMsg *pRsp) {
void *ptr = NULL;
void *pReq;
int32_t len;
@@ -110,6 +145,7 @@ int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
version);
pVnode->state.applied = version;
+ pVnode->state.applyTerm = pMsg->info.conn.applyTerm;
// skip header
pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
@@ -138,15 +174,18 @@ int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
case TDMT_VND_DROP_TTL_TABLE:
if (vnodeProcessDropTtlTbReq(pVnode, version, pReq, len, pRsp) < 0) goto _err;
break;
- case TDMT_VND_CREATE_SMA: {
+ case TDMT_VND_TRIM:
+ if (vnodeProcessTrimReq(pVnode, version, pReq, len, pRsp) < 0) goto _err;
+ break;
+ case TDMT_VND_CREATE_SMA:
if (vnodeProcessCreateTSmaReq(pVnode, version, pReq, len, pRsp) < 0) goto _err;
- } break;
+ break;
/* TSDB */
case TDMT_VND_SUBMIT:
if (vnodeProcessSubmitReq(pVnode, version, pMsg->pCont, pMsg->contLen, pRsp) < 0) goto _err;
break;
case TDMT_VND_DELETE:
- if (vnodeProcessWriteMsg(pVnode, version, pMsg, pRsp) < 0) goto _err;
+ if (vnodeProcessDeleteReq(pVnode, version, pReq, len, pRsp) < 0) goto _err;
break;
/* TQ */
case TDMT_VND_MQ_VG_CHANGE:
@@ -172,7 +211,7 @@ int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
goto _err;
}
} break;
- case TDMT_VND_STREAM_TASK_DROP: {
+ case TDMT_STREAM_TASK_DROP: {
if (tqProcessTaskDropReq(pVnode->pTq, pMsg->pCont, pMsg->contLen) < 0) {
goto _err;
}
@@ -181,10 +220,13 @@ int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
vnodeProcessAlterConfirmReq(pVnode, version, pReq, len, pRsp);
break;
case TDMT_VND_ALTER_HASHRANGE:
- vnodeProcessAlterHasnRangeReq(pVnode, version, pReq, len, pRsp);
+ vnodeProcessAlterHashRangeReq(pVnode, version, pReq, len, pRsp);
break;
case TDMT_VND_ALTER_CONFIG:
+ vnodeProcessAlterConfigReq(pVnode, version, pReq, len, pRsp);
break;
+ case TDMT_VND_COMMIT:
+ goto _do_commit;
default:
ASSERT(0);
break;
@@ -199,6 +241,7 @@ int32_t vnodeProcessWriteReq(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
// commit if need
if (vnodeShouldCommit(pVnode)) {
+ _do_commit:
vInfo("vgId:%d, commit at version %" PRId64, TD_VID(pVnode), version);
// commit current change
vnodeCommit(pVnode);
@@ -216,7 +259,7 @@ _err:
}
int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) {
- if (TDMT_VND_QUERY != pMsg->msgType) {
+ if (TDMT_SCH_QUERY != pMsg->msgType && TDMT_SCH_MERGE_QUERY != pMsg->msgType) {
return 0;
}
@@ -225,11 +268,17 @@ int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) {
int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) {
vTrace("message in vnode query queue is processing");
+ if ((pMsg->msgType == TDMT_SCH_QUERY) && !vnodeIsLeader(pVnode)) {
+ vnodeRedirectRpcMsg(pVnode, pMsg);
+ return 0;
+ }
+
SReadHandle handle = {.meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb};
switch (pMsg->msgType) {
- case TDMT_VND_QUERY:
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY:
return qWorkerProcessQueryMsg(&handle, pVnode->pQuery, pMsg, 0);
- case TDMT_VND_QUERY_CONTINUE:
+ case TDMT_SCH_QUERY_CONTINUE:
return qWorkerProcessCQueryMsg(&handle, pVnode->pQuery, pMsg, 0);
default:
vError("unknown msg type:%d in query queue", pMsg->msgType);
@@ -239,22 +288,32 @@ int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) {
int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
vTrace("message in fetch queue is processing");
+ if ((pMsg->msgType == TDMT_SCH_FETCH || pMsg->msgType == TDMT_VND_TABLE_META ||
+ pMsg->msgType == TDMT_VND_TABLE_CFG) &&
+ !vnodeIsLeader(pVnode)) {
+ vnodeRedirectRpcMsg(pVnode, pMsg);
+ return 0;
+ }
+
char *msgstr = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
switch (pMsg->msgType) {
- case TDMT_VND_FETCH:
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH:
return qWorkerProcessFetchMsg(pVnode, pVnode->pQuery, pMsg, 0);
- case TDMT_VND_FETCH_RSP:
- return qWorkerProcessFetchRsp(pVnode, pVnode->pQuery, pMsg, 0);
- case TDMT_VND_CANCEL_TASK:
+ case TDMT_SCH_FETCH_RSP:
+ return qWorkerProcessRspMsg(pVnode, pVnode->pQuery, pMsg, 0);
+ case TDMT_SCH_CANCEL_TASK:
return qWorkerProcessCancelMsg(pVnode, pVnode->pQuery, pMsg, 0);
- case TDMT_VND_DROP_TASK:
+ case TDMT_SCH_DROP_TASK:
return qWorkerProcessDropMsg(pVnode, pVnode->pQuery, pMsg, 0);
- case TDMT_VND_QUERY_HEARTBEAT:
+ case TDMT_SCH_QUERY_HEARTBEAT:
return qWorkerProcessHbMsg(pVnode, pVnode->pQuery, pMsg, 0);
case TDMT_VND_TABLE_META:
return vnodeGetTableMeta(pVnode, pMsg);
+ case TDMT_VND_TABLE_CFG:
+ return vnodeGetTableCfg(pVnode, pMsg);
case TDMT_VND_CONSUME:
return tqProcessPollReq(pVnode->pTq, pMsg, pInfo->workerId);
case TDMT_STREAM_TASK_RUN:
@@ -263,37 +322,25 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
return tqProcessTaskDispatchReq(pVnode->pTq, pMsg);
case TDMT_STREAM_TASK_RECOVER:
return tqProcessTaskRecoverReq(pVnode->pTq, pMsg);
+ case TDMT_STREAM_RETRIEVE:
+ return tqProcessTaskRetrieveReq(pVnode->pTq, pMsg);
case TDMT_STREAM_TASK_DISPATCH_RSP:
return tqProcessTaskDispatchRsp(pVnode->pTq, pMsg);
case TDMT_STREAM_TASK_RECOVER_RSP:
return tqProcessTaskRecoverRsp(pVnode->pTq, pMsg);
+ case TDMT_STREAM_RETRIEVE_RSP:
+ return tqProcessTaskRetrieveRsp(pVnode->pTq, pMsg);
default:
vError("unknown msg type:%d in fetch queue", pMsg->msgType);
return TSDB_CODE_VND_APP_ERROR;
}
}
-int32_t vnodeProcessWriteMsg(SVnode *pVnode, int64_t version, SRpcMsg *pMsg, SRpcMsg *pRsp) {
- vTrace("message in write queue is processing");
- char *msgstr = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
- int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
- SDeleteRes res = {0};
- SReadHandle handle = {.meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb};
-
- switch (pMsg->msgType) {
- case TDMT_VND_DELETE:
- return qWorkerProcessDeleteMsg(&handle, pVnode->pQuery, pMsg, pRsp, &res);
- default:
- vError("unknown msg type:%d in write queue", pMsg->msgType);
- return TSDB_CODE_VND_APP_ERROR;
- }
-}
-
// TODO: remove the function
void smaHandleRes(void *pVnode, int64_t smaId, const SArray *data) {
// TODO
- blockDebugShowData(data, __func__);
+ blockDebugShowDataBlocks(data, __func__);
tdProcessTSmaInsert(((SVnode *)pVnode)->pSma, smaId, (const char *)data);
}
@@ -304,13 +351,38 @@ void vnodeUpdateMetaRsp(SVnode *pVnode, STableMetaRsp *pMetaRsp) {
pMetaRsp->precision = pVnode->config.tsdbCfg.precision;
}
+static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
+ int32_t code = 0;
+ SVTrimDbReq trimReq = {0};
+
+ vInfo("vgId:%d, trim vnode request will be processed, time:%d", pVnode->config.vgId, trimReq.timestamp);
+
+ // decode
+ if (tDeserializeSVTrimDbReq(pReq, len, &trimReq) != 0) {
+ code = TSDB_CODE_INVALID_MSG;
+ goto _exit;
+ }
+
+ // process
+ code = tsdbDoRetention(pVnode->pTsdb, trimReq.timestamp);
+ if (code) goto _exit;
+
+_exit:
+ return code;
+}
+
static int32_t vnodeProcessDropTtlTbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
SArray *tbUids = taosArrayInit(8, sizeof(int64_t));
if (tbUids == NULL) return TSDB_CODE_OUT_OF_MEMORY;
- int32_t t = ntohl(*(int32_t *)pReq);
- vError("rec ttl time:%d", t);
- int32_t ret = metaTtlDropTable(pVnode->pMeta, t, tbUids);
+ SVDropTtlTableReq ttlReq = {0};
+ if (tDeserializeSVDropTtlTableReq(pReq, len, &ttlReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ goto end;
+ }
+
+ vInfo("vgId:%d, drop ttl table req will be processed, time:%d", pVnode->config.vgId, ttlReq.timestamp);
+ int32_t ret = metaTtlDropTable(pVnode->pMeta, ttlReq.timestamp, tbUids);
if (ret != 0) {
goto end;
}
@@ -345,15 +417,19 @@ static int32_t vnodeProcessCreateStbReq(SVnode *pVnode, int64_t version, void *p
goto _err;
}
- if (tdProcessRSmaCreate(pVnode, &req) < 0) {
+ if (tdProcessRSmaCreate(pVnode->pSma, &req) < 0) {
pRsp->code = terrno;
goto _err;
}
+ taosMemoryFree(req.schemaRow.pSchema);
+ taosMemoryFree(req.schemaTag.pSchema);
tDecoderClear(&coder);
return 0;
_err:
+ taosMemoryFree(req.schemaRow.pSchema);
+ taosMemoryFree(req.schemaTag.pSchema);
tDecoderClear(&coder);
return -1;
}
@@ -418,8 +494,6 @@ static int32_t vnodeProcessCreateTbReq(SVnode *pVnode, int64_t version, void *pR
taosArrayPush(rsp.pArray, &cRsp);
}
- tDecoderClear(&decoder);
-
tqUpdateTbUidList(pVnode->pTq, tbUids, true);
tdUpdateTbUidList(pVnode->pSma, pStore);
tdUidStoreFree(pStore);
@@ -436,9 +510,12 @@ static int32_t vnodeProcessCreateTbReq(SVnode *pVnode, int64_t version, void *pR
}
tEncoderInit(&encoder, pRsp->pCont, pRsp->contLen);
tEncodeSVCreateTbBatchRsp(&encoder, &rsp);
- tEncoderClear(&encoder);
_exit:
+ for (int32_t iReq = 0; iReq < req.nReqs; iReq++) {
+ pCreateReq = req.pReqs + iReq;
+ taosArrayDestroy(pCreateReq->ctb.tagName);
+ }
taosArrayDestroy(rsp.pArray);
taosArrayDestroy(tbUids);
tDecoderClear(&decoder);
@@ -497,6 +574,11 @@ static int32_t vnodeProcessDropStbReq(SVnode *pVnode, int64_t version, void *pRe
goto _exit;
}
+ if (tdProcessRSmaDrop(pVnode->pSma, &req) < 0) {
+ rcode = terrno;
+ goto _exit;
+ }
+
// return rsp
_exit:
pRsp->code = rcode;
@@ -530,7 +612,7 @@ static int32_t vnodeProcessAlterTbReq(SVnode *pVnode, int64_t version, void *pRe
// process
if (metaAlterTable(pVnode->pMeta, version, &vAlterTbReq, &vMetaRsp) < 0) {
- vAlterTbRsp.code = TSDB_CODE_INVALID_MSG;
+ vAlterTbRsp.code = terrno;
tDecoderClear(&dc);
rcode = -1;
goto _exit;
@@ -714,6 +796,7 @@ static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq
if (tDecodeSVCreateTbReq(&decoder, &createTbReq) < 0) {
pRsp->code = TSDB_CODE_INVALID_MSG;
tDecoderClear(&decoder);
+ taosArrayDestroy(createTbReq.ctb.tagName);
goto _exit;
}
@@ -721,6 +804,7 @@ static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq
if (terrno != TSDB_CODE_TDB_TABLE_ALREADY_EXIST) {
submitBlkRsp.code = terrno;
tDecoderClear(&decoder);
+ taosArrayDestroy(createTbReq.ctb.tagName);
goto _exit;
}
}
@@ -741,6 +825,7 @@ static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq
vnodeDebugPrintSingleSubmitMsg(pVnode->pMeta, pBlock, &msgIter, "real uid");
#endif
tDecoderClear(&decoder);
+ taosArrayDestroy(createTbReq.ctb.tagName);
} else {
submitBlkRsp.tblFName = taosMemoryMalloc(TSDB_TABLE_FNAME_LEN);
sprintf(submitBlkRsp.tblFName, "%s.", pVnode->config.dbname);
@@ -772,9 +857,11 @@ _exit:
taosArrayDestroy(submitRsp.pArray);
// TODO: the partial success scenario and the error case
+ // => If partial success, extract the success submitted rows and reconstruct a new submit msg, and push to level
+ // 1/level 2.
// TODO: refactor
if ((terrno == TSDB_CODE_SUCCESS) && (pRsp->code == TSDB_CODE_SUCCESS)) {
- tdProcessRSmaSubmit(pVnode->pSma, pReq, STREAM_DATA_TYPE_SUBMIT_BLOCK);
+ tdProcessRSmaSubmit(pVnode->pSma, pReq, STREAM_INPUT__DATA_SUBMIT);
}
return 0;
@@ -839,7 +926,7 @@ static int32_t vnodeProcessAlterConfirmReq(SVnode *pVnode, int64_t version, void
return 0;
}
-static int32_t vnodeProcessAlterHasnRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
+static int32_t vnodeProcessAlterHashRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
vInfo("vgId:%d, alter hashrange msg will be processed", TD_VID(pVnode));
// todo
@@ -848,3 +935,48 @@ static int32_t vnodeProcessAlterHasnRangeReq(SVnode *pVnode, int64_t version, vo
// 3. reload sync
return 0;
}
+
+static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
+ SAlterVnodeReq alterReq = {0};
+ if (tDeserializeSAlterVnodeReq(pReq, len, &alterReq) != 0) {
+ terrno = TSDB_CODE_INVALID_MSG;
+ return TSDB_CODE_INVALID_MSG;
+ }
+
+ vInfo("vgId:%d, start to alter vnode config, cacheLast:%d cacheLastSize:%d", TD_VID(pVnode), alterReq.cacheLast,
+ alterReq.cacheLastSize);
+ if (pVnode->config.cacheLastSize != alterReq.cacheLastSize) {
+ pVnode->config.cacheLastSize = alterReq.cacheLastSize;
+ // TODO: save config
+ tsdbCacheSetCapacity(pVnode, (size_t)pVnode->config.cacheLastSize * 1024 * 1024);
+ }
+ return 0;
+}
+
+static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
+ int32_t code = 0;
+ SDecoder *pCoder = &(SDecoder){0};
+ SDeleteRes *pRes = &(SDeleteRes){0};
+
+ pRes->uidList = taosArrayInit(0, sizeof(tb_uid_t));
+ if (pRes->uidList == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _err;
+ }
+
+ tDecoderInit(pCoder, pReq, len);
+ tDecodeDeleteRes(pCoder, pRes);
+
+ for (int32_t iUid = 0; iUid < taosArrayGetSize(pRes->uidList); iUid++) {
+ code = tsdbDeleteTableData(pVnode->pTsdb, version, pRes->suid, *(uint64_t *)taosArrayGet(pRes->uidList, iUid),
+ pRes->skey, pRes->ekey);
+ if (code) goto _err;
+ }
+
+ tDecoderClear(pCoder);
+ taosArrayDestroy(pRes->uidList);
+ return code;
+
+_err:
+ return code;
+}
diff --git a/source/dnode/vnode/src/vnd/vnodeSync.c b/source/dnode/vnode/src/vnd/vnodeSync.c
index f1c43512cec80c744f9a89f983ecc3c985e83d15..87148a8450da794b6dd0cf980b7415f2e490c014 100644
--- a/source/dnode/vnode/src/vnd/vnodeSync.c
+++ b/source/dnode/vnode/src/vnd/vnodeSync.c
@@ -25,12 +25,12 @@ static inline bool vnodeIsMsgWeak(tmsg_t type) { return false; }
static inline void vnodeAccumBlockMsg(SVnode *pVnode, tmsg_t type) {
if (!vnodeIsMsgBlock(type)) return;
- int32_t count = atomic_add_fetch_32(&pVnode->syncCount, 1);
+ int32_t count = atomic_add_fetch_32(&pVnode->blockCount, 1);
vTrace("vgId:%d, accum block, count:%d type:%s", pVnode->config.vgId, count, TMSG_INFO(type));
}
static inline void vnodeWaitBlockMsg(SVnode *pVnode) {
- int32_t count = atomic_load_32(&pVnode->syncCount);
+ int32_t count = atomic_load_32(&pVnode->blockCount);
if (count <= 0) return;
vTrace("vgId:%d, wait block finish, count:%d", pVnode->config.vgId, count);
@@ -40,10 +40,10 @@ static inline void vnodeWaitBlockMsg(SVnode *pVnode) {
static inline void vnodePostBlockMsg(SVnode *pVnode, tmsg_t type) {
if (!vnodeIsMsgBlock(type)) return;
- int32_t count = atomic_load_32(&pVnode->syncCount);
+ int32_t count = atomic_load_32(&pVnode->blockCount);
if (count <= 0) return;
- count = atomic_sub_fetch_32(&pVnode->syncCount, 1);
+ count = atomic_sub_fetch_32(&pVnode->blockCount, 1);
vTrace("vgId:%d, post block, count:%d type:%s", pVnode->config.vgId, count, TMSG_INFO(type));
if (count <= 0) {
tsem_post(&pVnode->syncSem);
@@ -73,7 +73,7 @@ static int32_t vnodeSetStandBy(SVnode *pVnode) {
vInfo("vgId:%d, set standby success", TD_VID(pVnode));
return 0;
} else {
- vError("vgId:%d, failed to set standby since %s", TD_VID(pVnode), terrstr());
+ vError("vgId:%d, failed to set standby after leader transfer since %s", TD_VID(pVnode), terrstr());
return -1;
}
}
@@ -84,8 +84,10 @@ static int32_t vnodeProcessAlterReplicaReq(SVnode *pVnode, SRpcMsg *pMsg) {
terrno = TSDB_CODE_INVALID_MSG;
return TSDB_CODE_INVALID_MSG;
}
- STraceId *trace = &pMsg->info.traceId;
+
+ const STraceId *trace = &pMsg->info.traceId;
vGTrace("vgId:%d, start to alter vnode replica to %d, handle:%p", TD_VID(pVnode), req.replica, pMsg->info.handle);
+
SSyncCfg cfg = {.replicaNum = req.replica, .myIndex = req.selfIndex};
for (int32_t r = 0; r < req.replica; ++r) {
SNodeInfo *pNode = &cfg.nodeInfo[r];
@@ -118,7 +120,24 @@ static int32_t vnodeProcessAlterReplicaReq(SVnode *pVnode, SRpcMsg *pMsg) {
return code;
}
-void vnodeProposeMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
+void vnodeRedirectRpcMsg(SVnode *pVnode, SRpcMsg *pMsg) {
+ SEpSet newEpSet = {0};
+ syncGetRetryEpSet(pVnode->sync, &newEpSet);
+
+ const STraceId *trace = &pMsg->info.traceId;
+ vGTrace("vgId:%d, msg:%p is redirect since not leader, numOfEps:%d inUse:%d", pVnode->config.vgId, pMsg,
+ newEpSet.numOfEps, newEpSet.inUse);
+ for (int32_t i = 0; i < newEpSet.numOfEps; ++i) {
+ vGTrace("vgId:%d, msg:%p redirect:%d ep:%s:%u", pVnode->config.vgId, pMsg, i, newEpSet.eps[i].fqdn,
+ newEpSet.eps[i].port);
+ }
+ pMsg->info.hasEpSet = 1;
+
+ SRpcMsg rsp = {.code = TSDB_CODE_RPC_REDIRECT, .info = pMsg->info, .msgType = pMsg->msgType + 1};
+ tmsgSendRedirectRsp(&rsp, &newEpSet);
+}
+
+void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
SVnode *pVnode = pInfo->ahandle;
int32_t vgId = pVnode->config.vgId;
int32_t code = 0;
@@ -126,43 +145,44 @@ void vnodeProposeMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
for (int32_t m = 0; m < numOfMsgs; m++) {
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
- STraceId *trace = &pMsg->info.traceId;
+ const STraceId *trace = &pMsg->info.traceId;
vGTrace("vgId:%d, msg:%p get from vnode-write queue handle:%p", vgId, pMsg, pMsg->info.handle);
- if (pMsg->msgType == TDMT_VND_ALTER_REPLICA) {
- code = vnodeProcessAlterReplicaReq(pVnode, pMsg);
+ code = vnodePreProcessWriteMsg(pVnode, pMsg);
+ if (code != 0) {
+ vError("vgId:%d, msg:%p failed to pre-process since %s", vgId, pMsg, terrstr());
} else {
- code = vnodePreprocessReq(pVnode, pMsg);
- if (code != 0) {
- vError("vgId:%d, failed to pre-process msg:%p since %s", vgId, pMsg, terrstr());
+ if (pMsg->msgType == TDMT_VND_ALTER_REPLICA) {
+ code = vnodeProcessAlterReplicaReq(pVnode, pMsg);
} else {
code = syncPropose(pVnode->sync, pMsg, vnodeIsMsgWeak(pMsg->msgType));
+ if (code > 0) {
+ SRpcMsg rsp = {.code = pMsg->code, .info = pMsg->info};
+ if (vnodeProcessWriteMsg(pVnode, pMsg, pMsg->info.conn.applyIndex, &rsp) < 0) {
+ rsp.code = terrno;
+ vError("vgId:%d, msg:%p failed to apply right now since %s", vgId, pMsg, terrstr());
+ }
+ if (rsp.info.handle != NULL) {
+ tmsgSendRsp(&rsp);
+ }
+ }
}
}
if (code == 0) {
vnodeAccumBlockMsg(pVnode, pMsg->msgType);
- } else if (code == -1 && terrno == TSDB_CODE_SYN_NOT_LEADER) {
- SEpSet newEpSet = {0};
- syncGetEpSet(pVnode->sync, &newEpSet);
- SEp *pEp = &newEpSet.eps[newEpSet.inUse];
- if (pEp->port == tsServerPort && strcmp(pEp->fqdn, tsLocalFqdn) == 0) {
- newEpSet.inUse = (newEpSet.inUse + 1) % newEpSet.numOfEps;
- }
-
- vGTrace("vgId:%d, msg:%p is redirect since not leader, numOfEps:%d inUse:%d", vgId, pMsg, newEpSet.numOfEps,
- newEpSet.inUse);
- for (int32_t i = 0; i < newEpSet.numOfEps; ++i) {
- vGTrace("vgId:%d, msg:%p redirect:%d ep:%s:%u", vgId, pMsg, i, newEpSet.eps[i].fqdn, newEpSet.eps[i].port);
+ } else if (code < 0) {
+ if (terrno == TSDB_CODE_SYN_NOT_LEADER) {
+ vnodeRedirectRpcMsg(pVnode, pMsg);
+ } else {
+ if (terrno != 0) code = terrno;
+ vError("vgId:%d, msg:%p failed to propose since %s, code:0x%x", vgId, pMsg, tstrerror(code), code);
+ SRpcMsg rsp = {.code = code, .info = pMsg->info};
+ if (rsp.info.handle != NULL) {
+ tmsgSendRsp(&rsp);
+ }
}
-
- SRpcMsg rsp = {.code = TSDB_CODE_RPC_REDIRECT, .info = pMsg->info};
- tmsgSendRedirectRsp(&rsp, &newEpSet);
} else {
- if (terrno != 0) code = terrno;
- vError("vgId:%d, msg:%p failed to propose since %s, code:0x%x", vgId, pMsg, tstrerror(code), code);
- SRpcMsg rsp = {.code = code, .info = pMsg->info};
- tmsgSendRsp(&rsp);
}
vGTrace("vgId:%d, msg:%p is freed, code:0x%x", vgId, pMsg, code);
@@ -173,7 +193,7 @@ void vnodeProposeMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
vnodeWaitBlockMsg(pVnode);
}
-void vnodeApplyMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
+void vnodeApplyWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
SVnode *pVnode = pInfo->ahandle;
int32_t vgId = pVnode->config.vgId;
int32_t code = 0;
@@ -181,13 +201,13 @@ void vnodeApplyMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
for (int32_t i = 0; i < numOfMsgs; ++i) {
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
- STraceId *trace = &pMsg->info.traceId;
+ const STraceId *trace = &pMsg->info.traceId;
vGTrace("vgId:%d, msg:%p get from vnode-apply queue, type:%s handle:%p", vgId, pMsg, TMSG_INFO(pMsg->msgType),
pMsg->info.handle);
SRpcMsg rsp = {.code = pMsg->code, .info = pMsg->info};
if (rsp.code == 0) {
- if (vnodeProcessWriteReq(pVnode, pMsg, pMsg->info.conn.applyIndex, &rsp) < 0) {
+ if (vnodeProcessWriteMsg(pVnode, pMsg, pMsg->info.conn.applyIndex, &rsp) < 0) {
rsp.code = terrno;
vError("vgId:%d, msg:%p failed to apply since %s", vgId, pMsg, terrstr());
}
@@ -204,109 +224,161 @@ void vnodeApplyMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
}
}
-int32_t vnodeProcessSyncReq(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
- int32_t ret = 0;
-
- if (syncEnvIsStart()) {
- SSyncNode *pSyncNode = syncNodeAcquire(pVnode->sync);
- assert(pSyncNode != NULL);
+int32_t vnodeProcessSyncMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
+ int32_t code = 0;
+ const STraceId *trace = &pMsg->info.traceId;
- SMsgHead *pHead = pMsg->pCont;
- STraceId *trace = &pMsg->info.traceId;
-
- do {
- char *syncNodeStr = sync2SimpleStr(pVnode->sync);
- static int64_t vndTick = 0;
- if (++vndTick % 10 == 1) {
- vGTrace("vgId:%d, sync heartbeat msg:%s, %s", syncGetVgId(pVnode->sync), TMSG_INFO(pMsg->msgType), syncNodeStr);
- }
- if (gRaftDetailLog) {
- char logBuf[512] = {0};
- snprintf(logBuf, sizeof(logBuf), "==vnodeProcessSyncReq== msgType:%d, syncNode: %s", pMsg->msgType,
- syncNodeStr);
- syncRpcMsgLog2(logBuf, pMsg);
- }
- taosMemoryFree(syncNodeStr);
- } while (0);
-
- SRpcMsg *pRpcMsg = pMsg;
+ if (!syncEnvIsStart()) {
+ vGError("vgId:%d, msg:%p failed to process since sync env not start", pVnode->config.vgId);
+ terrno = TSDB_CODE_APP_ERROR;
+ return -1;
+ }
- if (pRpcMsg->msgType == TDMT_SYNC_TIMEOUT) {
- SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ SSyncNode *pSyncNode = syncNodeAcquire(pVnode->sync);
+ if (pSyncNode == NULL) {
+ vGError("vgId:%d, msg:%p failed to process since invalid sync node", pVnode->config.vgId);
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
- ret = syncNodeOnTimeoutCb(pSyncNode, pSyncMsg);
+#if 1
+ do {
+ char *syncNodeStr = sync2SimpleStr(pVnode->sync);
+ static int64_t vndTick = 0;
+ if (++vndTick % 10 == 1) {
+ vGTrace("vgId:%d, sync trace msg:%s, %s", syncGetVgId(pVnode->sync), TMSG_INFO(pMsg->msgType), syncNodeStr);
+ }
+ taosMemoryFree(syncNodeStr);
+ } while (0);
+#endif
+
+ if (syncNodeStrategy(pSyncNode) == SYNC_STRATEGY_NO_SNAPSHOT) {
+ if (pMsg->msgType == TDMT_SYNC_TIMEOUT) {
+ SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnTimeoutCb(pSyncNode, pSyncMsg);
syncTimeoutDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_PING) {
- SyncPing *pSyncMsg = syncPingFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnPingCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_PING) {
+ SyncPing *pSyncMsg = syncPingFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnPingCb(pSyncNode, pSyncMsg);
syncPingDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_PING_REPLY) {
- SyncPingReply *pSyncMsg = syncPingReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnPingReplyCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_PING_REPLY) {
+ SyncPingReply *pSyncMsg = syncPingReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnPingReplyCb(pSyncNode, pSyncMsg);
syncPingReplyDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
- SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
+ SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg, NULL);
syncClientRequestDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
- SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnRequestVoteCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST_BATCH) {
+ SyncClientRequestBatch *pSyncMsg = syncClientRequestBatchFromRpcMsg(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnClientRequestBatchCb(pSyncNode, pSyncMsg);
+ syncClientRequestBatchDestroyDeep(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
+ SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnRequestVoteCb(pSyncNode, pSyncMsg);
syncRequestVoteDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_REQUEST_VOTE_REPLY) {
- SyncRequestVoteReply *pSyncMsg = syncRequestVoteReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnRequestVoteReplyCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE_REPLY) {
+ SyncRequestVoteReply *pSyncMsg = syncRequestVoteReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnRequestVoteReplyCb(pSyncNode, pSyncMsg);
syncRequestVoteReplyDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_APPEND_ENTRIES) {
- SyncAppendEntries *pSyncMsg = syncAppendEntriesFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnAppendEntriesCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_APPEND_ENTRIES) {
+ SyncAppendEntries *pSyncMsg = syncAppendEntriesFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnAppendEntriesCb(pSyncNode, pSyncMsg);
syncAppendEntriesDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_APPEND_ENTRIES_REPLY) {
- SyncAppendEntriesReply *pSyncMsg = syncAppendEntriesReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
-
- ret = syncNodeOnAppendEntriesReplyCb(pSyncNode, pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_APPEND_ENTRIES_REPLY) {
+ SyncAppendEntriesReply *pSyncMsg = syncAppendEntriesReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnAppendEntriesReplyCb(pSyncNode, pSyncMsg);
syncAppendEntriesReplyDestroy(pSyncMsg);
-
- } else if (pRpcMsg->msgType == TDMT_SYNC_SET_VNODE_STANDBY) {
- ret = vnodeSetStandBy(pVnode);
- if (ret != 0 && terrno != 0) ret = terrno;
- SRpcMsg rsp = {.code = ret, .info = pMsg->info};
+ } else if (pMsg->msgType == TDMT_SYNC_SET_VNODE_STANDBY) {
+ code = vnodeSetStandBy(pVnode);
+ if (code != 0 && terrno != 0) code = terrno;
+ SRpcMsg rsp = {.code = code, .info = pMsg->info};
tmsgSendRsp(&rsp);
} else {
- vError("==vnodeProcessSyncReq== error msg type:%d", pRpcMsg->msgType);
- ret = -1;
+ vGError("vgId:%d, msg:%p failed to process since error msg type:%d", pVnode->config.vgId, pMsg->msgType);
+ code = -1;
}
- syncNodeRelease(pSyncNode);
- } else {
- vError("==vnodeProcessSyncReq== error syncEnv stop");
- ret = -1;
+ } else if (syncNodeStrategy(pSyncNode) == SYNC_STRATEGY_WAL_FIRST) {
+ // use wal first strategy
+ if (pMsg->msgType == TDMT_SYNC_TIMEOUT) {
+ SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnTimeoutCb(pSyncNode, pSyncMsg);
+ syncTimeoutDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_PING) {
+ SyncPing *pSyncMsg = syncPingFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnPingCb(pSyncNode, pSyncMsg);
+ syncPingDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_PING_REPLY) {
+ SyncPingReply *pSyncMsg = syncPingReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnPingReplyCb(pSyncNode, pSyncMsg);
+ syncPingReplyDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
+ SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg, NULL);
+ syncClientRequestDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST_BATCH) {
+ SyncClientRequestBatch *pSyncMsg = syncClientRequestBatchFromRpcMsg(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnClientRequestBatchCb(pSyncNode, pSyncMsg);
+ syncClientRequestBatchDestroyDeep(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
+ SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnRequestVoteSnapshotCb(pSyncNode, pSyncMsg);
+ syncRequestVoteDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_REQUEST_VOTE_REPLY) {
+ SyncRequestVoteReply *pSyncMsg = syncRequestVoteReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnRequestVoteReplySnapshotCb(pSyncNode, pSyncMsg);
+ syncRequestVoteReplyDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_APPEND_ENTRIES_BATCH) {
+ SyncAppendEntriesBatch *pSyncMsg = syncAppendEntriesBatchFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnAppendEntriesSnapshot2Cb(pSyncNode, pSyncMsg);
+ syncAppendEntriesBatchDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_APPEND_ENTRIES_REPLY) {
+ SyncAppendEntriesReply *pSyncMsg = syncAppendEntriesReplyFromRpcMsg2(pMsg);
+ ASSERT(pSyncMsg != NULL);
+ code = syncNodeOnAppendEntriesReplySnapshot2Cb(pSyncNode, pSyncMsg);
+ syncAppendEntriesReplyDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_SNAPSHOT_SEND) {
+ SyncSnapshotSend *pSyncMsg = syncSnapshotSendFromRpcMsg2(pMsg);
+ code = syncNodeOnSnapshotSendCb(pSyncNode, pSyncMsg);
+ syncSnapshotSendDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_SNAPSHOT_RSP) {
+ SyncSnapshotRsp *pSyncMsg = syncSnapshotRspFromRpcMsg2(pMsg);
+ code = syncNodeOnSnapshotRspCb(pSyncNode, pSyncMsg);
+ syncSnapshotRspDestroy(pSyncMsg);
+ } else if (pMsg->msgType == TDMT_SYNC_SET_VNODE_STANDBY) {
+ code = vnodeSetStandBy(pVnode);
+ if (code != 0 && terrno != 0) code = terrno;
+ SRpcMsg rsp = {.code = code, .info = pMsg->info};
+ tmsgSendRsp(&rsp);
+ } else {
+ vGError("vgId:%d, msg:%p failed to process since error msg type:%d", pVnode->config.vgId, pMsg->msgType);
+ code = -1;
+ }
}
- if (ret != 0 && terrno == 0) {
+ syncNodeRelease(pSyncNode);
+ if (code != 0 && terrno == 0) {
terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
}
- return ret;
+ return code;
}
static int32_t vnodeSyncEqMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) {
@@ -336,10 +408,10 @@ static void vnodeSyncReconfig(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SReCon
SVnode *pVnode = pFsm->data;
SRpcMsg rpcMsg = {.msgType = pMsg->msgType, .contLen = pMsg->contLen};
- syncGetAndDelRespRpc(pVnode->sync, cbMeta.seqNum, &rpcMsg.info);
+ syncGetAndDelRespRpc(pVnode->sync, cbMeta.newCfgSeqNum, &rpcMsg.info);
rpcMsg.info.conn.applyIndex = cbMeta.index;
- STraceId *trace = (STraceId *)&pMsg->info.traceId;
+ const STraceId *trace = (STraceId *)&pMsg->info.traceId;
vGTrace("vgId:%d, alter vnode replica is confirmed, type:%s contLen:%d seq:%" PRIu64 " handle:%p", TD_VID(pVnode),
TMSG_INFO(pMsg->msgType), pMsg->contLen, cbMeta.seqNum, rpcMsg.info.handle);
if (rpcMsg.info.handle != NULL) {
@@ -350,67 +422,119 @@ static void vnodeSyncReconfig(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SReCon
}
static void vnodeSyncCommitMsg(SSyncFSM *pFsm, const SRpcMsg *pMsg, SFsmCbMeta cbMeta) {
- SVnode *pVnode = pFsm->data;
- SSnapshot snapshot = {0};
- SyncIndex beginIndex = SYNC_INDEX_INVALID;
- char logBuf[256] = {0};
-
- if (pFsm->FpGetSnapshotInfo != NULL) {
- (*pFsm->FpGetSnapshotInfo)(pFsm, &snapshot);
- beginIndex = snapshot.lastApplyIndex;
- }
-
- if (cbMeta.index > beginIndex) {
- snprintf(
- logBuf, sizeof(logBuf),
- "==callback== ==CommitCb== execute, pFsm:%p, index:%ld, isWeak:%d, code:%d, state:%d %s, beginIndex :%ld\n",
- pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state, syncUtilState2String(cbMeta.state), beginIndex);
- syncRpcMsgLog2(logBuf, (SRpcMsg *)pMsg);
+ SVnode *pVnode = pFsm->data;
+ vTrace("vgId:%d, commit-cb is excuted, fsm:%p, index:%" PRId64 ", isWeak:%d, code:%d, state:%d %s, msgtype:%d %s",
+ syncGetVgId(pVnode->sync), pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state,
+ syncUtilState2String(cbMeta.state), pMsg->msgType, TMSG_INFO(pMsg->msgType));
+ if (cbMeta.code == 0) {
SRpcMsg rpcMsg = {.msgType = pMsg->msgType, .contLen = pMsg->contLen};
rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen);
memcpy(rpcMsg.pCont, pMsg->pCont, pMsg->contLen);
syncGetAndDelRespRpc(pVnode->sync, cbMeta.seqNum, &rpcMsg.info);
rpcMsg.info.conn.applyIndex = cbMeta.index;
+ rpcMsg.info.conn.applyTerm = cbMeta.term;
tmsgPutToQueue(&pVnode->msgCb, APPLY_QUEUE, &rpcMsg);
-
} else {
- char logBuf[256] = {0};
- snprintf(logBuf, sizeof(logBuf),
- "==callback== ==CommitCb== do not execute, pFsm:%p, index:%ld, isWeak:%d, code:%d, state:%d %s, "
- "beginIndex :%ld\n",
- pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state, syncUtilState2String(cbMeta.state),
- beginIndex);
- syncRpcMsgLog2(logBuf, (SRpcMsg *)pMsg);
+ SRpcMsg rsp = {.code = cbMeta.code, .info = pMsg->info};
+ vError("vgId:%d, sync commit error, msgtype:%d,%s, error:0x%X, errmsg:%s", syncGetVgId(pVnode->sync), pMsg->msgType,
+ TMSG_INFO(pMsg->msgType), cbMeta.code, tstrerror(cbMeta.code));
+ if (rsp.info.handle != NULL) {
+ tmsgSendRsp(&rsp);
+ }
}
}
static void vnodeSyncPreCommitMsg(SSyncFSM *pFsm, const SRpcMsg *pMsg, SFsmCbMeta cbMeta) {
- char logBuf[256] = {0};
- snprintf(logBuf, sizeof(logBuf),
- "==callback== ==PreCommitCb== pFsm:%p, index:%ld, isWeak:%d, code:%d, state:%d %s \n", pFsm, cbMeta.index,
- cbMeta.isWeak, cbMeta.code, cbMeta.state, syncUtilState2String(cbMeta.state));
- syncRpcMsgLog2(logBuf, (SRpcMsg *)pMsg);
+ SVnode *pVnode = pFsm->data;
+ vTrace("vgId:%d, pre-commit-cb is excuted, fsm:%p, index:%" PRId64 ", isWeak:%d, code:%d, state:%d %s, msgtype:%d %s",
+ syncGetVgId(pVnode->sync), pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state,
+ syncUtilState2String(cbMeta.state), pMsg->msgType, TMSG_INFO(pMsg->msgType));
}
static void vnodeSyncRollBackMsg(SSyncFSM *pFsm, const SRpcMsg *pMsg, SFsmCbMeta cbMeta) {
- char logBuf[256] = {0};
- snprintf(logBuf, sizeof(logBuf), "==callback== ==RollBackCb== pFsm:%p, index:%ld, isWeak:%d, code:%d, state:%d %s \n",
- pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state, syncUtilState2String(cbMeta.state));
- syncRpcMsgLog2(logBuf, (SRpcMsg *)pMsg);
+ SVnode *pVnode = pFsm->data;
+ vTrace("vgId:%d, rollback-cb is excuted, fsm:%p, index:%" PRId64 ", isWeak:%d, code:%d, state:%d %s, msgtype:%d %s",
+ syncGetVgId(pVnode->sync), pFsm, cbMeta.index, cbMeta.isWeak, cbMeta.code, cbMeta.state,
+ syncUtilState2String(cbMeta.state), pMsg->msgType, TMSG_INFO(pMsg->msgType));
}
-static int32_t vnodeSnapshotStartRead(struct SSyncFSM *pFsm, void **ppReader) { return 0; }
+#define USE_TSDB_SNAPSHOT
-static int32_t vnodeSnapshotStopRead(struct SSyncFSM *pFsm, void *pReader) { return 0; }
+static int32_t vnodeSnapshotStartRead(struct SSyncFSM *pFsm, void *pParam, void **ppReader) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ SSnapshotParam *pSnapshotParam = pParam;
+ int32_t code = vnodeSnapReaderOpen(pVnode, pSnapshotParam->start, pSnapshotParam->end, (SVSnapReader **)ppReader);
+ return code;
+#else
+ *ppReader = taosMemoryMalloc(32);
+ return 0;
+#endif
+}
+
+static int32_t vnodeSnapshotStopRead(struct SSyncFSM *pFsm, void *pReader) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ int32_t code = vnodeSnapReaderClose(pReader);
+ return code;
+#else
+ taosMemoryFree(pReader);
+ return 0;
+#endif
+}
-static int32_t vnodeSnapshotDoRead(struct SSyncFSM *pFsm, void *pReader, void **ppBuf, int32_t *len) { return 0; }
+static int32_t vnodeSnapshotDoRead(struct SSyncFSM *pFsm, void *pReader, void **ppBuf, int32_t *len) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ int32_t code = vnodeSnapRead(pReader, (uint8_t **)ppBuf, len);
+ return code;
+#else
+ static int32_t times = 0;
+ if (times++ < 5) {
+ *len = 64;
+ *ppBuf = taosMemoryMalloc(*len);
+ snprintf(*ppBuf, *len, "snapshot block %d", times);
+ } else {
+ *len = 0;
+ *ppBuf = NULL;
+ }
+ return 0;
+#endif
+}
-static int32_t vnodeSnapshotStartWrite(struct SSyncFSM *pFsm, void **ppWriter) { return 0; }
+static int32_t vnodeSnapshotStartWrite(struct SSyncFSM *pFsm, void *pParam, void **ppWriter) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ SSnapshotParam *pSnapshotParam = pParam;
+ int32_t code = vnodeSnapWriterOpen(pVnode, pSnapshotParam->start, pSnapshotParam->end, (SVSnapWriter **)ppWriter);
+ return code;
+#else
+ *ppWriter = taosMemoryMalloc(32);
+ return 0;
+#endif
+}
-static int32_t vnodeSnapshotStopWrite(struct SSyncFSM *pFsm, void *pWriter, bool isApply) { return 0; }
+static int32_t vnodeSnapshotStopWrite(struct SSyncFSM *pFsm, void *pWriter, bool isApply) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ int32_t code = vnodeSnapWriterClose(pWriter, !isApply);
+ return code;
+#else
+ taosMemoryFree(pWriter);
+ return 0;
+#endif
+}
-static int32_t vnodeSnapshotDoWrite(struct SSyncFSM *pFsm, void *pWriter, void *pBuf, int32_t len) { return 0; }
+static int32_t vnodeSnapshotDoWrite(struct SSyncFSM *pFsm, void *pWriter, void *pBuf, int32_t len) {
+#ifdef USE_TSDB_SNAPSHOT
+ SVnode *pVnode = pFsm->data;
+ int32_t code = vnodeSnapWrite(pWriter, pBuf, len);
+ return code;
+#else
+ return 0;
+#endif
+}
static SSyncFSM *vnodeSyncMakeFsm(SVnode *pVnode) {
SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM));
@@ -433,7 +557,9 @@ static SSyncFSM *vnodeSyncMakeFsm(SVnode *pVnode) {
int32_t vnodeSyncOpen(SVnode *pVnode, char *path) {
SSyncInfo syncInfo = {
- .snapshotEnable = false,
+ .snapshotStrategy = SYNC_STRATEGY_WAL_FIRST,
+ //.snapshotStrategy = SYNC_STRATEGY_NO_SNAPSHOT,
+ .batchSize = 10,
.vgId = pVnode->config.vgId,
.isStandBy = pVnode->config.standby,
.syncCfg = pVnode->config.syncCfg,
@@ -452,7 +578,7 @@ int32_t vnodeSyncOpen(SVnode *pVnode, char *path) {
return -1;
}
- setPingTimerMS(pVnode->sync, 3000);
+ setPingTimerMS(pVnode->sync, 5000);
setElectTimerMS(pVnode->sync, 500);
setHeartbeatTimerMS(pVnode->sync, 100);
return 0;
@@ -464,3 +590,17 @@ void vnodeSyncStart(SVnode *pVnode) {
}
void vnodeSyncClose(SVnode *pVnode) { syncStop(pVnode->sync); }
+
+bool vnodeIsLeader(SVnode *pVnode) {
+ if (!syncIsReady(pVnode->sync)) {
+ return false;
+ }
+
+ // todo
+ // if (!pVnode->restored) {
+ // terrno = TSDB_CODE_APP_NOT_READY;
+ // return false;
+ // }
+
+ return true;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/vnd/vnodeUtil.c b/source/dnode/vnode/src/vnd/vnodeUtil.c
deleted file mode 100644
index cd942099bc8924fde06ea912b0eecdfbe72603cb..0000000000000000000000000000000000000000
--- a/source/dnode/vnode/src/vnd/vnodeUtil.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#include "vnd.h"
-
-int32_t vnodeRealloc(void** pp, int32_t size) {
- uint8_t* p = NULL;
- int32_t csize = 0;
-
- if (*pp) {
- p = (uint8_t*)(*pp) - sizeof(int32_t);
- csize = *(int32_t*)p;
- }
-
- if (csize >= size) {
- return 0;
- }
-
- p = (uint8_t*)taosMemoryRealloc(p, size);
- if (p == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- *(int32_t*)p = size;
- *pp = p + sizeof(int32_t);
-
- return 0;
-}
-
-void vnodeFree(void* p) {
- if (p) {
- taosMemoryFree(((uint8_t*)p) - sizeof(int32_t));
- }
-}
\ No newline at end of file
diff --git a/source/dnode/vnode/test/tsdbSmaTest.cpp b/source/dnode/vnode/test/tsdbSmaTest.cpp
index 2c1e6fbbbd55968d5bbf4d6057a09d814460aca9..2a8c7a583ccb4f5aa720f2fd83db85a19f76b93b 100644
--- a/source/dnode/vnode/test/tsdbSmaTest.cpp
+++ b/source/dnode/vnode/test/tsdbSmaTest.cpp
@@ -435,7 +435,7 @@ TEST(testCase, tSma_Data_Insert_Query_Test) {
SSDataBlock *pDataBlock = (SSDataBlock *)taosMemoryCalloc(1, sizeof(SSDataBlock));
EXPECT_NE(pDataBlock, nullptr);
pDataBlock->pBlockAgg = NULL;
- pDataBlock->info.numOfCols = tSmaNumOfCols;
+ taosArrayGetSize(pDataBlock->pDataBlock) = tSmaNumOfCols;
pDataBlock->info.rows = tSmaNumOfRows;
pDataBlock->info.groupId = tSmaGroupId + g;
diff --git a/source/libs/catalog/inc/catalogInt.h b/source/libs/catalog/inc/catalogInt.h
index 7c90c3538cc3428d6c6456c8c67f9acb4818e82c..fb9f588bae5c1a5ab14a25a6dbb0e47e831c1e4c 100644
--- a/source/libs/catalog/inc/catalogInt.h
+++ b/source/libs/catalog/inc/catalogInt.h
@@ -65,17 +65,26 @@ enum {
typedef enum {
CTG_TASK_GET_QNODE = 0,
+ CTG_TASK_GET_DNODE,
CTG_TASK_GET_DB_VGROUP,
CTG_TASK_GET_DB_CFG,
CTG_TASK_GET_DB_INFO,
CTG_TASK_GET_TB_META,
CTG_TASK_GET_TB_HASH,
CTG_TASK_GET_TB_INDEX,
+ CTG_TASK_GET_TB_CFG,
CTG_TASK_GET_INDEX,
CTG_TASK_GET_UDF,
CTG_TASK_GET_USER,
+ CTG_TASK_GET_SVR_VER,
} CTG_TASK_TYPE;
+typedef enum {
+ CTG_TASK_LAUNCHED = 1,
+ CTG_TASK_DONE,
+} CTG_TASK_STATUS;
+
+
typedef struct SCtgDebug {
bool lockEnable;
bool cacheEnable;
@@ -102,6 +111,12 @@ typedef struct SCtgTbIndexCtx {
SName* pName;
} SCtgTbIndexCtx;
+typedef struct SCtgTbCfgCtx {
+ SName* pName;
+ int32_t tbType;
+ SVgroupInfo* pVgInfo;
+} SCtgTbCfgCtx;
+
typedef struct SCtgDbVgCtx {
char dbFName[TSDB_DB_FNAME_LEN];
} SCtgDbVgCtx;
@@ -151,7 +166,7 @@ typedef struct SCtgDBCache {
int8_t deleted;
SCtgVgCache vgCache;
SHashObj *tbCache; // key:tbname, value:SCtgTbCache
- SHashObj *stbCache; // key:suid, value:STableMeta*
+ SHashObj *stbCache; // key:suid, value:char*
} SCtgDBCache;
typedef struct SCtgRentSlot {
@@ -190,7 +205,10 @@ typedef struct SCtgJob {
SArray* pTasks;
int32_t taskDone;
SMetaData jobRes;
-
+ int32_t jobResCode;
+ int32_t taskIdx;
+ SRWLatch taskLock;
+
uint64_t queryId;
SCatalog* pCtg;
SRequestConnInfo conn;
@@ -201,11 +219,14 @@ typedef struct SCtgJob {
int32_t dbVgNum;
int32_t udfNum;
int32_t qnodeNum;
+ int32_t dnodeNum;
int32_t dbCfgNum;
int32_t indexNum;
int32_t userNum;
int32_t dbInfoNum;
int32_t tbIndexNum;
+ int32_t tbCfgNum;
+ int32_t svrVerNum;
} SCtgJob;
typedef struct SCtgMsgCtx {
@@ -215,53 +236,75 @@ typedef struct SCtgMsgCtx {
char* target;
} SCtgMsgCtx;
+typedef struct SCtgTask SCtgTask;
+typedef int32_t (*ctgSubTaskCbFp)(SCtgTask*);
+
+typedef struct SCtgSubRes {
+ CTG_TASK_TYPE type;
+ int32_t code;
+ void* res;
+ ctgSubTaskCbFp fp;
+} SCtgSubRes;
+
typedef struct SCtgTask {
- CTG_TASK_TYPE type;
- int32_t taskId;
- SCtgJob* pJob;
- void* taskCtx;
- SCtgMsgCtx msgCtx;
- int32_t code;
- void* res;
+ CTG_TASK_TYPE type;
+ int32_t taskId;
+ SCtgJob* pJob;
+ void* taskCtx;
+ SCtgMsgCtx msgCtx;
+ int32_t code;
+ void* res;
+ CTG_TASK_STATUS status;
+ SRWLatch lock;
+ SArray* pParents;
+ SCtgSubRes subRes;
} SCtgTask;
+typedef int32_t (*ctgInitTaskFp)(SCtgJob*, int32_t, void*);
typedef int32_t (*ctgLanchTaskFp)(SCtgTask*);
typedef int32_t (*ctgHandleTaskMsgRspFp)(SCtgTask*, int32_t, const SDataBuf *, int32_t);
typedef int32_t (*ctgDumpTaskResFp)(SCtgTask*);
+typedef int32_t (*ctgCloneTaskResFp)(SCtgTask*, void**);
+typedef int32_t (*ctgCompTaskFp)(SCtgTask*, void*, bool*);
typedef struct SCtgAsyncFps {
- ctgLanchTaskFp launchFp;
+ ctgInitTaskFp initFp;
+ ctgLanchTaskFp launchFp;
ctgHandleTaskMsgRspFp handleRspFp;
- ctgDumpTaskResFp dumpResFp;
+ ctgDumpTaskResFp dumpResFp;
+ ctgCompTaskFp compFp;
+ ctgCloneTaskResFp cloneFp;
} SCtgAsyncFps;
typedef struct SCtgApiStat {
-#ifdef WINDOWS
+#if defined(WINDOWS) || defined(_TD_DARWIN_64)
size_t avoidCompilationErrors;
#endif
} SCtgApiStat;
typedef struct SCtgRuntimeStat {
- uint64_t qNum;
- uint64_t qDoneNum;
+ uint64_t numOfOpAbort;
+ uint64_t numOfOpEnqueue;
+ uint64_t numOfOpDequeue;
} SCtgRuntimeStat;
typedef struct SCtgCacheStat {
- uint64_t clusterNum;
- uint64_t dbNum;
- uint64_t tblNum;
- uint64_t stblNum;
- uint64_t userNum;
- uint64_t vgHitNum;
- uint64_t vgMissNum;
- uint64_t tbMetaHitNum;
- uint64_t tbMetaMissNum;
- uint64_t tbIndexHitNum;
- uint64_t tbIndexMissNum;
- uint64_t userHitNum;
- uint64_t userMissNum;
+ uint64_t numOfCluster;
+ uint64_t numOfDb;
+ uint64_t numOfTbl;
+ uint64_t numOfStb;
+ uint64_t numOfUser;
+ uint64_t numOfVgHit;
+ uint64_t numOfVgMiss;
+ uint64_t numOfMetaHit;
+ uint64_t numOfMetaMiss;
+ uint64_t numOfIndexHit;
+ uint64_t numOfIndexMiss;
+ uint64_t numOfUserHit;
+ uint64_t numOfUserMiss;
+ uint64_t numOfClear;
} SCtgCacheStat;
typedef struct SCatalogStat {
@@ -331,6 +374,7 @@ typedef struct SCtgDropTbIndexMsg {
typedef struct SCtgClearCacheMsg {
SCatalog* pCtg;
+ bool freeCtg;
} SCtgClearCacheMsg;
typedef struct SCtgUpdateEpsetMsg {
@@ -345,6 +389,7 @@ typedef struct SCtgCacheOperation {
void *data;
bool syncOp;
tsem_t rspSem;
+ bool stopQueue;
} SCtgCacheOperation;
typedef struct SCtgQNode {
@@ -354,6 +399,7 @@ typedef struct SCtgQNode {
typedef struct SCtgQueue {
SRWLatch qlock;
+ bool stopQueue;
SCtgQNode *head;
SCtgQNode *tail;
tsem_t reqSem;
@@ -434,8 +480,6 @@ typedef struct SCtgOperation {
#define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000
-#define CTG_IS_LOCKED(_lock) atomic_load_32((_lock))
-
#define CTG_LOCK(type, _lock) do { \
if (CTG_READ == (type)) { \
assert(atomic_load_32((_lock)) >= 0); \
@@ -473,8 +517,35 @@ typedef struct SCtgOperation {
#define CTG_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
#define CTG_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
-#define CTG_API_LEAVE(c) do { int32_t __code = c; CTG_UNLOCK(CTG_READ, &gCtgMgmt.lock); CTG_API_DEBUG("CTG API leave %s", __FUNCTION__); CTG_RET(__code); } while (0)
-#define CTG_API_ENTER() do { CTG_API_DEBUG("CTG API enter %s", __FUNCTION__); CTG_LOCK(CTG_READ, &gCtgMgmt.lock); if (atomic_load_8((int8_t*)&gCtgMgmt.exit)) { CTG_API_LEAVE(TSDB_CODE_CTG_OUT_OF_SERVICE); } } while (0)
+#define CTG_API_LEAVE(c) do { \
+ int32_t __code = c; \
+ CTG_UNLOCK(CTG_READ, &gCtgMgmt.lock); \
+ CTG_API_DEBUG("CTG API leave %s", __FUNCTION__); \
+ CTG_RET(__code); \
+} while (0)
+
+#define CTG_API_ENTER() do { \
+ CTG_API_DEBUG("CTG API enter %s", __FUNCTION__); \
+ CTG_LOCK(CTG_READ, &gCtgMgmt.lock); \
+ if (atomic_load_8((int8_t*)&gCtgMgmt.exit)) { \
+ CTG_API_LEAVE(TSDB_CODE_CTG_OUT_OF_SERVICE); \
+ } \
+} while (0)
+
+
+#define CTG_API_LEAVE_NOLOCK(c) do { \
+ int32_t __code = c; \
+ CTG_API_DEBUG("CTG API leave %s", __FUNCTION__); \
+ CTG_RET(__code); \
+ } while (0)
+
+#define CTG_API_ENTER_NOLOCK() do { \
+ CTG_API_DEBUG("CTG API enter %s", __FUNCTION__); \
+ if (atomic_load_8((int8_t*)&gCtgMgmt.exit)) { \
+ CTG_API_LEAVE_NOLOCK(TSDB_CODE_CTG_OUT_OF_SERVICE); \
+ } \
+} while (0)
+
void ctgdShowTableMeta(SCatalog* pCtg, const char *tbName, STableMeta* p);
void ctgdShowClusterCache(SCatalog* pCtg);
@@ -507,7 +578,7 @@ int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput *output, bool sy
int32_t ctgUpdateUserEnqueue(SCatalog* pCtg, SGetUserAuthRsp *pAuth, bool syncReq);
int32_t ctgUpdateVgEpsetEnqueue(SCatalog* pCtg, char *dbFName, int32_t vgId, SEpSet* pEpSet);
int32_t ctgUpdateTbIndexEnqueue(SCatalog* pCtg, STableIndex **pIndex, bool syncOp);
-int32_t ctgClearCacheEnqueue(SCatalog* pCtg, bool syncOp);
+int32_t ctgClearCacheEnqueue(SCatalog* pCtg, bool freeCtg, bool stopQueue, bool syncOp);
int32_t ctgMetaRentInit(SCtgRentMgmt *mgmt, uint32_t rentSec, int8_t type);
int32_t ctgMetaRentAdd(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t size);
int32_t ctgMetaRentGet(SCtgRentMgmt *mgmt, void **res, uint32_t *num, int32_t size);
@@ -520,6 +591,8 @@ int32_t ctgDropTbIndexEnqueue(SCatalog* pCtg, SName* pName, bool syncOp);
int32_t ctgOpDropTbIndex(SCtgCacheOperation *operation);
int32_t ctgOpUpdateTbIndex(SCtgCacheOperation *operation);
int32_t ctgOpClearCache(SCtgCacheOperation *operation);
+int32_t ctgReadTbTypeFromCache(SCatalog* pCtg, char* dbFName, char *tableName, int32_t *tbType);
+int32_t ctgGetTbHashVgroupFromCache(SCatalog *pCtg, const SName *pTableName, SVgroupInfo **pVgroup);
@@ -527,6 +600,7 @@ int32_t ctgOpClearCache(SCtgCacheOperation *operation);
int32_t ctgProcessRspMsg(void* out, int32_t reqType, char* msg, int32_t msgSize, int32_t rspCode, char* target);
int32_t ctgGetDBVgInfoFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SBuildUseDBInput *input, SUseDbOutput *out, SCtgTask* pTask);
int32_t ctgGetQnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SArray *out, SCtgTask* pTask);
+int32_t ctgGetDnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SArray **out, SCtgTask* pTask);
int32_t ctgGetDBCfgFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const char *dbFName, SDbCfgInfo *out, SCtgTask* pTask);
int32_t ctgGetIndexInfoFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const char *indexName, SIndexInfo *out, SCtgTask* pTask);
int32_t ctgGetTbIndexFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SName *name, STableIndex* out, SCtgTask* pTask);
@@ -535,16 +609,22 @@ int32_t ctgGetUserDbAuthFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const
int32_t ctgGetTbMetaFromMnodeImpl(SCatalog* pCtg, SRequestConnInfo *pConn, char *dbFName, char* tbName, STableMetaOutput* out, SCtgTask* pTask);
int32_t ctgGetTbMetaFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, STableMetaOutput* out, SCtgTask* pTask);
int32_t ctgGetTbMetaFromVnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, SVgroupInfo *vgroupInfo, STableMetaOutput* out, SCtgTask* pTask);
+int32_t ctgGetTableCfgFromVnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, SVgroupInfo *vgroupInfo, STableCfg **out, SCtgTask* pTask);
+int32_t ctgGetTableCfgFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, STableCfg **out, SCtgTask* pTask);
+int32_t ctgGetSvrVerFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, char **out, SCtgTask* pTask);
-int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, uint64_t reqId, const SCatalogReq* pReq, catalogCallback fp, void* param, int32_t* taskNum);
+int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, const SCatalogReq* pReq, catalogCallback fp, void* param);
int32_t ctgLaunchJob(SCtgJob *pJob);
int32_t ctgMakeAsyncRes(SCtgJob *pJob);
+int32_t ctgLaunchSubTask(SCtgTask *pTask, CTG_TASK_TYPE type, ctgSubTaskCbFp fp, void* param);
+int32_t ctgGetTbCfgCb(SCtgTask *pTask);
+void ctgFreeHandle(SCatalog* pCatalog);
int32_t ctgCloneVgInfo(SDBVgInfo *src, SDBVgInfo **dst);
int32_t ctgCloneMetaOutput(STableMetaOutput *output, STableMetaOutput **pOutput);
int32_t ctgGenerateVgList(SCatalog *pCtg, SHashObj *vgHash, SArray** pList);
void ctgFreeJob(void* job);
-void ctgFreeHandle(SCatalog* pCtg);
+void ctgFreeHandleImpl(SCatalog* pCtg);
void ctgFreeVgInfo(SDBVgInfo *vgInfo);
int32_t ctgGetVgInfoFromHashValue(SCatalog *pCtg, SDBVgInfo *dbInfo, const SName *pTableName, SVgroupInfo *pVgroup);
void ctgResetTbMetaTask(SCtgTask* pTask);
@@ -559,6 +639,10 @@ char * ctgTaskTypeStr(CTG_TASK_TYPE type);
int32_t ctgUpdateSendTargetInfo(SMsgSendInfo *pMsgSendInfo, int32_t msgType, SCtgTask* pTask);
int32_t ctgCloneTableIndex(SArray* pIndex, SArray** pRes);
void ctgFreeSTableIndex(void *info);
+void ctgClearSubTaskRes(SCtgSubRes *pRes);
+void ctgFreeQNode(SCtgQNode *node);
+void ctgClearHandle(SCatalog* pCtg);
+void ctgFreeTbCacheImpl(SCtgTbCache *pCache);
extern SCatalogMgmt gCtgMgmt;
diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c
index ce2456d8c35fe8e851406456c7aa7ac4d6ac97d1..1b7f53ae67c41ff8f757b8ab65d8f18cec549f84 100644
--- a/source/libs/catalog/src/catalog.c
+++ b/source/libs/catalog/src/catalog.c
@@ -22,36 +22,6 @@
SCatalogMgmt gCtgMgmt = {0};
-int32_t ctgRemoveTbMetaFromCache(SCatalog* pCtg, SName* pTableName, bool syncReq) {
- int32_t code = 0;
- STableMeta* tblMeta = NULL;
- SCtgTbMetaCtx tbCtx = {0};
- tbCtx.flag = CTG_FLAG_UNKNOWN_STB;
- tbCtx.pName = pTableName;
-
- CTG_ERR_JRET(ctgReadTbMetaFromCache(pCtg, &tbCtx, &tblMeta));
-
- if (NULL == tblMeta) {
- ctgDebug("table already not in cache, db:%s, tblName:%s", pTableName->dbname, pTableName->tname);
- return TSDB_CODE_SUCCESS;
- }
-
- char dbFName[TSDB_DB_FNAME_LEN];
- tNameGetFullDbName(pTableName, dbFName);
-
- if (TSDB_SUPER_TABLE == tblMeta->tableType) {
- CTG_ERR_JRET(ctgDropStbMetaEnqueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, tblMeta->suid, syncReq));
- } else {
- CTG_ERR_JRET(ctgDropTbMetaEnqueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, syncReq));
- }
-
-_return:
-
- taosMemoryFreeClear(tblMeta);
-
- CTG_RET(code);
-}
-
int32_t ctgGetDBVgInfo(SCatalog* pCtg, SRequestConnInfo *pConn, const char* dbFName, SCtgDBCache** dbCache, SDBVgInfo **pInfo) {
int32_t code = 0;
@@ -129,7 +99,7 @@ int32_t ctgRefreshTbMeta(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgTbMetaCtx*
STableMetaOutput* output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
if (NULL == output) {
ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
if (CTG_FLAG_IS_SYS_DB(ctx->flag)) {
@@ -212,29 +182,6 @@ _return:
CTG_RET(code);
}
-int32_t ctgGetTbMetaFromCache(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta) {
- if (CTG_IS_SYS_DBNAME(ctx->pName->dbname)) {
- CTG_FLAG_SET_SYS_DB(ctx->flag);
- }
-
- CTG_ERR_RET(ctgReadTbMetaFromCache(pCtg, ctx, pTableMeta));
-
- if (*pTableMeta) {
- if (CTG_FLAG_MATCH_STB(ctx->flag, (*pTableMeta)->tableType) &&
- ((!CTG_FLAG_IS_FORCE_UPDATE(ctx->flag)) || (CTG_FLAG_IS_SYS_DB(ctx->flag)))) {
- return TSDB_CODE_SUCCESS;
- }
-
- taosMemoryFreeClear(*pTableMeta);
- }
-
- if (CTG_FLAG_IS_UNKNOWN_STB(ctx->flag)) {
- CTG_FLAG_SET_STB(ctx->flag, ctx->tbInfo.tbType);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
int32_t ctgGetTbMeta(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta) {
int32_t code = 0;
STableMetaOutput *output = NULL;
@@ -317,7 +264,7 @@ int32_t ctgUpdateTbMeta(SCatalog* pCtg, STableMetaRsp* rspMsg, bool syncOp) {
STableMetaOutput* output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
if (NULL == output) {
ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
int32_t code = 0;
@@ -381,6 +328,23 @@ _return:
return TSDB_CODE_SUCCESS;
}
+int32_t ctgGetTbType(SCatalog* pCtg, SRequestConnInfo *pConn, SName* pTableName, int32_t *tbType) {
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(pTableName, dbFName);
+ CTG_ERR_RET(ctgReadTbTypeFromCache(pCtg, dbFName, pTableName->tname, tbType));
+ if (*tbType > 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ STableMeta* pMeta = NULL;
+ CTG_ERR_RET(catalogGetTableMeta(pCtg, pConn, pTableName, &pMeta));
+
+ *tbType = pMeta->tableType;
+ taosMemoryFree(pMeta);
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t ctgGetTbIndex(SCatalog* pCtg, SRequestConnInfo *pConn, SName* pTableName, SArray** pRes) {
CTG_ERR_RET(ctgReadTbIndexFromCache(pCtg, pTableName, pRes));
if (*pRes) {
@@ -419,6 +383,20 @@ _return:
CTG_RET(code);
}
+int32_t ctgGetTbCfg(SCatalog* pCtg, SRequestConnInfo *pConn, SName* pTableName, STableCfg** pCfg) {
+ int32_t tbType = 0;
+ CTG_ERR_RET(ctgGetTbType(pCtg, pConn, pTableName, &tbType));
+
+ if (TSDB_SUPER_TABLE == tbType) {
+ CTG_ERR_RET(ctgGetTableCfgFromMnode(pCtg, pConn, pTableName, pCfg, NULL));
+ } else {
+ SVgroupInfo vgroupInfo = {0};
+ CTG_ERR_RET(catalogGetTableHashVgroup(pCtg, pConn, pTableName, &vgroupInfo));
+ CTG_ERR_RET(ctgGetTableCfgFromVnode(pCtg, pConn, pTableName, &vgroupInfo, pCfg, NULL));
+ }
+
+ CTG_RET(TSDB_CODE_SUCCESS);
+}
int32_t ctgGetTbDistVgInfo(SCatalog* pCtg, SRequestConnInfo *pConn, SName* pTableName, SArray** pVgList) {
STableMeta *tbMeta = NULL;
@@ -464,7 +442,7 @@ int32_t ctgGetTbDistVgInfo(SCatalog* pCtg, SRequestConnInfo *pConn, SName* pTabl
vgList = taosArrayInit(1, sizeof(SVgroupInfo));
if (NULL == vgList) {
ctgError("taosArrayInit %d failed", (int32_t)sizeof(SVgroupInfo));
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
if (NULL == taosArrayPush(vgList, &vgroupInfo)) {
@@ -570,9 +548,11 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) {
CTG_ERR_RET(TSDB_CODE_CTG_INVALID_INPUT);
}
+ CTG_API_ENTER();
+
if (NULL == gCtgMgmt.pCluster) {
qError("catalog cluster cache are not ready, clusterId:0x%" PRIx64, clusterId);
- CTG_ERR_RET(TSDB_CODE_CTG_NOT_READY);
+ CTG_API_LEAVE(TSDB_CODE_CTG_NOT_READY);
}
int32_t code = 0;
@@ -584,13 +564,13 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) {
if (ctg && (*ctg)) {
*catalogHandle = *ctg;
qDebug("got catalog handle from cache, clusterId:0x%" PRIx64 ", CTG:%p", clusterId, *ctg);
- return TSDB_CODE_SUCCESS;
+ CTG_API_LEAVE(TSDB_CODE_SUCCESS);
}
clusterCtg = taosMemoryCalloc(1, sizeof(SCatalog));
if (NULL == clusterCtg) {
qError("calloc %d failed", (int32_t)sizeof(SCatalog));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_API_LEAVE(TSDB_CODE_OUT_OF_MEMORY);
}
clusterCtg->clusterId = clusterId;
@@ -602,13 +582,19 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) {
false, HASH_ENTRY_LOCK);
if (NULL == clusterCtg->dbCache) {
qError("taosHashInit %d dbCache failed", CTG_DEFAULT_CACHE_DB_NUMBER);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+
+ clusterCtg->userCache = taosHashInit(gCtgMgmt.cfg.maxUserCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
+ if (NULL == clusterCtg->userCache) {
+ qError("taosHashInit %d user cache failed", gCtgMgmt.cfg.maxUserCacheNum);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
code = taosHashPut(gCtgMgmt.pCluster, &clusterId, sizeof(clusterId), &clusterCtg, POINTER_BYTES);
if (code) {
if (HASH_NODE_EXIST(code)) {
- ctgFreeHandle(clusterCtg);
+ ctgFreeHandleImpl(clusterCtg);
continue;
}
@@ -623,34 +609,15 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) {
*catalogHandle = clusterCtg;
- CTG_CACHE_STAT_INC(clusterNum, 1);
+ CTG_CACHE_STAT_INC(numOfCluster, 1);
- return TSDB_CODE_SUCCESS;
+ CTG_API_LEAVE(TSDB_CODE_SUCCESS);
_return:
- ctgFreeHandle(clusterCtg);
-
- CTG_RET(code);
-}
-
-void catalogFreeHandle(SCatalog* pCtg) {
- if (NULL == pCtg) {
- return;
- }
-
- if (taosHashRemove(gCtgMgmt.pCluster, &pCtg->clusterId, sizeof(pCtg->clusterId))) {
- ctgWarn("taosHashRemove from cluster failed, may already be freed, clusterId:0x%" PRIx64, pCtg->clusterId);
- return;
- }
-
- CTG_CACHE_STAT_DEC(clusterNum, 1);
-
- uint64_t clusterId = pCtg->clusterId;
+ ctgFreeHandleImpl(clusterCtg);
- ctgFreeHandle(pCtg);
-
- ctgInfo("handle freed, culsterId:0x%" PRIx64, clusterId);
+ CTG_API_LEAVE(code);
}
int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t* tableNum) {
@@ -1030,7 +997,7 @@ int32_t catalogGetAllMeta(SCatalog* pCtg, SRequestConnInfo *pConn, const SCatalo
pRsp->pTableMeta = taosArrayInit(tbNum, POINTER_BYTES);
if (NULL == pRsp->pTableMeta) {
ctgError("taosArrayInit %d failed", tbNum);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
for (int32_t i = 0; i < tbNum; ++i) {
@@ -1045,7 +1012,7 @@ int32_t catalogGetAllMeta(SCatalog* pCtg, SRequestConnInfo *pConn, const SCatalo
if (NULL == taosArrayPush(pRsp->pTableMeta, &pTableMeta)) {
ctgError("taosArrayPush failed, idx:%d", i);
taosMemoryFreeClear(pTableMeta);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
}
}
@@ -1073,21 +1040,16 @@ _return:
CTG_API_LEAVE(code);
}
-int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, SRequestConnInfo *pConn, uint64_t reqId, const SCatalogReq* pReq, catalogCallback fp, void* param, int64_t* jobId) {
+int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, SRequestConnInfo *pConn, const SCatalogReq* pReq, catalogCallback fp, void* param, int64_t* jobId) {
CTG_API_ENTER();
if (NULL == pCtg || NULL == pConn || NULL == pReq || NULL == fp || NULL == param) {
CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
}
- int32_t code = 0, taskNum = 0;
+ int32_t code = 0;
SCtgJob *pJob = NULL;
- CTG_ERR_JRET(ctgInitJob(pCtg, pConn, &pJob, reqId, pReq, fp, param, &taskNum));
- if (taskNum <= 0) {
- SMetaData* pMetaData = taosMemoryCalloc(1, sizeof(SMetaData));
- fp(pMetaData, param, TSDB_CODE_SUCCESS);
- CTG_API_LEAVE(TSDB_CODE_SUCCESS);
- }
+ CTG_ERR_JRET(ctgInitJob(pCtg, pConn, &pJob, pReq, fp, param));
CTG_ERR_JRET(ctgLaunchJob(pJob));
@@ -1095,6 +1057,7 @@ int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, SRequestConnInfo *pConn, uint64_t
// *jobId = pJob->refId;
_return:
+
if (pJob) {
taosReleaseRef(gCtgMgmt.jobPool, pJob->refId);
@@ -1121,8 +1084,19 @@ _return:
CTG_API_LEAVE(TSDB_CODE_SUCCESS);
}
-int32_t catalogGetDnodeList(SCatalog* pCatalog, SRequestConnInfo* pConn, SArray** pDnodeList) {
- return TSDB_CODE_CTG_INVALID_INPUT;
+int32_t catalogGetDnodeList(SCatalog* pCtg, SRequestConnInfo* pConn, SArray** pDnodeList) {
+ CTG_API_ENTER();
+
+ int32_t code = 0;
+ if (NULL == pCtg || NULL == pConn || NULL == pDnodeList) {
+ CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
+ }
+
+ CTG_ERR_JRET(ctgGetDnodeListFromMnode(pCtg, pConn, pDnodeList, NULL));
+
+_return:
+
+ CTG_API_LEAVE(TSDB_CODE_SUCCESS);
}
int32_t catalogGetExpiredSTables(SCatalog* pCtg, SSTableVersion **stables, uint32_t *num) {
@@ -1153,12 +1127,14 @@ int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion** users, uint32_
}
*num = taosHashGetSize(pCtg->userCache);
- if (*num > 0) {
- *users = taosMemoryCalloc(*num, sizeof(SUserAuthVersion));
- if (NULL == *users) {
- ctgError("calloc %d userAuthVersion failed", *num);
- CTG_API_LEAVE(TSDB_CODE_OUT_OF_MEMORY);
- }
+ if (*num <= 0) {
+ CTG_API_LEAVE(TSDB_CODE_SUCCESS);
+ }
+
+ *users = taosMemoryCalloc(*num, sizeof(SUserAuthVersion));
+ if (NULL == *users) {
+ ctgError("calloc %d userAuthVersion failed", *num);
+ CTG_API_LEAVE(TSDB_CODE_OUT_OF_MEMORY);
}
uint32_t i = 0;
@@ -1170,6 +1146,11 @@ int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion** users, uint32_
(*users)[i].user[len] = 0;
(*users)[i].version = pAuth->version;
++i;
+ if (i >= *num) {
+ taosHashCancelIterate(pCtg->userCache, pAuth);
+ break;
+ }
+
pAuth = taosHashIterate(pCtg->userCache, pAuth);
}
@@ -1211,6 +1192,23 @@ _return:
CTG_API_LEAVE(code);
}
+int32_t catalogRefreshGetTableCfg(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, STableCfg** pCfg) {
+ CTG_API_ENTER();
+
+ if (NULL == pCtg || NULL == pConn || NULL == pTableName || NULL == pCfg) {
+ CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
+ }
+
+ int32_t code = 0;
+ CTG_ERR_JRET(catalogRemoveTableMeta(pCtg, (SName*)pTableName));
+
+ CTG_ERR_JRET(ctgGetTbCfg(pCtg, pConn, (SName*)pTableName, pCfg));
+
+_return:
+
+ CTG_API_LEAVE(code);
+}
+
int32_t catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo *pConn, const char* funcName, SFuncInfo* pInfo) {
CTG_API_ENTER();
@@ -1241,6 +1239,22 @@ _return:
CTG_API_LEAVE(code);
}
+int32_t catalogGetServerVersion(SCatalog* pCtg, SRequestConnInfo *pConn, char** pVersion) {
+ CTG_API_ENTER();
+
+ if (NULL == pCtg || NULL == pConn || NULL == pVersion) {
+ CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
+ }
+
+ int32_t code = 0;
+ CTG_ERR_JRET(ctgGetSvrVerFromMnode(pCtg, pConn, pVersion, NULL));
+
+_return:
+
+ CTG_API_LEAVE(code);
+}
+
+
int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth) {
CTG_API_ENTER();
@@ -1252,19 +1266,19 @@ int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth) {
}
int32_t catalogClearCache(void) {
- CTG_API_ENTER();
+ CTG_API_ENTER_NOLOCK();
qInfo("start to clear catalog cache");
if (NULL == gCtgMgmt.pCluster || atomic_load_8((int8_t*)&gCtgMgmt.exit)) {
- CTG_API_LEAVE(TSDB_CODE_SUCCESS);
+ CTG_API_LEAVE_NOLOCK(TSDB_CODE_SUCCESS);
}
- int32_t code = ctgClearCacheEnqueue(NULL, true);
+ int32_t code = ctgClearCacheEnqueue(NULL, false, false, true);
qInfo("clear catalog cache end, code: %s", tstrerror(code));
- CTG_API_LEAVE(code);
+ CTG_API_LEAVE_NOLOCK(code);
}
@@ -1277,32 +1291,13 @@ void catalogDestroy(void) {
atomic_store_8((int8_t*)&gCtgMgmt.exit, true);
- if (tsem_post(&gCtgMgmt.queue.reqSem)) {
- qError("tsem_post failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
- }
-
- while (CTG_IS_LOCKED(&gCtgMgmt.lock)) {
- taosUsleep(1);
- }
-
- CTG_LOCK(CTG_WRITE, &gCtgMgmt.lock);
-
- SCatalog* pCtg = NULL;
- void* pIter = taosHashIterate(gCtgMgmt.pCluster, NULL);
- while (pIter) {
- pCtg = *(SCatalog**)pIter;
-
- if (pCtg) {
- catalogFreeHandle(pCtg);
- }
-
- pIter = taosHashIterate(gCtgMgmt.pCluster, pIter);
+ if (!taosCheckCurrentInDll()) {
+ ctgClearCacheEnqueue(NULL, true, true, true);
+ taosThreadJoin(gCtgMgmt.updateThread, NULL);
}
taosHashCleanup(gCtgMgmt.pCluster);
gCtgMgmt.pCluster = NULL;
- if (CTG_IS_LOCKED(&gCtgMgmt.lock) == TD_RWLATCH_WRITE_FLAG_COPY) CTG_UNLOCK(CTG_WRITE, &gCtgMgmt.lock);
-
qInfo("catalog destroyed");
}
diff --git a/source/libs/catalog/src/ctgAsync.c b/source/libs/catalog/src/ctgAsync.c
index 6adadf50455950e5d49bf0a5a9e178673c6fcf6b..e77df8f7f2a95955db3990758553c82d19de7c2b 100644
--- a/source/libs/catalog/src/ctgAsync.c
+++ b/source/libs/catalog/src/ctgAsync.c
@@ -20,7 +20,8 @@
#include "systable.h"
#include "tref.h"
-int32_t ctgInitGetTbMetaTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
+int32_t ctgInitGetTbMetaTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SName *name = (SName*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_TB_META;
@@ -44,12 +45,13 @@ int32_t ctgInitGetTbMetaTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, tbName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, tbName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetDbVgTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
+int32_t ctgInitGetDbVgTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ char *dbFName = (char*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_DB_VGROUP;
@@ -67,12 +69,13 @@ int32_t ctgInitGetDbVgTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetDbCfgTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
+int32_t ctgInitGetDbCfgTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ char *dbFName = (char*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_DB_CFG;
@@ -90,12 +93,13 @@ int32_t ctgInitGetDbCfgTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetDbInfoTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
+int32_t ctgInitGetDbInfoTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ char *dbFName = (char*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_DB_INFO;
@@ -113,13 +117,14 @@ int32_t ctgInitGetDbInfoTask(SCtgJob *pJob, int32_t taskIdx, char *dbFName) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, dbFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), dbFName);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetTbHashTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
+int32_t ctgInitGetTbHashTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SName *name = (SName*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_TB_HASH;
@@ -143,12 +148,12 @@ int32_t ctgInitGetTbHashTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, tableName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, tableName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetQnodeTask(SCtgJob *pJob, int32_t taskIdx) {
+int32_t ctgInitGetQnodeTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
SCtgTask task = {0};
task.type = CTG_TASK_GET_QNODE;
@@ -163,7 +168,23 @@ int32_t ctgInitGetQnodeTask(SCtgJob *pJob, int32_t taskIdx) {
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetIndexTask(SCtgJob *pJob, int32_t taskIdx, char *name) {
+int32_t ctgInitGetDnodeTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SCtgTask task = {0};
+
+ task.type = CTG_TASK_GET_DNODE;
+ task.taskId = taskIdx;
+ task.pJob = pJob;
+ task.taskCtx = NULL;
+
+ taosArrayPush(pJob->pTasks, &task);
+
+ qDebug("QID:0x%" PRIx64 " the %d task type %s initialized", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgInitGetIndexTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ char *name = (char*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_INDEX;
@@ -181,12 +202,13 @@ int32_t ctgInitGetIndexTask(SCtgJob *pJob, int32_t taskIdx, char *name) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, indexFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, indexFName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetUdfTask(SCtgJob *pJob, int32_t taskIdx, char *name) {
+int32_t ctgInitGetUdfTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ char *name = (char*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_UDF;
@@ -204,12 +226,13 @@ int32_t ctgInitGetUdfTask(SCtgJob *pJob, int32_t taskIdx, char *name) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, udfName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, udfName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name);
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetUserTask(SCtgJob *pJob, int32_t taskIdx, SUserAuthInfo *user) {
+int32_t ctgInitGetUserTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SUserAuthInfo *user = (SUserAuthInfo*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_USER;
@@ -227,12 +250,27 @@ int32_t ctgInitGetUserTask(SCtgJob *pJob, int32_t taskIdx, SUserAuthInfo *user)
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, user:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), user->user);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, user:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), user->user);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgInitGetSvrVerTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SCtgTask task = {0};
+
+ task.type = CTG_TASK_GET_SVR_VER;
+ task.taskId = taskIdx;
+ task.pJob = pJob;
+
+ taosArrayPush(pJob->pTasks, &task);
+
+ qDebug("QID:0x%" PRIx64 " [%dth] task type %s initialized", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type));
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitGetTbIndexTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
+int32_t ctgInitGetTbIndexTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SName *name = (SName*)param;
SCtgTask task = {0};
task.type = CTG_TASK_GET_TB_INDEX;
@@ -255,11 +293,41 @@ int32_t ctgInitGetTbIndexTask(SCtgJob *pJob, int32_t taskIdx, SName *name) {
taosArrayPush(pJob->pTasks, &task);
- qDebug("QID:0x%" PRIx64 " the %d task type %s initialized, tbName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, tbName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
return TSDB_CODE_SUCCESS;
}
+int32_t ctgInitGetTbCfgTask(SCtgJob *pJob, int32_t taskIdx, void* param) {
+ SName *name = (SName*)param;
+ SCtgTask task = {0};
+
+ task.type = CTG_TASK_GET_TB_CFG;
+ task.taskId = taskIdx;
+ task.pJob = pJob;
+
+ task.taskCtx = taosMemoryCalloc(1, sizeof(SCtgTbCfgCtx));
+ if (NULL == task.taskCtx) {
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+
+ SCtgTbCfgCtx* ctx = task.taskCtx;
+ ctx->pName = taosMemoryMalloc(sizeof(*name));
+ if (NULL == ctx->pName) {
+ taosMemoryFree(task.taskCtx);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+
+ memcpy(ctx->pName, name, sizeof(*name));
+
+ taosArrayPush(pJob->pTasks, &task);
+
+ qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, tbName:%s", pJob->queryId, taskIdx, ctgTaskTypeStr(task.type), name->tname);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob *pJob, const SCatalogReq* pReq) {
SHashObj* pDb = taosHashInit(taskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
@@ -296,6 +364,13 @@ int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob *pJob, con
taosHashPut(pDb, dbFName, strlen(dbFName), dbFName, TSDB_DB_FNAME_LEN);
}
+ for (int32_t i = 0; i < pJob->tbCfgNum; ++i) {
+ SName* name = taosArrayGet(pReq->pTableCfg, i);
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(name, dbFName);
+ taosHashPut(pDb, dbFName, strlen(dbFName), dbFName, TSDB_DB_FNAME_LEN);
+ }
+
char* dbFName = taosHashIterate(pDb, NULL);
while (dbFName) {
ctgDropDbVgroupEnqueue(pCtg, dbFName, true);
@@ -304,40 +379,32 @@ int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob *pJob, con
taosHashCleanup(pDb);
- int32_t tbNum = pJob->tbMetaNum + pJob->tbHashNum;
- if (tbNum > 0) {
- if (tbNum > pJob->tbMetaNum && tbNum > pJob->tbHashNum) {
- SHashObj* pTb = taosHashInit(tbNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
- for (int32_t i = 0; i < pJob->tbMetaNum; ++i) {
- SName* name = taosArrayGet(pReq->pTableMeta, i);
- taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName));
- }
-
- for (int32_t i = 0; i < pJob->tbHashNum; ++i) {
- SName* name = taosArrayGet(pReq->pTableHash, i);
- taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName));
- }
+ // REFRESH TABLE META
+ SHashObj* pTb = taosHashInit(taskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
+ for (int32_t i = 0; i < pJob->tbMetaNum; ++i) {
+ SName* name = taosArrayGet(pReq->pTableMeta, i);
+ taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName));
+ }
+
+ for (int32_t i = 0; i < pJob->tbHashNum; ++i) {
+ SName* name = taosArrayGet(pReq->pTableHash, i);
+ taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName));
+ }
- SName* name = taosHashIterate(pTb, NULL);
- while (name) {
- catalogRemoveTableMeta(pCtg, name);
- name = taosHashIterate(pTb, name);
- }
+ for (int32_t i = 0; i < pJob->tbCfgNum; ++i) {
+ SName* name = taosArrayGet(pReq->pTableCfg, i);
+ taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName));
+ }
- taosHashCleanup(pTb);
- } else {
- for (int32_t i = 0; i < pJob->tbMetaNum; ++i) {
- SName* name = taosArrayGet(pReq->pTableMeta, i);
- catalogRemoveTableMeta(pCtg, name);
- }
-
- for (int32_t i = 0; i < pJob->tbHashNum; ++i) {
- SName* name = taosArrayGet(pReq->pTableHash, i);
- catalogRemoveTableMeta(pCtg, name);
- }
- }
+ SName* name = taosHashIterate(pTb, NULL);
+ while (name) {
+ catalogRemoveTableMeta(pCtg, name);
+ name = taosHashIterate(pTb, name);
}
+ taosHashCleanup(pTb);
+
+
for (int32_t i = 0; i < pJob->tbIndexNum; ++i) {
SName* name = taosArrayGet(pReq->pTableIndex, i);
ctgDropTbIndexEnqueue(pCtg, name, true);
@@ -346,34 +413,47 @@ int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob *pJob, con
return TSDB_CODE_SUCCESS;
}
-int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, uint64_t reqId, const SCatalogReq* pReq, catalogCallback fp, void* param, int32_t* taskNum) {
+int32_t ctgInitTask(SCtgJob *pJob, CTG_TASK_TYPE type, void* param, int32_t *taskId) {
+ int32_t tid = atomic_fetch_add_32(&pJob->taskIdx, 1);
+
+ CTG_LOCK(CTG_WRITE, &pJob->taskLock);
+ CTG_ERR_RET((*gCtgAsyncFps[type].initFp)(pJob, tid, param));
+ CTG_UNLOCK(CTG_WRITE, &pJob->taskLock);
+
+ if (taskId) {
+ *taskId = tid;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, const SCatalogReq* pReq, catalogCallback fp, void* param) {
int32_t code = 0;
int32_t tbMetaNum = (int32_t)taosArrayGetSize(pReq->pTableMeta);
int32_t dbVgNum = (int32_t)taosArrayGetSize(pReq->pDbVgroup);
int32_t tbHashNum = (int32_t)taosArrayGetSize(pReq->pTableHash);
int32_t udfNum = (int32_t)taosArrayGetSize(pReq->pUdf);
int32_t qnodeNum = pReq->qNodeRequired ? 1 : 0;
+ int32_t dnodeNum = pReq->dNodeRequired ? 1 : 0;
+ int32_t svrVerNum = pReq->svrVerRequired ? 1 : 0;
int32_t dbCfgNum = (int32_t)taosArrayGetSize(pReq->pDbCfg);
int32_t indexNum = (int32_t)taosArrayGetSize(pReq->pIndex);
int32_t userNum = (int32_t)taosArrayGetSize(pReq->pUser);
int32_t dbInfoNum = (int32_t)taosArrayGetSize(pReq->pDbInfo);
int32_t tbIndexNum = (int32_t)taosArrayGetSize(pReq->pTableIndex);
+ int32_t tbCfgNum = (int32_t)taosArrayGetSize(pReq->pTableCfg);
- *taskNum = tbMetaNum + dbVgNum + udfNum + tbHashNum + qnodeNum + dbCfgNum + indexNum + userNum + dbInfoNum + tbIndexNum;
- if (*taskNum <= 0) {
- ctgDebug("Empty input for job, no need to retrieve meta, reqId:0x%" PRIx64, reqId);
- return TSDB_CODE_SUCCESS;
- }
+ int32_t taskNum = tbMetaNum + dbVgNum + udfNum + tbHashNum + qnodeNum + dnodeNum + svrVerNum + dbCfgNum + indexNum + userNum + dbInfoNum + tbIndexNum + tbCfgNum;
*job = taosMemoryCalloc(1, sizeof(SCtgJob));
if (NULL == *job) {
- ctgError("failed to calloc, size:%d, reqId:0x%" PRIx64, (int32_t)sizeof(SCtgJob), reqId);
+ ctgError("failed to calloc, size:%d, reqId:0x%" PRIx64, (int32_t)sizeof(SCtgJob), pConn->requestId);
CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
SCtgJob *pJob = *job;
- pJob->queryId = reqId;
+ pJob->queryId = pConn->requestId;
pJob->userFp = fp;
pJob->pCtg = pCtg;
pJob->conn = *pConn;
@@ -382,6 +462,7 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, uint6
pJob->tbMetaNum = tbMetaNum;
pJob->tbHashNum = tbHashNum;
pJob->qnodeNum = qnodeNum;
+ pJob->dnodeNum = dnodeNum;
pJob->dbVgNum = dbVgNum;
pJob->udfNum = udfNum;
pJob->dbCfgNum = dbCfgNum;
@@ -389,66 +470,80 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, uint6
pJob->userNum = userNum;
pJob->dbInfoNum = dbInfoNum;
pJob->tbIndexNum = tbIndexNum;
+ pJob->tbCfgNum = tbCfgNum;
+ pJob->svrVerNum = svrVerNum;
- pJob->pTasks = taosArrayInit(*taskNum, sizeof(SCtgTask));
+ pJob->pTasks = taosArrayInit(taskNum, sizeof(SCtgTask));
if (NULL == pJob->pTasks) {
- ctgError("taosArrayInit %d tasks failed", *taskNum);
+ ctgError("taosArrayInit %d tasks failed", taskNum);
CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
- if (pReq->forceUpdate) {
- CTG_ERR_JRET(ctgHandleForceUpdate(pCtg, *taskNum, pJob, pReq));
+ if (pReq->forceUpdate && taskNum) {
+ CTG_ERR_JRET(ctgHandleForceUpdate(pCtg, taskNum, pJob, pReq));
}
- int32_t taskIdx = 0;
for (int32_t i = 0; i < dbVgNum; ++i) {
char* dbFName = taosArrayGet(pReq->pDbVgroup, i);
- CTG_ERR_JRET(ctgInitGetDbVgTask(pJob, taskIdx++, dbFName));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_DB_VGROUP, dbFName, NULL));
}
for (int32_t i = 0; i < dbCfgNum; ++i) {
char* dbFName = taosArrayGet(pReq->pDbCfg, i);
- CTG_ERR_JRET(ctgInitGetDbCfgTask(pJob, taskIdx++, dbFName));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_DB_CFG, dbFName, NULL));
}
for (int32_t i = 0; i < dbInfoNum; ++i) {
char* dbFName = taosArrayGet(pReq->pDbInfo, i);
- CTG_ERR_JRET(ctgInitGetDbInfoTask(pJob, taskIdx++, dbFName));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_DB_INFO, dbFName, NULL));
}
for (int32_t i = 0; i < tbMetaNum; ++i) {
SName* name = taosArrayGet(pReq->pTableMeta, i);
- CTG_ERR_JRET(ctgInitGetTbMetaTask(pJob, taskIdx++, name));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_META, name, NULL));
}
for (int32_t i = 0; i < tbHashNum; ++i) {
SName* name = taosArrayGet(pReq->pTableHash, i);
- CTG_ERR_JRET(ctgInitGetTbHashTask(pJob, taskIdx++, name));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_HASH, name, NULL));
}
for (int32_t i = 0; i < tbIndexNum; ++i) {
SName* name = taosArrayGet(pReq->pTableIndex, i);
- CTG_ERR_JRET(ctgInitGetTbIndexTask(pJob, taskIdx++, name));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_INDEX, name, NULL));
+ }
+
+ for (int32_t i = 0; i < tbCfgNum; ++i) {
+ SName* name = taosArrayGet(pReq->pTableCfg, i);
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_CFG, name, NULL));
}
for (int32_t i = 0; i < indexNum; ++i) {
char* indexName = taosArrayGet(pReq->pIndex, i);
- CTG_ERR_JRET(ctgInitGetIndexTask(pJob, taskIdx++, indexName));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_INDEX, indexName, NULL));
}
for (int32_t i = 0; i < udfNum; ++i) {
char* udfName = taosArrayGet(pReq->pUdf, i);
- CTG_ERR_JRET(ctgInitGetUdfTask(pJob, taskIdx++, udfName));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_UDF, udfName, NULL));
}
for (int32_t i = 0; i < userNum; ++i) {
SUserAuthInfo* user = taosArrayGet(pReq->pUser, i);
- CTG_ERR_JRET(ctgInitGetUserTask(pJob, taskIdx++, user));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_USER, user, NULL));
}
if (qnodeNum) {
- CTG_ERR_JRET(ctgInitGetQnodeTask(pJob, taskIdx++));
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_QNODE, NULL, NULL));
+ }
+
+ if (dnodeNum) {
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_DNODE, NULL, NULL));
+ }
+
+ if (svrVerNum) {
+ CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_SVR_VER, NULL, NULL));
}
pJob->refId = taosAddRef(gCtgMgmt.jobPool, pJob);
@@ -459,11 +554,12 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgJob** job, uint6
taosAcquireRef(gCtgMgmt.jobPool, pJob->refId);
- qDebug("QID:0x%" PRIx64 ", jobId: 0x%" PRIx64 " initialized, task num %d, forceUpdate %d", pJob->queryId, pJob->refId, *taskNum, pReq->forceUpdate);
+ qDebug("QID:0x%" PRIx64 ", jobId: 0x%" PRIx64 " initialized, task num %d, forceUpdate %d", pJob->queryId, pJob->refId, taskNum, pReq->forceUpdate);
return TSDB_CODE_SUCCESS;
_return:
+
taosMemoryFreeClear(*job);
CTG_RET(code);
}
@@ -528,6 +624,21 @@ int32_t ctgDumpTbIndexRes(SCtgTask* pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgDumpTbCfgRes(SCtgTask* pTask) {
+ SCtgJob* pJob = pTask->pJob;
+ if (NULL == pJob->jobRes.pTableCfg) {
+ pJob->jobRes.pTableCfg = taosArrayInit(pJob->tbCfgNum, sizeof(SMetaRes));
+ if (NULL == pJob->jobRes.pTableCfg) {
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+ }
+
+ SMetaRes res = {.code = pTask->code, .pRes = pTask->res};
+ taosArrayPush(pJob->jobRes.pTableCfg, &res);
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t ctgDumpIndexRes(SCtgTask* pTask) {
SCtgJob* pJob = pTask->pJob;
if (NULL == pJob->jobRes.pIndex) {
@@ -558,6 +669,22 @@ int32_t ctgDumpQnodeRes(SCtgTask* pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgDumpDnodeRes(SCtgTask* pTask) {
+ SCtgJob* pJob = pTask->pJob;
+ if (NULL == pJob->jobRes.pDnodeList) {
+ pJob->jobRes.pDnodeList = taosArrayInit(1, sizeof(SMetaRes));
+ if (NULL == pJob->jobRes.pDnodeList) {
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+ }
+
+ SMetaRes res = {.code = pTask->code, .pRes = pTask->res};
+ taosArrayPush(pJob->jobRes.pDnodeList, &res);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
int32_t ctgDumpDbCfgRes(SCtgTask* pTask) {
SCtgJob* pJob = pTask->pJob;
if (NULL == pJob->jobRes.pDbCfg) {
@@ -618,13 +745,76 @@ int32_t ctgDumpUserRes(SCtgTask* pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgDumpSvrVer(SCtgTask* pTask) {
+ SCtgJob* pJob = pTask->pJob;
+ if (NULL == pJob->jobRes.pSvrVer) {
+ pJob->jobRes.pSvrVer = taosMemoryCalloc(1, sizeof(SMetaRes));
+ if (NULL == pJob->jobRes.pSvrVer) {
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
+ }
+ }
+
+ pJob->jobRes.pSvrVer->code = pTask->code;
+ pJob->jobRes.pSvrVer->pRes = pTask->res;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgCallSubCb(SCtgTask *pTask) {
+ int32_t code = 0;
+
+ CTG_LOCK(CTG_WRITE, &pTask->lock);
+
+ int32_t parentNum = taosArrayGetSize(pTask->pParents);
+ for (int32_t i = 0; i < parentNum; ++i) {
+ SCtgTask* pParent = taosArrayGetP(pTask->pParents, i);
+
+ pParent->subRes.code = pTask->code;
+ if (TSDB_CODE_SUCCESS == pTask->code) {
+ code = (*gCtgAsyncFps[pTask->type].cloneFp)(pTask, &pParent->subRes.res);
+ if (code) {
+ pParent->subRes.code = code;
+ }
+ }
+
+ CTG_ERR_JRET(pParent->subRes.fp(pParent));
+ }
+
+_return:
+
+ CTG_UNLOCK(CTG_WRITE, &pTask->lock);
+
+ CTG_RET(code);
+}
+
+int32_t ctgCallUserCb(void* param) {
+ SCtgJob* pJob = (SCtgJob*)param;
+
+ qDebug("QID:0x%" PRIx64 " ctg start to call user cb with rsp %s", pJob->queryId, tstrerror(pJob->jobResCode));
+
+ (*pJob->userFp)(&pJob->jobRes, pJob->userParam, pJob->jobResCode);
+
+ qDebug("QID:0x%" PRIx64 " ctg end to call user cb", pJob->queryId);
+
+ taosRemoveRef(gCtgMgmt.jobPool, pJob->refId);
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t ctgHandleTaskEnd(SCtgTask* pTask, int32_t rspCode) {
SCtgJob* pJob = pTask->pJob;
int32_t code = 0;
+ if (CTG_TASK_DONE == pTask->status) {
+ return TSDB_CODE_SUCCESS;
+ }
+
qDebug("QID:0x%" PRIx64 " task %d end with res %s", pJob->queryId, pTask->taskId, tstrerror(rspCode));
pTask->code = rspCode;
+ pTask->status = CTG_TASK_DONE;
+
+ ctgCallSubCb(pTask);
int32_t taskDone = atomic_add_fetch_32(&pJob->taskDone, 1);
if (taskDone < taosArrayGetSize(pJob->pTasks)) {
@@ -636,11 +826,12 @@ int32_t ctgHandleTaskEnd(SCtgTask* pTask, int32_t rspCode) {
_return:
- qDebug("QID:0x%" PRIx64 " user callback with rsp %s", pJob->queryId, tstrerror(code));
-
- (*pJob->userFp)(&pJob->jobRes, pJob->userParam, code);
+ pJob->jobResCode = code;
- taosRemoveRef(gCtgMgmt.jobPool, pJob->refId);
+ //taosSsleep(2);
+ //qDebug("QID:0x%" PRIx64 " ctg after sleep", pJob->queryId);
+
+ taosAsyncExec(ctgCallUserCb, pJob, NULL);
CTG_RET(code);
}
@@ -802,11 +993,12 @@ int32_t ctgHandleGetDbVgRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pM
switch (reqType) {
case TDMT_MND_USE_DB: {
SUseDbOutput* pOut = (SUseDbOutput*)pTask->msgCtx.out;
-
- CTG_ERR_JRET(ctgGenerateVgList(pCtg, pOut->dbVgroup->vgHash, (SArray**)&pTask->res));
+ SDBVgInfo* pDb = NULL;
- CTG_ERR_JRET(ctgUpdateVgroupEnqueue(pCtg, ctx->dbFName, pOut->dbId, pOut->dbVgroup, false));
- pOut->dbVgroup = NULL;
+ CTG_ERR_JRET(ctgGenerateVgList(pCtg, pOut->dbVgroup->vgHash, (SArray**)&pTask->res));
+
+ CTG_ERR_JRET(cloneDbVgInfo(pOut->dbVgroup, &pDb));
+ CTG_ERR_JRET(ctgUpdateVgroupEnqueue(pCtg, ctx->dbFName, pOut->dbId, pDb, false));
break;
}
@@ -874,6 +1066,7 @@ int32_t ctgHandleGetTbIndexRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf
CTG_ERR_JRET(ctgUpdateTbIndexEnqueue(pTask->pJob->pCtg, (STableIndex**)&pTask->msgCtx.out, false));
_return:
+
if (TSDB_CODE_MND_DB_INDEX_NOT_EXIST == code) {
code = TSDB_CODE_SUCCESS;
}
@@ -882,6 +1075,18 @@ _return:
CTG_RET(code);
}
+int32_t ctgHandleGetTbCfgRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pMsg, int32_t rspCode) {
+ int32_t code = 0;
+ CTG_ERR_JRET(ctgProcessRspMsg(&pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target));
+
+ TSWAP(pTask->res, pTask->msgCtx.out);
+
+_return:
+
+ ctgHandleTaskEnd(pTask, code);
+
+ CTG_RET(code);
+}
int32_t ctgHandleGetDbCfgRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pMsg, int32_t rspCode) {
int32_t code = 0;
@@ -914,6 +1119,19 @@ _return:
CTG_RET(code);
}
+int32_t ctgHandleGetDnodeRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pMsg, int32_t rspCode) {
+ int32_t code = 0;
+ CTG_ERR_JRET(ctgProcessRspMsg(&pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target));
+
+ TSWAP(pTask->res, pTask->msgCtx.out);
+
+_return:
+
+ ctgHandleTaskEnd(pTask, code);
+
+ CTG_RET(code);
+}
+
int32_t ctgHandleGetIndexRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pMsg, int32_t rspCode) {
int32_t code = 0;
CTG_ERR_JRET(ctgProcessRspMsg(pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target));
@@ -984,6 +1202,20 @@ _return:
CTG_RET(code);
}
+int32_t ctgHandleGetSvrVerRsp(SCtgTask* pTask, int32_t reqType, const SDataBuf *pMsg, int32_t rspCode) {
+ int32_t code = 0;
+
+ CTG_ERR_JRET(ctgProcessRspMsg(&pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target));
+
+ TSWAP(pTask->res, pTask->msgCtx.out);
+
+_return:
+
+ ctgHandleTaskEnd(pTask, code);
+
+ CTG_RET(code);
+}
+
int32_t ctgAsyncRefreshTbMeta(SCtgTask *pTask) {
SCatalog* pCtg = pTask->pJob->pCtg;
SRequestConnInfo* pConn = &pTask->pJob->conn;
@@ -1138,6 +1370,48 @@ int32_t ctgLaunchGetTbIndexTask(SCtgTask *pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgLaunchGetTbCfgTask(SCtgTask *pTask) {
+ int32_t code = 0;
+ SCatalog* pCtg = pTask->pJob->pCtg;
+ SRequestConnInfo* pConn = &pTask->pJob->conn;
+ SCtgTbCfgCtx* pCtx = (SCtgTbCfgCtx*)pTask->taskCtx;
+ SArray* pRes = NULL;
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(pCtx->pName, dbFName);
+
+ if (pCtx->tbType <= 0) {
+ CTG_ERR_JRET(ctgReadTbTypeFromCache(pCtg, dbFName, pCtx->pName->tname, &pCtx->tbType));
+ if (pCtx->tbType <= 0) {
+ CTG_ERR_JRET(ctgLaunchSubTask(pTask, CTG_TASK_GET_TB_META, ctgGetTbCfgCb, pCtx->pName));
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+
+ if (TSDB_SUPER_TABLE == pCtx->tbType) {
+ CTG_ERR_JRET(ctgGetTableCfgFromMnode(pCtg, pConn, pCtx->pName, NULL, pTask));
+ } else {
+ if (NULL == pCtx->pVgInfo) {
+ CTG_ERR_JRET(ctgGetTbHashVgroupFromCache(pCtg, pCtx->pName, &pCtx->pVgInfo));
+ if (NULL == pCtx->pVgInfo) {
+ CTG_ERR_JRET(ctgLaunchSubTask(pTask, CTG_TASK_GET_DB_VGROUP, ctgGetTbCfgCb, dbFName));
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+
+ CTG_ERR_JRET(ctgGetTableCfgFromVnode(pCtg, pConn, pCtx->pName, pCtx->pVgInfo, NULL, pTask));
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ if (CTG_TASK_LAUNCHED == pTask->status) {
+ ctgHandleTaskEnd(pTask, code);
+ }
+
+ CTG_RET(code);
+}
+
int32_t ctgLaunchGetQnodeTask(SCtgTask *pTask) {
SCatalog* pCtg = pTask->pJob->pCtg;
@@ -1147,6 +1421,15 @@ int32_t ctgLaunchGetQnodeTask(SCtgTask *pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgLaunchGetDnodeTask(SCtgTask *pTask) {
+ SCatalog* pCtg = pTask->pJob->pCtg;
+ SRequestConnInfo* pConn = &pTask->pJob->conn;
+
+ CTG_ERR_RET(ctgGetDnodeListFromMnode(pCtg, pConn, NULL, pTask));
+ return TSDB_CODE_SUCCESS;
+}
+
+
int32_t ctgLaunchGetDbCfgTask(SCtgTask *pTask) {
SCatalog* pCtg = pTask->pJob->pCtg;
SRequestConnInfo* pConn = &pTask->pJob->conn;
@@ -1236,6 +1519,15 @@ int32_t ctgLaunchGetUserTask(SCtgTask *pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgLaunchGetSvrVerTask(SCtgTask *pTask) {
+ SCatalog* pCtg = pTask->pJob->pCtg;
+ SRequestConnInfo* pConn = &pTask->pJob->conn;
+
+ CTG_ERR_RET(ctgGetSvrVerFromMnode(pCtg, pConn, NULL, pTask));
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t ctgRelaunchGetTbMetaTask(SCtgTask *pTask) {
ctgResetTbMetaTask(pTask);
@@ -1244,17 +1536,72 @@ int32_t ctgRelaunchGetTbMetaTask(SCtgTask *pTask) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgGetTbCfgCb(SCtgTask *pTask) {
+ int32_t code = 0;
+
+ CTG_ERR_JRET(pTask->subRes.code);
+
+ SCtgTbCfgCtx* pCtx = (SCtgTbCfgCtx*)pTask->taskCtx;
+ if (CTG_TASK_GET_TB_META == pTask->subRes.type) {
+ pCtx->tbType = ((STableMeta*)pTask->subRes.res)->tableType;
+ } else if (CTG_TASK_GET_DB_VGROUP == pTask->subRes.type) {
+ SDBVgInfo* pDb = (SDBVgInfo*)pTask->subRes.res;
+
+ pCtx->pVgInfo = taosMemoryCalloc(1, sizeof(SVgroupInfo));
+ CTG_ERR_JRET(ctgGetVgInfoFromHashValue(pTask->pJob->pCtg, pDb, pCtx->pName, pCtx->pVgInfo));
+ }
+
+ CTG_RET(ctgLaunchGetTbCfgTask(pTask));
+
+_return:
+
+ CTG_RET(ctgHandleTaskEnd(pTask, pTask->subRes.code));
+}
+
+int32_t ctgCompDbVgTasks(SCtgTask* pTask, void* param, bool* equal) {
+ SCtgDbVgCtx* ctx = pTask->taskCtx;
+
+ *equal = (0 == strcmp(ctx->dbFName, param));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t ctgCompTbMetaTasks(SCtgTask* pTask, void* param, bool* equal) {
+ SCtgTbMetaCtx* ctx = pTask->taskCtx;
+
+ *equal = tNameTbNameEqual(ctx->pName, (SName*)param);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgCloneTbMeta(SCtgTask* pTask, void** pRes) {
+ STableMeta* pMeta = (STableMeta*)pTask->res;
+
+ CTG_RET(cloneTableMeta(pMeta, (STableMeta**)pRes));
+}
+
+int32_t ctgCloneDbVg(SCtgTask* pTask, void** pRes) {
+ SUseDbOutput* pOut = (SUseDbOutput*)pTask->msgCtx.out;
+
+ CTG_RET(cloneDbVgInfo(pOut->dbVgroup, (SDBVgInfo**)pRes));
+}
+
+
SCtgAsyncFps gCtgAsyncFps[] = {
- {ctgLaunchGetQnodeTask, ctgHandleGetQnodeRsp, ctgDumpQnodeRes},
- {ctgLaunchGetDbVgTask, ctgHandleGetDbVgRsp, ctgDumpDbVgRes},
- {ctgLaunchGetDbCfgTask, ctgHandleGetDbCfgRsp, ctgDumpDbCfgRes},
- {ctgLaunchGetDbInfoTask, ctgHandleGetDbInfoRsp, ctgDumpDbInfoRes},
- {ctgLaunchGetTbMetaTask, ctgHandleGetTbMetaRsp, ctgDumpTbMetaRes},
- {ctgLaunchGetTbHashTask, ctgHandleGetTbHashRsp, ctgDumpTbHashRes},
- {ctgLaunchGetTbIndexTask, ctgHandleGetTbIndexRsp, ctgDumpTbIndexRes},
- {ctgLaunchGetIndexTask, ctgHandleGetIndexRsp, ctgDumpIndexRes},
- {ctgLaunchGetUdfTask, ctgHandleGetUdfRsp, ctgDumpUdfRes},
- {ctgLaunchGetUserTask, ctgHandleGetUserRsp, ctgDumpUserRes},
+ {ctgInitGetQnodeTask, ctgLaunchGetQnodeTask, ctgHandleGetQnodeRsp, ctgDumpQnodeRes, NULL, NULL},
+ {ctgInitGetDnodeTask, ctgLaunchGetDnodeTask, ctgHandleGetDnodeRsp, ctgDumpDnodeRes, NULL, NULL},
+ {ctgInitGetDbVgTask, ctgLaunchGetDbVgTask, ctgHandleGetDbVgRsp, ctgDumpDbVgRes, ctgCompDbVgTasks, ctgCloneDbVg},
+ {ctgInitGetDbCfgTask, ctgLaunchGetDbCfgTask, ctgHandleGetDbCfgRsp, ctgDumpDbCfgRes, NULL, NULL},
+ {ctgInitGetDbInfoTask, ctgLaunchGetDbInfoTask, ctgHandleGetDbInfoRsp, ctgDumpDbInfoRes, NULL, NULL},
+ {ctgInitGetTbMetaTask, ctgLaunchGetTbMetaTask, ctgHandleGetTbMetaRsp, ctgDumpTbMetaRes, ctgCompTbMetaTasks, ctgCloneTbMeta},
+ {ctgInitGetTbHashTask, ctgLaunchGetTbHashTask, ctgHandleGetTbHashRsp, ctgDumpTbHashRes, NULL, NULL},
+ {ctgInitGetTbIndexTask, ctgLaunchGetTbIndexTask, ctgHandleGetTbIndexRsp, ctgDumpTbIndexRes, NULL, NULL},
+ {ctgInitGetTbCfgTask, ctgLaunchGetTbCfgTask, ctgHandleGetTbCfgRsp, ctgDumpTbCfgRes, NULL, NULL},
+ {ctgInitGetIndexTask, ctgLaunchGetIndexTask, ctgHandleGetIndexRsp, ctgDumpIndexRes, NULL, NULL},
+ {ctgInitGetUdfTask, ctgLaunchGetUdfTask, ctgHandleGetUdfRsp, ctgDumpUdfRes, NULL, NULL},
+ {ctgInitGetUserTask, ctgLaunchGetUserTask, ctgHandleGetUserRsp, ctgDumpUserRes, NULL, NULL},
+ {ctgInitGetSvrVerTask, ctgLaunchGetSvrVerTask, ctgHandleGetSvrVerRsp, ctgDumpSvrVer, NULL, NULL},
};
int32_t ctgMakeAsyncRes(SCtgJob *pJob) {
@@ -1269,6 +1616,86 @@ int32_t ctgMakeAsyncRes(SCtgJob *pJob) {
return TSDB_CODE_SUCCESS;
}
+int32_t ctgSearchExistingTask(SCtgJob *pJob, CTG_TASK_TYPE type, void* param, int32_t* taskId) {
+ bool equal = false;
+ SCtgTask* pTask = NULL;
+ int32_t code = 0;
+
+ CTG_LOCK(CTG_READ, &pJob->taskLock);
+
+ int32_t taskNum = taosArrayGetSize(pJob->pTasks);
+ for (int32_t i = 0; i < taskNum; ++i) {
+ pTask = taosArrayGet(pJob->pTasks, i);
+ if (type != pTask->type) {
+ continue;
+ }
+
+ CTG_ERR_JRET((*gCtgAsyncFps[type].compFp)(pTask, param, &equal));
+ if (equal) {
+ break;
+ }
+ }
+
+_return:
+
+ CTG_UNLOCK(CTG_READ, &pJob->taskLock);
+ if (equal) {
+ *taskId = pTask->taskId;
+ }
+
+ CTG_RET(code);
+}
+
+int32_t ctgSetSubTaskCb(SCtgTask *pSub, SCtgTask *pTask) {
+ int32_t code = 0;
+
+ CTG_LOCK(CTG_WRITE, &pSub->lock);
+ if (CTG_TASK_DONE == pSub->status) {
+ pTask->subRes.code = pSub->code;
+ CTG_ERR_JRET((*gCtgAsyncFps[pTask->type].cloneFp)(pSub, &pTask->subRes.res));
+ CTG_ERR_JRET(pTask->subRes.fp(pTask));
+ } else {
+ if (NULL == pSub->pParents) {
+ pSub->pParents = taosArrayInit(4, POINTER_BYTES);
+ }
+
+ taosArrayPush(pSub->pParents, &pTask);
+ }
+
+_return:
+
+ CTG_UNLOCK(CTG_WRITE, &pSub->lock);
+
+ CTG_RET(code);
+}
+
+
+int32_t ctgLaunchSubTask(SCtgTask *pTask, CTG_TASK_TYPE type, ctgSubTaskCbFp fp, void* param) {
+ SCtgJob* pJob = pTask->pJob;
+ int32_t subTaskId = -1;
+ bool newTask = false;
+
+ ctgClearSubTaskRes(&pTask->subRes);
+ pTask->subRes.type = type;
+ pTask->subRes.fp = fp;
+
+ CTG_ERR_RET(ctgSearchExistingTask(pJob, type, param, &subTaskId));
+ if (subTaskId < 0) {
+ CTG_ERR_RET(ctgInitTask(pJob, type, param, &subTaskId));
+ newTask = true;
+ }
+
+ SCtgTask* pSub = taosArrayGet(pJob->pTasks, subTaskId);
+
+ CTG_ERR_RET(ctgSetSubTaskCb(pSub, pTask));
+
+ if (newTask) {
+ CTG_ERR_RET((*gCtgAsyncFps[pSub->type].launchFp)(pSub));
+ pSub->status = CTG_TASK_LAUNCHED;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
int32_t ctgLaunchJob(SCtgJob *pJob) {
int32_t taskNum = taosArrayGetSize(pJob->pTasks);
@@ -1276,8 +1703,15 @@ int32_t ctgLaunchJob(SCtgJob *pJob) {
for (int32_t i = 0; i < taskNum; ++i) {
SCtgTask *pTask = taosArrayGet(pJob->pTasks, i);
- qDebug("QID:0x%" PRIx64 " ctg start to launch task %d", pJob->queryId, pTask->taskId);
+ qDebug("QID:0x%" PRIx64 " ctg launch [%dth] task", pJob->queryId, pTask->taskId);
CTG_ERR_RET((*gCtgAsyncFps[pTask->type].launchFp)(pTask));
+ pTask->status = CTG_TASK_LAUNCHED;
+ }
+
+ if (taskNum <= 0) {
+ qDebug("QID:0x%" PRIx64 " ctg call user callback with rsp %s", pJob->queryId, tstrerror(pJob->jobResCode));
+
+ taosAsyncExec(ctgCallUserCb, pJob, NULL);
}
return TSDB_CODE_SUCCESS;
diff --git a/source/libs/catalog/src/ctgCache.c b/source/libs/catalog/src/ctgCache.c
index 1de5ee3d7d9ea6c3ce24b6890e12cfc0cb9c75d8..499ce7727676381ad28ea0fb672d768e88ac7907 100644
--- a/source/libs/catalog/src/ctgCache.c
+++ b/source/libs/catalog/src/ctgCache.c
@@ -214,7 +214,7 @@ int32_t ctgAcquireVgInfoFromCache(SCatalog* pCtg, const char *dbFName, SCtgDBCac
*pCache = dbCache;
- CTG_CACHE_STAT_INC(vgHitNum, 1);
+ CTG_CACHE_STAT_INC(numOfVgHit, 1);
ctgDebug("Got db vgInfo from cache, dbFName:%s", dbFName);
@@ -228,7 +228,7 @@ _return:
*pCache = NULL;
- CTG_CACHE_STAT_INC(vgMissNum, 1);
+ CTG_CACHE_STAT_INC(numOfVgMiss, 1);
return TSDB_CODE_SUCCESS;
}
@@ -260,7 +260,7 @@ int32_t ctgAcquireTbMetaFromCache(SCatalog* pCtg, char *dbFName, char* tbName, S
ctgDebug("tb %s meta got in cache, dbFName:%s", tbName, dbFName);
- CTG_CACHE_STAT_INC(tbMetaHitNum, 1);
+ CTG_CACHE_STAT_INC(numOfMetaHit, 1);
return TSDB_CODE_SUCCESS;
@@ -268,7 +268,7 @@ _return:
ctgReleaseTbMetaToCache(pCtg, dbCache, pCache);
- CTG_CACHE_STAT_INC(tbMetaMissNum, 1);
+ CTG_CACHE_STAT_INC(numOfMetaMiss, 1);
return TSDB_CODE_SUCCESS;
}
@@ -307,7 +307,7 @@ int32_t ctgAcquireStbMetaFromCache(SCatalog* pCtg, char *dbFName, uint64_t suid,
ctgDebug("stb 0x%" PRIx64 " meta got in cache, dbFName:%s", suid, dbFName);
- CTG_CACHE_STAT_INC(tbMetaHitNum, 1);
+ CTG_CACHE_STAT_INC(numOfMetaHit, 1);
return TSDB_CODE_SUCCESS;
@@ -315,7 +315,7 @@ _return:
ctgReleaseTbMetaToCache(pCtg, dbCache, pCache);
- CTG_CACHE_STAT_INC(tbMetaMissNum, 1);
+ CTG_CACHE_STAT_INC(numOfMetaMiss, 1);
*pDb = NULL;
*pTb = NULL;
@@ -326,6 +326,7 @@ _return:
int32_t ctgAcquireTbIndexFromCache(SCatalog* pCtg, char *dbFName, char* tbName, SCtgDBCache **pDb, SCtgTbCache** pTb) {
SCtgDBCache *dbCache = NULL;
+ SCtgTbCache* pCache = NULL;
ctgAcquireDBCache(pCtg, dbFName, &dbCache);
if (NULL == dbCache) {
ctgDebug("db %s not in cache", dbFName);
@@ -333,7 +334,7 @@ int32_t ctgAcquireTbIndexFromCache(SCatalog* pCtg, char *dbFName, char* tbName,
}
int32_t sz = 0;
- SCtgTbCache* pCache = taosHashAcquire(dbCache->tbCache, tbName, strlen(tbName));
+ pCache = taosHashAcquire(dbCache->tbCache, tbName, strlen(tbName));
if (NULL == pCache) {
ctgDebug("tb %s not in cache, dbFName:%s", tbName, dbFName);
goto _return;
@@ -350,7 +351,7 @@ int32_t ctgAcquireTbIndexFromCache(SCatalog* pCtg, char *dbFName, char* tbName,
ctgDebug("tb %s index got in cache, dbFName:%s", tbName, dbFName);
- CTG_CACHE_STAT_INC(tbIndexHitNum, 1);
+ CTG_CACHE_STAT_INC(numOfIndexHit, 1);
return TSDB_CODE_SUCCESS;
@@ -358,7 +359,7 @@ _return:
ctgReleaseTbIndexToCache(pCtg, dbCache, pCache);
- CTG_CACHE_STAT_INC(tbIndexMissNum, 1);
+ CTG_CACHE_STAT_INC(numOfIndexMiss, 1);
return TSDB_CODE_SUCCESS;
}
@@ -454,7 +455,7 @@ int32_t ctgReadTbMetaFromCache(SCatalog* pCtg, SCtgTbMetaCtx* ctx, STableMeta**
*pTableMeta = taosMemoryRealloc(*pTableMeta, metaSize);
if (NULL == *pTableMeta) {
ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
memcpy(&(*pTableMeta)->sversion, &stbMeta->sversion, metaSize - sizeof(SCTableMeta));
@@ -540,10 +541,10 @@ int32_t ctgReadTbVerFromCache(SCatalog *pCtg, SName *pTableName, int32_t *sver,
}
-int32_t ctgReadTbTypeFromCache(SCatalog* pCtg, char* dbFName, char *tableName, int32_t *tbType) {
+int32_t ctgReadTbTypeFromCache(SCatalog* pCtg, char* dbFName, char *tbName, int32_t *tbType) {
SCtgDBCache *dbCache = NULL;
SCtgTbCache *tbCache = NULL;
- CTG_ERR_RET(ctgAcquireTbMetaFromCache(pCtg, dbFName, tableName, &dbCache, &tbCache));
+ CTG_ERR_RET(ctgAcquireTbMetaFromCache(pCtg, dbFName, tbName, &dbCache, &tbCache));
if (NULL == tbCache) {
ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache);
return TSDB_CODE_SUCCESS;
@@ -552,7 +553,7 @@ int32_t ctgReadTbTypeFromCache(SCatalog* pCtg, char* dbFName, char *tableName, i
*tbType = tbCache->pMeta->tableType;
ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache);
- ctgDebug("Got tb %s tbType %d from cache, dbFName:%s", tableName, *tbType, dbFName);
+ ctgDebug("Got tb %s tbType %d from cache, dbFName:%s", tbName, *tbType, dbFName);
return TSDB_CODE_SUCCESS;
}
@@ -582,11 +583,6 @@ _return:
}
int32_t ctgChkAuthFromCache(SCatalog* pCtg, char* user, char* dbFName, AUTH_TYPE type, bool *inCache, bool *pass) {
- if (NULL == pCtg->userCache) {
- ctgDebug("empty user auth cache, user:%s", user);
- goto _return;
- }
-
SCtgUserAuth *pUser = (SCtgUserAuth *)taosHashGet(pCtg->userCache, user, strlen(user));
if (NULL == pUser) {
ctgDebug("user not in cache, user:%s", user);
@@ -596,7 +592,7 @@ int32_t ctgChkAuthFromCache(SCatalog* pCtg, char* user, char* dbFName, AUTH_TYPE
*inCache = true;
ctgDebug("Got user from cache, user:%s", user);
- CTG_CACHE_STAT_INC(userHitNum, 1);
+ CTG_CACHE_STAT_INC(numOfUserHit, 1);
if (pUser->superUser) {
*pass = true;
@@ -625,7 +621,7 @@ int32_t ctgChkAuthFromCache(SCatalog* pCtg, char* user, char* dbFName, AUTH_TYPE
_return:
*inCache = false;
- CTG_CACHE_STAT_INC(userMissNum, 1);
+ CTG_CACHE_STAT_INC(numOfUserMiss, 1);
return TSDB_CODE_SUCCESS;
}
@@ -648,9 +644,11 @@ int32_t ctgEnqueue(SCatalog* pCtg, SCtgCacheOperation *operation) {
SCtgQNode *node = taosMemoryCalloc(1, sizeof(SCtgQNode));
if (NULL == node) {
qError("calloc %d failed", (int32_t)sizeof(SCtgQNode));
- CTG_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_RET(TSDB_CODE_OUT_OF_MEMORY);
}
+ bool syncOp = operation->syncOp;
+ char* opName = gCtgCacheOperation[operation->opId].name;
if (operation->syncOp) {
tsem_init(&operation->rspSem, 0, 0);
}
@@ -658,18 +656,24 @@ int32_t ctgEnqueue(SCatalog* pCtg, SCtgCacheOperation *operation) {
node->op = operation;
CTG_LOCK(CTG_WRITE, &gCtgMgmt.queue.qlock);
+ if (gCtgMgmt.queue.stopQueue) {
+ ctgFreeQNode(node);
+ CTG_UNLOCK(CTG_WRITE, &gCtgMgmt.queue.qlock);
+ CTG_RET(TSDB_CODE_CTG_EXIT);
+ }
+ gCtgMgmt.queue.stopQueue = operation->stopQueue;
gCtgMgmt.queue.tail->next = node;
gCtgMgmt.queue.tail = node;
CTG_UNLOCK(CTG_WRITE, &gCtgMgmt.queue.qlock);
+ ctgDebug("action [%s] added into queue", opName);
+
CTG_QUEUE_INC();
- CTG_RT_STAT_INC(qNum, 1);
+ CTG_RT_STAT_INC(numOfOpEnqueue, 1);
tsem_post(&gCtgMgmt.queue.reqSem);
- ctgDebug("action [%s] added into queue", gCtgCacheOperation[operation->opId].name);
-
- if (operation->syncOp) {
+ if (syncOp) {
tsem_wait(&operation->rspSem);
taosMemoryFree(operation);
}
@@ -686,7 +690,7 @@ int32_t ctgDropDbCacheEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId)
SCtgDropDBMsg *msg = taosMemoryMalloc(sizeof(SCtgDropDBMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgDropDBMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
char *p = strchr(dbFName, '.');
@@ -719,7 +723,7 @@ int32_t ctgDropDbVgroupEnqueue(SCatalog* pCtg, const char *dbFName, bool syncOp)
SCtgDropDbVgroupMsg *msg = taosMemoryMalloc(sizeof(SCtgDropDbVgroupMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgDropDbVgroupMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
char *p = strchr(dbFName, '.');
@@ -753,7 +757,7 @@ int32_t ctgDropStbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId,
SCtgDropStbMetaMsg *msg = taosMemoryMalloc(sizeof(SCtgDropStbMetaMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgDropStbMetaMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -785,7 +789,7 @@ int32_t ctgDropTbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId,
SCtgDropTblMetaMsg *msg = taosMemoryMalloc(sizeof(SCtgDropTblMetaMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgDropTblMetaMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -815,7 +819,7 @@ int32_t ctgUpdateVgroupEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateVgMsg));
ctgFreeVgInfo(dbInfo);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
char *p = strchr(dbFName, '.');
@@ -838,6 +842,7 @@ _return:
ctgFreeVgInfo(dbInfo);
taosMemoryFreeClear(op->data);
+ taosMemoryFreeClear(op);
CTG_RET(code);
}
@@ -850,7 +855,7 @@ int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput *output, bool sy
SCtgUpdateTbMetaMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateTbMetaMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateTbMetaMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
char *p = strchr(output->dbFName, '.');
@@ -869,6 +874,11 @@ int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput *output, bool sy
_return:
+ if (output) {
+ taosMemoryFree(output->tbMeta);
+ taosMemoryFree(output);
+ }
+
taosMemoryFreeClear(msg);
CTG_RET(code);
@@ -882,7 +892,7 @@ int32_t ctgUpdateVgEpsetEnqueue(SCatalog* pCtg, char *dbFName, int32_t vgId, SEp
SCtgUpdateEpsetMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateEpsetMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateEpsetMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -914,7 +924,7 @@ int32_t ctgUpdateUserEnqueue(SCatalog* pCtg, SGetUserAuthRsp *pAuth, bool syncOp
SCtgUpdateUserMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateUserMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateUserMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -943,7 +953,7 @@ int32_t ctgUpdateTbIndexEnqueue(SCatalog* pCtg, STableIndex **pIndex, bool syncO
SCtgUpdateTbIndexMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateTbIndexMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateTbIndexMsg));
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -974,7 +984,7 @@ int32_t ctgDropTbIndexEnqueue(SCatalog* pCtg, SName* pName, bool syncOp) {
SCtgDropTbIndexMsg *msg = taosMemoryMalloc(sizeof(SCtgDropTbIndexMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgDropTbIndexMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
@@ -995,19 +1005,21 @@ _return:
}
-int32_t ctgClearCacheEnqueue(SCatalog* pCtg, bool syncOp) {
+int32_t ctgClearCacheEnqueue(SCatalog* pCtg, bool freeCtg, bool stopQueue, bool syncOp) {
int32_t code = 0;
SCtgCacheOperation *op = taosMemoryCalloc(1, sizeof(SCtgCacheOperation));
op->opId = CTG_OP_CLEAR_CACHE;
op->syncOp = syncOp;
+ op->stopQueue = stopQueue;
SCtgClearCacheMsg *msg = taosMemoryMalloc(sizeof(SCtgClearCacheMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgClearCacheMsg));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
msg->pCtg = pCtg;
+ msg->freeCtg = freeCtg;
op->data = msg;
CTG_ERR_JRET(ctgEnqueue(pCtg, op));
@@ -1032,7 +1044,7 @@ int32_t ctgMetaRentInit(SCtgRentMgmt *mgmt, uint32_t rentSec, int8_t type) {
mgmt->slots = taosMemoryCalloc(1, msgSize);
if (NULL == mgmt->slots) {
qError("calloc %d failed", (int32_t)msgSize);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
qDebug("meta rent initialized, type:%d, slotNum:%d", type, mgmt->slotNum);
@@ -1052,13 +1064,13 @@ int32_t ctgMetaRentAdd(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t size)
slot->meta = taosArrayInit(CTG_DEFAULT_RENT_SLOT_SIZE, size);
if (NULL == slot->meta) {
qError("taosArrayInit %d failed, id:0x%"PRIx64", slot idx:%d, type:%d", CTG_DEFAULT_RENT_SLOT_SIZE, id, widx, mgmt->type);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
}
if (NULL == taosArrayPush(slot->meta, meta)) {
qError("taosArrayPush meta to rent failed, id:0x%"PRIx64", slot idx:%d, type:%d", id, widx, mgmt->type);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
slot->needSort = true;
@@ -1079,7 +1091,7 @@ int32_t ctgMetaRentUpdate(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t si
CTG_LOCK(CTG_WRITE, &slot->lock);
if (NULL == slot->meta) {
- qError("empty meta slot, id:0x%"PRIx64", slot idx:%d, type:%d", id, widx, mgmt->type);
+ qDebug("empty meta slot, id:0x%"PRIx64", slot idx:%d, type:%d", id, widx, mgmt->type);
CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
}
@@ -1176,7 +1188,7 @@ int32_t ctgMetaRentGetImpl(SCtgRentMgmt *mgmt, void **res, uint32_t *num, int32_
*res = taosMemoryMalloc(msize);
if (NULL == *res) {
qError("malloc %d failed", (int32_t)msize);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
void *meta = taosArrayGet(slot->meta, 0);
@@ -1226,13 +1238,13 @@ int32_t ctgAddNewDBCache(SCatalog *pCtg, const char *dbFName, uint64_t dbId) {
newDBCache.tbCache = taosHashInit(gCtgMgmt.cfg.maxTblCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
if (NULL == newDBCache.tbCache) {
ctgError("taosHashInit %d metaCache failed", gCtgMgmt.cfg.maxTblCacheNum);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
newDBCache.stbCache = taosHashInit(gCtgMgmt.cfg.maxTblCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), true, HASH_ENTRY_LOCK);
if (NULL == newDBCache.stbCache) {
ctgError("taosHashInit %d stbCache failed", gCtgMgmt.cfg.maxTblCacheNum);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
code = taosHashPut(pCtg->dbCache, dbFName, strlen(dbFName), &newDBCache, sizeof(SCtgDBCache));
@@ -1243,10 +1255,10 @@ int32_t ctgAddNewDBCache(SCatalog *pCtg, const char *dbFName, uint64_t dbId) {
}
ctgError("taosHashPut db to cache failed, dbFName:%s", dbFName);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
- CTG_CACHE_STAT_INC(dbNum, 1);
+ CTG_CACHE_STAT_INC(numOfDb, 1);
SDbVgVersion vgVersion = {.dbId = newDBCache.dbId, .vgVersion = -1};
strncpy(vgVersion.dbFName, dbFName, sizeof(vgVersion.dbFName));
@@ -1307,7 +1319,7 @@ int32_t ctgRemoveDBFromCache(SCatalog* pCtg, SCtgDBCache *dbCache, const char* d
CTG_ERR_RET(TSDB_CODE_CTG_DB_DROPPED);
}
- CTG_CACHE_STAT_DEC(dbNum, 1);
+ CTG_CACHE_STAT_DEC(numOfDb, 1);
ctgInfo("db removed from cache, dbFName:%s, dbId:0x%"PRIx64, dbFName, dbId);
return TSDB_CODE_SUCCESS;
@@ -1394,7 +1406,7 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam
if (orig) {
origType = orig->tableType;
- if (origType == meta->tableType && orig->uid == meta->uid && orig->sversion >= meta->sversion && orig->tversion >= meta->tversion) {
+ if (origType == meta->tableType && orig->uid == meta->uid && (origType == TSDB_CHILD_TABLE || (orig->sversion >= meta->sversion && orig->tversion >= meta->tversion))) {
taosMemoryFree(meta);
ctgDebug("ignore table %s meta update", tbName);
return TSDB_CODE_SUCCESS;
@@ -1404,7 +1416,7 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam
if (taosHashRemove(dbCache->stbCache, &orig->suid, sizeof(orig->suid))) {
ctgError("stb not exist in stbCache, dbFName:%s, stb:%s, suid:0x%"PRIx64, dbFName, tbName, orig->suid);
} else {
- CTG_CACHE_STAT_DEC(stblNum, 1);
+ CTG_CACHE_STAT_DEC(numOfStb, 1);
ctgDebug("stb removed from stbCache, dbFName:%s, stb:%s, suid:0x%"PRIx64, dbFName, tbName, orig->suid);
}
@@ -1418,7 +1430,7 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam
if (taosHashPut(dbCache->tbCache, tbName, strlen(tbName), &cache, sizeof(SCtgTbCache)) != 0) {
taosMemoryFree(meta);
ctgError("taosHashPut new tbCache failed, dbFName:%s, tbName:%s, tbType:%d", dbFName, tbName, meta->tableType);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
pCache = taosHashGet(dbCache->tbCache, tbName, strlen(tbName));
@@ -1428,7 +1440,7 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam
}
if (NULL == orig) {
- CTG_CACHE_STAT_INC(tblNum, 1);
+ CTG_CACHE_STAT_INC(numOfTbl, 1);
}
ctgDebug("tbmeta updated to cache, dbFName:%s, tbName:%s, tbType:%d", dbFName, tbName, meta->tableType);
@@ -1440,10 +1452,10 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam
if (origSuid != meta->suid && taosHashPut(dbCache->stbCache, &meta->suid, sizeof(meta->suid), tbName, strlen(tbName) + 1) != 0) {
ctgError("taosHashPut to stable cache failed, suid:0x%"PRIx64, meta->suid);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
- CTG_CACHE_STAT_INC(stblNum, 1);
+ CTG_CACHE_STAT_INC(numOfStb, 1);
ctgDebug("stb 0x%" PRIx64 " updated to cache, dbFName:%s, tbName:%s, tbType:%d", meta->suid, dbFName, tbName, meta->tableType);
@@ -1471,7 +1483,7 @@ int32_t ctgWriteTbIndexToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char* dbFNa
ctgFreeSTableIndex(*index);
taosMemoryFreeClear(*index);
ctgError("taosHashPut new tbCache failed, tbName:%s", tbName);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
*index = NULL;
@@ -1519,6 +1531,39 @@ _return:
CTG_RET(code);
}
+void ctgClearAllInstance(void) {
+ SCatalog* pCtg = NULL;
+
+ void* pIter = taosHashIterate(gCtgMgmt.pCluster, NULL);
+ while (pIter) {
+ pCtg = *(SCatalog**)pIter;
+
+ if (pCtg) {
+ ctgClearHandle(pCtg);
+ }
+
+ pIter = taosHashIterate(gCtgMgmt.pCluster, pIter);
+ }
+}
+
+void ctgFreeAllInstance(void) {
+ SCatalog* pCtg = NULL;
+
+ void* pIter = taosHashIterate(gCtgMgmt.pCluster, NULL);
+ while (pIter) {
+ pCtg = *(SCatalog**)pIter;
+
+ if (pCtg) {
+ ctgFreeHandle(pCtg);
+ }
+
+ pIter = taosHashIterate(gCtgMgmt.pCluster, pIter);
+ }
+
+ taosHashClear(gCtgMgmt.pCluster);
+}
+
+
int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) {
int32_t code = 0;
SCtgUpdateVgMsg *msg = operation->data;
@@ -1527,27 +1572,27 @@ int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) {
SCatalog* pCtg = msg->pCtg;
if (NULL == dbInfo->vgHash) {
- return TSDB_CODE_SUCCESS;
+ goto _return;
}
if (dbInfo->vgVersion < 0 || taosHashGetSize(dbInfo->vgHash) <= 0) {
ctgError("invalid db vgInfo, dbFName:%s, vgHash:%p, vgVersion:%d, vgHashSize:%d",
dbFName, dbInfo->vgHash, dbInfo->vgVersion, taosHashGetSize(dbInfo->vgHash));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_APP_ERROR);
}
bool newAdded = false;
SDbVgVersion vgVersion = {.dbId = msg->dbId, .vgVersion = dbInfo->vgVersion, .numOfTable = dbInfo->numOfTable};
SCtgDBCache *dbCache = NULL;
- CTG_ERR_RET(ctgGetAddDBCache(msg->pCtg, dbFName, msg->dbId, &dbCache));
+ CTG_ERR_JRET(ctgGetAddDBCache(msg->pCtg, dbFName, msg->dbId, &dbCache));
if (NULL == dbCache) {
ctgInfo("conflict db update, ignore this update, dbFName:%s, dbId:0x%"PRIx64, dbFName, msg->dbId);
- CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
}
SCtgVgCache *vgCache = &dbCache->vgCache;
- CTG_ERR_RET(ctgWLockVgInfo(msg->pCtg, dbCache));
+ CTG_ERR_JRET(ctgWLockVgInfo(msg->pCtg, dbCache));
if (vgCache->vgInfo) {
SDBVgInfo *vgInfo = vgCache->vgInfo;
@@ -1556,14 +1601,14 @@ int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) {
ctgDebug("db vgVer is old, dbFName:%s, vgVer:%d, curVer:%d", dbFName, dbInfo->vgVersion, vgInfo->vgVersion);
ctgWUnlockVgInfo(dbCache);
- return TSDB_CODE_SUCCESS;
+ goto _return;
}
if (dbInfo->vgVersion == vgInfo->vgVersion && dbInfo->numOfTable == vgInfo->numOfTable) {
ctgDebug("no new db vgVer or numOfTable, dbFName:%s, vgVer:%d, numOfTable:%d", dbFName, dbInfo->vgVersion, dbInfo->numOfTable);
ctgWUnlockVgInfo(dbCache);
- return TSDB_CODE_SUCCESS;
+ goto _return;
}
ctgFreeVgInfo(vgInfo);
@@ -1713,13 +1758,23 @@ int32_t ctgOpDropStbMeta(SCtgCacheOperation *operation) {
if (taosHashRemove(dbCache->stbCache, &msg->suid, sizeof(msg->suid))) {
ctgDebug("stb not exist in stbCache, may be removed, dbFName:%s, stb:%s, suid:0x%"PRIx64, msg->dbFName, msg->stbName, msg->suid);
} else {
- CTG_CACHE_STAT_DEC(stblNum, 1);
+ CTG_CACHE_STAT_DEC(numOfStb, 1);
+ }
+
+ SCtgTbCache* pTbCache = taosHashGet(dbCache->tbCache, msg->stbName, strlen(msg->stbName));
+ if (NULL == pTbCache) {
+ ctgDebug("stb %s already not in cache", msg->stbName);
+ goto _return;
}
+ CTG_LOCK(CTG_WRITE, &pTbCache->metaLock);
+ ctgFreeTbCacheImpl(pTbCache);
+ CTG_UNLOCK(CTG_WRITE, &pTbCache->metaLock);
+
if (taosHashRemove(dbCache->tbCache, msg->stbName, strlen(msg->stbName))) {
ctgError("stb not exist in cache, dbFName:%s, stb:%s, suid:0x%"PRIx64, msg->dbFName, msg->stbName, msg->suid);
} else {
- CTG_CACHE_STAT_DEC(tblNum, 1);
+ CTG_CACHE_STAT_DEC(numOfTbl, 1);
}
ctgInfo("stb removed from cache, dbFName:%s, stbName:%s, suid:0x%"PRIx64, msg->dbFName, msg->stbName, msg->suid);
@@ -1743,19 +1798,29 @@ int32_t ctgOpDropTbMeta(SCtgCacheOperation *operation) {
SCtgDBCache *dbCache = NULL;
ctgGetDBCache(pCtg, msg->dbFName, &dbCache);
if (NULL == dbCache) {
- return TSDB_CODE_SUCCESS;
+ goto _return;
}
if (dbCache->dbId != msg->dbId) {
ctgDebug("dbId 0x%" PRIx64 " not match with curId 0x%"PRIx64", dbFName:%s, tbName:%s", msg->dbId, dbCache->dbId, msg->dbFName, msg->tbName);
- return TSDB_CODE_SUCCESS;
+ goto _return;
}
+ SCtgTbCache* pTbCache = taosHashGet(dbCache->tbCache, msg->tbName, strlen(msg->tbName));
+ if (NULL == pTbCache) {
+ ctgDebug("tb %s already not in cache", msg->tbName);
+ goto _return;
+ }
+
+ CTG_LOCK(CTG_WRITE, &pTbCache->metaLock);
+ ctgFreeTbCacheImpl(pTbCache);
+ CTG_UNLOCK(CTG_WRITE, &pTbCache->metaLock);
+
if (taosHashRemove(dbCache->tbCache, msg->tbName, strlen(msg->tbName))) {
ctgError("tb %s not exist in cache, dbFName:%s", msg->tbName, msg->dbFName);
CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
} else {
- CTG_CACHE_STAT_DEC(tblNum, 1);
+ CTG_CACHE_STAT_DEC(numOfTbl, 1);
}
ctgDebug("table %s removed from cache, dbFName:%s", msg->tbName, msg->dbFName);
@@ -1771,14 +1836,6 @@ int32_t ctgOpUpdateUser(SCtgCacheOperation *operation) {
int32_t code = 0;
SCtgUpdateUserMsg *msg = operation->data;
SCatalog* pCtg = msg->pCtg;
-
- if (NULL == pCtg->userCache) {
- pCtg->userCache = taosHashInit(gCtgMgmt.cfg.maxUserCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
- if (NULL == pCtg->userCache) {
- ctgError("taosHashInit %d user cache failed", gCtgMgmt.cfg.maxUserCacheNum);
- CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
- }
- }
SCtgUserAuth *pUser = (SCtgUserAuth *)taosHashGet(pCtg->userCache, msg->userAuth.user, strlen(msg->userAuth.user));
if (NULL == pUser) {
@@ -1936,49 +1993,59 @@ int32_t ctgOpClearCache(SCtgCacheOperation *operation) {
SCtgClearCacheMsg *msg = operation->data;
SCatalog* pCtg = msg->pCtg;
+ CTG_LOCK(CTG_WRITE, &gCtgMgmt.lock);
+
if (pCtg) {
- catalogFreeHandle(pCtg);
+ if (msg->freeCtg) {
+ ctgFreeHandle(pCtg);
+ } else {
+ ctgClearHandle(pCtg);
+ }
+
goto _return;
}
-
- void* pIter = taosHashIterate(gCtgMgmt.pCluster, NULL);
- while (pIter) {
- pCtg = *(SCatalog**)pIter;
-
- if (pCtg) {
- catalogFreeHandle(pCtg);
- }
- pIter = taosHashIterate(gCtgMgmt.pCluster, pIter);
+ if (msg->freeCtg) {
+ ctgFreeAllInstance();
+ } else {
+ ctgClearAllInstance();
}
- taosHashClear(gCtgMgmt.pCluster);
-
_return:
+
+ CTG_UNLOCK(CTG_WRITE, &gCtgMgmt.lock);
taosMemoryFreeClear(msg);
CTG_RET(code);
}
-
-void ctgUpdateThreadUnexpectedStopped(void) {
- if (!atomic_load_8((int8_t*)&gCtgMgmt.exit) && CTG_IS_LOCKED(&gCtgMgmt.lock) > 0) CTG_UNLOCK(CTG_READ, &gCtgMgmt.lock);
-}
-
void ctgCleanupCacheQueue(void) {
SCtgQNode *node = NULL;
SCtgQNode *nodeNext = NULL;
+ SCtgCacheOperation *op = NULL;
+ bool stopQueue = false;
while (true) {
node = gCtgMgmt.queue.head->next;
while (node) {
if (node->op) {
- taosMemoryFree(node->op->data);
- if (node->op->syncOp) {
- tsem_post(&node->op->rspSem);
+ op = node->op;
+ if (op->stopQueue) {
+ SCatalog *pCtg = ((SCtgUpdateMsgHeader *)op->data)->pCtg;
+ ctgDebug("process [%s] operation", gCtgCacheOperation[op->opId].name);
+ (*gCtgCacheOperation[op->opId].func)(op);
+ stopQueue = true;
+ CTG_RT_STAT_INC(numOfOpDequeue, 1);
} else {
- taosMemoryFree(node->op);
+ taosMemoryFree(op->data);
+ CTG_RT_STAT_INC(numOfOpAbort, 1);
+ }
+
+ if (op->syncOp) {
+ tsem_post(&op->rspSem);
+ } else {
+ taosMemoryFree(op);
}
}
@@ -1988,7 +2055,7 @@ void ctgCleanupCacheQueue(void) {
node = nodeNext;
}
- if (CTG_IS_LOCKED(&gCtgMgmt.lock)) {
+ if (!stopQueue) {
taosUsleep(1);
} else {
break;
@@ -2001,22 +2068,15 @@ void ctgCleanupCacheQueue(void) {
void* ctgUpdateThreadFunc(void* param) {
setThreadName("catalog");
-#ifdef WINDOWS
- if (taosCheckCurrentInDll()) {
- atexit(ctgUpdateThreadUnexpectedStopped);
- }
-#endif
+
qInfo("catalog update thread started");
- CTG_LOCK(CTG_READ, &gCtgMgmt.lock);
-
while (true) {
if (tsem_wait(&gCtgMgmt.queue.reqSem)) {
qError("ctg tsem_wait failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
}
if (atomic_load_8((int8_t*)&gCtgMgmt.exit)) {
- CTG_UNLOCK(CTG_READ, &gCtgMgmt.lock);
ctgCleanupCacheQueue();
break;
}
@@ -2031,9 +2091,11 @@ void* ctgUpdateThreadFunc(void* param) {
if (operation->syncOp) {
tsem_post(&operation->rspSem);
+ } else {
+ taosMemoryFreeClear(operation);
}
- CTG_RT_STAT_INC(qDoneNum, 1);
+ CTG_RT_STAT_INC(numOfOpDequeue, 1);
ctgdShowCacheInfo();
ctgdShowClusterCache(pCtg);
@@ -2060,4 +2122,92 @@ int32_t ctgStartUpdateThread() {
}
+int32_t ctgGetTbMetaFromCache(SCatalog* pCtg, SRequestConnInfo *pConn, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta) {
+ if (CTG_IS_SYS_DBNAME(ctx->pName->dbname)) {
+ CTG_FLAG_SET_SYS_DB(ctx->flag);
+ }
+
+ CTG_ERR_RET(ctgReadTbMetaFromCache(pCtg, ctx, pTableMeta));
+
+ if (*pTableMeta) {
+ if (CTG_FLAG_MATCH_STB(ctx->flag, (*pTableMeta)->tableType) &&
+ ((!CTG_FLAG_IS_FORCE_UPDATE(ctx->flag)) || (CTG_FLAG_IS_SYS_DB(ctx->flag)))) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ taosMemoryFreeClear(*pTableMeta);
+ }
+
+ if (CTG_FLAG_IS_UNKNOWN_STB(ctx->flag)) {
+ CTG_FLAG_SET_STB(ctx->flag, ctx->tbInfo.tbType);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t ctgRemoveTbMetaFromCache(SCatalog* pCtg, SName* pTableName, bool syncReq) {
+ int32_t code = 0;
+ STableMeta* tblMeta = NULL;
+ SCtgTbMetaCtx tbCtx = {0};
+ tbCtx.flag = CTG_FLAG_UNKNOWN_STB;
+ tbCtx.pName = pTableName;
+
+ CTG_ERR_JRET(ctgReadTbMetaFromCache(pCtg, &tbCtx, &tblMeta));
+
+ if (NULL == tblMeta) {
+ ctgDebug("table already not in cache, db:%s, tblName:%s", pTableName->dbname, pTableName->tname);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(pTableName, dbFName);
+
+ if (TSDB_SUPER_TABLE == tblMeta->tableType) {
+ CTG_ERR_JRET(ctgDropStbMetaEnqueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, tblMeta->suid, syncReq));
+ } else {
+ CTG_ERR_JRET(ctgDropTbMetaEnqueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, syncReq));
+ }
+
+_return:
+
+ taosMemoryFreeClear(tblMeta);
+
+ CTG_RET(code);
+}
+
+int32_t ctgGetTbHashVgroupFromCache(SCatalog *pCtg, const SName *pTableName, SVgroupInfo **pVgroup) {
+ if (CTG_IS_SYS_DBNAME(pTableName->dbname)) {
+ ctgError("no valid vgInfo for db, dbname:%s", pTableName->dbname);
+ CTG_ERR_RET(TSDB_CODE_CTG_INVALID_INPUT);
+ }
+
+ SCtgDBCache* dbCache = NULL;
+ int32_t code = 0;
+ char dbFName[TSDB_DB_FNAME_LEN] = {0};
+ tNameGetFullDbName(pTableName, dbFName);
+
+ CTG_ERR_RET(ctgAcquireVgInfoFromCache(pCtg, dbFName, &dbCache));
+
+ if (NULL == dbCache) {
+ *pVgroup = NULL;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ *pVgroup = taosMemoryCalloc(1, sizeof(SVgroupInfo));
+ CTG_ERR_JRET(ctgGetVgInfoFromHashValue(pCtg, dbCache->vgCache.vgInfo, pTableName, *pVgroup));
+
+_return:
+
+ if (dbCache) {
+ ctgReleaseVgInfoToCache(pCtg, dbCache);
+ }
+
+ if (code) {
+ taosMemoryFreeClear(*pVgroup);
+ }
+
+ CTG_RET(code);
+}
+
diff --git a/source/libs/catalog/src/ctgDbg.c b/source/libs/catalog/src/ctgDbg.c
index 7f2b919f175adfa79a5bc3916813c8b6619e1b3f..bd3402dc394186b03d116c2c2ebe5e83838bdddb 100644
--- a/source/libs/catalog/src/ctgDbg.c
+++ b/source/libs/catalog/src/ctgDbg.c
@@ -19,7 +19,7 @@
#include "catalogInt.h"
extern SCatalogMgmt gCtgMgmt;
-SCtgDebug gCTGDebug = {.cacheEnable = true};
+SCtgDebug gCTGDebug = {0};
void ctgdUserCallback(SMetaData* pResult, void* param, int32_t code) {
ASSERT(*(int32_t*)param == 1);
@@ -64,7 +64,7 @@ void ctgdUserCallback(SMetaData* pResult, void* param, int32_t code) {
qDebug("db %d vgInfo:", i);
for (int32_t j = 0; j < vgNum; ++j) {
SVgroupInfo* pInfo = taosArrayGet(pDb, j);
- qDebug("vg %d info: vgId:%d", j, pInfo->vgId);
+ qDebug("vg :%d info: vgId:%d", j, pInfo->vgId);
}
}
} else {
@@ -210,7 +210,7 @@ int32_t ctgdLaunchAsyncCall(SCatalog* pCtg, SRequestConnInfo* pConn, uint64_t re
int64_t jobId = 0;
- CTG_ERR_JRET(catalogAsyncGetAllMeta(pCtg, pConn, reqId, &req, ctgdUserCallback, param, &jobId));
+ CTG_ERR_JRET(catalogAsyncGetAllMeta(pCtg, pConn, &req, ctgdUserCallback, param, &jobId));
_return:
@@ -255,8 +255,8 @@ int32_t ctgdEnableDebug(char *option) {
}
int32_t ctgdGetStatNum(char *option, void *res) {
- if (0 == strcasecmp(option, "runtime.qDoneNum")) {
- *(uint64_t *)res = atomic_load_64(&gCtgMgmt.stat.runtime.qDoneNum);
+ if (0 == strcasecmp(option, "runtime.numOfOpDequeue")) {
+ *(uint64_t *)res = atomic_load_64(&gCtgMgmt.stat.runtime.numOfOpDequeue);
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/catalog/src/ctgRemote.c b/source/libs/catalog/src/ctgRemote.c
index fa1a26283286d01cc4574c4babbb28ad5fb36996..8e0a5b7de3753baaf08d4628032f40dcf51c711e 100644
--- a/source/libs/catalog/src/ctgRemote.c
+++ b/source/libs/catalog/src/ctgRemote.c
@@ -40,6 +40,21 @@ int32_t ctgProcessRspMsg(void* out, int32_t reqType, char* msg, int32_t msgSize,
qDebug("Got qnode list from mnode, listNum:%d", (int32_t)taosArrayGetSize(out));
break;
}
+ case TDMT_MND_DNODE_LIST: {
+ if (TSDB_CODE_SUCCESS != rspCode) {
+ qError("error rsp for dnode list, error:%s", tstrerror(rspCode));
+ CTG_ERR_RET(rspCode);
+ }
+
+ code = queryProcessMsgRsp[TMSG_INDEX(reqType)](out, msg, msgSize);
+ if (code) {
+ qError("Process dnode list rsp failed, error:%s", tstrerror(rspCode));
+ CTG_ERR_RET(code);
+ }
+
+ qDebug("Got dnode list from mnode, listNum:%d", (int32_t)taosArrayGetSize(*(SArray**)out));
+ break;
+ }
case TDMT_MND_USE_DB: {
if (TSDB_CODE_SUCCESS != rspCode) {
qError("error rsp for use db, error:%s, dbFName:%s", tstrerror(rspCode), target);
@@ -172,13 +187,61 @@ int32_t ctgProcessRspMsg(void* out, int32_t reqType, char* msg, int32_t msgSize,
qDebug("Got table meta from vnode, tbFName:%s", target);
break;
}
+ case TDMT_VND_TABLE_CFG: {
+ if (TSDB_CODE_SUCCESS != rspCode) {
+ qError("error rsp for table cfg from vnode, code:%s, tbFName:%s", tstrerror(rspCode), target);
+ CTG_ERR_RET(rspCode);
+ }
+
+ code = queryProcessMsgRsp[TMSG_INDEX(reqType)](out, msg, msgSize);
+ if (code) {
+ qError("Process vnode tb cfg rsp failed, code:%s, tbFName:%s", tstrerror(code), target);
+ CTG_ERR_RET(code);
+ }
+
+ qDebug("Got table cfg from vnode, tbFName:%s", target);
+ break;
+ }
+ case TDMT_MND_TABLE_CFG: {
+ if (TSDB_CODE_SUCCESS != rspCode) {
+ qError("error rsp for stb cfg from mnode, error:%s, tbFName:%s", tstrerror(rspCode), target);
+ CTG_ERR_RET(rspCode);
+ }
+
+ code = queryProcessMsgRsp[TMSG_INDEX(reqType)](out, msg, msgSize);
+ if (code) {
+ qError("Process mnode stb cfg rsp failed, error:%s, tbFName:%s", tstrerror(code), target);
+ CTG_ERR_RET(code);
+ }
+
+ qDebug("Got stb cfg from mnode, tbFName:%s", target);
+ break;
+ }
+ case TDMT_MND_SERVER_VERSION: {
+ if (TSDB_CODE_SUCCESS != rspCode) {
+ qError("error rsp for svr ver from mnode, error:%s", tstrerror(rspCode));
+ CTG_ERR_RET(rspCode);
+ }
+
+ code = queryProcessMsgRsp[TMSG_INDEX(reqType)](out, msg, msgSize);
+ if (code) {
+ qError("Process svr ver rsp failed, error:%s", tstrerror(code));
+ CTG_ERR_RET(code);
+ }
+
+ qDebug("Got svr ver from mnode");
+ break;
+ }
+ default:
+ qError("invalid req type %s", TMSG_INFO(reqType));
+ return TSDB_CODE_APP_ERROR;
}
return TSDB_CODE_SUCCESS;
}
-int32_t ctgHandleMsgCallback(void *param, const SDataBuf *pMsg, int32_t rspCode) {
+int32_t ctgHandleMsgCallback(void *param, SDataBuf *pMsg, int32_t rspCode) {
SCtgTaskCallbackParam* cbParam = (SCtgTaskCallbackParam*)param;
int32_t code = 0;
@@ -198,6 +261,8 @@ int32_t ctgHandleMsgCallback(void *param, const SDataBuf *pMsg, int32_t rspCode)
_return:
+ taosMemoryFree(pMsg->pData);
+
if (pJob) {
taosReleaseRef(gCtgMgmt.jobPool, cbParam->refId);
}
@@ -276,9 +341,6 @@ _return:
CTG_RET(code);
}
-
-
-
int32_t ctgGetQnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SArray *out, SCtgTask* pTask) {
char *msg = NULL;
int32_t msgLen = 0;
@@ -316,6 +378,39 @@ int32_t ctgGetQnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SArray
return TSDB_CODE_SUCCESS;
}
+int32_t ctgGetDnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SArray **out, SCtgTask* pTask) {
+ char *msg = NULL;
+ int32_t msgLen = 0;
+ int32_t reqType = TDMT_MND_DNODE_LIST;
+ void*(*mallocFp)(int32_t) = pTask ? taosMemoryMalloc : rpcMallocCont;
+
+ ctgDebug("try to get dnode list from mnode, mgmtEpInUse:%d", pConn->mgmtEps.inUse);
+
+ int32_t code = queryBuildMsg[TMSG_INDEX(reqType)](NULL, &msg, 0, &msgLen, mallocFp);
+ if (code) {
+ ctgError("Build dnode list msg failed, error:%s", tstrerror(code));
+ CTG_ERR_RET(code);
+ }
+
+ if (pTask) {
+ CTG_ERR_RET(ctgUpdateMsgCtx(&pTask->msgCtx, reqType, NULL, NULL));
+ CTG_RET(ctgAsyncSendMsg(pCtg, pConn, pTask, reqType, msg, msgLen));
+ }
+
+ SRpcMsg rpcMsg = {
+ .msgType = reqType,
+ .pCont = msg,
+ .contLen = msgLen,
+ };
+
+ SRpcMsg rpcRsp = {0};
+ rpcSendRecv(pConn->pTrans, &pConn->mgmtEps, &rpcMsg, &rpcRsp);
+
+ CTG_ERR_RET(ctgProcessRspMsg(out, reqType, rpcRsp.pCont, rpcRsp.contLen, rpcRsp.code, NULL));
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t ctgGetDBVgInfoFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, SBuildUseDBInput *input, SUseDbOutput *out, SCtgTask* pTask) {
char *msg = NULL;
@@ -550,7 +645,7 @@ int32_t ctgGetUserDbAuthFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const
int32_t ctgGetTbMetaFromMnodeImpl(SCatalog* pCtg, SRequestConnInfo *pConn, char *dbFName, char* tbName, STableMetaOutput* out, SCtgTask* pTask) {
- SBuildTableMetaInput bInput = {.vgId = 0, .dbFName = dbFName, .tbName = tbName};
+ SBuildTableInput bInput = {.vgId = 0, .dbFName = dbFName, .tbName = tbName};
char *msg = NULL;
SEpSet *pVnodeEpSet = NULL;
int32_t msgLen = 0;
@@ -606,9 +701,11 @@ int32_t ctgGetTbMetaFromVnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SNa
sprintf(tbFName, "%s.%s", dbFName, pTableName->tname);
void*(*mallocFp)(int32_t) = pTask ? taosMemoryMalloc : rpcMallocCont;
- ctgDebug("try to get table meta from vnode, vgId:%d, tbFName:%s", vgroupInfo->vgId, tbFName);
+ SEp* pEp = &vgroupInfo->epSet.eps[vgroupInfo->epSet.inUse];
+ ctgDebug("try to get table meta from vnode, vgId:%d, ep num:%d, ep %s:%d, tbFName:%s",
+ vgroupInfo->vgId, vgroupInfo->epSet.numOfEps, pEp->fqdn, pEp->port, tbFName);
- SBuildTableMetaInput bInput = {.vgId = vgroupInfo->vgId, .dbFName = dbFName, .tbName = (char *)tNameGetTableName(pTableName)};
+ SBuildTableInput bInput = {.vgId = vgroupInfo->vgId, .dbFName = dbFName, .tbName = (char *)tNameGetTableName(pTableName)};
char *msg = NULL;
int32_t msgLen = 0;
@@ -646,4 +743,123 @@ int32_t ctgGetTbMetaFromVnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SNa
return TSDB_CODE_SUCCESS;
}
+int32_t ctgGetTableCfgFromVnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, SVgroupInfo *vgroupInfo, STableCfg **out, SCtgTask* pTask) {
+ char *msg = NULL;
+ int32_t msgLen = 0;
+ int32_t reqType = TDMT_VND_TABLE_CFG;
+ char tbFName[TSDB_TABLE_FNAME_LEN];
+ tNameExtractFullName(pTableName, tbFName);
+ void*(*mallocFp)(int32_t) = pTask ? taosMemoryMalloc : rpcMallocCont;
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(pTableName, dbFName);
+ SBuildTableInput bInput = {.vgId = vgroupInfo->vgId, .dbFName = dbFName, .tbName = (char*)pTableName->tname};
+
+ SEp* pEp = &vgroupInfo->epSet.eps[vgroupInfo->epSet.inUse];
+ ctgDebug("try to get table cfg from vnode, vgId:%d, ep num:%d, ep %s:%d, tbFName:%s",
+ vgroupInfo->vgId, vgroupInfo->epSet.numOfEps, pEp->fqdn, pEp->port, tbFName);
+
+ int32_t code = queryBuildMsg[TMSG_INDEX(reqType)](&bInput, &msg, 0, &msgLen, mallocFp);
+ if (code) {
+ ctgError("Build get tb cfg msg failed, code:%s, tbFName:%s", tstrerror(code), tbFName);
+ CTG_ERR_RET(code);
+ }
+
+ if (pTask) {
+ CTG_ERR_RET(ctgUpdateMsgCtx(&pTask->msgCtx, reqType, NULL, (char*)tbFName));
+
+ SRequestConnInfo vConn = {.pTrans = pConn->pTrans,
+ .requestId = pConn->requestId,
+ .requestObjRefId = pConn->requestObjRefId,
+ .mgmtEps = vgroupInfo->epSet};
+ CTG_RET(ctgAsyncSendMsg(pCtg, &vConn, pTask, reqType, msg, msgLen));
+ }
+
+ SRpcMsg rpcMsg = {
+ .msgType = reqType,
+ .pCont = msg,
+ .contLen = msgLen,
+ };
+
+ SRpcMsg rpcRsp = {0};
+ rpcSendRecv(pConn->pTrans, &vgroupInfo->epSet, &rpcMsg, &rpcRsp);
+
+ CTG_ERR_RET(ctgProcessRspMsg(out, reqType, rpcRsp.pCont, rpcRsp.contLen, rpcRsp.code, (char*)tbFName));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t ctgGetTableCfgFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, const SName* pTableName, STableCfg **out, SCtgTask* pTask) {
+ char *msg = NULL;
+ int32_t msgLen = 0;
+ int32_t reqType = TDMT_MND_TABLE_CFG;
+ char tbFName[TSDB_TABLE_FNAME_LEN];
+ tNameExtractFullName(pTableName, tbFName);
+ void*(*mallocFp)(int32_t) = pTask ? taosMemoryMalloc : rpcMallocCont;
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(pTableName, dbFName);
+ SBuildTableInput bInput = {.vgId = 0, .dbFName = dbFName, .tbName = (char*)pTableName->tname};
+
+ ctgDebug("try to get table cfg from mnode, tbFName:%s", tbFName);
+
+ int32_t code = queryBuildMsg[TMSG_INDEX(reqType)](&bInput, &msg, 0, &msgLen, mallocFp);
+ if (code) {
+ ctgError("Build get tb cfg msg failed, code:%s, tbFName:%s", tstrerror(code), tbFName);
+ CTG_ERR_RET(code);
+ }
+
+ if (pTask) {
+ CTG_ERR_RET(ctgUpdateMsgCtx(&pTask->msgCtx, reqType, NULL, (char*)tbFName));
+
+ CTG_RET(ctgAsyncSendMsg(pCtg, pConn, pTask, reqType, msg, msgLen));
+ }
+
+ SRpcMsg rpcMsg = {
+ .msgType = reqType,
+ .pCont = msg,
+ .contLen = msgLen,
+ };
+
+ SRpcMsg rpcRsp = {0};
+ rpcSendRecv(pConn->pTrans, &pConn->mgmtEps, &rpcMsg, &rpcRsp);
+
+ CTG_ERR_RET(ctgProcessRspMsg(out, reqType, rpcRsp.pCont, rpcRsp.contLen, rpcRsp.code, (char*)tbFName));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t ctgGetSvrVerFromMnode(SCatalog* pCtg, SRequestConnInfo *pConn, char **out, SCtgTask* pTask) {
+ char *msg = NULL;
+ int32_t msgLen = 0;
+ int32_t reqType = TDMT_MND_SERVER_VERSION;
+ void*(*mallocFp)(int32_t) = pTask ? taosMemoryMalloc : rpcMallocCont;
+
+ qDebug("try to get svr ver from mnode");
+
+ int32_t code = queryBuildMsg[TMSG_INDEX(reqType)](NULL, &msg, 0, &msgLen, mallocFp);
+ if (code) {
+ ctgError("Build get svr ver msg failed, code:%s", tstrerror(code));
+ CTG_ERR_RET(code);
+ }
+
+ if (pTask) {
+ CTG_ERR_RET(ctgUpdateMsgCtx(&pTask->msgCtx, reqType, NULL, NULL));
+
+ CTG_RET(ctgAsyncSendMsg(pCtg, pConn, pTask, reqType, msg, msgLen));
+ }
+
+ SRpcMsg rpcMsg = {
+ .msgType = reqType,
+ .pCont = msg,
+ .contLen = msgLen,
+ };
+
+ SRpcMsg rpcRsp = {0};
+ rpcSendRecv(pConn->pTrans, &pConn->mgmtEps, &rpcMsg, &rpcRsp);
+
+ CTG_ERR_RET(ctgProcessRspMsg(out, reqType, rpcRsp.pCont, rpcRsp.contLen, rpcRsp.code, NULL));
+
+ return TSDB_CODE_SUCCESS;
+}
+
diff --git a/source/libs/catalog/src/ctgUtil.c b/source/libs/catalog/src/ctgUtil.c
index 476eb371b057e27a2420dd6b35582b58db8aca72..a996a70973a18caa8573af224f0bcaa03938e3a3 100644
--- a/source/libs/catalog/src/ctgUtil.c
+++ b/source/libs/catalog/src/ctgUtil.c
@@ -23,6 +23,8 @@ char *ctgTaskTypeStr(CTG_TASK_TYPE type) {
switch (type) {
case CTG_TASK_GET_QNODE:
return "[get qnode list]";
+ case CTG_TASK_GET_DNODE:
+ return "[get dnode list]";
case CTG_TASK_GET_DB_VGROUP:
return "[get db vgroup]";
case CTG_TASK_GET_DB_CFG:
@@ -33,17 +35,27 @@ char *ctgTaskTypeStr(CTG_TASK_TYPE type) {
return "[get table meta]";
case CTG_TASK_GET_TB_HASH:
return "[get table hash]";
+ case CTG_TASK_GET_TB_INDEX:
+ return "[get table index]";
+ case CTG_TASK_GET_TB_CFG:
+ return "[get table cfg]";
case CTG_TASK_GET_INDEX:
return "[get index]";
case CTG_TASK_GET_UDF:
return "[get udf]";
case CTG_TASK_GET_USER:
return "[get user]";
+ case CTG_TASK_GET_SVR_VER:
+ return "[get svr ver]";
default:
return "unknown";
}
}
+void ctgFreeQNode(SCtgQNode *node) {
+ //TODO
+}
+
void ctgFreeSTableIndex(void *info) {
if (NULL == info) {
return;
@@ -96,6 +108,14 @@ void ctgFreeSMetaData(SMetaData* pData) {
taosArrayDestroy(pData->pQnodeList);
pData->pQnodeList = NULL;
+
+ taosArrayDestroy(pData->pDnodeList);
+ pData->pDnodeList = NULL;
+
+ taosArrayDestroy(pData->pTableCfg);
+ pData->pTableCfg = NULL;
+
+ taosMemoryFreeClear(pData->pSvrVer);
}
void ctgFreeSCtgUserAuth(SCtgUserAuth *userCache) {
@@ -125,13 +145,14 @@ void ctgFreeStbMetaCache(SCtgDBCache *dbCache) {
return;
}
- int32_t stblNum = taosHashGetSize(dbCache->stbCache);
+ int32_t stbNum = taosHashGetSize(dbCache->stbCache);
taosHashCleanup(dbCache->stbCache);
dbCache->stbCache = NULL;
- CTG_CACHE_STAT_DEC(stblNum, stblNum);
+ CTG_CACHE_STAT_DEC(numOfStb, stbNum);
}
void ctgFreeTbCacheImpl(SCtgTbCache *pCache) {
+ qDebug("tbMeta freed, p:%p", pCache->pMeta);
taosMemoryFreeClear(pCache->pMeta);
if (pCache->pIndex) {
taosArrayDestroyEx(pCache->pIndex->pIndex, tFreeSTableIndexInfo);
@@ -152,7 +173,7 @@ void ctgFreeTbCache(SCtgDBCache *dbCache) {
}
taosHashCleanup(dbCache->tbCache);
dbCache->tbCache = NULL;
- CTG_CACHE_STAT_DEC(tblNum, tblNum);
+ CTG_CACHE_STAT_DEC(numOfTbl, tblNum);
}
void ctgFreeVgInfo(SDBVgInfo *vgInfo) {
@@ -182,45 +203,108 @@ void ctgFreeDbCache(SCtgDBCache *dbCache) {
ctgFreeTbCache(dbCache);
}
+void ctgFreeInstDbCache(SHashObj* pDbCache) {
+ if (NULL == pDbCache) {
+ return;
+ }
+
+ int32_t dbNum = taosHashGetSize(pDbCache);
+
+ void *pIter = taosHashIterate(pDbCache, NULL);
+ while (pIter) {
+ SCtgDBCache *dbCache = pIter;
+ atomic_store_8(&dbCache->deleted, 1);
+ ctgFreeDbCache(dbCache);
+
+ pIter = taosHashIterate(pDbCache, pIter);
+ }
+
+ taosHashCleanup(pDbCache);
+
+ CTG_CACHE_STAT_DEC(numOfDb, dbNum);
+}
-void ctgFreeHandle(SCatalog* pCtg) {
+void ctgFreeInstUserCache(SHashObj* pUserCache) {
+ if (NULL == pUserCache) {
+ return;
+ }
+
+ int32_t userNum = taosHashGetSize(pUserCache);
+
+ void *pIter = taosHashIterate(pUserCache, NULL);
+ while (pIter) {
+ SCtgUserAuth *userCache = pIter;
+ ctgFreeSCtgUserAuth(userCache);
+
+ pIter = taosHashIterate(pUserCache, pIter);
+ }
+
+ taosHashCleanup(pUserCache);
+
+ CTG_CACHE_STAT_DEC(numOfUser, userNum);
+}
+
+void ctgFreeHandleImpl(SCatalog* pCtg) {
ctgFreeMetaRent(&pCtg->dbRent);
ctgFreeMetaRent(&pCtg->stbRent);
-
- if (pCtg->dbCache) {
- int32_t dbNum = taosHashGetSize(pCtg->dbCache);
-
- void *pIter = taosHashIterate(pCtg->dbCache, NULL);
- while (pIter) {
- SCtgDBCache *dbCache = pIter;
- atomic_store_8(&dbCache->deleted, 1);
- ctgFreeDbCache(dbCache);
-
- pIter = taosHashIterate(pCtg->dbCache, pIter);
- }
- taosHashCleanup(pCtg->dbCache);
- CTG_CACHE_STAT_DEC(dbNum, dbNum);
+ ctgFreeInstDbCache(pCtg->dbCache);
+ ctgFreeInstUserCache(pCtg->userCache);
+
+ taosMemoryFree(pCtg);
+}
+
+
+void ctgFreeHandle(SCatalog* pCtg) {
+ if (NULL == pCtg) {
+ return;
}
- if (pCtg->userCache) {
- int32_t userNum = taosHashGetSize(pCtg->userCache);
+ uint64_t clusterId = pCtg->clusterId;
- void *pIter = taosHashIterate(pCtg->userCache, NULL);
- while (pIter) {
- SCtgUserAuth *userCache = pIter;
- ctgFreeSCtgUserAuth(userCache);
+ ctgFreeMetaRent(&pCtg->dbRent);
+ ctgFreeMetaRent(&pCtg->stbRent);
- pIter = taosHashIterate(pCtg->userCache, pIter);
- }
+ ctgFreeInstDbCache(pCtg->dbCache);
+ ctgFreeInstUserCache(pCtg->userCache);
- taosHashCleanup(pCtg->userCache);
- CTG_CACHE_STAT_DEC(userNum, userNum);
- }
+ CTG_CACHE_STAT_DEC(numOfCluster, 1);
taosMemoryFree(pCtg);
+
+ ctgInfo("handle freed, culsterId:0x%" PRIx64, clusterId);
}
+void ctgClearHandle(SCatalog* pCtg) {
+ if (NULL == pCtg) {
+ return;
+ }
+
+ uint64_t clusterId = pCtg->clusterId;
+
+ ctgFreeMetaRent(&pCtg->dbRent);
+ ctgFreeMetaRent(&pCtg->stbRent);
+
+ ctgFreeInstDbCache(pCtg->dbCache);
+ ctgFreeInstUserCache(pCtg->userCache);
+
+ ctgMetaRentInit(&pCtg->dbRent, gCtgMgmt.cfg.dbRentSec, CTG_RENT_DB);
+ ctgMetaRentInit(&pCtg->stbRent, gCtgMgmt.cfg.stbRentSec, CTG_RENT_STABLE);
+
+ pCtg->dbCache = taosHashInit(gCtgMgmt.cfg.maxDBCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
+ if (NULL == pCtg->dbCache) {
+ qError("taosHashInit %d dbCache failed", CTG_DEFAULT_CACHE_DB_NUMBER);
+ }
+
+ pCtg->userCache = taosHashInit(gCtgMgmt.cfg.maxUserCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
+ if (NULL == pCtg->userCache) {
+ ctgError("taosHashInit %d user cache failed", gCtgMgmt.cfg.maxUserCacheNum);
+ }
+
+ CTG_CACHE_STAT_INC(numOfClear, 1);
+
+ ctgInfo("handle cleared, culsterId:0x%" PRIx64, clusterId);
+}
void ctgFreeSUseDbOutput(SUseDbOutput* pOutput) {
if (NULL == pOutput) {
@@ -280,6 +364,13 @@ void ctgFreeMsgCtx(SCtgMsgCtx* pCtx) {
}
break;
}
+ case TDMT_VND_TABLE_CFG:
+ case TDMT_MND_TABLE_CFG: {
+ STableCfgRsp* pOut = (STableCfgRsp*)pCtx->out;
+ tFreeSTableCfgRsp(pOut);
+ taosMemoryFreeClear(pCtx->out);
+ break;
+ }
case TDMT_MND_RETRIEVE_FUNC: {
SFuncInfo* pOut = (SFuncInfo*)pCtx->out;
taosMemoryFree(pOut->pCode);
@@ -328,74 +419,156 @@ void ctgResetTbMetaTask(SCtgTask* pTask) {
taosMemoryFreeClear(pTask->res);
}
-void ctgFreeTask(SCtgTask* pTask) {
- ctgFreeMsgCtx(&pTask->msgCtx);
-
- switch (pTask->type) {
- case CTG_TASK_GET_QNODE: {
- taosArrayDestroy((SArray*)pTask->res);
- taosMemoryFreeClear(pTask->taskCtx);
- pTask->res = NULL;
+void ctgFreeTaskRes(CTG_TASK_TYPE type, void **pRes) {
+ switch (type) {
+ case CTG_TASK_GET_QNODE:
+ case CTG_TASK_GET_DNODE:
+ case CTG_TASK_GET_DB_VGROUP: {
+ taosArrayDestroy((SArray*)*pRes);
+ *pRes = NULL;
break;
}
- case CTG_TASK_GET_TB_META: {
- SCtgTbMetaCtx* taskCtx = (SCtgTbMetaCtx*)pTask->taskCtx;
- taosMemoryFreeClear(taskCtx->pName);
- if (pTask->msgCtx.lastOut) {
- ctgFreeSTableMetaOutput((STableMetaOutput*)pTask->msgCtx.lastOut);
- pTask->msgCtx.lastOut = NULL;
+ case CTG_TASK_GET_DB_CFG: {
+ if (*pRes) {
+ SDbCfgInfo* pInfo = (SDbCfgInfo*)*pRes;
+ taosArrayDestroy(pInfo->pRetensions);
+ taosMemoryFreeClear(*pRes);
}
- taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
+ break;
+ }
+ case CTG_TASK_GET_TB_INDEX: {
+ taosArrayDestroyEx(*pRes, tFreeSTableIndexInfo);
+ *pRes = NULL;
+ break;
+ }
+ case CTG_TASK_GET_TB_CFG: {
+ if (*pRes) {
+ STableCfg* pInfo = (STableCfg*)*pRes;
+ tFreeSTableCfgRsp(pInfo);
+ taosMemoryFreeClear(*pRes);
+ }
+ break;
+ }
+ case CTG_TASK_GET_TB_HASH:
+ case CTG_TASK_GET_DB_INFO:
+ case CTG_TASK_GET_INDEX:
+ case CTG_TASK_GET_UDF:
+ case CTG_TASK_GET_USER:
+ case CTG_TASK_GET_SVR_VER:
+ case CTG_TASK_GET_TB_META: {
+ taosMemoryFreeClear(*pRes);
+ break;
+ }
+ default:
+ qError("invalid task type %d", type);
+ break;
+ }
+}
+
+
+void ctgFreeSubTaskRes(CTG_TASK_TYPE type, void **pRes) {
+ switch (type) {
+ case CTG_TASK_GET_QNODE:
+ case CTG_TASK_GET_DNODE: {
+ taosArrayDestroy((SArray*)*pRes);
+ *pRes = NULL;
break;
}
case CTG_TASK_GET_DB_VGROUP: {
- taosArrayDestroy((SArray*)pTask->res);
- taosMemoryFreeClear(pTask->taskCtx);
- pTask->res = NULL;
+ if (*pRes) {
+ SDBVgInfo* pInfo = (SDBVgInfo*)*pRes;
+ taosHashCleanup(pInfo->vgHash);
+ taosMemoryFreeClear(*pRes);
+ }
break;
}
case CTG_TASK_GET_DB_CFG: {
- taosMemoryFreeClear(pTask->taskCtx);
- if (pTask->res) {
- SDbCfgInfo* pInfo = (SDbCfgInfo*)pTask->res;
+ if (*pRes) {
+ SDbCfgInfo* pInfo = (SDbCfgInfo*)*pRes;
taosArrayDestroy(pInfo->pRetensions);
- taosMemoryFreeClear(pTask->res);
+ taosMemoryFreeClear(*pRes);
}
break;
}
- case CTG_TASK_GET_DB_INFO: {
- taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
+ case CTG_TASK_GET_TB_INDEX: {
+ taosArrayDestroyEx(*pRes, tFreeSTableIndexInfo);
+ *pRes = NULL;
+ break;
+ }
+ case CTG_TASK_GET_TB_CFG: {
+ if (*pRes) {
+ STableCfg* pInfo = (STableCfg*)*pRes;
+ tFreeSTableCfgRsp(pInfo);
+ taosMemoryFreeClear(*pRes);
+ }
+ break;
+ }
+ case CTG_TASK_GET_TB_META:
+ case CTG_TASK_GET_DB_INFO:
+ case CTG_TASK_GET_TB_HASH:
+ case CTG_TASK_GET_INDEX:
+ case CTG_TASK_GET_UDF:
+ case CTG_TASK_GET_SVR_VER:
+ case CTG_TASK_GET_USER: {
+ taosMemoryFreeClear(*pRes);
+ break;
+ }
+ default:
+ qError("invalid task type %d", type);
+ break;
+ }
+}
+
+
+void ctgClearSubTaskRes(SCtgSubRes *pRes) {
+ pRes->code = 0;
+
+ if (NULL == pRes->res) {
+ return;
+ }
+
+ ctgFreeSubTaskRes(pRes->type, &pRes->res);
+}
+
+void ctgFreeTaskCtx(SCtgTask* pTask) {
+ switch (pTask->type) {
+ case CTG_TASK_GET_TB_META: {
+ SCtgTbMetaCtx* taskCtx = (SCtgTbMetaCtx*)pTask->taskCtx;
+ taosMemoryFreeClear(taskCtx->pName);
+ if (pTask->msgCtx.lastOut) {
+ ctgFreeSTableMetaOutput((STableMetaOutput*)pTask->msgCtx.lastOut);
+ pTask->msgCtx.lastOut = NULL;
+ }
+ taosMemoryFreeClear(pTask->taskCtx);
break;
}
case CTG_TASK_GET_TB_HASH: {
SCtgTbHashCtx* taskCtx = (SCtgTbHashCtx*)pTask->taskCtx;
taosMemoryFreeClear(taskCtx->pName);
taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
break;
}
case CTG_TASK_GET_TB_INDEX: {
SCtgTbIndexCtx* taskCtx = (SCtgTbIndexCtx*)pTask->taskCtx;
taosMemoryFreeClear(taskCtx->pName);
taosMemoryFreeClear(pTask->taskCtx);
- taosArrayDestroyEx(pTask->res, tFreeSTableIndexInfo);
break;
}
- case CTG_TASK_GET_INDEX: {
- taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
- break;
- }
- case CTG_TASK_GET_UDF: {
+ case CTG_TASK_GET_TB_CFG: {
+ SCtgTbCfgCtx* taskCtx = (SCtgTbCfgCtx*)pTask->taskCtx;
+ taosMemoryFreeClear(taskCtx->pName);
+ taosMemoryFreeClear(taskCtx->pVgInfo);
taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
break;
}
+ case CTG_TASK_GET_DB_VGROUP:
+ case CTG_TASK_GET_DB_CFG:
+ case CTG_TASK_GET_DB_INFO:
+ case CTG_TASK_GET_INDEX:
+ case CTG_TASK_GET_UDF:
+ case CTG_TASK_GET_QNODE:
case CTG_TASK_GET_USER: {
taosMemoryFreeClear(pTask->taskCtx);
- taosMemoryFreeClear(pTask->res);
break;
}
default:
@@ -404,6 +577,16 @@ void ctgFreeTask(SCtgTask* pTask) {
}
}
+
+void ctgFreeTask(SCtgTask* pTask) {
+ ctgFreeMsgCtx(&pTask->msgCtx);
+ ctgFreeTaskRes(pTask->type, &pTask->res);
+ ctgFreeTaskCtx(pTask);
+
+ taosArrayDestroy(pTask->pParents);
+ ctgClearSubTaskRes(&pTask->subRes);
+}
+
void ctgFreeTasks(SArray* pArray) {
if (NULL == pArray) {
return;
@@ -475,7 +658,7 @@ int32_t ctgGenerateVgList(SCatalog *pCtg, SHashObj *vgHash, SArray** pList) {
vgList = taosArrayInit(vgNum, sizeof(SVgroupInfo));
if (NULL == vgList) {
ctgError("taosArrayInit failed, num:%d", vgNum);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
void *pIter = taosHashIterate(vgHash, NULL);
@@ -485,7 +668,7 @@ int32_t ctgGenerateVgList(SCatalog *pCtg, SHashObj *vgHash, SArray** pList) {
if (NULL == taosArrayPush(vgList, vgInfo)) {
ctgError("taosArrayPush failed, vgId:%d", vgInfo->vgId);
taosHashCancelIterate(vgHash, pIter);
- CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
}
pIter = taosHashIterate(vgHash, pIter);
@@ -549,7 +732,7 @@ int32_t ctgGetVgInfoFromHashValue(SCatalog *pCtg, SDBVgInfo *dbInfo, const SName
*pVgroup = *vgInfo;
- ctgDebug("Got tb %s hash vgroup, vgId %d, epNum %d, current %s port %d", tbFullName, vgInfo->vgId, vgInfo->epSet.numOfEps,
+ ctgDebug("Got tb %s hash vgroup, vgId:%d, epNum %d, current %s port %d", tbFullName, vgInfo->vgId, vgInfo->epSet.numOfEps,
vgInfo->epSet.eps[vgInfo->epSet.inUse].fqdn, vgInfo->epSet.eps[vgInfo->epSet.inUse].port);
CTG_RET(code);
@@ -602,7 +785,7 @@ int32_t ctgCloneVgInfo(SDBVgInfo *src, SDBVgInfo **dst) {
*dst = taosMemoryMalloc(sizeof(SDBVgInfo));
if (NULL == *dst) {
qError("malloc %d failed", (int32_t)sizeof(SDBVgInfo));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
memcpy(*dst, src, sizeof(SDBVgInfo));
@@ -612,7 +795,7 @@ int32_t ctgCloneVgInfo(SDBVgInfo *src, SDBVgInfo **dst) {
if (NULL == (*dst)->vgHash) {
qError("taosHashInit %d failed", (int32_t)hashSize);
taosMemoryFreeClear(*dst);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
int32_t *vgId = NULL;
@@ -625,7 +808,7 @@ int32_t ctgCloneVgInfo(SDBVgInfo *src, SDBVgInfo **dst) {
taosHashCancelIterate(src->vgHash, pIter);
taosHashCleanup((*dst)->vgHash);
taosMemoryFreeClear(*dst);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
pIter = taosHashIterate(src->vgHash, pIter);
@@ -641,7 +824,7 @@ int32_t ctgCloneMetaOutput(STableMetaOutput *output, STableMetaOutput **pOutput)
*pOutput = taosMemoryMalloc(sizeof(STableMetaOutput));
if (NULL == *pOutput) {
qError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
memcpy(*pOutput, output, sizeof(STableMetaOutput));
@@ -649,10 +832,11 @@ int32_t ctgCloneMetaOutput(STableMetaOutput *output, STableMetaOutput **pOutput)
if (output->tbMeta) {
int32_t metaSize = CTG_META_SIZE(output->tbMeta);
(*pOutput)->tbMeta = taosMemoryMalloc(metaSize);
+ qDebug("tbMeta cloned, size:%d, p:%p", metaSize, (*pOutput)->tbMeta);
if (NULL == (*pOutput)->tbMeta) {
qError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
taosMemoryFreeClear(*pOutput);
- CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
memcpy((*pOutput)->tbMeta, output->tbMeta, metaSize);
diff --git a/source/libs/catalog/test/CMakeLists.txt b/source/libs/catalog/test/CMakeLists.txt
index d74eef785517e15c52794120d743c6d320f5758c..b2e1c3b4ca5f3e169920acc8236e717db1e5766c 100644
--- a/source/libs/catalog/test/CMakeLists.txt
+++ b/source/libs/catalog/test/CMakeLists.txt
@@ -1,23 +1,25 @@
MESSAGE(STATUS "build catalog unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(catalogTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- catalogTest
- PUBLIC os util common catalog transport gtest qcom taos_static
-)
+ ADD_EXECUTABLE(catalogTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ catalogTest
+ PUBLIC os util common catalog transport gtest qcom taos_static
+ )
-TARGET_INCLUDE_DIRECTORIES(
- catalogTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/catalog/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/catalog/inc"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ catalogTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/catalog/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/catalog/inc"
+ )
-# add_test(
-# NAME catalogTest
-# COMMAND catalogTest
-# )
+ # add_test(
+ # NAME catalogTest
+ # COMMAND catalogTest
+ # )
+ENDIF()
diff --git a/source/libs/catalog/test/catalogTests.cpp b/source/libs/catalog/test/catalogTests.cpp
index aab341544f764047fed14430e5d718f603fef080..51b721f818d7404202be539a18234326d5b1372e 100644
--- a/source/libs/catalog/test/catalogTests.cpp
+++ b/source/libs/catalog/test/catalogTests.cpp
@@ -109,7 +109,7 @@ void sendCreateDbMsg(void *shandle, SEpSet *pEpSet) {
createReq.compression = 2;
createReq.replications = 1;
createReq.strict = 1;
- createReq.cacheLastRow = 0;
+ createReq.cacheLast = 0;
createReq.ignoreExist = 1;
int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq);
@@ -1386,7 +1386,7 @@ TEST(tableMeta, updateStbMeta) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n != 3) {
taosMsleep(50);
} else {
@@ -1456,7 +1456,7 @@ TEST(refreshGetMeta, normal2normal) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -1535,7 +1535,7 @@ TEST(refreshGetMeta, normal2notexist) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -1609,7 +1609,7 @@ TEST(refreshGetMeta, normal2child) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -1693,7 +1693,7 @@ TEST(refreshGetMeta, stable2child) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -1778,7 +1778,7 @@ TEST(refreshGetMeta, stable2stable) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -1866,7 +1866,7 @@ TEST(refreshGetMeta, child2stable) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -2083,7 +2083,7 @@ TEST(dbVgroup, getSetDbVgroupCase) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n > 0) {
break;
}
@@ -2109,7 +2109,7 @@ TEST(dbVgroup, getSetDbVgroupCase) {
while (true) {
uint64_t n = 0;
- ctgdGetStatNum("runtime.qDoneNum", (void *)&n);
+ ctgdGetStatNum("runtime.numOfOpDequeue", (void *)&n);
if (n != 3) {
taosMsleep(50);
} else {
diff --git a/source/libs/command/inc/commandInt.h b/source/libs/command/inc/commandInt.h
index 06e9af756968e917a9a2cd53fe3f9b6aea9c56d8..6aca581f45d186e76ab2c4b38a86f2851dd6810e 100644
--- a/source/libs/command/inc/commandInt.h
+++ b/source/libs/command/inc/commandInt.h
@@ -29,13 +29,17 @@ extern "C" {
#define EXPLAIN_TAG_SCAN_FORMAT "Tag Scan on %s"
#define EXPLAIN_TBL_SCAN_FORMAT "Table Scan on %s"
#define EXPLAIN_SYSTBL_SCAN_FORMAT "System Table Scan on %s"
+#define EXPLAIN_DISTBLK_SCAN_FORMAT "Block Dist Scan on %s"
+#define EXPLAIN_LASTROW_SCAN_FORMAT "Last Row Scan on %s"
#define EXPLAIN_PROJECTION_FORMAT "Projection"
#define EXPLAIN_JOIN_FORMAT "%s"
#define EXPLAIN_AGG_FORMAT "Aggragate"
#define EXPLAIN_INDEF_ROWS_FORMAT "Indefinite Rows Function"
#define EXPLAIN_EXCHANGE_FORMAT "Data Exchange %d:1"
#define EXPLAIN_SORT_FORMAT "Sort"
+#define EXPLAIN_GROUP_SORT_FORMAT "Group Sort"
#define EXPLAIN_INTERVAL_FORMAT "Interval on Column %s"
+#define EXPLAIN_MERGE_INTERVAL_FORMAT "Merge Interval on Column %s"
#define EXPLAIN_FILL_FORMAT "Fill"
#define EXPLAIN_SESSION_FORMAT "Session"
#define EXPLAIN_STATE_WINDOW_FORMAT "StateWindow on Column %s"
@@ -62,10 +66,12 @@ extern "C" {
#define EXPLAIN_COST_FORMAT "cost=%.2f..%.2f"
#define EXPLAIN_ROWS_FORMAT "rows=%" PRIu64
#define EXPLAIN_COLUMNS_FORMAT "columns=%d"
+#define EXPLAIN_PSEUDO_COLUMNS_FORMAT "pseudo_columns=%d"
#define EXPLAIN_WIDTH_FORMAT "width=%d"
#define EXPLAIN_TABLE_SCAN_FORMAT "order=[asc|%d desc|%d]"
#define EXPLAIN_GROUPS_FORMAT "groups=%d"
#define EXPLAIN_WIDTH_FORMAT "width=%d"
+#define EXPLAIN_INTERVAL_VALUE_FORMAT "interval=%" PRId64 "%c"
#define EXPLAIN_FUNCTIONS_FORMAT "functions=%d"
#define EXPLAIN_EXECINFO_FORMAT "cost=%.3f..%.3f rows=%" PRIu64
#define EXPLAIN_MODE_FORMAT "mode=%s"
diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c
index 6a3852abbcc4ee84e423790821d6d7ab5afd2baa..034778e5bfd4f527ca4782d7e91015244db8b012 100644
--- a/source/libs/command/src/command.c
+++ b/source/libs/command/src/command.c
@@ -16,6 +16,32 @@
#include "command.h"
#include "catalog.h"
#include "tdatablock.h"
+#include "tglobal.h"
+
+extern SConfig* tsCfg;
+
+static int32_t buildRetrieveTableRsp(SSDataBlock* pBlock, int32_t numOfCols, SRetrieveTableRsp** pRsp) {
+ size_t rspSize = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
+ *pRsp = taosMemoryCalloc(1, rspSize);
+ if (NULL == *pRsp) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ (*pRsp)->useconds = 0;
+ (*pRsp)->completed = 1;
+ (*pRsp)->precision = 0;
+ (*pRsp)->compressed = 0;
+ (*pRsp)->compLen = 0;
+ (*pRsp)->numOfRows = htonl(pBlock->info.rows);
+ (*pRsp)->numOfCols = htonl(numOfCols);
+
+ int32_t len = 0;
+ blockEncode(pBlock, (*pRsp)->data, &len, numOfCols, false);
+ ASSERT(len == rspSize - sizeof(SRetrieveTableRsp));
+
+ blockDataDestroy(pBlock);
+ return TSDB_CODE_SUCCESS;
+}
static int32_t getSchemaBytes(const SSchema* pSchema) {
switch (pSchema->type) {
@@ -30,31 +56,19 @@ static int32_t getSchemaBytes(const SSchema* pSchema) {
}
static SSDataBlock* buildDescResultDataBlock() {
- SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
- pBlock->info.numOfCols = DESCRIBE_RESULT_COLS;
- pBlock->info.hasVarCol = true;
+ SSDataBlock* pBlock = createDataBlock();
- pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, DESCRIBE_RESULT_FIELD_LEN, 1);
+ blockDataAppendColInfo(pBlock, &infoData);
- SColumnInfoData infoData = {0};
- infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
- infoData.info.bytes = DESCRIBE_RESULT_FIELD_LEN;
+ infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, DESCRIBE_RESULT_TYPE_LEN, 2);
+ blockDataAppendColInfo(pBlock, &infoData);
- taosArrayPush(pBlock->pDataBlock, &infoData);
-
- infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
- infoData.info.bytes = DESCRIBE_RESULT_TYPE_LEN;
- taosArrayPush(pBlock->pDataBlock, &infoData);
-
- infoData.info.type = TSDB_DATA_TYPE_INT;
- infoData.info.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
-
- taosArrayPush(pBlock->pDataBlock, &infoData);
-
- infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
- infoData.info.bytes = DESCRIBE_RESULT_NOTE_LEN;
- taosArrayPush(pBlock->pDataBlock, &infoData);
+ infoData = createColumnInfoData(TSDB_DATA_TYPE_INT, tDataTypes[TSDB_DATA_TYPE_INT].bytes, 3);
+ blockDataAppendColInfo(pBlock, &infoData);
+ infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, DESCRIBE_RESULT_NOTE_LEN, 4);
+ blockDataAppendColInfo(pBlock, &infoData);
return pBlock;
}
@@ -99,39 +113,489 @@ static int32_t execDescribe(SNode* pStmt, SRetrieveTableRsp** pRsp) {
SSDataBlock* pBlock = buildDescResultDataBlock();
setDescResultIntoDataBlock(pBlock, numOfRows, pDesc->pMeta);
- size_t rspSize = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
- *pRsp = taosMemoryCalloc(1, rspSize);
- if (NULL == *pRsp) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return buildRetrieveTableRsp(pBlock, DESCRIBE_RESULT_COLS, pRsp);
+}
+
+static int32_t execResetQueryCache() { return catalogClearCache(); }
+
+static SSDataBlock* buildCreateDBResultDataBlock() {
+ SSDataBlock* pBlock = createDataBlock();
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, SHOW_CREATE_DB_RESULT_COLS, 1);
+ blockDataAppendColInfo(pBlock, &infoData);
+
+ infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, SHOW_CREATE_DB_RESULT_FIELD2_LEN, 2);
+ blockDataAppendColInfo(pBlock, &infoData);
+ return pBlock;
+}
+
+int64_t getValOfDiffPrecision(int8_t unit, int64_t val) {
+ int64_t v = 0;
+ switch (unit) {
+ case 's':
+ v = val / 1000;
+ break;
+ case 'm':
+ v = val / tsTickPerMin[TSDB_TIME_PRECISION_MILLI];
+ break;
+ case 'h':
+ v = val / (tsTickPerMin[TSDB_TIME_PRECISION_MILLI] * 60);
+ break;
+ case 'd':
+ v = val / (tsTickPerMin[TSDB_TIME_PRECISION_MILLI] * 24 * 60);
+ break;
+ case 'w':
+ v = val / (tsTickPerMin[TSDB_TIME_PRECISION_MILLI] * 24 * 60 * 7);
+ break;
+ default:
+ break;
}
- (*pRsp)->useconds = 0;
- (*pRsp)->completed = 1;
- (*pRsp)->precision = 0;
- (*pRsp)->compressed = 0;
- (*pRsp)->compLen = 0;
- (*pRsp)->numOfRows = htonl(numOfRows);
- (*pRsp)->numOfCols = htonl(DESCRIBE_RESULT_COLS);
+ return v;
+}
+
+char* buildRetension(SArray* pRetension) {
+ size_t size = taosArrayGetSize(pRetension);
+ if (size == 0) {
+ return NULL;
+ }
+
+ char* p1 = taosMemoryCalloc(1, 100);
+ SRetention* p = taosArrayGet(pRetension, 0);
int32_t len = 0;
- blockCompressEncode(pBlock, (*pRsp)->data, &len, DESCRIBE_RESULT_COLS, false);
- ASSERT(len == rspSize - sizeof(SRetrieveTableRsp));
- blockDataDestroy(pBlock);
+ int64_t v1 = getValOfDiffPrecision(p->freqUnit, p->freq);
+ int64_t v2 = getValOfDiffPrecision(p->keepUnit, p->keep);
+ len += sprintf(p1 + len, "%" PRId64 "%c:%" PRId64 "%c", v1, p->freqUnit, v2, p->keepUnit);
+
+ if (size > 1) {
+ len += sprintf(p1 + len, ",");
+ p = taosArrayGet(pRetension, 1);
+
+ v1 = getValOfDiffPrecision(p->freqUnit, p->freq);
+ v2 = getValOfDiffPrecision(p->keepUnit, p->keep);
+ len += sprintf(p1 + len, "%" PRId64 "%c:%" PRId64 "%c", v1, p->freqUnit, v2, p->keepUnit);
+ }
+
+ if (size > 2) {
+ len += sprintf(p1 + len, ",");
+ p = taosArrayGet(pRetension, 2);
+
+ v1 = getValOfDiffPrecision(p->freqUnit, p->freq);
+ v2 = getValOfDiffPrecision(p->keepUnit, p->keep);
+ len += sprintf(p1 + len, "%" PRId64 "%c:%" PRId64 "%c", v1, p->freqUnit, v2, p->keepUnit);
+ }
+
+ return p1;
+}
+
+static void setCreateDBResultIntoDataBlock(SSDataBlock* pBlock, char* dbFName, SDbCfgInfo* pCfg) {
+ blockDataEnsureCapacity(pBlock, 1);
+ pBlock->info.rows = 1;
+
+ SColumnInfoData* pCol1 = taosArrayGet(pBlock->pDataBlock, 0);
+ char buf1[SHOW_CREATE_DB_RESULT_FIELD1_LEN] = {0};
+ STR_TO_VARSTR(buf1, dbFName);
+ colDataAppend(pCol1, 0, buf1, false);
+
+ SColumnInfoData* pCol2 = taosArrayGet(pBlock->pDataBlock, 1);
+ char buf2[SHOW_CREATE_DB_RESULT_FIELD2_LEN] = {0};
+ int32_t len = 0;
+ char* prec = NULL;
+ switch (pCfg->precision) {
+ case TSDB_TIME_PRECISION_MILLI:
+ prec = TSDB_TIME_PRECISION_MILLI_STR;
+ break;
+ case TSDB_TIME_PRECISION_MICRO:
+ prec = TSDB_TIME_PRECISION_MICRO_STR;
+ break;
+ case TSDB_TIME_PRECISION_NANO:
+ prec = TSDB_TIME_PRECISION_NANO_STR;
+ break;
+ default:
+ prec = "none";
+ break;
+ }
+
+ char* retentions = buildRetension(pCfg->pRetensions);
+
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE,
+ "CREATE DATABASE `%s` BUFFER %d CACHELAST %d COMP %d DURATION %dm "
+ "FSYNC %d MAXROWS %d MINROWS %d KEEP %dm,%dm,%dm PAGES %d PAGESIZE %d PRECISION '%s' REPLICA %d "
+ "STRICT %d WAL %d VGROUPS %d SINGLE_STABLE %d",
+ dbFName, pCfg->buffer, pCfg->cacheLast, pCfg->compression, pCfg->daysPerFile, pCfg->fsyncPeriod,
+ pCfg->maxRows, pCfg->minRows, pCfg->daysToKeep0, pCfg->daysToKeep1, pCfg->daysToKeep2, pCfg->pages,
+ pCfg->pageSize, prec, pCfg->replications, pCfg->strict, pCfg->walLevel, pCfg->numOfVgroups,
+ 1 == pCfg->numOfStables);
+
+ if (retentions) {
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, " RETENTIONS %s", retentions);
+ taosMemoryFree(retentions);
+ }
+
+ (varDataLen(buf2)) = len;
+
+ colDataAppend(pCol2, 0, buf2, false);
+}
+
+static int32_t execShowCreateDatabase(SShowCreateDatabaseStmt* pStmt, SRetrieveTableRsp** pRsp) {
+ SSDataBlock* pBlock = buildCreateDBResultDataBlock();
+ setCreateDBResultIntoDataBlock(pBlock, pStmt->dbName, pStmt->pCfg);
+ return buildRetrieveTableRsp(pBlock, SHOW_CREATE_DB_RESULT_COLS, pRsp);
+}
+
+static SSDataBlock* buildCreateTbResultDataBlock() {
+ SSDataBlock* pBlock = createDataBlock();
+
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, SHOW_CREATE_TB_RESULT_FIELD1_LEN, 1);
+ blockDataAppendColInfo(pBlock, &infoData);
+
+ infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, SHOW_CREATE_TB_RESULT_FIELD2_LEN, 2);
+ blockDataAppendColInfo(pBlock, &infoData);
+
+ return pBlock;
+}
+
+void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) {
+ for (int32_t i = 0; i < pCfg->numOfColumns; ++i) {
+ SSchema* pSchema = pCfg->pSchemas + i;
+ char type[32];
+ sprintf(type, "%s", tDataTypes[pSchema->type].name);
+ if (TSDB_DATA_TYPE_VARCHAR == pSchema->type) {
+ sprintf(type + strlen(type), "(%d)", (int32_t)(pSchema->bytes - VARSTR_HEADER_SIZE));
+ } else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) {
+ sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
+ }
+
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type);
+ }
+}
+
+void appendTagFields(char* buf, int32_t* len, STableCfg* pCfg) {
+ for (int32_t i = 0; i < pCfg->numOfTags; ++i) {
+ SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i;
+ char type[32];
+ sprintf(type, "%s", tDataTypes[pSchema->type].name);
+ if (TSDB_DATA_TYPE_VARCHAR == pSchema->type) {
+ sprintf(type + strlen(type), "(%d)", (int32_t)(pSchema->bytes - VARSTR_HEADER_SIZE));
+ } else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) {
+ sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
+ }
+
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type);
+ }
+}
+
+void appendTagNameFields(char* buf, int32_t* len, STableCfg* pCfg) {
+ for (int32_t i = 0; i < pCfg->numOfTags; ++i) {
+ SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i;
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s`", ((i > 0) ? ", " : ""), pSchema->name);
+ }
+}
+
+int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) {
+ SArray* pTagVals = NULL;
+ STag* pTag = (STag*)pCfg->pTags;
+
+ if (pCfg->pTags && tTagIsJson(pTag)) {
+ char* pJson = parseTagDatatoJson(pTag);
+ if (pJson) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s", pJson);
+ taosMemoryFree(pJson);
+ }
+
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t code = tTagToValArray((const STag*)pCfg->pTags, &pTagVals);
+ if (code) {
+ return code;
+ }
+
+ int16_t valueNum = taosArrayGetSize(pTagVals);
+ int32_t num = 0;
+ int32_t j = 0;
+ for (int32_t i = 0; i < pCfg->numOfTags; ++i) {
+ SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i;
+ if (i > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", ");
+ }
+
+ if (j >= valueNum) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL");
+ continue;
+ }
+
+ STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, j);
+ if (pSchema->colId > pTagVal->cid) {
+ qError("tag value and column mismatch, schemaId:%d, valId:%d", pSchema->colId, pTagVal->cid);
+ taosArrayDestroy(pTagVals);
+ return TSDB_CODE_APP_ERROR;
+ } else if (pSchema->colId == pTagVal->cid) {
+ char type = pTagVal->type;
+ int32_t tlen = 0;
+
+ if (IS_VAR_DATA_TYPE(type)) {
+ dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, pTagVal->pData, pTagVal->nData, &tlen);
+ } else {
+ dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, &pTagVal->i64, tDataTypes[type].bytes, &tlen);
+ }
+ *len += tlen;
+ j++;
+ } else {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL");
+ }
+
+ /*
+ if (type == TSDB_DATA_TYPE_BINARY) {
+ if (pTagVal->nData > 0) {
+ if (num) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", ");
+ }
+
+ memcpy(buf + VARSTR_HEADER_SIZE + *len, pTagVal->pData, pTagVal->nData);
+ *len += pTagVal->nData;
+ }
+ } else if (type == TSDB_DATA_TYPE_NCHAR) {
+ if (pTagVal->nData > 0) {
+ if (num) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", ");
+ }
+ int32_t tlen = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, buf + VARSTR_HEADER_SIZE + *len);
+ }
+ } else if (type == TSDB_DATA_TYPE_DOUBLE) {
+ double val = *(double *)(&pTagVal->i64);
+ int len = 0;
+ term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, (const char *)&val, len);
+ } else if (type == TSDB_DATA_TYPE_BOOL) {
+ int val = *(int *)(&pTagVal->i64);
+ int len = 0;
+ term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_INT, key, nKey, (const char *)&val, len);
+ }
+ */
+ }
+
+ taosArrayDestroy(pTagVals);
+
return TSDB_CODE_SUCCESS;
}
-static int32_t execResetQueryCache() { return catalogClearCache(); }
+void appendTableOptions(char* buf, int32_t* len, STableCfg* pCfg) {
+ if (pCfg->commentLen > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT '%s'", pCfg->pComment);
+ } else if (0 == pCfg->commentLen) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT ''");
+ }
-static int32_t execShowCreateDatabase(SShowCreateDatabaseStmt* pStmt) { return TSDB_CODE_FAILED; }
+ if (pCfg->watermark1 > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " WATERMARK %" PRId64 "a", pCfg->watermark1);
+ if (pCfg->watermark2 > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->watermark2);
+ }
+ }
-static int32_t execShowCreateTable(SShowCreateTableStmt* pStmt) { return TSDB_CODE_FAILED; }
+ if (pCfg->delay1 > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " MAX_DELAY %" PRId64 "a", pCfg->delay1);
+ if (pCfg->delay2 > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->delay2);
+ }
+ }
+
+ int32_t funcNum = taosArrayGetSize(pCfg->pFuncs);
+ if (funcNum > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " ROLLUP(");
+ for (int32_t i = 0; i < funcNum; ++i) {
+ char* pFunc = taosArrayGet(pCfg->pFuncs, i);
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s%s", ((i > 0) ? ", " : ""), pFunc);
+ }
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ")");
+ }
+
+ if (pCfg->ttl > 0) {
+ *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " TTL %d", pCfg->ttl);
+ }
+}
+
+static int32_t setCreateTBResultIntoDataBlock(SSDataBlock* pBlock, char* tbName, STableCfg* pCfg) {
+ int32_t code = 0;
+ blockDataEnsureCapacity(pBlock, 1);
+ pBlock->info.rows = 1;
+
+ SColumnInfoData* pCol1 = taosArrayGet(pBlock->pDataBlock, 0);
+ char buf1[SHOW_CREATE_TB_RESULT_FIELD1_LEN] = {0};
+ STR_TO_VARSTR(buf1, tbName);
+ colDataAppend(pCol1, 0, buf1, false);
+
+ SColumnInfoData* pCol2 = taosArrayGet(pBlock->pDataBlock, 1);
+ char buf2[SHOW_CREATE_TB_RESULT_FIELD2_LEN] = {0};
+ int32_t len = 0;
+
+ if (TSDB_SUPER_TABLE == pCfg->tableType) {
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE STABLE `%s` (", tbName);
+ appendColumnFields(buf2, &len, pCfg);
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS (");
+ appendTagFields(buf2, &len, pCfg);
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")");
+ appendTableOptions(buf2, &len, pCfg);
+ } else if (TSDB_CHILD_TABLE == pCfg->tableType) {
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` USING `%s` (", tbName, pCfg->stbName);
+ appendTagNameFields(buf2, &len, pCfg);
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS (");
+ code = appendTagValues(buf2, &len, pCfg);
+ if (code) {
+ return code;
+ }
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")");
+ appendTableOptions(buf2, &len, pCfg);
+ } else {
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` (", tbName);
+ appendColumnFields(buf2, &len, pCfg);
+ len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")");
+ }
-static int32_t execShowCreateSTable(SShowCreateTableStmt* pStmt) { return TSDB_CODE_FAILED; }
+ varDataLen(buf2) = len;
-static int32_t execAlterLocal(SAlterLocalStmt* pStmt) { return TSDB_CODE_FAILED; }
+ colDataAppend(pCol2, 0, buf2, false);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t execShowCreateTable(SShowCreateTableStmt* pStmt, SRetrieveTableRsp** pRsp) {
+ SSDataBlock* pBlock = buildCreateTbResultDataBlock();
+ int32_t code = setCreateTBResultIntoDataBlock(pBlock, pStmt->tableName, pStmt->pCfg);
+ if (code) {
+ return code;
+ }
+ return buildRetrieveTableRsp(pBlock, SHOW_CREATE_TB_RESULT_COLS, pRsp);
+}
+
+static int32_t execShowCreateSTable(SShowCreateTableStmt* pStmt, SRetrieveTableRsp** pRsp) {
+ STableCfg* pCfg = (STableCfg*)pStmt->pCfg;
+ if (TSDB_SUPER_TABLE != pCfg->tableType) {
+ terrno = TSDB_CODE_TSC_NOT_STABLE_ERROR;
+ return terrno;
+ }
+
+ return execShowCreateTable(pStmt, pRsp);
+}
+
+static int32_t execAlterLocal(SAlterLocalStmt* pStmt) {
+ if (cfgSetItem(tsCfg, pStmt->config, pStmt->value, CFG_STYPE_ALTER_CMD)) {
+ return terrno;
+ }
-static int32_t execShowLocalVariables() { return TSDB_CODE_FAILED; }
+ if (taosSetCfg(tsCfg, pStmt->config)) {
+ return terrno;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static SSDataBlock* buildLocalVariablesResultDataBlock() {
+ SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ pBlock->info.hasVarCol = true;
+
+ pBlock->pDataBlock = taosArrayInit(SHOW_LOCAL_VARIABLES_RESULT_COLS, sizeof(SColumnInfoData));
+
+ SColumnInfoData infoData = {0};
+ infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
+ infoData.info.bytes = SHOW_LOCAL_VARIABLES_RESULT_FIELD1_LEN;
+
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
+ infoData.info.bytes = SHOW_LOCAL_VARIABLES_RESULT_FIELD2_LEN;
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ return pBlock;
+}
+
+int32_t setLocalVariablesResultIntoDataBlock(SSDataBlock* pBlock) {
+ int32_t numOfCfg = taosArrayGetSize(tsCfg->array);
+ int32_t numOfRows = 0;
+ blockDataEnsureCapacity(pBlock, numOfCfg);
+
+ for (int32_t i = 0, c = 0; i < numOfCfg; ++i, c = 0) {
+ SConfigItem* pItem = taosArrayGet(tsCfg->array, i);
+
+ char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0};
+ STR_WITH_MAXSIZE_TO_VARSTR(name, pItem->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE);
+ SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, name, false);
+
+ char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
+ int32_t valueLen = 0;
+ cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen);
+ varDataSetLen(value, valueLen);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, c++);
+ colDataAppend(pColInfo, i, value, false);
+
+ numOfRows++;
+ }
+
+ pBlock->info.rows = numOfRows;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t execShowLocalVariables(SRetrieveTableRsp** pRsp) {
+ SSDataBlock* pBlock = buildLocalVariablesResultDataBlock();
+ int32_t code = setLocalVariablesResultIntoDataBlock(pBlock);
+ if (code) {
+ return code;
+ }
+ return buildRetrieveTableRsp(pBlock, SHOW_LOCAL_VARIABLES_RESULT_COLS, pRsp);
+}
+
+static int32_t createSelectResultDataBlock(SNodeList* pProjects, SSDataBlock** pOutput) {
+ SSDataBlock* pBlock = createDataBlock();
+ if (NULL == pBlock) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ SNode* pProj = NULL;
+ FOREACH(pProj, pProjects) {
+ SColumnInfoData infoData = {0};
+ infoData.info.type = ((SExprNode*)pProj)->resType.type;
+ infoData.info.bytes = ((SExprNode*)pProj)->resType.bytes;
+ blockDataAppendColInfo(pBlock, &infoData);
+ }
+ *pOutput = pBlock;
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t buildSelectResultDataBlock(SNodeList* pProjects, SSDataBlock* pBlock) {
+ blockDataEnsureCapacity(pBlock, 1);
+
+ int32_t index = 0;
+ SNode* pProj = NULL;
+ FOREACH(pProj, pProjects) {
+ if (QUERY_NODE_VALUE != nodeType(pProj)) {
+ return TSDB_CODE_PAR_INVALID_SELECTED_EXPR;
+ } else {
+ if (((SValueNode*)pProj)->isNull) {
+ colDataAppend(taosArrayGet(pBlock->pDataBlock, index++), 0, NULL, true);
+ } else {
+ colDataAppend(taosArrayGet(pBlock->pDataBlock, index++), 0, nodesGetValueFromNode((SValueNode*)pProj), false);
+ }
+ }
+ }
+
+ pBlock->info.rows = 1;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t execSelectWithoutFrom(SSelectStmt* pSelect, SRetrieveTableRsp** pRsp) {
+ SSDataBlock* pBlock = NULL;
+ int32_t code = createSelectResultDataBlock(pSelect->pProjectionList, &pBlock);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = buildSelectResultDataBlock(pSelect->pProjectionList, pBlock);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = buildRetrieveTableRsp(pBlock, LIST_LENGTH(pSelect->pProjectionList), pRsp);
+ }
+ return code;
+}
int32_t qExecCommand(SNode* pStmt, SRetrieveTableRsp** pRsp) {
switch (nodeType(pStmt)) {
@@ -140,15 +604,17 @@ int32_t qExecCommand(SNode* pStmt, SRetrieveTableRsp** pRsp) {
case QUERY_NODE_RESET_QUERY_CACHE_STMT:
return execResetQueryCache();
case QUERY_NODE_SHOW_CREATE_DATABASE_STMT:
- return execShowCreateDatabase((SShowCreateDatabaseStmt*)pStmt);
+ return execShowCreateDatabase((SShowCreateDatabaseStmt*)pStmt, pRsp);
case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
- return execShowCreateTable((SShowCreateTableStmt*)pStmt);
+ return execShowCreateTable((SShowCreateTableStmt*)pStmt, pRsp);
case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
- return execShowCreateSTable((SShowCreateTableStmt*)pStmt);
+ return execShowCreateSTable((SShowCreateTableStmt*)pStmt, pRsp);
case QUERY_NODE_ALTER_LOCAL_STMT:
return execAlterLocal((SAlterLocalStmt*)pStmt);
case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
- return execShowLocalVariables();
+ return execShowLocalVariables(pRsp);
+ case QUERY_NODE_SELECT_STMT:
+ return execSelectWithoutFrom((SSelectStmt*)pStmt, pRsp);
default:
break;
}
diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c
index ae0f669d656a458a310339e461ad2e55918ee211..fde53b7064db29815f7e3008ff2d308947003b0c 100644
--- a/source/libs/command/src/explain.c
+++ b/source/libs/command/src/explain.c
@@ -13,11 +13,11 @@
* along with this program. If not, see .
*/
-#include "tdatablock.h"
#include "commandInt.h"
#include "plannodes.h"
#include "query.h"
#include "tcommon.h"
+#include "tdatablock.h"
int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pRes);
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level);
@@ -184,8 +184,8 @@ int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNo
pPhysiChildren = indefPhysiNode->node.pChildren;
break;
}
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
- SMergeIntervalPhysiNode *intPhysiNode = (SMergeIntervalPhysiNode *)pNode;
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: {
+ SMergeAlignedIntervalPhysiNode *intPhysiNode = (SMergeAlignedIntervalPhysiNode *)pNode;
pPhysiChildren = intPhysiNode->window.node.pChildren;
break;
}
@@ -199,6 +199,31 @@ int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNo
pPhysiChildren = mergePhysiNode->scan.node.pChildren;
break;
}
+ case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: {
+ SBlockDistScanPhysiNode *distPhysiNode = (SBlockDistScanPhysiNode *)pNode;
+ pPhysiChildren = distPhysiNode->node.pChildren;
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: {
+ SLastRowScanPhysiNode *lastRowPhysiNode = (SLastRowScanPhysiNode *)pNode;
+ pPhysiChildren = lastRowPhysiNode->node.pChildren;
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
+ SGroupSortPhysiNode *groupSortPhysiNode = (SGroupSortPhysiNode *)pNode;
+ pPhysiChildren = groupSortPhysiNode->node.pChildren;
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
+ SMergeIntervalPhysiNode *mergeIntPhysiNode = (SMergeIntervalPhysiNode *)pNode;
+ pPhysiChildren = mergeIntPhysiNode->window.node.pChildren;
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC: {
+ SInterpFuncPhysiNode *interpPhysiNode = (SInterpFuncPhysiNode *)pNode;
+ pPhysiChildren = interpPhysiNode->node.pChildren;
+ break;
+ }
default:
qError("not supported physical node type %d", pNode->type);
QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
@@ -216,7 +241,7 @@ int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNo
SExplainResNode *pResNode = NULL;
FOREACH(node, pPhysiChildren) {
QRY_ERR_RET(qExplainGenerateResNode((SPhysiNode *)node, group, &pResNode));
- QRY_ERR_RET(nodesListAppend(*pChildren, (SNode*)pResNode));
+ QRY_ERR_RET(nodesListAppend(*pChildren, (SNode *)pResNode));
}
return TSDB_CODE_SUCCESS;
@@ -232,14 +257,14 @@ int32_t qExplainGenerateResNodeExecInfo(SArray **pExecInfo, SExplainGroup *group
SExplainRsp *rsp = NULL;
for (int32_t i = 0; i < group->nodeNum; ++i) {
rsp = taosArrayGet(group->nodeExecInfo, i);
-/*
- if (group->physiPlanExecIdx >= rsp->numOfPlans) {
- qError("physiPlanIdx %d exceed plan num %d", group->physiPlanExecIdx, rsp->numOfPlans);
- return TSDB_CODE_QRY_APP_ERROR;
- }
+ /*
+ if (group->physiPlanExecIdx >= rsp->numOfPlans) {
+ qError("physiPlanIdx %d exceed plan num %d", group->physiPlanExecIdx, rsp->numOfPlans);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
- taosArrayPush(*pExecInfo, rsp->subplanInfo + group->physiPlanExecIdx);
-*/
+ taosArrayPush(*pExecInfo, rsp->subplanInfo + group->physiPlanExecIdx);
+ */
taosArrayPush(*pExecInfo, rsp->subplanInfo);
}
@@ -378,6 +403,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
}
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pTagScanNode->pScanCols->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ if (pTagScanNode->pScanPseudoCols) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pTagScanNode->pScanPseudoCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTagScanNode->node.pOutputDataBlockDesc->totalRowSize);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
@@ -415,6 +444,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pTblScanNode->scan.pScanCols->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ if (pTblScanNode->scan.pScanPseudoCols) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pTblScanNode->scan.pScanPseudoCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTblScanNode->scan.node.pOutputDataBlockDesc->totalRowSize);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_TABLE_SCAN_FORMAT, pTblScanNode->scanSeq[0], pTblScanNode->scanSeq[1]);
@@ -426,23 +459,23 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
if (EXPLAIN_MODE_ANALYZE == ctx->mode) {
EXPLAIN_ROW_NEW(level + 1, "I/O: ");
- int32_t nodeNum = taosArrayGetSize(pResNode->pExecInfo);
+ int32_t nodeNum = taosArrayGetSize(pResNode->pExecInfo);
struct STableScanAnalyzeInfo info = {0};
int32_t maxIndex = 0;
int32_t totalRows = 0;
- for(int32_t i = 0; i < nodeNum; ++i) {
+ for (int32_t i = 0; i < nodeNum; ++i) {
SExplainExecInfo *execInfo = taosArrayGet(pResNode->pExecInfo, i);
STableScanAnalyzeInfo *pScanInfo = (STableScanAnalyzeInfo *)execInfo->verboseInfo;
- info.totalBlocks += pScanInfo->totalBlocks;
- info.loadBlocks += pScanInfo->loadBlocks;
- info.totalRows += pScanInfo->totalRows;
- info.skipBlocks += pScanInfo->skipBlocks;
- info.filterTime += pScanInfo->filterTime;
- info.loadBlockStatis += pScanInfo->loadBlockStatis;
+ info.totalBlocks += pScanInfo->totalBlocks;
+ info.loadBlocks += pScanInfo->loadBlocks;
+ info.totalRows += pScanInfo->totalRows;
+ info.skipBlocks += pScanInfo->skipBlocks;
+ info.filterTime += pScanInfo->filterTime;
+ info.loadBlockStatis += pScanInfo->loadBlockStatis;
info.totalCheckedRows += pScanInfo->totalCheckedRows;
- info.filterOutBlocks += pScanInfo->filterOutBlocks;
+ info.filterOutBlocks += pScanInfo->filterOutBlocks;
if (pScanInfo->totalRows > totalRows) {
totalRows = pScanInfo->totalRows;
@@ -468,13 +501,14 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
- //Rows out: Avg 4166.7 rows x 24 workers. Max 4187 rows (seg7) with 0.220 ms to first row, 1.738 ms to end, start offset by 1.470 ms.
+ // Rows out: Avg 4166.7 rows x 24 workers. Max 4187 rows (seg7) with 0.220 ms to first row, 1.738 ms to end,
+ // start offset by 1.470 ms.
SExplainExecInfo *execInfo = taosArrayGet(pResNode->pExecInfo, maxIndex);
STableScanAnalyzeInfo *p1 = (STableScanAnalyzeInfo *)execInfo->verboseInfo;
EXPLAIN_ROW_NEW(level + 1, " ");
- EXPLAIN_ROW_APPEND("max_row_task=%d, total_rows:%" PRId64 ", ep:%s (cost=%.3f..%.3f)", maxIndex, p1->totalRows, "tbd",
- execInfo->startupCost, execInfo->totalCost);
+ EXPLAIN_ROW_APPEND("max_row_task=%d, total_rows:%" PRId64 ", ep:%s (cost=%.3f..%.3f)", maxIndex, p1->totalRows,
+ "tbd", execInfo->startupCost, execInfo->totalCost);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_END();
@@ -515,6 +549,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
}
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pSTblScanNode->scan.pScanCols->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ if (pSTblScanNode->scan.pScanPseudoCols) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pSTblScanNode->scan.pScanPseudoCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSTblScanNode->scan.node.pOutputDataBlockDesc->totalRowSize);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
@@ -752,7 +790,7 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_NEW(level + 1, "Sort Key: ");
if (pResNode->pExecInfo) {
for (int32_t i = 0; i < LIST_LENGTH(pSortNode->pSortKeys); ++i) {
- SOrderByExprNode *ptn = (SOrderByExprNode*)nodesListGetNode(pSortNode->pSortKeys, i);
+ SOrderByExprNode *ptn = (SOrderByExprNode *)nodesListGetNode(pSortNode->pSortKeys, i);
EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
}
}
@@ -841,8 +879,8 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
}
break;
}
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
- SMergeIntervalPhysiNode *pIntNode = (SMergeIntervalPhysiNode *)pNode;
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: {
+ SMergeAlignedIntervalPhysiNode *pIntNode = (SMergeAlignedIntervalPhysiNode *)pNode;
EXPLAIN_ROW_NEW(level, EXPLAIN_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
if (pResNode->pExecInfo) {
@@ -907,16 +945,16 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
if (pFillNode->pValues) {
- SNodeListNode *pValues = (SNodeListNode*)pFillNode->pValues;
+ SNodeListNode *pValues = (SNodeListNode *)pFillNode->pValues;
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILL_VALUE_FORMAT);
- SNode* tNode = NULL;
+ SNode *tNode = NULL;
int32_t i = 0;
FOREACH(tNode, pValues->pNodeList) {
if (i) {
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
}
- SValueNode* tValue = (SValueNode*)tNode;
- char *value = nodesGetStrValueFromNode(tValue);
+ SValueNode *tValue = (SValueNode *)tNode;
+ char *value = nodesGetStrValueFromNode(tValue);
EXPLAIN_ROW_APPEND(EXPLAIN_STRING_TYPE_FORMAT, value);
taosMemoryFree(value);
++i;
@@ -926,8 +964,7 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
}
- EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pFillNode->timeRange.skey,
- pFillNode->timeRange.ekey);
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pFillNode->timeRange.skey, pFillNode->timeRange.ekey);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
@@ -1070,13 +1107,13 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
-
+
if (EXPLAIN_MODE_ANALYZE == ctx->mode) {
// sort key
EXPLAIN_ROW_NEW(level + 1, "Merge Key: ");
if (pResNode->pExecInfo) {
for (int32_t i = 0; i < LIST_LENGTH(pMergeNode->pMergeKeys); ++i) {
- SOrderByExprNode *ptn = (SOrderByExprNode*)nodesListGetNode(pMergeNode->pMergeKeys, i);
+ SOrderByExprNode *ptn = (SOrderByExprNode *)nodesListGetNode(pMergeNode->pMergeKeys, i);
EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
}
}
@@ -1115,7 +1152,7 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_MERGE_KEYS_FORMAT);
for (int32_t i = 0; i < LIST_LENGTH(pMergeNode->pMergeKeys); ++i) {
- SOrderByExprNode *ptn = (SOrderByExprNode*)nodesListGetNode(pMergeNode->pMergeKeys, i);
+ SOrderByExprNode *ptn = (SOrderByExprNode *)nodesListGetNode(pMergeNode->pMergeKeys, i);
EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
}
EXPLAIN_ROW_END();
@@ -1130,6 +1167,258 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
}
}
break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: {
+ SBlockDistScanPhysiNode *pDistScanNode = (SBlockDistScanPhysiNode *)pNode;
+ EXPLAIN_ROW_NEW(level, EXPLAIN_DISTBLK_SCAN_FORMAT, pDistScanNode->tableName.tname);
+ EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
+ if (pResNode->pExecInfo) {
+ QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pDistScanNode->pScanCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ if (pDistScanNode->pScanPseudoCols) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pDistScanNode->pScanPseudoCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDistScanNode->node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ if (verbose) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
+ nodesGetOutputNumFromSlotList(pDistScanNode->node.pOutputDataBlockDesc->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDistScanNode->node.pOutputDataBlockDesc->outputRowSize);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+
+ if (pDistScanNode->node.pConditions) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
+ QRY_ERR_RET(nodesNodeToSQL(pDistScanNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
+ TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+ }
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: {
+ SLastRowScanPhysiNode *pLastRowNode = (SLastRowScanPhysiNode *)pNode;
+ EXPLAIN_ROW_NEW(level, EXPLAIN_LASTROW_SCAN_FORMAT, pLastRowNode->tableName.tname);
+ EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
+ if (pResNode->pExecInfo) {
+ QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pLastRowNode->pScanCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ if (pLastRowNode->pScanPseudoCols) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pLastRowNode->pScanPseudoCols->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pLastRowNode->node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ if (verbose) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
+ nodesGetOutputNumFromSlotList(pLastRowNode->node.pOutputDataBlockDesc->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pLastRowNode->node.pOutputDataBlockDesc->outputRowSize);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+
+ if (pLastRowNode->node.pConditions) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
+ QRY_ERR_RET(nodesNodeToSQL(pLastRowNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
+ TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+ }
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
+ SGroupSortPhysiNode *pSortNode = (SGroupSortPhysiNode *)pNode;
+ EXPLAIN_ROW_NEW(level, EXPLAIN_GROUP_SORT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
+ if (pResNode->pExecInfo) {
+ QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+
+ SDataBlockDescNode *pDescNode = pSortNode->node.pOutputDataBlockDesc;
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, nodesGetOutputNumFromSlotList(pDescNode->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDescNode->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ if (EXPLAIN_MODE_ANALYZE == ctx->mode) {
+ // sort key
+ EXPLAIN_ROW_NEW(level + 1, "Sort Key: ");
+ if (pResNode->pExecInfo) {
+ for (int32_t i = 0; i < LIST_LENGTH(pSortNode->pSortKeys); ++i) {
+ SOrderByExprNode *ptn = (SOrderByExprNode *)nodesListGetNode(pSortNode->pSortKeys, i);
+ EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
+ }
+ }
+
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ // sort method
+ EXPLAIN_ROW_NEW(level + 1, "Sort Method: ");
+
+ int32_t nodeNum = taosArrayGetSize(pResNode->pExecInfo);
+ SExplainExecInfo *execInfo = taosArrayGet(pResNode->pExecInfo, 0);
+ SSortExecInfo *pExecInfo = (SSortExecInfo *)execInfo->verboseInfo;
+ EXPLAIN_ROW_APPEND("%s", pExecInfo->sortMethod == SORT_QSORT_T ? "quicksort" : "merge sort");
+ if (pExecInfo->sortBuffer > 1024 * 1024) {
+ EXPLAIN_ROW_APPEND(" Buffers:%.2f Mb", pExecInfo->sortBuffer / (1024 * 1024.0));
+ } else if (pExecInfo->sortBuffer > 1024) {
+ EXPLAIN_ROW_APPEND(" Buffers:%.2f Kb", pExecInfo->sortBuffer / (1024.0));
+ } else {
+ EXPLAIN_ROW_APPEND(" Buffers:%d b", pExecInfo->sortBuffer);
+ }
+
+ EXPLAIN_ROW_APPEND(" loops:%d", pExecInfo->loops);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+ }
+
+ if (verbose) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
+ nodesGetOutputNumFromSlotList(pSortNode->node.pOutputDataBlockDesc->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSortNode->node.pOutputDataBlockDesc->outputRowSize);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+
+ if (pSortNode->node.pConditions) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
+ QRY_ERR_RET(nodesNodeToSQL(pSortNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
+ TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+ }
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
+ SMergeIntervalPhysiNode *pIntNode = (SMergeIntervalPhysiNode *)pNode;
+ EXPLAIN_ROW_NEW(level, EXPLAIN_MERGE_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
+ EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
+ if (pResNode->pExecInfo) {
+ QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pIntNode->window.pFuncs->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ if (verbose) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
+ nodesGetOutputNumFromSlotList(pIntNode->window.node.pOutputDataBlockDesc->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pIntNode->window.node.pOutputDataBlockDesc->outputRowSize);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ uint8_t precision = getIntervalPrecision(pIntNode);
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIME_WINDOWS_FORMAT,
+ INVERAL_TIME_FROM_PRECISION_TO_UNIT(pIntNode->interval, pIntNode->intervalUnit, precision),
+ pIntNode->intervalUnit, pIntNode->offset, getPrecisionUnit(precision),
+ INVERAL_TIME_FROM_PRECISION_TO_UNIT(pIntNode->sliding, pIntNode->slidingUnit, precision),
+ pIntNode->slidingUnit);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+
+ if (pIntNode->window.node.pConditions) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
+ QRY_ERR_RET(nodesNodeToSQL(pIntNode->window.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
+ TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+ }
+ break;
+ }
+ case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC: {
+ SInterpFuncPhysiNode *pInterpNode = (SInterpFuncPhysiNode *)pNode;
+ EXPLAIN_ROW_NEW(level, EXPLAIN_AGG_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
+ if (pResNode->pExecInfo) {
+ QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ if (pInterpNode->pFuncs) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pInterpNode->pFuncs->length);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+
+ EXPLAIN_ROW_APPEND(EXPLAIN_MODE_FORMAT, nodesGetFillModeString(pInterpNode->fillMode));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+
+ EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
+
+ if (verbose) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
+ nodesGetOutputNumFromSlotList(pInterpNode->node.pOutputDataBlockDesc->pSlots));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pInterpNode->node.pOutputDataBlockDesc->outputRowSize);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ if (pInterpNode->pFillValues) {
+ SNodeListNode *pValues = (SNodeListNode *)pInterpNode->pFillValues;
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILL_VALUE_FORMAT);
+ SNode *tNode = NULL;
+ int32_t i = 0;
+ FOREACH(tNode, pValues->pNodeList) {
+ if (i) {
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ }
+ SValueNode *tValue = (SValueNode *)tNode;
+ char *value = nodesGetStrValueFromNode(tValue);
+ EXPLAIN_ROW_APPEND(EXPLAIN_STRING_TYPE_FORMAT, value);
+ taosMemoryFree(value);
+ ++i;
+ }
+
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_INTERVAL_VALUE_FORMAT, pInterpNode->interval, pInterpNode->intervalUnit);
+ EXPLAIN_ROW_END();
+
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pInterpNode->timeRange.skey, pInterpNode->timeRange.ekey);
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+
+ if (pInterpNode->node.pConditions) {
+ EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
+ QRY_ERR_RET(nodesNodeToSQL(pInterpNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
+ TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
+ EXPLAIN_ROW_END();
+ QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
+ }
+ }
+ break;
}
default:
qError("not supported physical node type %d", pNode->type);
@@ -1190,17 +1479,12 @@ int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
}
- SSDataBlock *pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
- SColumnInfoData infoData = {0};
- infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
- infoData.info.bytes = TSDB_EXPLAIN_RESULT_ROW_SIZE;
-
- pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
- taosArrayPush(pBlock->pDataBlock, &infoData);
+ SSDataBlock *pBlock = createDataBlock();
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, TSDB_EXPLAIN_RESULT_ROW_SIZE, 1);
+ blockDataAppendColInfo(pBlock, &infoData);
+ blockDataEnsureCapacity(pBlock, rowNum);
- SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0);
- pInfoData->hasNull = false;
- colInfoDataEnsureCapacity(pInfoData, 0, rowNum);
+ SColumnInfoData *pInfoData = taosArrayGet(pBlock->pDataBlock, 0);
char buf[1024] = {0};
for (int32_t i = 0; i < rowNum; ++i) {
@@ -1210,9 +1494,7 @@ int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
colDataAppend(pInfoData, i, buf, false);
}
- pBlock->info.numOfCols = 1;
pBlock->info.rows = rowNum;
- pBlock->info.hasVarCol = true;
int32_t rspSize = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
@@ -1226,7 +1508,7 @@ int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
rsp->numOfRows = htonl(rowNum);
int32_t len = 0;
- blockCompressEncode(pBlock, rsp->data, &len, pBlock->info.numOfCols, 0);
+ blockEncode(pBlock, rsp->data, &len, taosArrayGetSize(pBlock->pDataBlock), 0);
ASSERT(len == rspSize - sizeof(SRetrieveTableRsp));
rsp->compLen = htonl(len);
diff --git a/source/libs/executor/CMakeLists.txt b/source/libs/executor/CMakeLists.txt
index ed15aeb0387dc0ab34e06458111bbca257047b36..89d08b3078d184e77bbc966f2f14e15dc09fddc9 100644
--- a/source/libs/executor/CMakeLists.txt
+++ b/source/libs/executor/CMakeLists.txt
@@ -8,7 +8,7 @@ add_library(executor STATIC ${EXECUTOR_SRC})
# )
target_link_libraries(executor
- PRIVATE os util common function parser planner qcom vnode scalar nodes index
+ PRIVATE os util common function parser planner qcom vnode scalar nodes index stream
)
target_include_directories(
diff --git a/source/libs/executor/inc/dataSinkInt.h b/source/libs/executor/inc/dataSinkInt.h
index dead1aff7383a0f6da2b8d83d290bdd7a1be3a31..9426c99a0fc4fa55429fb1541f80be3efe0ef62f 100644
--- a/source/libs/executor/inc/dataSinkInt.h
+++ b/source/libs/executor/inc/dataSinkInt.h
@@ -34,7 +34,7 @@ typedef struct SDataSinkManager {
typedef int32_t (*FPutDataBlock)(struct SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue);
typedef void (*FEndPut)(struct SDataSinkHandle* pHandle, uint64_t useconds);
-typedef void (*FGetDataLength)(struct SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryEnd);
+typedef void (*FGetDataLength)(struct SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryEnd);
typedef int32_t (*FGetDataBlock)(struct SDataSinkHandle* pHandle, SOutputData* pOutput);
typedef int32_t (*FDestroyDataSinker)(struct SDataSinkHandle* pHandle);
typedef int32_t (*FGetCacheSize)(struct SDataSinkHandle* pHandle, uint64_t* size);
@@ -50,6 +50,7 @@ typedef struct SDataSinkHandle {
int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle);
int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void *pParam);
+int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void *pParam);
#ifdef __cplusplus
}
diff --git a/source/libs/executor/inc/executil.h b/source/libs/executor/inc/executil.h
index 4ecf2ee7192d6ef847e7ee4d8697e67f0a446043..f9aba30a468c445757fa4cc21e083ba7813767f9 100644
--- a/source/libs/executor/inc/executil.h
+++ b/source/libs/executor/inc/executil.h
@@ -25,37 +25,36 @@
#define SET_RES_WINDOW_KEY(_k, _ori, _len, _uid) \
do { \
assert(sizeof(_uid) == sizeof(uint64_t)); \
- *(uint64_t *)(_k) = (_uid); \
+ *(uint64_t*)(_k) = (_uid); \
memcpy((_k) + sizeof(uint64_t), (_ori), (_len)); \
} while (0)
-#define SET_RES_EXT_WINDOW_KEY(_k, _ori, _len, _uid, _buf) \
- do { \
- assert(sizeof(_uid) == sizeof(uint64_t)); \
- *(void **)(_k) = (_buf); \
- *(uint64_t *)((_k) + POINTER_BYTES) = (_uid); \
- memcpy((_k) + POINTER_BYTES + sizeof(uint64_t), (_ori), (_len)); \
+#define SET_RES_EXT_WINDOW_KEY(_k, _ori, _len, _uid, _buf) \
+ do { \
+ assert(sizeof(_uid) == sizeof(uint64_t)); \
+ *(void**)(_k) = (_buf); \
+ *(uint64_t*)((_k) + POINTER_BYTES) = (_uid); \
+ memcpy((_k) + POINTER_BYTES + sizeof(uint64_t), (_ori), (_len)); \
} while (0)
-
-#define GET_RES_WINDOW_KEY_LEN(_l) ((_l) + sizeof(uint64_t))
+#define GET_RES_WINDOW_KEY_LEN(_l) ((_l) + sizeof(uint64_t))
#define GET_RES_EXT_WINDOW_KEY_LEN(_l) ((_l) + sizeof(uint64_t) + POINTER_BYTES)
-#define GET_TASKID(_t) (((SExecTaskInfo*)(_t))->id.str)
+#define GET_TASKID(_t) (((SExecTaskInfo*)(_t))->id.str)
typedef struct SGroupResInfo {
int32_t index;
- SArray* pRows; // SArray
+ SArray* pRows; // SArray
} SGroupResInfo;
typedef struct SResultRow {
- int32_t pageId; // pageId & rowId is the position of current result in disk-based output buffer
- int32_t offset:29; // row index in buffer page
- bool startInterp; // the time window start timestamp has done the interpolation already.
- bool endInterp; // the time window end timestamp has done the interpolation already.
- bool closed; // this result status: closed or opened
- uint32_t numOfRows; // number of rows of current time window
- STimeWindow win;
+ int32_t pageId; // pageId & rowId is the position of current result in disk-based output buffer
+ int32_t offset : 29; // row index in buffer page
+ bool startInterp; // the time window start timestamp has done the interpolation already.
+ bool endInterp; // the time window end timestamp has done the interpolation already.
+ bool closed; // this result status: closed or opened
+ uint32_t numOfRows; // number of rows of current time window
+ STimeWindow win;
struct SResultRowEntryInfo pEntryInfo[]; // For each result column, there is a resultInfo
} SResultRow;
@@ -66,56 +65,58 @@ typedef struct SResultRowPosition {
typedef struct SResKeyPos {
SResultRowPosition pos;
- uint64_t groupId;
- char key[];
+ uint64_t groupId;
+ char key[];
} SResKeyPos;
typedef struct SResultRowInfo {
- int32_t size; // number of result set
+ int32_t size; // number of result set
SResultRowPosition cur;
- SList* openWindow;
+ SList* openWindow;
} SResultRowInfo;
struct SqlFunctionCtx;
-size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput);
-void initResultRowInfo(SResultRowInfo* pResultRowInfo);
-void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo);
+size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput);
+void initResultRowInfo(SResultRowInfo* pResultRowInfo);
+void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo);
-void closeAllResultRows(SResultRowInfo* pResultRowInfo);
+void closeAllResultRows(SResultRowInfo* pResultRowInfo);
-void initResultRow(SResultRow *pResultRow);
-void closeResultRow(SResultRow* pResultRow);
-bool isResultRowClosed(SResultRow* pResultRow);
+void initResultRow(SResultRow* pResultRow);
+void closeResultRow(SResultRow* pResultRow);
+bool isResultRowClosed(SResultRow* pResultRow);
struct SResultRowEntryInfo* getResultEntryInfo(const SResultRow* pRow, int32_t index, const int32_t* offset);
-static FORCE_INLINE SResultRow *getResultRowByPos(SDiskbasedBuf* pBuf, SResultRowPosition* pos) {
- SFilePage* bufPage = (SFilePage*) getBufPage(pBuf, pos->pageId);
+static FORCE_INLINE SResultRow* getResultRowByPos(SDiskbasedBuf* pBuf, SResultRowPosition* pos) {
+ SFilePage* bufPage = (SFilePage*)getBufPage(pBuf, pos->pageId);
SResultRow* pRow = (SResultRow*)((char*)bufPage + pos->offset);
return pRow;
}
-void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SHashObj* pHashmap, int32_t order);
-void initMultiResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList);
+void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SHashObj* pHashmap, int32_t order);
+void initMultiResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList);
-void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo);
-bool hasDataInGroupInfo(SGroupResInfo* pGroupResInfo);
+void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo);
+bool hasDataInGroupInfo(SGroupResInfo* pGroupResInfo);
int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo);
SSDataBlock* createResDataBlock(SDataBlockDescNode* pNode);
-int32_t getTableList(void* metaHandle, SScanPhysiNode* pScanNode, STableListInfo* pListInfo, SNode* pTagCond);
-SArray* createSortInfo(SNodeList* pNodeList);
-SArray* extractPartitionColInfo(SNodeList* pNodeList);
-SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols, int32_t type);
+EDealRes doTranslateTagExpr(SNode** pNode, void* pContext);
+int32_t getTableList(void* metaHandle, void* vnode, SScanPhysiNode* pScanNode, STableListInfo* pListInfo);
+SArray* createSortInfo(SNodeList* pNodeList);
+SArray* extractPartitionColInfo(SNodeList* pNodeList);
+SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols,
+ int32_t type);
SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs);
SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, int32_t** rowEntryInfoOffset);
-void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols, bool outputEveryColumn);
-void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow);
+void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols, bool outputEveryColumn);
+void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow);
SInterval extractIntervalInfo(const STableScanPhysiNode* pTableScanNode);
SColumn extractColumnFromColumnNode(SColumnNode* pColNode);
@@ -125,4 +126,6 @@ void cleanupQueryTableDataCond(SQueryTableDataCond* pCond);
int32_t convertFillType(int32_t mode);
+int32_t resultrowComparAsc(const void* p1, const void* p2);
+
#endif // TDENGINE_QUERYUTIL_H
diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h
index 2a0f34cd03e02ac13b570907ab26f0f946557133..74bb80eed17f9e82539c37e425c5dc7a2d4fc1f3 100644
--- a/source/libs/executor/inc/executorimpl.h
+++ b/source/libs/executor/inc/executorimpl.h
@@ -39,6 +39,7 @@ extern "C" {
#include "tmsg.h"
#include "tpagedbuf.h"
#include "tstreamUpdate.h"
+#include "tstream.h"
#include "vnode.h"
#include "executorInt.h"
@@ -51,6 +52,12 @@ typedef int32_t (*__block_search_fn_t)(char* data, int32_t num, int64_t key, int
#define NEEDTO_COMPRESS_QUERY(size) ((size) > tsCompressColData ? 1 : 0)
+#define START_TS_COLUMN_INDEX 0
+#define END_TS_COLUMN_INDEX 1
+#define UID_COLUMN_INDEX 2
+#define GROUPID_COLUMN_INDEX UID_COLUMN_INDEX
+#define DELETE_GROUPID_COLUMN_INDEX 2
+
enum {
// when this task starts to execute, this status will set
TASK_NOT_COMPLETED = 0x1u,
@@ -74,8 +81,8 @@ typedef struct SResultInfo { // TODO refactor
} SResultInfo;
typedef struct STableQueryInfo {
- TSKEY lastKey; // last check ts, todo remove it later
- SResultRowPosition pos; // current active time window
+ TSKEY lastKey; // last check ts, todo remove it later
+ SResultRowPosition pos; // current active time window
} STableQueryInfo;
typedef struct SLimit {
@@ -98,7 +105,7 @@ typedef struct STaskCostInfo {
uint64_t loadDataTime;
SFileBlockLoadRecorder* pRecoder;
- uint64_t elapsedTime;
+ uint64_t elapsedTime;
uint64_t firstStageMergeTime;
uint64_t winInfoSize;
@@ -111,8 +118,8 @@ typedef struct STaskCostInfo {
} STaskCostInfo;
typedef struct SOperatorCostInfo {
- double openCost;
- double totalCost;
+ double openCost;
+ double totalCost;
} SOperatorCostInfo;
struct SOperatorInfo;
@@ -132,24 +139,38 @@ typedef struct STaskIdInfo {
char* str;
} STaskIdInfo;
+typedef struct {
+ //TODO remove prepareStatus
+ STqOffsetVal prepareStatus; // for tmq
+ STqOffsetVal lastStatus; // for tmq
+ void* metaBlk; // for tmq fetching meta
+ SSDataBlock* pullOverBlk; // for streaming
+ SWalFilterCond cond;
+ int64_t lastScanUid;
+ SStreamQueue* inputQueue;
+} SStreamTaskInfo;
+
typedef struct SExecTaskInfo {
- STaskIdInfo id;
- uint32_t status;
- STimeWindow window;
- STaskCostInfo cost;
- int64_t owner; // if it is in execution
- int32_t code;
+ STaskIdInfo id;
+ uint32_t status;
+ STimeWindow window;
+ STaskCostInfo cost;
+ int64_t owner; // if it is in execution
+ int32_t code;
+
+ SStreamTaskInfo streamInfo;
+
struct {
- char *tablename;
- char *dbname;
- int32_t sversion;
- int32_t tversion;
+ char* tablename;
+ char* dbname;
+ int32_t tversion;
+ SSchemaWrapper* sw;
} schemaVer;
- STableListInfo tableqinfoList; // this is a table list
- const char* sql; // query sql string
- jmp_buf env; // jump to this position when error happens.
- EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model]
+ STableListInfo tableqinfoList; // this is a table list
+ const char* sql; // query sql string
+ jmp_buf env; // jump to this position when error happens.
+ EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model]
struct SOperatorInfo* pRoot;
} SExecTaskInfo;
@@ -161,36 +182,36 @@ enum {
};
typedef struct SOperatorFpSet {
- __optr_open_fn_t _openFn; // DO NOT invoke this function directly
- __optr_fn_t getNextFn;
- __optr_fn_t getStreamResFn; // execute the aggregate in the stream model, todo remove it
- __optr_fn_t cleanupFn; // call this function to release the allocated resources ASAP
- __optr_close_fn_t closeFn;
- __optr_encode_fn_t encodeResultRow;
- __optr_decode_fn_t decodeResultRow;
- __optr_explain_fn_t getExplainFn;
+ __optr_open_fn_t _openFn; // DO NOT invoke this function directly
+ __optr_fn_t getNextFn;
+ __optr_fn_t getStreamResFn; // execute the aggregate in the stream model, todo remove it
+ __optr_fn_t cleanupFn; // call this function to release the allocated resources ASAP
+ __optr_close_fn_t closeFn;
+ __optr_encode_fn_t encodeResultRow;
+ __optr_decode_fn_t decodeResultRow;
+ __optr_explain_fn_t getExplainFn;
} SOperatorFpSet;
typedef struct SExprSupp {
SExprInfo* pExprInfo;
- int32_t numOfExprs; // the number of scalar expression in group operator
+ int32_t numOfExprs; // the number of scalar expression in group operator
SqlFunctionCtx* pCtx;
int32_t* rowEntryInfoOffset; // offset value for each row result cell info
} SExprSupp;
typedef struct SOperatorInfo {
- uint8_t operatorType;
- bool blocking; // block operator or not
- uint8_t status; // denote if current operator is completed
- char* name; // name, for debug purpose
- void* info; // extension attribution
- SExprSupp exprSupp;
- SExecTaskInfo* pTaskInfo;
- SOperatorCostInfo cost;
- SResultInfo resultInfo;
- struct SOperatorInfo** pDownstream; // downstram pointer list
- int32_t numOfDownstream; // number of downstream. The value is always ONE expect for join operator
- SOperatorFpSet fpSet;
+ uint8_t operatorType;
+ bool blocking; // block operator or not
+ uint8_t status; // denote if current operator is completed
+ char* name; // name, for debug purpose
+ void* info; // extension attribution
+ SExprSupp exprSupp;
+ SExecTaskInfo* pTaskInfo;
+ SOperatorCostInfo cost;
+ SResultInfo resultInfo;
+ struct SOperatorInfo** pDownstream; // downstram pointer list
+ int32_t numOfDownstream; // number of downstream. The value is always ONE expect for join operator
+ SOperatorFpSet fpSet;
} SOperatorInfo;
typedef enum {
@@ -203,12 +224,12 @@ typedef enum {
#define COL_MATCH_FROM_SLOT_ID 0x2
typedef struct SSourceDataInfo {
- int32_t index;
- SRetrieveTableRsp* pRsp;
- uint64_t totalRows;
- int32_t code;
- EX_SOURCE_STATUS status;
- const char* taskId;
+ int32_t index;
+ SRetrieveTableRsp* pRsp;
+ uint64_t totalRows;
+ int32_t code;
+ EX_SOURCE_STATUS status;
+ const char* taskId;
} SSourceDataInfo;
typedef struct SLoadRemoteDataInfo {
@@ -233,7 +254,8 @@ typedef struct SColMatchInfo {
int32_t srcSlotId; // source slot id
int32_t colId;
int32_t targetSlotId;
- bool output;
+ bool output; // todo remove this?
+ bool reserved;
int32_t matchType; // determinate the source according to col id or slot id
} SColMatchInfo;
@@ -247,32 +269,41 @@ typedef struct SSampleExecInfo {
uint32_t seed; // random seed value
} SSampleExecInfo;
+enum {
+ TABLE_SCAN__TABLE_ORDER = 1,
+ TABLE_SCAN__BLOCK_ORDER = 2,
+};
+
typedef struct STableScanInfo {
- void* dataReader;
+ STsdbReader* dataReader;
SReadHandle readHandle;
SFileBlockLoadRecorder readRecorder;
- int64_t numOfRows;
-// int32_t prevGroupId; // previous table group id
SScanInfo scanInfo;
int32_t scanTimes;
SNode* pFilterNode; // filter info, which is push down by optimizer
- SqlFunctionCtx* pCtx; // which belongs to the direct upstream operator operator query context
- SResultRowInfo* pResultRowInfo;
- int32_t* rowEntryInfoOffset;
- SExprInfo* pExpr;
+
SSDataBlock* pResBlock;
SArray* pColMatchInfo;
- int32_t numOfOutput;
-
SExprSupp pseudoSup;
SQueryTableDataCond cond;
int32_t scanFlag; // table scan flag to denote if it is a repeat/reverse/main scan
int32_t dataBlockLoadFlag;
SInterval interval; // if the upstream is an interval operator, the interval info is also kept here to get the time window to check if current data block needs to be loaded.
-
SSampleExecInfo sample; // sample execution info
- int32_t curTWinIdx;
+
+ int32_t currentGroupId;
+ int32_t currentTable;
+
+#if 0
+ struct {
+ uint64_t uid;
+ int64_t ts;
+ } lastStatus;
+#endif
+
+ int8_t scanMode;
+ int8_t noTable;
} STableScanInfo;
typedef struct STagScanInfo {
@@ -282,21 +313,32 @@ typedef struct STagScanInfo {
int32_t curPos;
SReadHandle readHandle;
STableListInfo *pTableList;
- SNode* pFilterNode; // filter info,
} STagScanInfo;
+typedef struct SLastrowScanInfo {
+ SSDataBlock *pRes;
+ SArray *pTableList;
+ SReadHandle readHandle;
+ void *pLastrowReader;
+ SArray *pColMatchInfo;
+ int32_t *pSlotIds;
+ SExprSupp pseudoExprSup;
+} SLastrowScanInfo;
+
typedef enum EStreamScanMode {
STREAM_SCAN_FROM_READERHANDLE = 1,
STREAM_SCAN_FROM_RES,
STREAM_SCAN_FROM_UPDATERES,
- STREAM_SCAN_FROM_DATAREADER,
+ STREAM_SCAN_FROM_DATAREADER, // todo(liuyao) delete it
+ STREAM_SCAN_FROM_DATAREADER_RETRIEVE,
+ STREAM_SCAN_FROM_DATAREADER_RANGE,
} EStreamScanMode;
typedef struct SCatchSupporter {
- SHashObj* pWindowHashTable; // quick locate the window object for each window
- SDiskbasedBuf* pDataBuf; // buffer based on blocked-wised disk file
- int32_t keySize;
- int64_t* pKeyBuf;
+ SHashObj* pWindowHashTable; // quick locate the window object for each window
+ SDiskbasedBuf* pDataBuf; // buffer based on blocked-wised disk file
+ int32_t keySize;
+ int64_t* pKeyBuf;
} SCatchSupporter;
typedef struct SStreamAggSupporter {
@@ -312,42 +354,52 @@ typedef struct SStreamAggSupporter {
typedef struct SessionWindowSupporter {
SStreamAggSupporter* pStreamAggSup;
- int64_t gap;
- uint8_t parentType;
+ int64_t gap;
+ uint8_t parentType;
} SessionWindowSupporter;
-typedef struct SStreamBlockScanInfo {
- SArray* pBlockLists; // multiple SSDatablock.
- SSDataBlock* pRes; // result SSDataBlock
- SSDataBlock* pUpdateRes; // update SSDataBlock
- int32_t updateResIndex;
- int32_t blockType; // current block type
- int32_t validBlockIndex; // Is current data has returned?
- SColumnInfo* pCols; // the output column info
- uint64_t numOfExec; // execution times
- void* streamBlockReader;// stream block reader handle
- SArray* pColMatchInfo; //
- SNode* pCondition;
- int32_t tsArrayIndex;
- SArray* tsArray;
- uint64_t groupId;
- SUpdateInfo* pUpdateInfo;
+typedef struct SStreamScanInfo {
+ uint64_t tableUid; // queried super table uid
+ SExprInfo* pPseudoExpr;
+ int32_t numOfPseudoExpr;
+ int32_t primaryTsIndex; // primary time stamp slot id
+ SReadHandle readHandle;
+ SInterval interval; // if the upstream is an interval operator, the interval info is also kept here.
+ SArray* pColMatchInfo; //
+ SNode* pCondition;
+
+ SArray* pBlockLists; // multiple SSDatablock.
+ SSDataBlock* pRes; // result SSDataBlock
+ SSDataBlock* pUpdateRes; // update SSDataBlock
+ int32_t updateResIndex;
+ int32_t blockType; // current block type
+ int32_t validBlockIndex; // Is current data has returned?
+ uint64_t numOfExec; // execution times
+ STqReader* tqReader;
+
+ int32_t tsArrayIndex;
+ SArray* tsArray;
+ uint64_t groupId;
+ SUpdateInfo* pUpdateInfo;
+
+ EStreamScanMode scanMode;
+ SOperatorInfo* pStreamScanOp;
+ SOperatorInfo* pTableScanOp;
+ SArray* childIds;
+ SessionWindowSupporter sessionSup;
+ bool assignBlockUid; // assign block uid to groupId, temporarily used for generating rollup SMA.
+ int32_t scanWinIndex; // for state operator
+ int32_t pullDataResIndex;
+ SSDataBlock* pPullDataRes; // pull data SSDataBlock
+ SSDataBlock* pDeleteDataRes; // delete data SSDataBlock
+ int32_t deleteDataIndex;
+ STimeWindow updateWin;
- SExprInfo* pPseudoExpr;
- int32_t numOfPseudoExpr;
+ // status for tmq
+ // SSchemaWrapper schema;
+ STqOffset offset;
- int32_t primaryTsIndex; // primary time stamp slot id
- void* pDataReader;
- SReadHandle readHandle;
- uint64_t tableUid; // queried super table uid
- EStreamScanMode scanMode;
- SOperatorInfo* pOperatorDumy;
- SInterval interval; // if the upstream is an interval operator, the interval info is also kept here.
- SArray* childIds;
- SessionWindowSupporter sessionSup;
- bool assignBlockUid; // assign block uid to groupId, temporarily used for generating rollup SMA.
- int32_t scanWinIndex;
-} SStreamBlockScanInfo;
+} SStreamScanInfo;
typedef struct SSysTableScanInfo {
SRetrieveMetaTableRsp* pRsp;
@@ -356,6 +408,7 @@ typedef struct SSysTableScanInfo {
tsem_t ready;
SReadHandle readHandle;
int32_t accountId;
+ const char* pUser;
bool showRewrite;
SNode* pCondition; // db_name filter condition, to discard data that are not in current database
SMTbCursor* pCur; // cursor for iterate the local table meta store.
@@ -397,26 +450,43 @@ typedef struct SIntervalAggOperatorInfo {
// SOptrBasicInfo should be first, SAggSupporter should be second for stream encode
SOptrBasicInfo binfo; // basic info
SAggSupporter aggSup; // aggregate supporter
-
+ SExprSupp scalarSupp; // supporter for perform scalar function
SGroupResInfo groupResInfo; // multiple results build supporter
SInterval interval; // interval info
int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator.
STimeWindow win; // query time range
bool timeWindowInterpo; // interpolation needed or not
- char** pRow; // previous row/tuple of already processed datablock
SArray* pInterpCols; // interpolation columns
int32_t order; // current SSDataBlock scan order
EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model]
STimeWindowAggSupp twAggSup;
bool invertible;
SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation.
+ bool ignoreExpiredData;
+ SArray* pRecycledPages;
+ SArray* pDelWins; // SWinRes
+ int32_t delIndex;
+ SSDataBlock* pDelRes;
+
+ SNode *pCondition;
} SIntervalAggOperatorInfo;
+typedef struct SMergeAlignedIntervalAggOperatorInfo {
+ SIntervalAggOperatorInfo *intervalAggOperatorInfo;
+
+ bool hasGroupId;
+ uint64_t groupId;
+ SSDataBlock* prefetchedBlock;
+ bool inputBlocksFinished;
+
+ SNode* pCondition;
+} SMergeAlignedIntervalAggOperatorInfo;
+
typedef struct SStreamFinalIntervalOperatorInfo {
// SOptrBasicInfo should be first, SAggSupporter should be second for stream encode
SOptrBasicInfo binfo; // basic info
SAggSupporter aggSup; // aggregate supporter
-
+ SExprSupp scalarSupp; // supporter for perform scalar function
SGroupResInfo groupResInfo; // multiple results build supporter
SInterval interval; // interval info
int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator.
@@ -424,8 +494,18 @@ typedef struct SStreamFinalIntervalOperatorInfo {
STimeWindowAggSupp twAggSup;
SArray* pChildren;
SSDataBlock* pUpdateRes;
+ bool returnUpdate;
SPhysiNode* pPhyNode; // create new child
bool isFinal;
+ SHashObj* pPullDataMap;
+ SArray* pPullWins; // SPullWindowInfo
+ int32_t pullIndex;
+ SSDataBlock* pPullDataRes;
+ bool ignoreExpiredData;
+ SArray* pRecycledPages;
+ SArray* pDelWins; // SWinRes
+ int32_t delIndex;
+ SSDataBlock* pDelRes;
} SStreamFinalIntervalOperatorInfo;
typedef struct SAggOperatorInfo {
@@ -437,6 +517,8 @@ typedef struct SAggOperatorInfo {
uint64_t groupId;
SGroupResInfo groupResInfo;
SExprSupp scalarExprSup;
+
+ SNode *pCondition;
} SAggOperatorInfo;
typedef struct SProjectOperatorInfo {
@@ -462,6 +544,10 @@ typedef struct SIndefOperatorInfo {
SAggSupporter aggSup;
SArray* pPseudoColInfo;
SExprSupp scalarSup;
+ SNode* pCondition;
+ uint64_t groupId;
+
+ SSDataBlock* pNextGroupRes;
} SIndefOperatorInfo;
typedef struct SFillOperatorInfo {
@@ -471,6 +557,10 @@ typedef struct SFillOperatorInfo {
void** p;
SSDataBlock* existNewGroupBlock;
bool multigroupResult;
+ STimeWindow win;
+ SNode* pCondition;
+ SArray* pColMatchColInfo;
+ int32_t primaryTsCol;
} SFillOperatorInfo;
typedef struct SGroupbyOperatorInfo {
@@ -531,6 +621,7 @@ typedef struct SSessionAggOperatorInfo {
int64_t gap; // session window gap
int32_t tsSlotId; // primary timestamp slot id
STimeWindowAggSupp twAggSup;
+ const SNode* pCondition;
} SSessionAggOperatorInfo;
typedef struct SResultWindowInfo {
@@ -548,6 +639,7 @@ typedef struct SStateWindowInfo {
typedef struct SStreamSessionAggOperatorInfo {
SOptrBasicInfo binfo;
SStreamAggSupporter streamAggSup;
+ SExprSupp scalarSupp; // supporter for perform scalar function
SGroupResInfo groupResInfo;
int64_t gap; // session window gap
int32_t primaryTsIndex; // primary timestamp slot id
@@ -557,12 +649,14 @@ typedef struct SStreamSessionAggOperatorInfo {
SSDataBlock* pWinBlock; // window result
SqlFunctionCtx* pDummyCtx; // for combine
SSDataBlock* pDelRes; // delete result
+ bool returnDelete;
SSDataBlock* pUpdateRes; // update window
SHashObj* pStDeleted;
void* pDelIterator;
SArray* pChildren; // cache for children's result; final stream operator
SPhysiNode* pPhyNode; // create new child
bool isFinal;
+ bool ignoreExpiredData;
} SStreamSessionAggOperatorInfo;
typedef struct STimeSliceOperatorInfo {
@@ -590,22 +684,25 @@ typedef struct SStateWindowOperatorInfo {
int32_t tsSlotId; // primary timestamp column slot id
STimeWindowAggSupp twAggSup;
// bool reptScan;
+ const SNode* pCondition;
} SStateWindowOperatorInfo;
typedef struct SStreamStateAggOperatorInfo {
SOptrBasicInfo binfo;
SStreamAggSupporter streamAggSup;
+ SExprSupp scalarSupp; // supporter for perform scalar function
SGroupResInfo groupResInfo;
int32_t primaryTsIndex; // primary timestamp slot id
int32_t order; // current SSDataBlock scan order
STimeWindowAggSupp twAggSup;
- SColumn stateCol; // start row index
+ SColumn stateCol;
SqlFunctionCtx* pDummyCtx; // for combine
SSDataBlock* pDelRes;
SHashObj* pSeDeleted;
void* pDelIterator;
SArray* pScanWindow;
SArray* pChildren; // cache for children's result;
+ bool ignoreExpiredData;
} SStreamStateAggOperatorInfo;
typedef struct SSortedMergeOperatorInfo {
@@ -636,6 +733,8 @@ typedef struct SSortOperatorInfo {
int64_t startTs; // sort start time
uint64_t sortElapsed; // sort elapsed time, time to flush to disk not included.
+
+ SNode* pCondition;
} SSortOperatorInfo;
typedef struct STagFilterOperatorInfo {
@@ -653,7 +752,7 @@ typedef struct SJoinOperatorInfo {
SSDataBlock *pRight;
int32_t rightPos;
SColumnInfo rightCol;
- SNode *pOnCondition;
+ SNode *pCondAfterMerge;
} SJoinOperatorInfo;
#define OPTR_IS_OPENED(_optr) (((_optr)->status & OP_OPENED) == OP_OPENED)
@@ -672,7 +771,7 @@ int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t
void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock);
void cleanupBasicInfo(SOptrBasicInfo* pInfo);
int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr);
-void cleanupExprSup(SExprSupp* pSup);
+void cleanupExprSupp(SExprSupp* pSup);
int32_t initAggInfo(SExprSupp *pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize,
const char* pkey);
void initResultSizeInfo(SOperatorInfo* pOperator, int32_t numOfRows);
@@ -685,18 +784,23 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLo
int32_t compLen, int32_t numOfOutput, int64_t startTs, uint64_t* total,
SArray* pColList);
void getAlignQueryTimeWindow(SInterval* pInterval, int32_t precision, int64_t key, STimeWindow* win);
+STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order);
+
int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t *order, int32_t* scanFlag);
int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz);
void doSetOperatorCompleted(SOperatorInfo* pOperator);
void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock);
+int32_t addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr,
+ SSDataBlock* pBlock, const char* idStr);
void cleanupAggSup(SAggSupporter* pAggSup);
void destroyBasicOperatorInfo(void* param, int32_t numOfOutput);
void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle);
void setTbNameColData(void* pMeta, const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId);
-void cleanupExecSupp(SExprSupp* pSupp);
+int32_t doPrepareScan(SOperatorInfo* pOperator, uint64_t uid, int64_t ts);
+int32_t doGetScanStatus(SOperatorInfo* pOperator, uint64_t* uid, int64_t* ts);
SSDataBlock* loadNextDataBlock(void* param);
@@ -708,31 +812,34 @@ SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pR
SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode* pExNode, SExecTaskInfo* pTaskInfo);
-SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, tsdbReaderT pDataReader, SReadHandle* pHandle, SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode,
STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo);
-SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode *pScanPhyNode, SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode *pScanPhyNode, const char* pUser, SExecTaskInfo* pTaskInfo);
-SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols, SSDataBlock* pResultBlock, SExprInfo* pScalarExprInfo,
+SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols, SSDataBlock* pResultBlock, SNode* pCondition, SExprInfo* pScalarExprInfo,
int32_t numOfScalarExpr, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhysiNode *pNode, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhysiNode* pProjPhyNode, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode, SExecTaskInfo* pTaskInfo);
-
-SOperatorInfo* createMultiwaySortMergeOperatorInfo(SOperatorInfo** downStreams, int32_t numStreams, SSDataBlock* pInputBlock,
- SSDataBlock* pResBlock, SArray* pSortInfo, SArray* pColMatchColInfo,
- SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** dowStreams, size_t numStreams, SMergePhysiNode* pMergePhysiNode, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t numOfDownstream, SExprInfo* pExprInfo, int32_t num, SArray* pSortInfo, SArray* pGroupInfo, SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createLastrowScanOperator(SLastRowScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
+ SArray* pTableList, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
- STimeWindowAggSupp *pTwAggSupp, SExecTaskInfo* pTaskInfo, bool isStream);
+ STimeWindowAggSupp* pTwAggSupp, SIntervalPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, bool isStream);
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
+ SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
+ SNode* pCondition, SExecTaskInfo* pTaskInfo);
+
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild);
SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
@@ -740,21 +847,22 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SExpr
STimeWindowAggSupp *pTwAggSupp, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, int64_t gap, int32_t tsSlotId, STimeWindowAggSupp* pTwAggSupp,
- SExecTaskInfo* pTaskInfo);
+ SNode* pCondition, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResultBlock, SArray* pGroupColList, SNode* pCondition,
SExprInfo* pScalarExprInfo, int32_t numOfScalarExpr, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createDataBlockInfoScanOperator(void* dataReader, SReadHandle* readHandle, uint64_t uid, SBlockDistScanPhysiNode* pBlockScanNode,
SExecTaskInfo* pTaskInfo);
-SOperatorInfo* createStreamScanOperatorInfo(void* pDataReader, SReadHandle* pHandle,
- STableScanPhysiNode* pTableScanNode, SExecTaskInfo* pTaskInfo, STimeWindowAggSupp* pTwSup);
+SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle,
+ STableScanPhysiNode* pTableScanNode, SExecTaskInfo* pTaskInfo, STimeWindowAggSupp* pTwSup, uint64_t queryId, uint64_t taskId);
SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode* pPhyFillNode, bool multigroupResult,
SExecTaskInfo* pTaskInfo);
SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfCols,
- SSDataBlock* pResBlock, STimeWindowAggSupp *pTwAggSupp, int32_t tsSlotId, SColumn* pStateKeyCol, SExecTaskInfo* pTaskInfo);
+ SSDataBlock* pResBlock, STimeWindowAggSupp *pTwAggSupp, int32_t tsSlotId,
+ SColumn* pStateKeyCol, SNode* pCondition, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo);
@@ -793,9 +901,10 @@ int32_t getMaximumIdleDurationSec();
* ops: root operator
* data: *data save the result of encode, need to be freed by caller
* length: *length save the length of *data
+ * nOptrWithVal: *nOptrWithVal save the number of optr with value
* return: result code, 0 means success
*/
-int32_t encodeOperator(SOperatorInfo* ops, char** data, int32_t *length);
+int32_t encodeOperator(SOperatorInfo* ops, char** data, int32_t *length, int32_t *nOptrWithVal);
/*
* ops: root operator, created by caller
@@ -808,7 +917,7 @@ int32_t decodeOperator(SOperatorInfo* ops, const char* data, int32_t length);
void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status);
int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId,
const char* sql, EOPTR_EXEC_MODEL model);
-int32_t createDataSinkParam(SDataSinkNode *pNode, void **pParam, qTaskInfo_t* pTaskInfo);
+int32_t createDataSinkParam(SDataSinkNode *pNode, void **pParam, qTaskInfo_t* pTaskInfo, SReadHandle* readHandle);
int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SExplainExecInfo** pRes, int32_t* capacity,
int32_t* resNum);
@@ -816,7 +925,7 @@ int32_t aggDecodeResultRow(SOperatorInfo* pOperator, char* result);
int32_t aggEncodeResultRow(SOperatorInfo* pOperator, char** result, int32_t* length);
STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval,
- int32_t precision, STimeWindow* win);
+ int32_t order);
int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimaryColumn, int32_t startPos, TSKEY ekey,
__block_search_fn_t searchFn, STableQueryInfo* item, int32_t order);
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);
@@ -825,23 +934,29 @@ int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, const char* pKey, SqlF
SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize);
SResultWindowInfo* getSessionTimeWindow(SStreamAggSupporter* pAggSup, TSKEY startTs,
TSKEY endTs, uint64_t groupId, int64_t gap, int32_t* pIndex);
+SResultWindowInfo* getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs,
+ TSKEY endTs, uint64_t groupId, int64_t gap, int32_t* pIndex);
+bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap);
int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
TSKEY* pEndTs, int32_t rows, int32_t start, int64_t gap, SHashObj* pStDeleted);
bool functionNeedToExecute(SqlFunctionCtx* pCtx);
-int32_t compareTimeWindow(const void* p1, const void* p2, const void* param);
int32_t finalizeResultRowIntoResultDataBlock(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition,
SqlFunctionCtx* pCtx, SExprInfo* pExprInfo, int32_t numOfExprs, const int32_t* rowCellOffset,
SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo);
-int32_t createMultipleDataReaders(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
- STableListInfo* pTableListInfo, SArray* arrayReader, uint64_t queryId,
- uint64_t taskId, SNode* pTagCond);
-SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SArray* dataReaders,
- SReadHandle* readHandle, SExecTaskInfo* pTaskInfo);
+int32_t createScanTableListInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
+ STableListInfo* pTableListInfo, uint64_t queryId, uint64_t taskId);
+SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSortPhysiNode* pSortPhyNode,
+ SExecTaskInfo* pTaskInfo);
+SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, STableListInfo *pTableListInfo,
+ SReadHandle* readHandle, SExecTaskInfo* pTaskInfo, uint64_t queryId, uint64_t taskId);
void copyUpdateDataBlock(SSDataBlock* pDest, SSDataBlock* pSource, int32_t tsColIndex);
+int32_t generateGroupIdMap(STableListInfo* pTableListInfo, SReadHandle* pHandle, SNodeList* groupKey);
+SSDataBlock* createPullDataBlock();
+
#ifdef __cplusplus
}
#endif
diff --git a/source/libs/executor/inc/tfill.h b/source/libs/executor/inc/tfill.h
index 3b80b262ca41830c569fefb4f4230fa3362b9911..0349632b9aa177a140c21b39e96232bfed8ce8b1 100644
--- a/source/libs/executor/inc/tfill.h
+++ b/source/libs/executor/inc/tfill.h
@@ -42,6 +42,7 @@ typedef struct SFillInfo {
TSKEY start; // start timestamp
TSKEY end; // endKey for fill
TSKEY currentKey; // current active timestamp, the value may be changed during the fill procedure.
+ int32_t tsSlotId; // primary time stamp slot id
int32_t order; // order [TSDB_ORDER_ASC|TSDB_ORDER_DESC]
int32_t type; // fill type
int32_t numOfRows; // number of rows in the input data block
@@ -74,8 +75,8 @@ struct SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, co
bool taosFillHasMoreResults(struct SFillInfo* pFillInfo);
SFillInfo* taosCreateFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int32_t capacity, int32_t numOfCols,
- SInterval* pInterval, int32_t fillType,
- struct SFillColInfo* pCol, const char* id);
+ SInterval* pInterval, int32_t fillType, struct SFillColInfo* pCol, int32_t slotId,
+ const char* id);
void* taosDestroyFillInfo(struct SFillInfo *pFillInfo);
int64_t taosFillResultDataBlock(struct SFillInfo* pFillInfo, SSDataBlock* p, int32_t capacity);
diff --git a/source/libs/executor/inc/tsort.h b/source/libs/executor/inc/tsort.h
index 363f379ee471e9d9d604784f1fcd24880b4ae3e7..972f4469e47cef127a0137d3d360cf98f7657976 100644
--- a/source/libs/executor/inc/tsort.h
+++ b/source/libs/executor/inc/tsort.h
@@ -50,6 +50,7 @@ typedef struct SMsortComparParam {
void **pSources;
int32_t numOfSources;
SArray *orderInfo; // SArray
+ bool cmpGroupId;
} SMsortComparParam;
typedef struct SSortHandle SSortHandle;
@@ -99,6 +100,11 @@ int32_t tsortSetFetchRawDataFp(SSortHandle* pHandle, _sort_fetch_block_fn_t fetc
*/
int32_t tsortSetComparFp(SSortHandle* pHandle, _sort_merge_compar_fn_t fp);
+/**
+ *
+ */
+int32_t tsortSetCompareGroupId(SSortHandle* pHandle, bool compareGroupId);
+
/**
*
* @param pHandle
@@ -130,6 +136,13 @@ bool tsortIsNullVal(STupleHandle* pVHandle, int32_t colId);
*/
void* tsortGetValue(STupleHandle* pVHandle, int32_t colId);
+/**
+ *
+ * @param pVHandle
+ * @return
+ */
+uint64_t tsortGetGroupId(STupleHandle* pVHandle);
+
/**
*
* @param pSortHandle
diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f6817cd6bc4380f542e84976edb2145566eb625
--- /dev/null
+++ b/source/libs/executor/src/cachescanoperator.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "os.h"
+#include "function.h"
+#include "tname.h"
+
+#include "tdatablock.h"
+#include "tmsg.h"
+
+#include "executorimpl.h"
+#include "tcompare.h"
+#include "thash.h"
+#include "ttypes.h"
+#include "executorInt.h"
+
+static SSDataBlock* doScanLastrow(SOperatorInfo* pOperator);
+static void destroyLastrowScanOperator(void* param, int32_t numOfOutput);
+static int32_t extractTargetSlotId(const SArray* pColMatchInfo, SExecTaskInfo* pTaskInfo, int32_t** pSlotIds);
+
+SOperatorInfo* createLastrowScanOperator(SLastRowScanPhysiNode* pScanNode, SReadHandle* readHandle, SArray* pTableList,
+ SExecTaskInfo* pTaskInfo) {
+ SLastrowScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SLastrowScanInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+ if (pInfo == NULL || pOperator == NULL) {
+ goto _error;
+ }
+
+ pInfo->pTableList = pTableList;
+ pInfo->readHandle = *readHandle;
+ pInfo->pRes = createResDataBlock(pScanNode->node.pOutputDataBlockDesc);
+
+ int32_t numOfCols = 0;
+ pInfo->pColMatchInfo = extractColMatchInfo(pScanNode->pScanCols, pScanNode->node.pOutputDataBlockDesc, &numOfCols,
+ COL_MATCH_FROM_COL_ID);
+ int32_t code = extractTargetSlotId(pInfo->pColMatchInfo, pTaskInfo, &pInfo->pSlotIds);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+
+ tsdbLastRowReaderOpen(readHandle->vnode, LASTROW_RETRIEVE_TYPE_SINGLE, pTableList, taosArrayGetSize(pInfo->pColMatchInfo),
+ &pInfo->pLastrowReader);
+
+ if (pScanNode->pScanPseudoCols != NULL) {
+ SExprSupp* pPseudoExpr = &pInfo->pseudoExprSup;
+
+ pPseudoExpr->pExprInfo = createExprInfo(pScanNode->pScanPseudoCols, NULL, &pPseudoExpr->numOfExprs);
+ pPseudoExpr->pCtx = createSqlFunctionCtx(pPseudoExpr->pExprInfo, pPseudoExpr->numOfExprs, &pPseudoExpr->rowEntryInfoOffset);
+ }
+
+ pOperator->name = "LastrowScanOperator";
+ pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->pTaskInfo = pTaskInfo;
+ pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock);
+
+ initResultSizeInfo(pOperator, 1024);
+ blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
+
+ pOperator->fpSet =
+ createOperatorFpSet(operatorDummyOpenFn, doScanLastrow, NULL, NULL, destroyLastrowScanOperator, NULL, NULL, NULL);
+ pOperator->cost.openCost = 0;
+ return pOperator;
+
+ _error:
+ pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
+ taosMemoryFree(pInfo);
+ taosMemoryFree(pOperator);
+ return NULL;
+}
+
+SSDataBlock* doScanLastrow(SOperatorInfo* pOperator) {
+ if (pOperator->status == OP_EXEC_DONE) {
+ return NULL;
+ }
+
+ SLastrowScanInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ int32_t size = taosArrayGetSize(pInfo->pTableList);
+ if (size == 0) {
+ setTaskStatus(pTaskInfo, TASK_COMPLETED);
+ return NULL;
+ }
+
+ // check if it is a group by tbname
+ if (size == taosArrayGetSize(pInfo->pTableList)) {
+ blockDataCleanup(pInfo->pRes);
+ SArray* pUidList = taosArrayInit(1, sizeof(tb_uid_t));
+ int32_t code = tsdbRetrieveLastRow(pInfo->pLastrowReader, pInfo->pRes, pInfo->pSlotIds, pUidList);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
+
+ // check for tag values
+ if (pInfo->pRes->info.rows > 0 && pInfo->pseudoExprSup.numOfExprs > 0) {
+ SExprSupp* pSup = &pInfo->pseudoExprSup;
+ pInfo->pRes->info.uid = *(tb_uid_t*) taosArrayGet(pUidList, 0);
+ addTagPseudoColumnData(&pInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pInfo->pRes, GET_TASKID(pTaskInfo));
+ }
+
+ doSetOperatorCompleted(pOperator);
+ return (pInfo->pRes->info.rows == 0) ? NULL : pInfo->pRes;
+ } else {
+ // todo fetch the result for each group
+ }
+
+ return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes;
+}
+
+void destroyLastrowScanOperator(void* param, int32_t numOfOutput) {
+ SLastrowScanInfo* pInfo = (SLastrowScanInfo*)param;
+ blockDataDestroy(pInfo->pRes);
+ tsdbLastrowReaderClose(pInfo->pLastrowReader);
+
+ taosMemoryFreeClear(param);
+}
+
+int32_t extractTargetSlotId(const SArray* pColMatchInfo, SExecTaskInfo* pTaskInfo, int32_t** pSlotIds) {
+ size_t numOfCols = taosArrayGetSize(pColMatchInfo);
+
+ *pSlotIds = taosMemoryMalloc(numOfCols * sizeof(int32_t));
+ if (*pSlotIds == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColMatchInfo* pColMatch = taosArrayGet(pColMatchInfo, i);
+ for (int32_t j = 0; j < pTaskInfo->schemaVer.sw->nCols; ++j) {
+ if (pColMatch->colId == pTaskInfo->schemaVer.sw->pSchema[j].colId &&
+ pColMatch->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
+ (*pSlotIds)[pColMatch->targetSlotId] = -1;
+ break;
+ }
+
+ if (pColMatch->colId == pTaskInfo->schemaVer.sw->pSchema[j].colId) {
+ (*pSlotIds)[pColMatch->targetSlotId] = j;
+ break;
+ }
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
\ No newline at end of file
diff --git a/source/libs/executor/src/dataDeleter.c b/source/libs/executor/src/dataDeleter.c
index 33b7811e6c0c26032d1bca8cc8643dce2b0ea984..3c56abbd15395d7c1a1f8942e8ea9587a4e1a2ce 100644
--- a/source/libs/executor/src/dataDeleter.c
+++ b/source/libs/executor/src/dataDeleter.c
@@ -75,7 +75,7 @@ static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInp
SDataCacheEntry* pEntry = (SDataCacheEntry*)pBuf->pData;
pEntry->compressed = 0;
pEntry->numOfRows = pInput->pData->info.rows;
- pEntry->numOfCols = pInput->pData->info.numOfCols;
+ pEntry->numOfCols = taosArrayGetSize(pInput->pData->pDataBlock);
pEntry->dataLen = sizeof(SDeleterRes);
ASSERT(1 == pEntry->numOfRows);
@@ -86,7 +86,7 @@ static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInp
SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 0);
SDeleterRes* pRes = (SDeleterRes*)pEntry->data;
- pRes->uid = pHandle->pDeleter->tableId;
+ pRes->suid = pHandle->pParam->suid;
pRes->uidList = pHandle->pParam->pUidList;
pRes->skey = pHandle->pDeleter->deleteTimeRange.skey;
pRes->ekey = pHandle->pDeleter->deleteTimeRange.ekey;
@@ -154,7 +154,7 @@ static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) {
taosThreadMutexUnlock(&pDeleter->mutex);
}
-static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryEnd) {
+static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryEnd) {
SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle;
if (taosQueueEmpty(pDeleter->pDataBlocks)) {
*pQueryEnd = pDeleter->queryEnd;
@@ -168,7 +168,7 @@ static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryE
taosFreeQitem(pBuf);
*pLen = ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->dataLen;
*pQueryEnd = pDeleter->queryEnd;
- qDebug("got data len %d, row num %d in sink", *pLen, ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->numOfRows);
+ qDebug("got data len %" PRId64 ", row num %d in sink", *pLen, ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->numOfRows);
}
static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) {
diff --git a/source/libs/executor/src/dataDispatcher.c b/source/libs/executor/src/dataDispatcher.c
index 802f9ea5b5f6885dbd16674d368c855f037c78f2..b8495faffd52aa5d4146598bd00bc45034ff6bdf 100644
--- a/source/libs/executor/src/dataDispatcher.c
+++ b/source/libs/executor/src/dataDispatcher.c
@@ -69,14 +69,16 @@ static bool needCompress(const SSDataBlock* pData, int32_t numOfCols) {
// data format:
// +----------------+--------------+----------+--------------------------------------------+--------------------------------------+-------------+-----------+-------------+-----------+
-// |SDataCacheEntry | total length | group id | col1_schema | col2_schema | col3_schema ...| column#1 length, column#2 length ... | col1 bitmap | col1 data | col2 bitmap | col2 data | ....
-// | | (4 bytes) |(8 bytes) |(sizeof(int16_t)+sizeof(int32_t))*numOfCols | sizeof(int32_t) * numOfCols | actual size | | actual size | |
+// |SDataCacheEntry | total length | group id | col1_schema | col2_schema | col3_schema ...| column#1 length, column#2
+// length ... | col1 bitmap | col1 data | col2 bitmap | col2 data | .... | | (4 bytes) |(8 bytes)
+// |(sizeof(int16_t)+sizeof(int32_t))*numOfCols | sizeof(int32_t) * numOfCols | actual size | |
+// actual size | |
// +----------------+--------------+----------+--------------------------------------------+--------------------------------------+-------------+-----------+-------------+-----------+
// The length of bitmap is decided by number of rows of this data block, and the length of each column data is
// recorded in the first segment, next to the struct header
static void toDataCacheEntry(SDataDispatchHandle* pHandle, const SInputData* pInput, SDataDispatchBuf* pBuf) {
int32_t numOfCols = 0;
- SNode* pNode;
+ SNode* pNode;
FOREACH(pNode, pHandle->pSchema->pSlots) {
SSlotDescNode* pSlotDesc = (SSlotDescNode*)pNode;
if (pSlotDesc->output) {
@@ -90,12 +92,12 @@ static void toDataCacheEntry(SDataDispatchHandle* pHandle, const SInputData* pIn
pEntry->dataLen = 0;
pBuf->useSize = sizeof(SDataCacheEntry);
- blockCompressEncode(pInput->pData, pEntry->data, &pEntry->dataLen, numOfCols, pEntry->compressed);
+ blockEncode(pInput->pData, pEntry->data, &pEntry->dataLen, numOfCols, pEntry->compressed);
pBuf->useSize += pEntry->dataLen;
-
- atomic_add_fetch_64(&pHandle->cachedSize, pEntry->dataLen);
- atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen);
+
+ atomic_add_fetch_64(&pHandle->cachedSize, pEntry->dataLen);
+ atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen);
}
static bool allocBuf(SDataDispatchHandle* pDispatcher, const SInputData* pInput, SDataDispatchBuf* pBuf) {
@@ -154,7 +156,7 @@ static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) {
taosThreadMutexUnlock(&pDispatcher->mutex);
}
-static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryEnd) {
+static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryEnd) {
SDataDispatchHandle* pDispatcher = (SDataDispatchHandle*)pHandle;
if (taosQueueEmpty(pDispatcher->pDataBlocks)) {
*pQueryEnd = pDispatcher->queryEnd;
@@ -168,7 +170,7 @@ static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryE
taosFreeQitem(pBuf);
*pLen = ((SDataCacheEntry*)(pDispatcher->nextOutput.pData))->dataLen;
*pQueryEnd = pDispatcher->queryEnd;
- qDebug("got data len %d, row num %d in sink", *pLen, ((SDataCacheEntry*)(pDispatcher->nextOutput.pData))->numOfRows);
+ qDebug("got data len %" PRId64 ", row num %d in sink", *pLen, ((SDataCacheEntry*)(pDispatcher->nextOutput.pData))->numOfRows);
}
static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) {
@@ -187,8 +189,8 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) {
pOutput->numOfCols = pEntry->numOfCols;
pOutput->compressed = pEntry->compressed;
- atomic_sub_fetch_64(&pDispatcher->cachedSize, pEntry->dataLen);
- atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen);
+ atomic_sub_fetch_64(&pDispatcher->cachedSize, pEntry->dataLen);
+ atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen);
taosMemoryFreeClear(pDispatcher->nextOutput.pData); // todo persistent
pOutput->bufStatus = updateStatus(pDispatcher);
@@ -198,7 +200,6 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) {
pOutput->precision = pDispatcher->pSchema->precision;
taosThreadMutexUnlock(&pDispatcher->mutex);
-
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c
new file mode 100644
index 0000000000000000000000000000000000000000..e53c9fae6f8a0f8feffde8397a42aa2cb3e334fe
--- /dev/null
+++ b/source/libs/executor/src/dataInserter.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "dataSinkInt.h"
+#include "dataSinkMgt.h"
+#include "executorimpl.h"
+#include "planner.h"
+#include "tcompression.h"
+#include "tdatablock.h"
+#include "tglobal.h"
+#include "tqueue.h"
+
+extern SDataSinkStat gDataSinkStat;
+
+typedef struct SSubmitRes {
+ int64_t affectedRows;
+ int32_t code;
+ SSubmitRsp *pRsp;
+} SSubmitRes;
+
+typedef struct SDataInserterHandle {
+ SDataSinkHandle sink;
+ SDataSinkManager* pManager;
+ STSchema* pSchema;
+ SQueryInserterNode* pNode;
+ SSubmitRes submitRes;
+ SInserterParam* pParam;
+ SArray* pDataBlocks;
+ SHashObj* pCols;
+ int32_t status;
+ bool queryEnd;
+ uint64_t useconds;
+ uint64_t cachedSize;
+ TdThreadMutex mutex;
+ tsem_t ready;
+} SDataInserterHandle;
+
+typedef struct SSubmitRspParam {
+ SDataInserterHandle* pInserter;
+} SSubmitRspParam;
+
+int32_t inserterCallback(void* param, SDataBuf* pMsg, int32_t code) {
+ SSubmitRspParam* pParam = (SSubmitRspParam*)param;
+ SDataInserterHandle* pInserter = pParam->pInserter;
+
+ pInserter->submitRes.code = code;
+
+ if (code == TSDB_CODE_SUCCESS) {
+ pInserter->submitRes.pRsp = taosMemoryCalloc(1, sizeof(SSubmitRsp));
+ SDecoder coder = {0};
+ tDecoderInit(&coder, pMsg->pData, pMsg->len);
+ code = tDecodeSSubmitRsp(&coder, pInserter->submitRes.pRsp);
+ if (code) {
+ tFreeSSubmitRsp(pInserter->submitRes.pRsp);
+ pInserter->submitRes.code = code;
+ goto _return;
+ }
+
+ if (pInserter->submitRes.pRsp->nBlocks > 0) {
+ for (int32_t i = 0; i < pInserter->submitRes.pRsp->nBlocks; ++i) {
+ SSubmitBlkRsp *blk = pInserter->submitRes.pRsp->pBlocks + i;
+ if (TSDB_CODE_SUCCESS != blk->code) {
+ code = blk->code;
+ tFreeSSubmitRsp(pInserter->submitRes.pRsp);
+ pInserter->submitRes.code = code;
+ goto _return;
+ }
+ }
+ }
+
+ pInserter->submitRes.affectedRows += pInserter->submitRes.pRsp->affectedRows;
+ qDebug("submit rsp received, affectedRows:%d, total:%d", pInserter->submitRes.pRsp->affectedRows, pInserter->submitRes.affectedRows);
+
+ tFreeSSubmitRsp(pInserter->submitRes.pRsp);
+ }
+
+_return:
+
+ tsem_post(&pInserter->ready);
+
+ taosMemoryFree(param);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, SSubmitReq* pMsg, void* pTransporter, SEpSet* pEpset) {
+ // send the fetch remote task result reques
+ SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
+ if (NULL == pMsgSendInfo) {
+ taosMemoryFreeClear(pMsg);
+ terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
+ return terrno;
+ }
+
+ SSubmitRspParam* pParam = taosMemoryCalloc(1, sizeof(SSubmitRspParam));
+ pParam->pInserter = pInserter;
+
+ pMsgSendInfo->param = pParam;
+ pMsgSendInfo->msgInfo.pData = pMsg;
+ pMsgSendInfo->msgInfo.len = ntohl(pMsg->length);
+ pMsgSendInfo->msgType = TDMT_VND_SUBMIT;
+ pMsgSendInfo->fp = inserterCallback;
+
+ int64_t transporterId = 0;
+ return asyncSendMsgToServer(pTransporter, pEpset, &transporterId, pMsgSendInfo);
+}
+
+
+int32_t dataBlockToSubmit(SDataInserterHandle* pInserter, SSubmitReq** pReq) {
+ const SArray* pBlocks = pInserter->pDataBlocks;
+ const STSchema* pTSchema = pInserter->pSchema;
+ int64_t uid = pInserter->pNode->tableId;
+ int64_t suid = pInserter->pNode->stableId;
+ int32_t vgId = pInserter->pNode->vgId;
+ bool fullCol = (pInserter->pNode->pCols->length == pTSchema->numOfCols);
+
+ SSubmitReq* ret = NULL;
+ int32_t sz = taosArrayGetSize(pBlocks);
+
+ // cal size
+ int32_t cap = sizeof(SSubmitReq);
+ for (int32_t i = 0; i < sz; i++) {
+ SSDataBlock* pDataBlock = taosArrayGetP(pBlocks, i);
+ int32_t rows = pDataBlock->info.rows;
+ // TODO min
+ int32_t rowSize = pDataBlock->info.rowSize;
+ int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema);
+
+ cap += sizeof(SSubmitBlk) + rows * maxLen;
+ }
+
+ // assign data
+ // TODO
+ ret = taosMemoryCalloc(1, cap);
+ ret->header.vgId = htonl(vgId);
+ ret->version = htonl(pTSchema->version);
+ ret->length = sizeof(SSubmitReq);
+ ret->numOfBlocks = htonl(sz);
+
+ SSubmitBlk* blkHead = POINTER_SHIFT(ret, sizeof(SSubmitReq));
+ for (int32_t i = 0; i < sz; i++) {
+ SSDataBlock* pDataBlock = taosArrayGetP(pBlocks, i);
+
+ blkHead->sversion = htonl(pTSchema->version);
+ // TODO
+ blkHead->suid = htobe64(suid);
+ blkHead->uid = htobe64(uid);
+ blkHead->schemaLen = htonl(0);
+
+ int32_t rows = 0;
+ int32_t dataLen = 0;
+ STSRow* rowData = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk));
+ int64_t lastTs = TSKEY_MIN;
+ bool ignoreRow = false;
+ for (int32_t j = 0; j < pDataBlock->info.rows; j++) {
+ SRowBuilder rb = {0};
+ tdSRowInit(&rb, pTSchema->version);
+ tdSRowSetTpInfo(&rb, pTSchema->numOfCols, pTSchema->flen);
+ tdSRowResetBuf(&rb, rowData);
+
+ ignoreRow = false;
+ for (int32_t k = 0; k < pTSchema->numOfCols; k++) {
+ const STColumn* pColumn = &pTSchema->columns[k];
+ SColumnInfoData* pColData = NULL;
+ int16_t colIdx = k;
+ if (!fullCol) {
+ int16_t *slotId = taosHashGet(pInserter->pCols, &pColumn->colId, sizeof(pColumn->colId));
+ if (NULL == slotId) {
+ continue;
+ }
+
+ colIdx = *slotId;
+ }
+
+ pColData = taosArrayGet(pDataBlock->pDataBlock, colIdx);
+ if (pColData->info.type != pColumn->type) {
+ qError("col type mis-match, schema type:%d, type in block:%d", pColumn->type, pColData->info.type);
+ terrno = TSDB_CODE_APP_ERROR;
+ return TSDB_CODE_APP_ERROR;
+ }
+
+ if (colDataIsNull_s(pColData, j)) {
+ if (0 == k && TSDB_DATA_TYPE_TIMESTAMP == pColumn->type) {
+ ignoreRow = true;
+ break;
+ }
+
+ tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, pColumn->offset, k);
+ } else {
+ void* data = colDataGetData(pColData, j);
+ if (0 == k && TSDB_DATA_TYPE_TIMESTAMP == pColumn->type) {
+ if (*(int64_t*)data == lastTs) {
+ ignoreRow = true;
+ break;
+ } else {
+ lastTs = *(int64_t*)data;
+ }
+ }
+ tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, pColumn->offset, k);
+ }
+ }
+
+ if (ignoreRow) {
+ continue;
+ }
+
+ rows++;
+ int32_t rowLen = TD_ROW_LEN(rowData);
+ rowData = POINTER_SHIFT(rowData, rowLen);
+ dataLen += rowLen;
+ }
+
+ blkHead->dataLen = htonl(dataLen);
+ blkHead->numOfRows = htons(rows);
+
+ ret->length += sizeof(SSubmitBlk) + dataLen;
+ blkHead = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk) + dataLen);
+ }
+
+ ret->length = htonl(ret->length);
+
+ *pReq = ret;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue) {
+ SDataInserterHandle* pInserter = (SDataInserterHandle*)pHandle;
+ taosArrayPush(pInserter->pDataBlocks, &pInput->pData);
+ SSubmitReq* pMsg = NULL;
+ int32_t code = dataBlockToSubmit(pInserter, &pMsg);
+ if (code) {
+ return code;
+ }
+
+ code = sendSubmitRequest(pInserter, pMsg, pInserter->pParam->readHandle->pMsgCb->clientRpc, &pInserter->pNode->epSet);
+ if (code) {
+ return code;
+ }
+
+ tsem_wait(&pInserter->ready);
+
+ if (pInserter->submitRes.code) {
+ return pInserter->submitRes.code;
+ }
+
+ *pContinue = true;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) {
+ SDataInserterHandle* pInserter = (SDataInserterHandle*)pHandle;
+ taosThreadMutexLock(&pInserter->mutex);
+ pInserter->queryEnd = true;
+ pInserter->useconds = useconds;
+ taosThreadMutexUnlock(&pInserter->mutex);
+}
+
+static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryEnd) {
+ SDataInserterHandle* pDispatcher = (SDataInserterHandle*)pHandle;
+ *pLen = pDispatcher->submitRes.affectedRows;
+ qDebug("got total affectedRows %" PRId64 , *pLen);
+}
+
+
+static int32_t destroyDataSinker(SDataSinkHandle* pHandle) {
+ SDataInserterHandle* pInserter = (SDataInserterHandle*)pHandle;
+ atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pInserter->cachedSize);
+ taosArrayDestroy(pInserter->pDataBlocks);
+ taosMemoryFree(pInserter->pSchema);
+ taosThreadMutexDestroy(&pInserter->mutex);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) {
+ SDataInserterHandle* pDispatcher = (SDataInserterHandle*)pHandle;
+
+ *size = atomic_load_64(&pDispatcher->cachedSize);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void *pParam) {
+ SDataInserterHandle* inserter = taosMemoryCalloc(1, sizeof(SDataInserterHandle));
+ if (NULL == inserter) {
+ terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
+ return TSDB_CODE_QRY_OUT_OF_MEMORY;
+ }
+
+ SQueryInserterNode* pInserterNode = (SQueryInserterNode *)pDataSink;
+ inserter->sink.fPut = putDataBlock;
+ inserter->sink.fEndPut = endPut;
+ inserter->sink.fGetLen = getDataLength;
+ inserter->sink.fGetData = NULL;
+ inserter->sink.fDestroy = destroyDataSinker;
+ inserter->sink.fGetCacheSize = getCacheSize;
+ inserter->pManager = pManager;
+ inserter->pNode = pInserterNode;
+ inserter->pParam = pParam;
+ inserter->status = DS_BUF_EMPTY;
+ inserter->queryEnd = false;
+
+ int64_t suid = 0;
+ int32_t code = tsdbGetTableSchema(inserter->pParam->readHandle->vnode, pInserterNode->tableId, &inserter->pSchema, &suid);
+ if (code) {
+ return code;
+ }
+
+ if (pInserterNode->stableId != suid) {
+ terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
+ return terrno;
+ }
+
+ inserter->pDataBlocks = taosArrayInit(1, POINTER_BYTES);
+ taosThreadMutexInit(&inserter->mutex, NULL);
+ if (NULL == inserter->pDataBlocks) {
+ terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
+ return TSDB_CODE_QRY_OUT_OF_MEMORY;
+ }
+
+ inserter->pCols = taosHashInit(pInserterNode->pCols->length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
+ SNode* pNode = NULL;
+ FOREACH(pNode, pInserterNode->pCols) {
+ SColumnNode* pCol = (SColumnNode*)pNode;
+ taosHashPut(inserter->pCols, &pCol->colId, sizeof(pCol->colId), &pCol->slotId, sizeof(pCol->slotId));
+ }
+
+ tsem_init(&inserter->ready, 0, 0);
+
+ *pHandle = inserter;
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/libs/executor/src/dataSinkMgt.c b/source/libs/executor/src/dataSinkMgt.c
index ffa9822e927fc10e42a43064e428ccbe45acd00f..0aa5e6266c06ff2c0fed2dfc1ee33fc75db801ea 100644
--- a/source/libs/executor/src/dataSinkMgt.c
+++ b/source/libs/executor/src/dataSinkMgt.c
@@ -35,11 +35,13 @@ int32_t dsDataSinkGetCacheSize(SDataSinkStat *pStat) {
int32_t dsCreateDataSinker(const SDataSinkNode *pDataSink, DataSinkHandle* pHandle, void* pParam) {
- switch (nodeType(pDataSink)) {
+ switch ((int)nodeType(pDataSink)) {
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
return createDataDispatcher(&gDataSinkManager, pDataSink, pHandle);
case QUERY_NODE_PHYSICAL_PLAN_DELETE:
return createDataDeleter(&gDataSinkManager, pDataSink, pHandle, pParam);
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
+ return createDataInserter(&gDataSinkManager, pDataSink, pHandle, pParam);
}
return TSDB_CODE_FAILED;
}
@@ -54,7 +56,7 @@ void dsEndPut(DataSinkHandle handle, uint64_t useconds) {
return pHandleImpl->fEndPut(pHandleImpl, useconds);
}
-void dsGetDataLength(DataSinkHandle handle, int32_t* pLen, bool* pQueryEnd) {
+void dsGetDataLength(DataSinkHandle handle, int64_t* pLen, bool* pQueryEnd) {
SDataSinkHandle* pHandleImpl = (SDataSinkHandle*)handle;
pHandleImpl->fGetLen(pHandleImpl, pLen, pQueryEnd);
}
diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c
index 27096fe7f9cefe3ea4c0ce1f144c127e9f551a7f..95b4fdcd6e626ea66421beb2c543db8b784e8c4c 100644
--- a/source/libs/executor/src/executil.c
+++ b/source/libs/executor/src/executil.c
@@ -13,10 +13,11 @@
* along with this program. If not, see .
*/
-#include "os.h"
-#include "index.h"
+#include
#include "function.h"
#include "functionMgt.h"
+#include "index.h"
+#include "os.h"
#include "tdatablock.h"
#include "thash.h"
#include "tmsg.h"
@@ -25,48 +26,46 @@
#include "executorimpl.h"
#include "tcompression.h"
-void initResultRowInfo(SResultRowInfo *pResultRowInfo) {
- pResultRowInfo->size = 0;
+void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
+ pResultRowInfo->size = 0;
pResultRowInfo->cur.pageId = -1;
}
-void cleanupResultRowInfo(SResultRowInfo *pResultRowInfo) {
+void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo) {
if (pResultRowInfo == NULL) {
return;
}
- for(int32_t i = 0; i < pResultRowInfo->size; ++i) {
-// if (pResultRowInfo->pResult[i]) {
-// taosMemoryFreeClear(pResultRowInfo->pResult[i]->key);
-// }
+ for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
+ // if (pResultRowInfo->pResult[i]) {
+ // taosMemoryFreeClear(pResultRowInfo->pResult[i]->key);
+ // }
}
}
-void closeAllResultRows(SResultRowInfo *pResultRowInfo) {
-// do nothing
+void closeAllResultRows(SResultRowInfo* pResultRowInfo) {
+ // do nothing
}
-bool isResultRowClosed(SResultRow* pRow) {
- return (pRow->closed == true);
-}
+bool isResultRowClosed(SResultRow* pRow) { return (pRow->closed == true); }
-void closeResultRow(SResultRow* pResultRow) {
- pResultRow->closed = true;
-}
+void closeResultRow(SResultRow* pResultRow) { pResultRow->closed = true; }
// TODO refactor: use macro
SResultRowEntryInfo* getResultEntryInfo(const SResultRow* pRow, int32_t index, const int32_t* offset) {
assert(index >= 0 && offset != NULL);
- return (SResultRowEntryInfo*)((char*) pRow->pEntryInfo + offset[index]);
+ return (SResultRowEntryInfo*)((char*)pRow->pEntryInfo + offset[index]);
}
size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
int32_t rowSize = (numOfOutput * sizeof(SResultRowEntryInfo)) + sizeof(SResultRow);
- for(int32_t i = 0; i < numOfOutput; ++i) {
+ for (int32_t i = 0; i < numOfOutput; ++i) {
rowSize += pCtx[i].resDataInfo.interBufSize;
}
+ rowSize +=
+ (numOfOutput * sizeof(bool)); // expand rowSize to mark if col is null for top/bottom result(saveTupleData)
return rowSize;
}
@@ -74,31 +73,29 @@ void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) {
assert(pGroupResInfo != NULL);
taosArrayDestroy(pGroupResInfo->pRows);
- pGroupResInfo->pRows = NULL;
- pGroupResInfo->index = 0;
+ pGroupResInfo->pRows = NULL;
+ pGroupResInfo->index = 0;
}
-static int32_t resultrowComparAsc(const void* p1, const void* p2) {
- SResKeyPos* pp1 = *(SResKeyPos**) p1;
- SResKeyPos* pp2 = *(SResKeyPos**) p2;
+int32_t resultrowComparAsc(const void* p1, const void* p2) {
+ SResKeyPos* pp1 = *(SResKeyPos**)p1;
+ SResKeyPos* pp2 = *(SResKeyPos**)p2;
if (pp1->groupId == pp2->groupId) {
- int64_t pts1 = *(int64_t*) pp1->key;
- int64_t pts2 = *(int64_t*) pp2->key;
+ int64_t pts1 = *(int64_t*)pp1->key;
+ int64_t pts2 = *(int64_t*)pp2->key;
if (pts1 == pts2) {
return 0;
} else {
- return pts1 < pts2? -1:1;
+ return pts1 < pts2 ? -1 : 1;
}
} else {
- return pp1->groupId < pp2->groupId? -1:1;
+ return pp1->groupId < pp2->groupId ? -1 : 1;
}
}
-static int32_t resultrowComparDesc(const void* p1, const void* p2) {
- return resultrowComparAsc(p2, p1);
-}
+static int32_t resultrowComparDesc(const void* p1, const void* p2) { return resultrowComparAsc(p2, p1); }
void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SHashObj* pHashmap, int32_t order) {
if (pGroupResInfo->pRows != NULL) {
@@ -110,21 +107,23 @@ void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SHashObj* pHashmap, int
pGroupResInfo->pRows = taosArrayInit(10, POINTER_BYTES);
size_t keyLen = 0;
- while((pData = taosHashIterate(pHashmap, pData)) != NULL) {
+ while ((pData = taosHashIterate(pHashmap, pData)) != NULL) {
void* key = taosHashGetKey(pData, &keyLen);
SResKeyPos* p = taosMemoryMalloc(keyLen + sizeof(SResultRowPosition));
- p->groupId = *(uint64_t*) key;
- p->pos = *(SResultRowPosition*) pData;
+ p->groupId = *(uint64_t*)key;
+ p->pos = *(SResultRowPosition*)pData;
memcpy(p->key, (char*)key + sizeof(uint64_t), keyLen - sizeof(uint64_t));
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_groupRes, groupId:%" PRIu64 ",pageId:%d,offset:%d\n", p->groupId, p->pos.pageId, p->pos.offset);
+#endif
taosArrayPush(pGroupResInfo->pRows, &p);
}
if (order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC) {
- __compar_fn_t fn = (order == TSDB_ORDER_ASC)? resultrowComparAsc:resultrowComparDesc;
- qsort(pGroupResInfo->pRows->pData, taosArrayGetSize(pGroupResInfo->pRows), POINTER_BYTES, fn);
+ __compar_fn_t fn = (order == TSDB_ORDER_ASC) ? resultrowComparAsc : resultrowComparDesc;
+ taosSort(pGroupResInfo->pRows->pData, taosArrayGetSize(pGroupResInfo->pRows), POINTER_BYTES, fn);
}
pGroupResInfo->index = 0;
@@ -155,11 +154,16 @@ int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) {
return 0;
}
- return (int32_t) taosArrayGetSize(pGroupResInfo->pRows);
+ return (int32_t)taosArrayGetSize(pGroupResInfo->pRows);
}
SArray* createSortInfo(SNodeList* pNodeList) {
- size_t numOfCols = LIST_LENGTH(pNodeList);
+ size_t numOfCols = 0;
+ if (pNodeList != NULL) {
+ numOfCols = LIST_LENGTH(pNodeList);
+ } else {
+ numOfCols = 0;
+ }
SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo));
if (pList == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
@@ -183,79 +187,186 @@ SArray* createSortInfo(SNodeList* pNodeList) {
SSDataBlock* createResDataBlock(SDataBlockDescNode* pNode) {
int32_t numOfCols = LIST_LENGTH(pNode->pSlots);
- SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
- pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
+ SSDataBlock* pBlock = createDataBlock();
pBlock->info.blockId = pNode->dataBlockId;
- pBlock->info.rowSize = pNode->totalRowSize; // todo ??
pBlock->info.type = STREAM_INVALID;
+ pBlock->info.calWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData idata = {{0}};
- SSlotDescNode* pDescNode = (SSlotDescNode*)nodesListGetNode(pNode->pSlots, i);
-// if (!pDescNode->output) { // todo disable it temporarily
-// continue;
-// }
-
- idata.info.type = pDescNode->dataType.type;
- idata.info.bytes = pDescNode->dataType.bytes;
+ SSlotDescNode* pDescNode = (SSlotDescNode*)nodesListGetNode(pNode->pSlots, i);
+ /*if (!pDescNode->output) { // todo disable it temporarily*/
+ /*continue;*/
+ /*}*/
+
+ SColumnInfoData idata =
+ createColumnInfoData(pDescNode->dataType.type, pDescNode->dataType.bytes, pDescNode->slotId);
idata.info.scale = pDescNode->dataType.scale;
- idata.info.slotId = pDescNode->slotId;
idata.info.precision = pDescNode->dataType.precision;
- if (IS_VAR_DATA_TYPE(idata.info.type)) {
- pBlock->info.hasVarCol = true;
+ blockDataAppendColInfo(pBlock, &idata);
+ }
+
+ return pBlock;
+}
+
+EDealRes doTranslateTagExpr(SNode** pNode, void* pContext) {
+ SMetaReader* mr = (SMetaReader*)pContext;
+ if (nodeType(*pNode) == QUERY_NODE_COLUMN) {
+ SColumnNode* pSColumnNode = *(SColumnNode**)pNode;
+
+ SValueNode* res = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ if (NULL == res) {
+ return DEAL_RES_ERROR;
+ }
+
+ res->translate = true;
+ res->node.resType = pSColumnNode->node.resType;
+
+ STagVal tagVal = {0};
+ tagVal.cid = pSColumnNode->colId;
+ const char* p = metaGetTableTagVal(&mr->me, pSColumnNode->node.resType.type, &tagVal);
+ if (p == NULL) {
+ res->node.resType.type = TSDB_DATA_TYPE_NULL;
+ } else if (pSColumnNode->node.resType.type == TSDB_DATA_TYPE_JSON) {
+ int32_t len = ((const STag*)p)->len;
+ res->datum.p = taosMemoryCalloc(len + 1, 1);
+ memcpy(res->datum.p, p, len);
+ } else if (IS_VAR_DATA_TYPE(pSColumnNode->node.resType.type)) {
+ res->datum.p = taosMemoryCalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1, 1);
+ memcpy(varDataVal(res->datum.p), tagVal.pData, tagVal.nData);
+ varDataSetLen(res->datum.p, tagVal.nData);
+ } else {
+ nodesSetValueNodeValue(res, &(tagVal.i64));
+ }
+ nodesDestroyNode(*pNode);
+ *pNode = (SNode*)res;
+ } else if (nodeType(*pNode) == QUERY_NODE_FUNCTION) {
+ SFunctionNode* pFuncNode = *(SFunctionNode**)pNode;
+ if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
+ SValueNode* res = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ if (NULL == res) {
+ return DEAL_RES_ERROR;
+ }
+
+ res->translate = true;
+ res->node.resType = pFuncNode->node.resType;
+
+ int32_t len = strlen(mr->me.name);
+ res->datum.p = taosMemoryCalloc(len + VARSTR_HEADER_SIZE + 1, 1);
+ memcpy(varDataVal(res->datum.p), mr->me.name, len);
+ varDataSetLen(res->datum.p, len);
+ nodesDestroyNode(*pNode);
+ *pNode = (SNode*)res;
}
+ }
+
+ return DEAL_RES_CONTINUE;
+}
+
+static bool isTableOk(STableKeyInfo* info, SNode* pTagCond, SMeta* metaHandle) {
+ SMetaReader mr = {0};
+ metaReaderInit(&mr, metaHandle, 0);
+ metaGetTableEntryByUid(&mr, info->uid);
- taosArrayPush(pBlock->pDataBlock, &idata);
+ SNode* pTagCondTmp = nodesCloneNode(pTagCond);
+
+ nodesRewriteExprPostOrder(&pTagCondTmp, doTranslateTagExpr, &mr);
+ metaReaderClear(&mr);
+
+ SNode* pNew = NULL;
+ int32_t code = scalarCalculateConstants(pTagCondTmp, &pNew);
+ if (TSDB_CODE_SUCCESS != code) {
+ terrno = code;
+ nodesDestroyNode(pTagCondTmp);
+ return false;
}
- pBlock->info.numOfCols = taosArrayGetSize(pBlock->pDataBlock);
- return pBlock;
+ ASSERT(nodeType(pNew) == QUERY_NODE_VALUE);
+ SValueNode* pValue = (SValueNode*)pNew;
+
+ ASSERT(pValue->node.resType.type == TSDB_DATA_TYPE_BOOL);
+ bool result = pValue->datum.b;
+ nodesDestroyNode(pNew);
+ return result;
}
-int32_t getTableList(void* metaHandle, SScanPhysiNode* pScanNode, STableListInfo* pListInfo, SNode* pTagCond) {
+int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, STableListInfo* pListInfo) {
int32_t code = TSDB_CODE_SUCCESS;
+
pListInfo->pTableList = taosArrayInit(8, sizeof(STableKeyInfo));
+ if (pListInfo->pTableList == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
uint64_t tableUid = pScanNode->uid;
+ pListInfo->suid = pScanNode->suid;
+
+ SNode* pTagCond = (SNode*)pListInfo->pTagCond;
+ SNode* pTagIndexCond = (SNode*)pListInfo->pTagIndexCond;
if (pScanNode->tableType == TSDB_SUPER_TABLE) {
- if (pTagCond) {
+ if (pTagIndexCond) {
SIndexMetaArg metaArg = {
.metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = tsdbGetIvtIdx(metaHandle), .suid = tableUid};
- SArray* res = taosArrayInit(8, sizeof(uint64_t));
- code = doFilterTag(pTagCond, &metaArg, res);
- if (code == TSDB_CODE_INDEX_REBUILDING) { // todo
- // doFilter();
- } else if (code != TSDB_CODE_SUCCESS) {
- qError("failed to get tableIds, reason: %s, suid: %" PRIu64 "", tstrerror(code), tableUid);
- taosArrayDestroy(res);
- terrno = code;
- return code;
+ SArray* res = taosArrayInit(8, sizeof(uint64_t));
+ SIdxFltStatus status = SFLT_NOT_INDEX;
+ code = doFilterTag(pTagIndexCond, &metaArg, res, &status);
+ if (code != 0 || status == SFLT_NOT_INDEX) {
+ qError("failed to get tableIds from index, reason:%s, suid:%" PRIu64, tstrerror(code), tableUid);
+// code = TSDB_CODE_INDEX_REBUILDING;
+ code = vnodeGetAllTableList(pVnode, tableUid, pListInfo->pTableList);
} else {
- qDebug("success to get tableIds, size: %d, suid: %" PRIu64 "", (int)taosArrayGetSize(res), tableUid);
+ qDebug("success to get tableIds, size:%d, suid:%" PRIu64, (int)taosArrayGetSize(res), tableUid);
}
for (int i = 0; i < taosArrayGetSize(res); i++) {
- STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, .uid = *(uint64_t*)taosArrayGet(res, i)};
+ STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, .uid = *(uint64_t*)taosArrayGet(res, i), .groupId = 0};
taosArrayPush(pListInfo->pTableList, &info);
}
taosArrayDestroy(res);
} else {
- code = tsdbGetAllTableList(metaHandle, tableUid, pListInfo->pTableList);
+ code = vnodeGetAllTableList(pVnode, tableUid, pListInfo->pTableList);
+ }
+
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get tableIds, reason:%s, suid:%" PRIu64, tstrerror(code), tableUid);
+ terrno = code;
+ return code;
}
} else { // Create one table group.
- STableKeyInfo info = {.lastKey = 0, .uid = tableUid};
+ STableKeyInfo info = {.lastKey = 0, .uid = tableUid, .groupId = 0};
taosArrayPush(pListInfo->pTableList, &info);
}
+ if (pTagCond) {
+ int32_t i = 0;
+ while (i < taosArrayGetSize(pListInfo->pTableList)) {
+ STableKeyInfo* info = taosArrayGet(pListInfo->pTableList, i);
+ bool isOk = isTableOk(info, pTagCond, metaHandle);
+ if (terrno) return terrno;
+ if (!isOk) {
+ taosArrayRemove(pListInfo->pTableList, i);
+ continue;
+ }
+ i++;
+ }
+ }
+
+ pListInfo->pGroupList = taosArrayInit(4, POINTER_BYTES);
+ if (pListInfo->pGroupList == NULL) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ // put into list as default group, remove it if grouping sorting is required later
+ taosArrayPush(pListInfo->pGroupList, &pListInfo->pTableList);
+
return code;
}
SArray* extractPartitionColInfo(SNodeList* pNodeList) {
- if(!pNodeList) {
+ if (!pNodeList) {
return NULL;
}
@@ -284,7 +395,6 @@ SArray* extractPartitionColInfo(SNodeList* pNodeList) {
return pList;
}
-
SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols,
int32_t type) {
size_t numOfCols = LIST_LENGTH(pNodeList);
@@ -493,13 +603,16 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu
}
for (int32_t i = 0; i < numOfOutput; ++i) {
- if (strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
+ if (strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_select_value") == 0 ||
+ strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_group_key") == 0) {
pValCtx[num++] = &pCtx[i];
} else if (fmIsSelectFunc(pCtx[i].functionId)) {
p = &pCtx[i];
}
}
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_setSelect num:%d", num);
+#endif
if (p != NULL) {
p->subsidiaries.pCtx = pValCtx;
p->subsidiaries.num = num;
@@ -576,8 +689,8 @@ SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput,
}
for (int32_t i = 1; i < numOfOutput; ++i) {
- (*rowEntryInfoOffset)[i] =
- (int32_t)((*rowEntryInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pFuncCtx[i - 1].resDataInfo.interBufSize);
+ (*rowEntryInfoOffset)[i] = (int32_t)((*rowEntryInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) +
+ pFuncCtx[i - 1].resDataInfo.interBufSize);
}
setSelectValueColumnInfo(pFuncCtx, numOfOutput);
@@ -593,14 +706,14 @@ void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray
while (i < numOfSrcCols && j < taosArrayGetSize(pColMatchInfo)) {
SColumnInfoData* p = taosArrayGet(pCols, i);
SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, j);
- if (!outputEveryColumn && !pmInfo->output) {
+ if (!outputEveryColumn && pmInfo->reserved) {
j++;
continue;
}
if (p->info.colId == pmInfo->colId) {
SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, pmInfo->targetSlotId);
- colDataAssign(pDst, p, pBlock->info.rows);
+ colDataAssign(pDst, p, pBlock->info.rows, &pBlock->info);
i++;
j++;
} else if (p->info.colId < pmInfo->colId) {
@@ -625,18 +738,17 @@ SInterval extractIntervalInfo(const STableScanPhysiNode* pTableScanNode) {
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
SColumn c = {0};
- c.slotId = pColNode->slotId;
- c.colId = pColNode->colId;
- c.type = pColNode->node.resType.type;
- c.bytes = pColNode->node.resType.bytes;
- c.scale = pColNode->node.resType.scale;
+
+ c.slotId = pColNode->slotId;
+ c.colId = pColNode->colId;
+ c.type = pColNode->node.resType.type;
+ c.bytes = pColNode->node.resType.bytes;
+ c.scale = pColNode->node.resType.scale;
c.precision = pColNode->node.resType.precision;
return c;
}
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode) {
- pCond->loadExternalRows = false;
-
pCond->order = pTableScanNode->scanSeq[0] > 0 ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
pCond->numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols);
pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
@@ -647,30 +759,11 @@ int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysi
// pCond->twindow = pTableScanNode->scanRange;
// TODO: get it from stable scan node
- pCond->numOfTWindows = 1;
- pCond->twindows = taosMemoryCalloc(pCond->numOfTWindows, sizeof(STimeWindow));
- pCond->twindows[0] = pTableScanNode->scanRange;
- pCond->suid = pTableScanNode->scan.suid;
-
-#if 1
- // todo work around a problem, remove it later
- for (int32_t i = 0; i < pCond->numOfTWindows; ++i) {
- if ((pCond->order == TSDB_ORDER_ASC && pCond->twindows[i].skey > pCond->twindows[i].ekey) ||
- (pCond->order == TSDB_ORDER_DESC && pCond->twindows[i].skey < pCond->twindows[i].ekey)) {
- TSWAP(pCond->twindows[i].skey, pCond->twindows[i].ekey);
- }
- }
-#endif
-
- for (int32_t i = 0; i < pCond->numOfTWindows; ++i) {
- if ((pCond->order == TSDB_ORDER_ASC && pCond->twindows[i].skey > pCond->twindows[i].ekey) ||
- (pCond->order == TSDB_ORDER_DESC && pCond->twindows[i].skey < pCond->twindows[i].ekey)) {
- TSWAP(pCond->twindows[i].skey, pCond->twindows[i].ekey);
- }
- }
- taosqsort(pCond->twindows, pCond->numOfTWindows, sizeof(STimeWindow), pCond, compareTimeWindow);
-
- pCond->type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
+ pCond->twindows = pTableScanNode->scanRange;
+ pCond->suid = pTableScanNode->scan.suid;
+ pCond->type = BLOCK_LOAD_OFFSET_ORDER;
+ pCond->startVersion = -1;
+ pCond->endVersion = -1;
// pCond->type = pTableScanNode->scanFlag;
int32_t j = 0;
@@ -691,10 +784,7 @@ int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysi
return TSDB_CODE_SUCCESS;
}
-void cleanupQueryTableDataCond(SQueryTableDataCond* pCond) {
- taosMemoryFree(pCond->twindows);
- taosMemoryFree(pCond->colList);
-}
+void cleanupQueryTableDataCond(SQueryTableDataCond* pCond) { taosMemoryFree(pCond->colList); }
int32_t convertFillType(int32_t mode) {
int32_t type = TSDB_FILL_NONE;
@@ -723,3 +813,90 @@ int32_t convertFillType(int32_t mode) {
return type;
}
+
+static void getInitialStartTimeWindow(SInterval* pInterval, TSKEY ts, STimeWindow* w, bool ascQuery) {
+ if (ascQuery) {
+ getAlignQueryTimeWindow(pInterval, pInterval->precision, ts, w);
+ } else {
+ // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
+ getAlignQueryTimeWindow(pInterval, pInterval->precision, ts, w);
+
+ int64_t key = w->skey;
+ while (key < ts) { // moving towards end
+ key = taosTimeAdd(key, pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
+ if (key >= ts) {
+ break;
+ }
+
+ w->skey = key;
+ }
+ }
+}
+
+static STimeWindow doCalculateTimeWindow(int64_t ts, SInterval* pInterval) {
+ STimeWindow w = {0};
+
+ if (pInterval->intervalUnit == 'n' || pInterval->intervalUnit == 'y') {
+ w.skey = taosTimeTruncate(ts, pInterval, pInterval->precision);
+ w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
+ } else {
+ int64_t st = w.skey;
+ if (pInterval->offset > 0) {
+ st = taosTimeAdd(st, pInterval->offset, pInterval->offsetUnit, pInterval->precision);
+ }
+
+ if (st > ts) {
+ st -= ((st - ts + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
+ }
+
+ int64_t et = st + pInterval->interval - 1;
+ if (et < ts) {
+ st += ((ts - et + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
+ }
+
+ w.skey = st;
+ w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
+ }
+
+ return w;
+}
+
+STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order) {
+ int32_t factor = (order == TSDB_ORDER_ASC)? -1:1;
+
+ STimeWindow win = *pWindow;
+ STimeWindow save = win;
+ while(win.skey <= ts && win.ekey >= ts) {
+ save = win;
+ win.skey = taosTimeAdd(win.skey, factor * pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
+ win.ekey = taosTimeAdd(win.ekey, factor * pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
+ }
+
+ return save;
+}
+
+// get the correct time window according to the handled timestamp
+STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval,
+ int32_t order) {
+ STimeWindow w = {0};
+ if (pResultRowInfo->cur.pageId == -1) { // the first window, from the previous stored value
+ getInitialStartTimeWindow(pInterval, ts, &w, (order == TSDB_ORDER_ASC));
+ w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
+ return w;
+ }
+
+ w = getResultRowByPos(pBuf, &pResultRowInfo->cur)->win;
+
+ // in case of typical time window, we can calculate time window directly.
+ if (w.skey > ts || w.ekey < ts) {
+ w = doCalculateTimeWindow(ts, pInterval);
+ }
+
+ if (pInterval->interval != pInterval->sliding) {
+ // it is an sliding window query, in which sliding value is not equalled to
+ // interval value, and we need to find the first qualified time window.
+ w = getFirstQualifiedTimeWindow(ts, &w, pInterval, order);
+ }
+
+ return w;
+}
\ No newline at end of file
diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c
index cf72dfd7966deec976b90d615d8bb90329f69cc3..f2008ed97a5c54f1fae090fa721d396ee5eaa49c 100644
--- a/source/libs/executor/src/executor.c
+++ b/source/libs/executor/src/executor.c
@@ -37,29 +37,19 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, size_t nu
} else {
pOperator->status = OP_NOT_OPENED;
- SStreamBlockScanInfo* pInfo = pOperator->info;
+ SStreamScanInfo* pInfo = pOperator->info;
pInfo->assignBlockUid = assignUid;
- // the block type can not be changed in the streamscan operators
-#if 0
- if (pInfo->blockType == 0) {
- pInfo->blockType = type;
- } else if (pInfo->blockType != type) {
- ASSERT(0);
- return TSDB_CODE_QRY_APP_ERROR;
- }
-#endif
- // rollup sma, the same qTaskInfo is used to insert data by SubmitReq and fetch result by SSDataBlock
- if (pInfo->blockType != type) {
- pInfo->blockType = type;
- }
+ // TODO: if a block was set but not consumed,
+ // prevent setting a different type of block
+ pInfo->blockType = type;
- if (type == STREAM_DATA_TYPE_SUBMIT_BLOCK) {
- if (tqReadHandleSetMsg(pInfo->streamBlockReader, input, 0) < 0) {
+ if (type == STREAM_INPUT__DATA_SUBMIT) {
+ if (tqReaderSetDataMsg(pInfo->tqReader, input, 0) < 0) {
qError("submit msg messed up when initing stream block, %s" PRIx64, id);
return TSDB_CODE_QRY_APP_ERROR;
}
- } else if (type == STREAM_DATA_TYPE_SSDATA_BLOCK) {
+ } else if (type == STREAM_INPUT__DATA_BLOCK) {
for (int32_t i = 0; i < numOfBlocks; ++i) {
SSDataBlock* pDataBlock = &((SSDataBlock*)input)[i];
@@ -78,6 +68,16 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, size_t nu
}
}
+#if 0
+int32_t qStreamScanSnapshot(qTaskInfo_t tinfo) {
+ if (tinfo == NULL) {
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ return doSetStreamBlock(pTaskInfo->pRoot, NULL, 0, STREAM_INPUT__TABLE_SCAN, 0, NULL);
+}
+#endif
+
int32_t qSetStreamInput(qTaskInfo_t tinfo, const void* input, int32_t type, bool assignUid) {
return qSetMultiStreamInput(tinfo, input, 1, type, assignUid);
}
@@ -104,18 +104,34 @@ int32_t qSetMultiStreamInput(qTaskInfo_t tinfo, const void* pBlocks, size_t numO
return code;
}
-qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, void* streamReadHandle) {
+qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers) {
if (msg == NULL) {
+ // TODO create raw scan
return NULL;
}
- // print those info into log
-#if 0
- pMsg->sId = pMsg->sId;
- pMsg->queryId = pMsg->queryId;
- pMsg->taskId = pMsg->taskId;
- pMsg->contentLen = pMsg->contentLen;
-#endif
+ struct SSubplan* plan = NULL;
+ int32_t code = qStringToSubplan(msg, &plan);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return NULL;
+ }
+
+ qTaskInfo_t pTaskInfo = NULL;
+ code = qCreateExecTask(readers, 0, 0, plan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_QUEUE);
+ if (code != TSDB_CODE_SUCCESS) {
+ // TODO: destroy SSubplan & pTaskInfo
+ terrno = code;
+ return NULL;
+ }
+
+ return pTaskInfo;
+}
+
+qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers) {
+ if (msg == NULL) {
+ return NULL;
+ }
/*qDebugL("stream task string %s", (const char*)msg);*/
@@ -127,7 +143,7 @@ qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, void* streamReadHandle) {
}
qTaskInfo_t pTaskInfo = NULL;
- code = qCreateExecTask(streamReadHandle, 0, 0, plan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_STREAM);
+ code = qCreateExecTask(readers, 0, 0, plan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_STREAM);
if (code != TSDB_CODE_SUCCESS) {
// TODO: destroy SSubplan & pTaskInfo
terrno = code;
@@ -137,7 +153,7 @@ qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, void* streamReadHandle) {
return pTaskInfo;
}
-static SArray* filterQualifiedChildTables(const SStreamBlockScanInfo* pScanInfo, const SArray* tableIdList) {
+static SArray* filterQualifiedChildTables(const SStreamScanInfo* pScanInfo, const SArray* tableIdList) {
SArray* qa = taosArrayInit(4, sizeof(tb_uid_t));
// let's discard the tables those are not created according to the queried super table.
@@ -152,10 +168,12 @@ static SArray* filterQualifiedChildTables(const SStreamBlockScanInfo* pScanInfo,
continue;
}
- ASSERT(mr.me.type == TSDB_CHILD_TABLE);
- if (mr.me.ctbEntry.suid != pScanInfo->tableUid) {
+ // TODO handle ntb case
+ if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != pScanInfo->tableUid) {
continue;
}
+ /*pScanInfo->pStreamScanOp->pTaskInfo->tableqinfoList.*/
+ // handle multiple partition
taosArrayPush(qa, id);
}
@@ -173,28 +191,32 @@ int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bo
pInfo = pInfo->pDownstream[0];
}
- int32_t code = 0;
- SStreamBlockScanInfo* pScanInfo = pInfo->info;
+ int32_t code = 0;
+ SStreamScanInfo* pScanInfo = pInfo->info;
if (isAdd) { // add new table id
SArray* qa = filterQualifiedChildTables(pScanInfo, tableIdList);
qDebug(" %d qualified child tables added into stream scanner", (int32_t)taosArrayGetSize(qa));
- code = tqReadHandleAddTbUidList(pScanInfo->streamBlockReader, qa);
+ code = tqReaderAddTbUidList(pScanInfo->tqReader, qa);
taosArrayDestroy(qa);
} else { // remove the table id in current list
qDebug(" %d remove child tables from the stream scanner", (int32_t)taosArrayGetSize(tableIdList));
- code = tqReadHandleRemoveTbUidList(pScanInfo->streamBlockReader, tableIdList);
+ code = tqReaderRemoveTbUidList(pScanInfo->tqReader, tableIdList);
}
return code;
}
-int32_t qGetQueriedTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* tableName, int32_t* sversion,
- int32_t* tversion) {
+int32_t qGetQueryTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* tableName, int32_t* sversion,
+ int32_t* tversion) {
ASSERT(tinfo != NULL && dbName != NULL && tableName != NULL);
SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
- *sversion = pTaskInfo->schemaVer.sversion;
+ if (pTaskInfo->schemaVer.sw == NULL) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ *sversion = pTaskInfo->schemaVer.sw->version;
*tversion = pTaskInfo->schemaVer.tversion;
if (pTaskInfo->schemaVer.dbname) {
strcpy(dbName, pTaskInfo->schemaVer.dbname);
diff --git a/source/libs/executor/src/executorMain.c b/source/libs/executor/src/executorMain.c
index a9e1e03178b0a28780ecfdd696d44e244d2648a1..6381d20255004a71541f0e6c227ea90fa6613769 100644
--- a/source/libs/executor/src/executorMain.c
+++ b/source/libs/executor/src/executorMain.c
@@ -27,6 +27,10 @@ static TdThreadOnce initPoolOnce = PTHREAD_ONCE_INIT;
int32_t exchangeObjRefPool = -1;
static void initRefPool() { exchangeObjRefPool = taosOpenRef(1024, doDestroyExchangeOperatorInfo); }
+static void cleanupRefPool() {
+ int32_t ref = atomic_val_compare_exchange_32(&exchangeObjRefPool, exchangeObjRefPool, 0);
+ taosCloseRef(ref);
+}
int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, SSubplan* pSubplan,
qTaskInfo_t* pTaskInfo, DataSinkHandle* handle, const char* sql, EOPTR_EXEC_MODEL model) {
@@ -34,12 +38,19 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId,
SExecTaskInfo** pTask = (SExecTaskInfo**)pTaskInfo;
taosThreadOnce(&initPoolOnce, initRefPool);
-
+ atexit(cleanupRefPool);
int32_t code = createExecTaskInfoImpl(pSubplan, pTask, readHandle, taskId, sql, model);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
+ if (model == OPTR_EXEC_MODEL_STREAM) {
+ (*pTask)->streamInfo.inputQueue = streamQueueOpen();
+ if ((*pTask)->streamInfo.inputQueue == NULL) {
+ goto _error;
+ }
+ }
+
SDataSinkMgtCfg cfg = {.maxDataBlockNum = 1000, .maxDataBlockNumPerQuery = 100};
code = dsDataSinkMgtInit(&cfg);
if (code != TSDB_CODE_SUCCESS) {
@@ -48,7 +59,7 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId,
if (handle) {
void* pSinkParam = NULL;
- code = createDataSinkParam(pSubplan->pDataSink, &pSinkParam, pTaskInfo);
+ code = createDataSinkParam(pSubplan->pDataSink, &pSinkParam, pTaskInfo, readHandle);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
@@ -139,6 +150,7 @@ int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pRes, uint64_t* useconds) {
qDebug("%s execTask is launched", GET_TASKID(pTaskInfo));
int64_t st = taosGetTimestampUs();
+
*pRes = pTaskInfo->pRoot->fpSet.getNextFn(pTaskInfo->pRoot);
uint64_t el = (taosGetTimestampUs() - st);
@@ -191,16 +203,6 @@ int32_t qAsyncKillTask(qTaskInfo_t qinfo) {
return TSDB_CODE_SUCCESS;
}
-int32_t qIsTaskCompleted(qTaskInfo_t qinfo) {
- SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)qinfo;
-
- if (pTaskInfo == NULL) {
- return TSDB_CODE_QRY_INVALID_QHANDLE;
- }
-
- return isTaskKilled(pTaskInfo);
-}
-
void qDestroyTask(qTaskInfo_t qTaskHandle) {
SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)qTaskHandle;
qDebug("%s execTask completed, numOfRows:%" PRId64, GET_TASKID(pTaskInfo), pTaskInfo->pRoot->resultInfo.totalRows);
@@ -222,11 +224,17 @@ int32_t qSerializeTaskStatus(qTaskInfo_t tinfo, char** pOutput, int32_t* len) {
return TSDB_CODE_INVALID_PARA;
}
- return encodeOperator(pTaskInfo->pRoot, pOutput, len);
+ int32_t nOptrWithVal = 0;
+ int32_t code = encodeOperator(pTaskInfo->pRoot, pOutput, len, &nOptrWithVal);
+ if ((code == TSDB_CODE_SUCCESS) && (nOptrWithVal = 0)) {
+ taosMemoryFreeClear(*pOutput);
+ *len = 0;
+ }
+ return code;
}
int32_t qDeserializeTaskStatus(qTaskInfo_t tinfo, const char* pInput, int32_t len) {
- SExecTaskInfo* pTaskInfo = (struct SExecTaskInfo*) tinfo;
+ SExecTaskInfo* pTaskInfo = (struct SExecTaskInfo*)tinfo;
if (pTaskInfo == NULL || pInput == NULL || len == 0) {
return TSDB_CODE_INVALID_PARA;
@@ -235,4 +243,152 @@ int32_t qDeserializeTaskStatus(qTaskInfo_t tinfo, const char* pInput, int32_t le
return decodeOperator(pTaskInfo->pRoot, pInput, len);
}
+int32_t qExtractStreamScanner(qTaskInfo_t tinfo, void** scanner) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ SOperatorInfo* pOperator = pTaskInfo->pRoot;
+
+ while (1) {
+ uint8_t type = pOperator->operatorType;
+ if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
+ *scanner = pOperator->info;
+ return 0;
+ } else {
+ ASSERT(pOperator->numOfDownstream == 1);
+ pOperator = pOperator->pDownstream[0];
+ }
+ }
+}
+
+int32_t qStreamInput(qTaskInfo_t tinfo, void* pItem) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM);
+ taosWriteQitem(pTaskInfo->streamInfo.inputQueue->queue, pItem);
+ return 0;
+}
+
+void* qExtractReaderFromStreamScanner(void* scanner) {
+ SStreamScanInfo* pInfo = scanner;
+ return (void*)pInfo->tqReader;
+}
+
+const SSchemaWrapper* qExtractSchemaFromStreamScanner(void* scanner) {
+ SStreamScanInfo* pInfo = scanner;
+ return pInfo->tqReader->pSchemaWrapper;
+}
+
+const STqOffset* qExtractStatusFromStreamScanner(void* scanner) {
+ SStreamScanInfo* pInfo = scanner;
+ return &pInfo->offset;
+}
+
+void* qStreamExtractMetaMsg(qTaskInfo_t tinfo) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE);
+ return pTaskInfo->streamInfo.metaBlk;
+}
+int32_t qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE);
+ memcpy(pOffset, &pTaskInfo->streamInfo.lastStatus, sizeof(STqOffsetVal));
+ return 0;
+}
+
+int32_t qStreamPrepareScan(qTaskInfo_t tinfo, const STqOffsetVal* pOffset) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+ SOperatorInfo* pOperator = pTaskInfo->pRoot;
+ ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE);
+ pTaskInfo->streamInfo.prepareStatus = *pOffset;
+ if (!tOffsetEqual(pOffset, &pTaskInfo->streamInfo.lastStatus)) {
+ while (1) {
+ uint8_t type = pOperator->operatorType;
+ pOperator->status = OP_OPENED;
+ if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
+ SStreamScanInfo* pInfo = pOperator->info;
+ if (pOffset->type == TMQ_OFFSET__LOG) {
+#if 0
+ if (tOffsetEqual(pOffset, &pTaskInfo->streamInfo.lastStatus) &&
+ pInfo->tqReader->pWalReader->curVersion != pOffset->version) {
+ qError("prepare scan ver %ld actual ver %ld, last %ld", pOffset->version,
+ pInfo->tqReader->pWalReader->curVersion, pTaskInfo->streamInfo.lastStatus.version);
+ ASSERT(0);
+ }
+#endif
+ if (tqSeekVer(pInfo->tqReader, pOffset->version + 1) < 0) {
+ return -1;
+ }
+ ASSERT(pInfo->tqReader->pWalReader->curVersion == pOffset->version + 1);
+ } else if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ /*pInfo->blockType = STREAM_INPUT__TABLE_SCAN;*/
+ int64_t uid = pOffset->uid;
+ int64_t ts = pOffset->ts;
+
+ if (uid == 0) {
+ if (taosArrayGetSize(pTaskInfo->tableqinfoList.pTableList) != 0) {
+ STableKeyInfo* pTableInfo = taosArrayGet(pTaskInfo->tableqinfoList.pTableList, 0);
+ uid = pTableInfo->uid;
+ ts = INT64_MIN;
+ }
+ }
+ /*if (pTaskInfo->streamInfo.lastStatus.type != TMQ_OFFSET__SNAPSHOT_DATA ||*/
+ /*pTaskInfo->streamInfo.lastStatus.uid != uid || pTaskInfo->streamInfo.lastStatus.ts != ts) {*/
+ STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
+ int32_t tableSz = taosArrayGetSize(pTaskInfo->tableqinfoList.pTableList);
+ bool found = false;
+ for (int32_t i = 0; i < tableSz; i++) {
+ STableKeyInfo* pTableInfo = taosArrayGet(pTaskInfo->tableqinfoList.pTableList, i);
+ if (pTableInfo->uid == uid) {
+ found = true;
+ pTableScanInfo->currentTable = i;
+ break;
+ }
+ }
+
+ // TODO after dropping table, table may be not found
+ ASSERT(found);
+
+ tsdbSetTableId(pTableScanInfo->dataReader, uid);
+ int64_t oldSkey = pTableScanInfo->cond.twindows.skey;
+ pTableScanInfo->cond.twindows.skey = ts + 1;
+ tsdbReaderReset(pTableScanInfo->dataReader, &pTableScanInfo->cond);
+ pTableScanInfo->cond.twindows.skey = oldSkey;
+ pTableScanInfo->scanTimes = 0;
+
+ qDebug("tsdb reader offset seek to uid %ld ts %ld, table cur set to %d , all table num %d", uid, ts,
+ pTableScanInfo->currentTable, tableSz);
+ /*}*/
+
+ } else {
+ ASSERT(0);
+ }
+ return 0;
+ } else {
+ ASSERT(pOperator->numOfDownstream == 1);
+ pOperator = pOperator->pDownstream[0];
+ }
+ }
+ }
+ return 0;
+}
+
+#if 0
+int32_t qStreamPrepareTsdbScan(qTaskInfo_t tinfo, uint64_t uid, int64_t ts) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+
+ if (uid == 0) {
+ if (taosArrayGetSize(pTaskInfo->tableqinfoList.pTableList) != 0) {
+ STableKeyInfo* pTableInfo = taosArrayGet(pTaskInfo->tableqinfoList.pTableList, 0);
+ uid = pTableInfo->uid;
+ ts = INT64_MIN;
+ }
+ }
+
+ return doPrepareScan(pTaskInfo->pRoot, uid, ts);
+}
+
+int32_t qGetStreamScanStatus(qTaskInfo_t tinfo, uint64_t* uid, int64_t* ts) {
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
+
+ return doGetScanStatus(pTaskInfo->pRoot, uid, ts);
+}
+#endif
diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c
index 94675ce253a3149551548521f596ba79b98a18ed..674bbfef0b227729f49ee4584b080547e0090f70 100644
--- a/source/libs/executor/src/executorimpl.c
+++ b/source/libs/executor/src/executorimpl.c
@@ -13,6 +13,7 @@
* along with this program. If not, see .
*/
+#include
#include "filter.h"
#include "function.h"
#include "functionMgt.h"
@@ -273,8 +274,10 @@ SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pR
}
// 1. close current opened time window
- if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId &&
- pResult->offset != pResultRowInfo->cur.offset))) {
+ if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId))) {
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_1");
+#endif
SResultRowPosition pos = pResultRowInfo->cur;
SFilePage* pPage = getBufPage(pResultBuf, pos.pageId);
releaseBufPage(pResultBuf, pPage);
@@ -282,6 +285,9 @@ SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pR
// allocate a new buffer page
if (pResult == NULL) {
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_2");
+#endif
ASSERT(pSup->resultRowSize > 0);
pResult = getNewResultRow(pResultBuf, groupId, pSup->resultRowSize);
@@ -356,7 +362,7 @@ void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow
pColData->info.type = TSDB_DATA_TYPE_TIMESTAMP;
pColData->info.bytes = sizeof(int64_t);
- colInfoDataEnsureCapacity(pColData, 0, 5);
+ colInfoDataEnsureCapacity(pColData, 5);
colDataAppendInt64(pColData, 0, &pQueryWindow->skey);
colDataAppendInt64(pColData, 1, &pQueryWindow->ekey);
@@ -458,7 +464,7 @@ static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunc
pColInfo = pInput->pData[paramIndex];
}
- colInfoDataEnsureCapacity(pColInfo, 0, numOfRows);
+ colInfoDataEnsureCapacity(pColInfo, numOfRows);
int8_t type = pFuncParam->param.nType;
if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT) {
@@ -532,7 +538,7 @@ static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCt
return code;
}
-static int32_t doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunctionCtx* pCtx) {
+static int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx) {
for (int32_t k = 0; k < pOperator->exprSupp.numOfExprs; ++k) {
if (functionNeedToExecute(&pCtx[k])) {
// todo add a dummy funtion to avoid process check
@@ -563,34 +569,39 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
setPseudoOutputColInfo(pResult, pCtx, pPseudoList);
pResult->info.groupId = pSrcBlock->info.groupId;
- // if the source equals to the destination, it is to create a new column as the result of scalar function or some
- // operators.
+ // if the source equals to the destination, it is to create a new column as the result of scalar
+ // function or some operators.
bool createNewColModel = (pResult == pSrcBlock);
int32_t numOfRows = 0;
for (int32_t k = 0; k < numOfOutput; ++k) {
- int32_t outputSlotId = pExpr[k].base.resSchema.slotId;
- SqlFunctionCtx* pfCtx = &pCtx[k];
+ int32_t outputSlotId = pExpr[k].base.resSchema.slotId;
+ SqlFunctionCtx* pfCtx = &pCtx[k];
+ SInputColumnInfoData* pInputData = &pfCtx->input;
if (pExpr[k].pExpr->nodeType == QUERY_NODE_COLUMN) { // it is a project query
SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
if (pResult->info.rows > 0 && !createNewColModel) {
- colDataMergeCol(pColInfoData, pResult->info.rows, &pResult->info.capacity, pfCtx->input.pData[0],
- pfCtx->input.numOfRows);
+ colDataMergeCol(pColInfoData, pResult->info.rows, &pResult->info.capacity, pInputData->pData[0],
+ pInputData->numOfRows);
} else {
- colDataAssign(pColInfoData, pfCtx->input.pData[0], pfCtx->input.numOfRows);
+ colDataAssign(pColInfoData, pInputData->pData[0], pInputData->numOfRows, &pResult->info);
}
- numOfRows = pfCtx->input.numOfRows;
+ numOfRows = pInputData->numOfRows;
} else if (pExpr[k].pExpr->nodeType == QUERY_NODE_VALUE) {
SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
int32_t offset = createNewColModel ? 0 : pResult->info.rows;
- for (int32_t i = 0; i < pSrcBlock->info.rows; ++i) {
- colDataAppend(pColInfoData, i + offset,
- taosVariantGet(&pExpr[k].base.pParam[0].param, pExpr[k].base.pParam[0].param.nType),
- TSDB_DATA_TYPE_NULL == pExpr[k].base.pParam[0].param.nType);
+
+ int32_t type = pExpr[k].base.pParam[0].param.nType;
+ if (TSDB_DATA_TYPE_NULL == type) {
+ colDataAppendNNULL(pColInfoData, offset, pSrcBlock->info.rows);
+ } else {
+ for (int32_t i = 0; i < pSrcBlock->info.rows; ++i) {
+ colDataAppend(pColInfoData, i + offset, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false);
+ }
}
numOfRows = pSrcBlock->info.rows;
@@ -609,20 +620,18 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
}
int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
- colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
+ ASSERT(pResult->info.capacity > 0);
colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
numOfRows = dest.numOfRows;
taosArrayDestroy(pBlockList);
} else if (pExpr[k].pExpr->nodeType == QUERY_NODE_FUNCTION) {
- ASSERT(!fmIsAggFunc(pfCtx->functionId));
-
// _rowts/_c0, not tbname column
if (fmIsPseudoColumnFunc(pfCtx->functionId) && (!fmIsScanPseudoColumnFunc(pfCtx->functionId))) {
// do nothing
} else if (fmIsIndefiniteRowsFunc(pfCtx->functionId)) {
- SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[k]);
- pfCtx->fpSet.init(&pCtx[k], pResInfo);
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pfCtx);
+ pfCtx->fpSet.init(pfCtx, pResInfo);
pfCtx->pOutput = taosArrayGet(pResult->pDataBlock, outputSlotId);
pfCtx->offset = createNewColModel ? 0 : pResult->info.rows; // set the start offset
@@ -634,6 +643,23 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
}
numOfRows = pfCtx->fpSet.process(pfCtx);
+ } else if (fmIsAggFunc(pfCtx->functionId)) {
+ // _group_key function for "partition by tbname" + csum(col_name) query
+ SColumnInfoData* pOutput = taosArrayGet(pResult->pDataBlock, outputSlotId);
+ int32_t slotId = pfCtx->param[0].pCol->slotId;
+
+ // todo handle the json tag
+ SColumnInfoData* pInput = taosArrayGet(pSrcBlock->pDataBlock, slotId);
+ for (int32_t f = 0; f < pSrcBlock->info.rows; ++f) {
+ bool isNull = colDataIsNull_s(pInput, f);
+ if (isNull) {
+ colDataAppendNULL(pOutput, pResult->info.rows + f);
+ } else {
+ char* data = colDataGetData(pInput, f);
+ colDataAppend(pOutput, pResult->info.rows + f, data, isNull);
+ }
+ }
+
} else {
SArray* pBlockList = taosArrayInit(4, POINTER_BYTES);
taosArrayPush(pBlockList, &pSrcBlock);
@@ -649,7 +675,7 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
}
int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
- colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
+ ASSERT(pResult->info.capacity > 0);
colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
numOfRows = dest.numOfRows;
@@ -667,25 +693,6 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
return TSDB_CODE_SUCCESS;
}
-static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
- if (IS_VAR_DATA_TYPE(type)) {
- // todo disable this
-
- // if (pResultRow->key == NULL) {
- // pResultRow->key = taosMemoryMalloc(varDataTLen(pData));
- // varDataCopy(pResultRow->key, pData);
- // } else {
- // ASSERT(memcmp(pResultRow->key, pData, varDataTLen(pData)) == 0);
- // }
- } else {
- int64_t v = -1;
- GET_TYPED_DATA(v, int64_t, type, pData);
-
- pResultRow->win.skey = v;
- pResultRow->win.ekey = v;
- }
-}
-
bool functionNeedToExecute(SqlFunctionCtx* pCtx) {
struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
@@ -734,10 +741,10 @@ static int32_t doCreateConstantValColumnAggInfo(SInputColumnInfoData* pInput, SF
if (type == TSDB_DATA_TYPE_BIGINT) {
int64_t v = pFuncParam->param.i;
- *da = (SColumnDataAgg){.numOfNull = 0, .min = v, .max = v, .maxIndex = 0, .minIndex = 0, .sum = v * numOfRows};
+ *da = (SColumnDataAgg){.numOfNull = 0, .min = v, .max = v, .sum = v * numOfRows};
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
double v = pFuncParam->param.d;
- *da = (SColumnDataAgg){.numOfNull = 0, .maxIndex = 0, .minIndex = 0};
+ *da = (SColumnDataAgg){.numOfNull = 0};
*(double*)&da->min = v;
*(double*)&da->max = v;
@@ -745,7 +752,7 @@ static int32_t doCreateConstantValColumnAggInfo(SInputColumnInfoData* pInput, SF
} else if (type == TSDB_DATA_TYPE_BOOL) { // todo validate this data type
bool v = pFuncParam->param.i;
- *da = (SColumnDataAgg){.numOfNull = 0, .maxIndex = 0, .minIndex = 0};
+ *da = (SColumnDataAgg){.numOfNull = 0};
*(bool*)&da->min = 0;
*(bool*)&da->max = v;
*(bool*)&da->sum = v * numOfRows;
@@ -1031,10 +1038,11 @@ static bool overlapWithTimeWindow(STaskAttr* pQueryAttr, SDataBlockInfo* pBlockI
#endif
static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) {
+#if 0
SqlFunctionCtx* pCtx = pTableScanInfo->pCtx;
uint32_t status = BLK_DATA_NOT_LOAD;
- int32_t numOfOutput = pTableScanInfo->numOfOutput;
+ int32_t numOfOutput = 0; // pTableScanInfo->numOfOutput;
for (int32_t i = 0; i < numOfOutput; ++i) {
int32_t functionId = pCtx[i].functionId;
int32_t colId = pTableScanInfo->pExpr[i].base.pParam[0].pCol->colId;
@@ -1052,6 +1060,8 @@ static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSData
}
return status;
+#endif
+ return 0;
}
int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
@@ -1123,7 +1133,7 @@ int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableSc
} else if ((*status) == BLK_DATA_SMA_LOAD) {
// this function never returns error?
pCost->loadBlockStatis += 1;
-// tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
+// tsdbRetrieveDatablockSMA(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
if (pBlock->pBlockAgg == NULL) { // data block statistics does not exist, load data block
// pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL);
@@ -1134,7 +1144,7 @@ int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableSc
// load the data block statistics to perform further filter
pCost->loadBlockStatis += 1;
-// tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
+// tsdbRetrieveDatablockSMA(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
if (pQueryAttr->topBotQuery && pBlock->pBlockAgg != NULL) {
{ // set previous window
@@ -1186,7 +1196,7 @@ int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableSc
// }
// if (pQueryAttr->pFilters != NULL) {
-// filterSetColFieldData(pQueryAttr->pFilters, pBlock->info.numOfCols, pBlock->pDataBlock);
+// filterSetColFieldData(pQueryAttr->pFilters, taosArrayGetSize(pBlock->pDataBlock), pBlock->pDataBlock);
// }
// if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) {
@@ -1321,7 +1331,8 @@ void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock) {
// todo move to the initialization function
int32_t code = filterInitFromNode((SNode*)pFilterNode, &filter, 0);
- SFilterColumnParam param1 = {.numOfCols = pBlock->info.numOfCols, .pDataBlock = pBlock->pDataBlock};
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ SFilterColumnParam param1 = {.numOfCols = numOfCols, .pDataBlock = pBlock->pDataBlock};
code = filterSetDataFromSlotId(filter, ¶m1);
int8_t* rowRes = NULL;
@@ -1332,6 +1343,8 @@ void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock) {
extractQualifiedTupleByFilterResult(pBlock, rowRes, keep);
blockDataUpdateTsWindow(pBlock, 0);
+
+ taosMemoryFree(rowRes);
}
void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowRes, bool keep) {
@@ -1340,14 +1353,15 @@ void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowR
}
if (rowRes != NULL) {
+ int32_t totalRows = pBlock->info.rows;
SSDataBlock* px = createOneDataBlock(pBlock, true);
- int32_t totalRows = pBlock->info.rows;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pSrc = taosArrayGet(px->pDataBlock, i);
SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
// it is a reserved column for scalar function, and no data in this column yet.
- if (pDst->pData == NULL) {
+ if (pDst->pData == NULL || pSrc->pData == NULL) {
continue;
}
@@ -1412,7 +1426,9 @@ void setExecutionContext(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t
if (pAggInfo->groupId != INT32_MIN && pAggInfo->groupId == groupId) {
return;
}
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_setbuf, groupId:%" PRIu64, groupId);
+#endif
doSetTableGroupOutputBuf(pOperator, pAggInfo, numOfOutput, groupId);
// record the current active group id
@@ -1467,8 +1483,8 @@ int32_t finalizeResultRowIntoResultDataBlock(SDiskbasedBuf* pBuf, SResultRowPosi
} else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
// do nothing, todo refactor
} else {
- // expand the result into multiple rows. E.g., _wstartts, top(k, 20)
- // the _wstartts needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
+ // expand the result into multiple rows. E.g., _wstart, top(k, 20)
+ // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
for (int32_t k = 0; k < pRow->numOfRows; ++k) {
@@ -1488,11 +1504,15 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
int32_t numOfExprs) {
int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
int32_t start = pGroupResInfo->index;
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("\npage_copytoblock rows:%d", numOfRows);
+#endif
for (int32_t i = start; i < numOfRows; i += 1) {
SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
SFilePage* page = getBufPage(pBuf, pPos->pos.pageId);
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_copytoblock pos pageId:%d, offset:%d", pPos->pos.pageId, pPos->pos.offset);
+#endif
SResultRow* pRow = (SResultRow*)((char*)page + pPos->pos.offset);
doUpdateNumOfRows(pRow, numOfExprs, rowCellOffset);
@@ -1524,6 +1544,9 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowCellOffset);
if (pCtx[j].fpSet.finalize) {
+#ifdef BUF_PAGE_DEBUG
+ qDebug("\npage_finalize %d", numOfExprs);
+#endif
int32_t code = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
if (TAOS_FAILED(code)) {
qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code));
@@ -1532,8 +1555,8 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
} else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
// do nothing, todo refactor
} else {
- // expand the result into multiple rows. E.g., _wstartts, top(k, 20)
- // the _wstartts needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
+ // expand the result into multiple rows. E.g., _wstart, top(k, 20)
+ // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
if (pCtx[j].increase) {
@@ -1552,9 +1575,9 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
releaseBufPage(pBuf, page);
pBlock->info.rows += pRow->numOfRows;
- if (pBlock->info.rows >= pBlock->info.capacity) { // output buffer is full
- break;
- }
+ // if (pBlock->info.rows >= pBlock->info.capacity) { // output buffer is full
+ // break;
+ // }
}
qDebug("%s result generated, rows:%d, groupId:%" PRIu64, GET_TASKID(pTaskInfo), pBlock->info.rows,
@@ -1932,7 +1955,7 @@ typedef struct SFetchRspHandleWrapper {
int32_t sourceIndex;
} SFetchRspHandleWrapper;
-int32_t loadRemoteDataCallback(void* param, const SDataBuf* pMsg, int32_t code) {
+int32_t loadRemoteDataCallback(void* param, SDataBuf* pMsg, int32_t code) {
SFetchRspHandleWrapper* pWrapper = (SFetchRspHandleWrapper*)param;
SExchangeInfo* pExchangeInfo = taosAcquireRef(exchangeObjRefPool, pWrapper->exchangeId);
@@ -1974,7 +1997,7 @@ static void destroySendMsgInfo(SMsgSendInfo* pMsgBody) {
taosMemoryFreeClear(pMsgBody);
}
-void qProcessFetchRsp(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
+void qProcessRspMsg(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->info.ahandle;
assert(pMsg->info.ahandle != NULL);
@@ -2009,13 +2032,15 @@ static int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInf
ASSERT(pDataInfo->status == EX_SOURCE_DATA_NOT_READY);
- qDebug("%s build fetch msg and send to vgId:%d, ep:%s, taskId:0x%" PRIx64 ", %d/%" PRIzu, GET_TASKID(pTaskInfo),
- pSource->addr.nodeId, pSource->addr.epSet.eps[0].fqdn, pSource->taskId, sourceIndex, totalSources);
+ qDebug("%s build fetch msg and send to vgId:%d, ep:%s, taskId:0x%" PRIx64 ", execId:%d, %d/%" PRIzu,
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->addr.epSet.eps[0].fqdn, pSource->taskId, pSource->execId,
+ sourceIndex, totalSources);
pMsg->header.vgId = htonl(pSource->addr.nodeId);
pMsg->sId = htobe64(pSource->schedId);
pMsg->taskId = htobe64(pSource->taskId);
pMsg->queryId = htobe64(pTaskInfo->id.queryId);
+ pMsg->execId = htonl(pSource->execId);
// send the fetch remote task result reques
SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
@@ -2033,7 +2058,7 @@ static int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInf
pMsgSendInfo->param = pWrapper;
pMsgSendInfo->msgInfo.pData = pMsg;
pMsgSendInfo->msgInfo.len = sizeof(SResFetchReq);
- pMsgSendInfo->msgType = TDMT_VND_FETCH;
+ pMsgSendInfo->msgType = pSource->fetchMsgType;
pMsgSendInfo->fp = loadRemoteDataCallback;
int64_t transporterId = 0;
@@ -2045,8 +2070,9 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLo
int32_t compLen, int32_t numOfOutput, int64_t startTs, uint64_t* total,
SArray* pColList) {
if (pColList == NULL) { // data from other sources
- blockCompressDecode(pRes, numOfOutput, numOfRows, pData);
- pRes->info.rows = numOfRows;
+ blockDataCleanup(pRes);
+ // blockDataEnsureCapacity(pRes, numOfRows);
+ blockDecode(pRes, numOfOutput, numOfRows, pData);
} else { // extract data according to pColList
ASSERT(numOfOutput == taosArrayGetSize(pColList));
char* pStart = pData;
@@ -2064,32 +2090,19 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLo
pStart += sizeof(SSysTableSchema);
}
- SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
- pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
- pBlock->info.numOfCols = numOfCols;
-
+ SSDataBlock* pBlock = createDataBlock();
for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData idata = {0};
-
- idata.info.type = pSchema[i].type;
- idata.info.bytes = pSchema[i].bytes;
- idata.info.colId = pSchema[i].colId;
- idata.hasNull = true;
-
- taosArrayPush(pBlock->pDataBlock, &idata);
- if (IS_VAR_DATA_TYPE(idata.info.type)) {
- pBlock->info.hasVarCol = true;
- }
+ SColumnInfoData idata = createColumnInfoData(pSchema[i].type, pSchema[i].bytes, pSchema[i].colId);
+ blockDataAppendColInfo(pBlock, &idata);
}
- blockCompressDecode(pBlock, numOfCols, numOfRows, pStart);
+ blockDecode(pBlock, numOfCols, numOfRows, pStart);
+ blockDataEnsureCapacity(pRes, numOfRows);
// data from mnode
pRes->info.rows = numOfRows;
relocateColumnData(pRes, pColList, pBlock->pDataBlock, false);
- taosArrayDestroy(pBlock->pDataBlock);
- taosMemoryFree(pBlock);
- // blockDataDestroy(pBlock);
+ blockDataDestroy(pBlock);
}
// todo move this to time window aggregator, since the primary timestamp may not be known by exchange operator.
@@ -2156,9 +2169,9 @@ static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SEx
SSDataBlock* pRes = pExchangeInfo->pResult;
SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
if (pRsp->numOfRows == 0) {
- qDebug("%s vgId:%d, taskId:0x%" PRIx64 " index:%d completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
- ", completed:%d try next %d/%" PRIzu,
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, i, pDataInfo->totalRows,
+ qDebug("%s vgId:%d, taskId:0x%" PRIx64 " execId:%d index:%d completed, rowsOfSource:%" PRIu64
+ ", totalRows:%" PRIu64 ", completed:%d try next %d/%" PRIzu,
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, i, pDataInfo->totalRows,
pExchangeInfo->loadInfo.totalRows, completed + 1, i + 1, totalSources);
pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
completed += 1;
@@ -2177,17 +2190,18 @@ static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SEx
if (pRsp->completed == 1) {
qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64
+ " execId:%d"
" index:%d completed, numOfRows:%d, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64 ", totalBytes:%" PRIu64
", completed:%d try next %d/%" PRIzu,
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, i, pRes->info.rows, pDataInfo->totalRows,
- pLoadInfo->totalRows, pLoadInfo->totalSize, completed + 1, i + 1, totalSources);
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, i, pRes->info.rows,
+ pDataInfo->totalRows, pLoadInfo->totalRows, pLoadInfo->totalSize, completed + 1, i + 1, totalSources);
completed += 1;
pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
} else {
- qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64
+ qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " execId:%d numOfRows:%d, totalRows:%" PRIu64
", totalBytes:%" PRIu64,
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pLoadInfo->totalRows,
- pLoadInfo->totalSize);
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, pRes->info.rows,
+ pLoadInfo->totalRows, pLoadInfo->totalSize);
}
taosMemoryFreeClear(pDataInfo->pRsp);
@@ -2260,8 +2274,8 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo* pOperator) {
SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current);
if (pDataInfo->code != TSDB_CODE_SUCCESS) {
- qError("%s vgId:%d, taskID:0x%" PRIx64 " error happens, code:%s", GET_TASKID(pTaskInfo), pSource->addr.nodeId,
- pSource->taskId, tstrerror(pDataInfo->code));
+ qError("%s vgId:%d, taskID:0x%" PRIx64 " execId:%d error happens, code:%s", GET_TASKID(pTaskInfo),
+ pSource->addr.nodeId, pSource->taskId, pSource->execId, tstrerror(pDataInfo->code));
pOperator->pTaskInfo->code = pDataInfo->code;
return NULL;
}
@@ -2269,9 +2283,9 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo* pOperator) {
SRetrieveTableRsp* pRsp = pDataInfo->pRsp;
SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
if (pRsp->numOfRows == 0) {
- qDebug("%s vgId:%d, taskID:0x%" PRIx64 " %d of total completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
- " try next",
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pExchangeInfo->current + 1,
+ qDebug("%s vgId:%d, taskID:0x%" PRIx64 " execId:%d %d of total completed, rowsOfSource:%" PRIu64
+ ", totalRows:%" PRIu64 " try next",
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, pExchangeInfo->current + 1,
pDataInfo->totalRows, pLoadInfo->totalRows);
pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
@@ -2287,18 +2301,19 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo* pOperator) {
pTableRsp->compLen, pTableRsp->numOfCols, startTs, &pDataInfo->totalRows, NULL);
if (pRsp->completed == 1) {
- qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, rowsOfSource:%" PRIu64
+ qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " execId:%d numOfRows:%d, rowsOfSource:%" PRIu64
", totalRows:%" PRIu64 ", totalBytes:%" PRIu64 " try next %d/%" PRIzu,
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pDataInfo->totalRows,
- pLoadInfo->totalRows, pLoadInfo->totalSize, pExchangeInfo->current + 1, totalSources);
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, pRes->info.rows,
+ pDataInfo->totalRows, pLoadInfo->totalRows, pLoadInfo->totalSize, pExchangeInfo->current + 1,
+ totalSources);
pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
pExchangeInfo->current += 1;
} else {
- qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64
+ qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " execId:%d numOfRows:%d, totalRows:%" PRIu64
", totalBytes:%" PRIu64,
- GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pLoadInfo->totalRows,
- pLoadInfo->totalSize);
+ GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pSource->execId, pRes->info.rows,
+ pLoadInfo->totalRows, pLoadInfo->totalSize);
}
pOperator->resultInfo.totalRows += pRes->info.rows;
@@ -2383,13 +2398,12 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo*
}
pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode));
- pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo));
- if (pInfo->pSourceDataInfo == NULL || pInfo->pSources == NULL) {
+ if (pInfo->pSources == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
for (int32_t i = 0; i < numOfSources; ++i) {
- SNodeListNode* pNode = (SNodeListNode*)nodesListGetNode((SNodeList*)pExNode->pSrcEndPoints, i);
+ SDownstreamSourceNode* pNode = (SDownstreamSourceNode*)nodesListGetNode((SNodeList*)pExNode->pSrcEndPoints, i);
taosArrayPush(pInfo->pSources, pNode);
}
@@ -2420,7 +2434,7 @@ SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode
pOperator->blocking = false;
pOperator->status = OP_NOT_OPENED;
pOperator->info = pInfo;
- pOperator->exprSupp.numOfExprs = pInfo->pResult->info.numOfCols;
+ pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pResult->pDataBlock);
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet = createOperatorFpSet(prepareLoadRemoteData, doLoadRemoteData, NULL, NULL,
@@ -2432,7 +2446,6 @@ _error:
doDestroyExchangeOperatorInfo(pInfo);
}
- taosMemoryFreeClear(pInfo);
taosMemoryFreeClear(pOperator);
pTaskInfo->code = code;
return NULL;
@@ -2452,6 +2465,8 @@ static void destroySortedMergeOperatorInfo(void* param, int32_t numOfOutput) {
blockDataDestroy(pInfo->binfo.pRes);
cleanupAggSup(&pInfo->aggSup);
+
+ taosMemoryFreeClear(param);
}
static bool needToMerge(SSDataBlock* pBlock, SArray* groupInfo, char** buf, int32_t rowIndex) {
@@ -2542,9 +2557,6 @@ static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock
SSortedMergeOperatorInfo* pInfo = pOperator->info;
SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
- // pCtx[i].size = 1;
- }
for (int32_t i = 0; i < pBlock->info.rows; ++i) {
if (!pInfo->hasGroupVal) {
@@ -2653,7 +2665,7 @@ SSDataBlock* getSortedMergeBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlo
SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId);
SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId);
- colDataAssign(pDst, pSrc, p->info.rows);
+ colDataAssign(pDst, pSrc, p->info.rows, &pDataBlock->info);
}
pDataBlock->info.rows = p->info.rows;
@@ -2765,7 +2777,7 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t
goto _error;
}
- size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
+ size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
code = doInitAggInfoSup(&pInfo->aggSup, pOperator->exprSupp.pCtx, num, keyBufSize, pTaskInfo->id.str);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
@@ -2787,9 +2799,9 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t
pOperator->name = "SortedMerge";
// pOperator->operatorType = OP_SortedMerge;
- pOperator->blocking = true;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
+ pOperator->blocking = true;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doSortedMerge, NULL, NULL, destroySortedMergeOperatorInfo,
@@ -2817,7 +2829,7 @@ int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scan
int32_t type = pOperator->operatorType;
if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN ||
type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN ||
- type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN) {
+ type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN) {
*order = TSDB_ORDER_ASC;
*scanFlag = MAIN_SCAN;
return TSDB_CODE_SUCCESS;
@@ -2834,6 +2846,92 @@ int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scan
}
}
}
+#if 0
+int32_t doPrepareScan(SOperatorInfo* pOperator, uint64_t uid, int64_t ts) {
+ uint8_t type = pOperator->operatorType;
+
+ pOperator->status = OP_OPENED;
+
+ if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
+ SStreamScanInfo* pScanInfo = pOperator->info;
+ pScanInfo->blockType = STREAM_INPUT__TABLE_SCAN;
+
+ pScanInfo->pTableScanOp->status = OP_OPENED;
+
+ STableScanInfo* pInfo = pScanInfo->pTableScanOp->info;
+ ASSERT(pInfo->scanMode == TABLE_SCAN__TABLE_ORDER);
+
+ if (uid == 0) {
+ pInfo->noTable = 1;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ /*if (pSnapShotScanInfo->dataReader == NULL) {*/
+ /*pSnapShotScanInfo->dataReader = tsdbReaderOpen(pHandle->vnode, &pSTInfo->cond, tableList, 0, 0);*/
+ /*pSnapShotScanInfo->scanMode = TABLE_SCAN__TABLE_ORDER;*/
+ /*}*/
+
+ pInfo->noTable = 0;
+
+ if (pInfo->lastStatus.uid != uid || pInfo->lastStatus.ts != ts) {
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ int32_t tableSz = taosArrayGetSize(pTaskInfo->tableqinfoList.pTableList);
+ bool found = false;
+ for (int32_t i = 0; i < tableSz; i++) {
+ STableKeyInfo* pTableInfo = taosArrayGet(pTaskInfo->tableqinfoList.pTableList, i);
+ if (pTableInfo->uid == uid) {
+ found = true;
+ pInfo->currentTable = i;
+ }
+ }
+ // TODO after processing drop, found can be false
+ ASSERT(found);
+
+ tsdbSetTableId(pInfo->dataReader, uid);
+ int64_t oldSkey = pInfo->cond.twindows.skey;
+ pInfo->cond.twindows.skey = ts + 1;
+ tsdbReaderReset(pInfo->dataReader, &pInfo->cond);
+ pInfo->cond.twindows.skey = oldSkey;
+ pInfo->scanTimes = 0;
+
+ qDebug("tsdb reader offset seek to uid %" PRId64 " ts %" PRId64 ", table cur set to %d , all table num %d", uid, ts,
+ pInfo->currentTable, tableSz);
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+ } else {
+ if (pOperator->numOfDownstream == 1) {
+ return doPrepareScan(pOperator->pDownstream[0], uid, ts);
+ } else if (pOperator->numOfDownstream == 0) {
+ qError("failed to find stream scan operator to set the input data block");
+ return TSDB_CODE_QRY_APP_ERROR;
+ } else {
+ qError("join not supported for stream block scan");
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ }
+}
+
+int32_t doGetScanStatus(SOperatorInfo* pOperator, uint64_t* uid, int64_t* ts) {
+ int32_t type = pOperator->operatorType;
+ if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
+ SStreamScanInfo* pScanInfo = pOperator->info;
+ STableScanInfo* pSnapShotScanInfo = pScanInfo->pTableScanOp->info;
+ *uid = pSnapShotScanInfo->lastStatus.uid;
+ *ts = pSnapShotScanInfo->lastStatus.ts;
+ } else {
+ if (pOperator->pDownstream[0] == NULL) {
+ return TSDB_CODE_INVALID_PARA;
+ } else {
+ doGetScanStatus(pOperator->pDownstream[0], uid, ts);
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+#endif
// this is a blocking operator
static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
@@ -2844,8 +2942,8 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SAggOperatorInfo* pAggInfo = pOperator->info;
- SExprSupp* pSup = &pOperator->exprSupp;
- SOperatorInfo* downstream = pOperator->pDownstream[0];
+ SExprSupp* pSup = &pOperator->exprSupp;
+ SOperatorInfo* downstream = pOperator->pDownstream[0];
int64_t st = taosGetTimestampUs();
@@ -2875,25 +2973,10 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
// the pDataBlock are always the same one, no need to call this again
setExecutionContext(pOperator, pOperator->exprSupp.numOfExprs, pBlock->info.groupId, pAggInfo);
setInputDataBlock(pOperator, pSup->pCtx, pBlock, order, scanFlag, true);
- code = doAggregateImpl(pOperator, 0, pSup->pCtx);
+ code = doAggregateImpl(pOperator, pSup->pCtx);
if (code != 0) {
longjmp(pTaskInfo->env, code);
}
-
-#if 0 // test for encode/decode result info
- if(pOperator->fpSet.encodeResultRow){
- char *result = NULL;
- int32_t length = 0;
- pOperator->fpSet.encodeResultRow(pOperator, &result, &length);
- SAggSupporter* pSup = &pAggInfo->aggSup;
- taosHashClear(pSup->pResultRowHashTable);
- pInfo->resultRowInfo.size = 0;
- pOperator->fpSet.decodeResultRow(pOperator, result);
- if(result){
- taosMemoryFree(result);
- }
- }
-#endif
}
closeAllResultRows(&pAggInfo->binfo.resultRowInfo);
@@ -2920,11 +3003,19 @@ static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) {
}
blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
- doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf);
- if (pInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pAggInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
- }
+ while (1) {
+ doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf);
+ doFilter(pAggInfo->pCondition, pInfo->pRes);
+ if (!hasDataInGroupInfo(&pAggInfo->groupResInfo)) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (pInfo->pRes->info.rows > 0) {
+ break;
+ }
+ }
size_t rows = blockDataGetNumOfRows(pInfo->pRes);
pOperator->resultInfo.totalRows += rows;
@@ -2942,6 +3033,13 @@ int32_t aggEncodeResultRow(SOperatorInfo* pOperator, char** result, int32_t* len
int32_t totalSize =
sizeof(int32_t) + sizeof(int32_t) + size * (sizeof(int32_t) + keyLen + sizeof(int32_t) + pSup->resultRowSize);
+ // no result
+ if (getTotalBufSize(pSup->pResultBuf) == 0) {
+ *result = NULL;
+ *length = 0;
+ return TSDB_CODE_SUCCESS;
+ }
+
*result = (char*)taosMemoryCalloc(1, totalSize);
if (*result == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -3110,8 +3208,9 @@ static int32_t handleLimitOffset(SOperatorInfo* pOperator, SSDataBlock* pBlock)
}
// check for the limitation in each group
- if (pProjectInfo->limit.limit > 0 && pProjectInfo->curOutput + pRes->info.rows >= pProjectInfo->limit.limit) {
- pRes->info.rows = (int32_t)(pProjectInfo->limit.limit - pProjectInfo->curOutput);
+ if (pProjectInfo->limit.limit >= 0 && pProjectInfo->curOutput + pRes->info.rows >= pProjectInfo->limit.limit) {
+ int32_t keepRows = (int32_t)(pProjectInfo->limit.limit - pProjectInfo->curOutput);
+ blockDataKeepFirstNRows(pRes, keepRows);
if (pProjectInfo->slimit.limit > 0 && pProjectInfo->slimit.limit <= pProjectInfo->curGroupOutput) {
pOperator->status = OP_EXEC_DONE;
}
@@ -3140,6 +3239,10 @@ static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
if (pOperator->status == OP_EXEC_DONE) {
+ if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE) {
+ pOperator->status = OP_OPENED;
+ return NULL;
+ }
return NULL;
}
@@ -3173,11 +3276,22 @@ static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
while (1) {
// The downstream exec may change the value of the newgroup, so use a local variable instead.
+ qDebug("projection call next");
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
if (pBlock == NULL) {
+ qDebug("projection get null");
+
+ /*if (pTaskInfo->execModel == OPTR_EXEC_MODEL_BATCH) {*/
doSetOperatorCompleted(pOperator);
+ /*} else if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE) {*/
+ /*pOperator->status = OP_RES_TO_RETURN;*/
+ /*}*/
break;
}
+ if (pBlock->info.type == STREAM_RETRIEVE) {
+ // for stream interval
+ return pBlock;
+ }
// the pDataBlock are always the same one, no need to call this again
int32_t code = getTableScanInfo(pOperator->pDownstream[0], &order, &scanFlag);
@@ -3185,8 +3299,6 @@ static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
longjmp(pTaskInfo->env, code);
}
- doFilter(pProjectInfo->pFilterNode, pBlock);
-
setInputDataBlock(pOperator, pSup->pCtx, pBlock, order, scanFlag, false);
blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);
@@ -3197,6 +3309,10 @@ static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
}
int32_t status = handleLimitOffset(pOperator, pBlock);
+
+ // filter shall be applied after apply functions and limit/offset on the result
+ doFilter(pProjectInfo->pFilterNode, pInfo->pRes);
+
if (status == PROJECT_RETRIEVE_CONTINUE) {
continue;
} else if (status == PROJECT_RETRIEVE_DONE) {
@@ -3220,8 +3336,8 @@ static void doHandleRemainBlockForNewGroupImpl(SFillOperatorInfo* pInfo, SResult
SExecTaskInfo* pTaskInfo) {
pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
- int64_t ekey = Q_STATUS_EQUAL(pTaskInfo->status, TASK_COMPLETED) ? pTaskInfo->window.ekey
- : pInfo->existNewGroupBlock->info.window.ekey;
+ int64_t ekey =
+ Q_STATUS_EQUAL(pTaskInfo->status, TASK_COMPLETED) ? pInfo->win.ekey : pInfo->existNewGroupBlock->info.window.ekey;
taosResetFillInfo(pInfo->pFillInfo, getFillInfoStart(pInfo->pFillInfo));
taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
@@ -3248,7 +3364,7 @@ static void doHandleRemainBlockFromNewGroup(SFillOperatorInfo* pInfo, SResultInf
}
}
-static SSDataBlock* doFill(SOperatorInfo* pOperator) {
+static SSDataBlock* doFillImpl(SOperatorInfo* pOperator) {
SFillOperatorInfo* pInfo = pOperator->info;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
@@ -3256,9 +3372,6 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) {
SSDataBlock* pResBlock = pInfo->pRes;
blockDataCleanup(pResBlock);
- if (pOperator->status == OP_EXEC_DONE) {
- return NULL;
- }
// todo handle different group data interpolation
bool n = false;
@@ -3275,13 +3388,15 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) {
assert(pBlock != NULL);
}
+ blockDataUpdateTsWindow(pBlock, pInfo->primaryTsCol);
+
if (*newgroup && pInfo->totalInputRows > 0) { // there are already processed current group data block
pInfo->existNewGroupBlock = pBlock;
*newgroup = false;
// Fill the previous group data block, before handle the data block of new group.
// Close the fill operation for previous group data block
- taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
+ taosFillSetStartInfo(pInfo->pFillInfo, 0, pInfo->win.ekey);
} else {
if (pBlock == NULL) {
if (pInfo->totalInputRows == 0) {
@@ -3289,7 +3404,7 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) {
return NULL;
}
- taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
+ taosFillSetStartInfo(pInfo->pFillInfo, 0, pInfo->win.ekey);
} else {
pInfo->totalInputRows += pBlock->info.rows;
taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey);
@@ -3324,12 +3439,48 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) {
}
}
+static SSDataBlock* doFill(SOperatorInfo* pOperator) {
+ SFillOperatorInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ if (pOperator->status == OP_EXEC_DONE) {
+ return NULL;
+ }
+
+ SSDataBlock* fillResult = NULL;
+ while (true) {
+ fillResult = doFillImpl(pOperator);
+ if (fillResult != NULL) {
+ doFilter(pInfo->pCondition, fillResult);
+ }
+
+ if (fillResult == NULL) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (fillResult->info.rows > 0) {
+ break;
+ }
+ }
+
+ if (fillResult != NULL) {
+ size_t rows = fillResult->info.rows;
+ pOperator->resultInfo.totalRows += rows;
+ }
+
+ return fillResult;
+}
+
static void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs) {
for (int32_t i = 0; i < numOfExprs; ++i) {
SExprInfo* pExprInfo = &pExpr[i];
- if (pExprInfo->pExpr->nodeType == QUERY_NODE_COLUMN) {
- taosMemoryFree(pExprInfo->base.pParam[0].pCol);
+ for(int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) {
+ if (pExprInfo->base.pParam[j].type == FUNC_PARAM_TYPE_COLUMN) {
+ taosMemoryFreeClear(pExprInfo->base.pParam[j].pCol);
+ }
}
+
taosMemoryFree(pExprInfo->base.pParam);
taosMemoryFree(pExprInfo->pExpr);
}
@@ -3353,12 +3504,7 @@ static void destroyOperatorInfo(SOperatorInfo* pOperator) {
pOperator->numOfDownstream = 0;
}
- if (pOperator->exprSupp.pExprInfo != NULL) {
- destroyExprInfo(pOperator->exprSupp.pExprInfo, pOperator->exprSupp.numOfExprs);
- }
-
- taosMemoryFreeClear(pOperator->exprSupp.pExprInfo);
- taosMemoryFreeClear(pOperator->info);
+ cleanupExprSupp(&pOperator->exprSupp);
taosMemoryFreeClear(pOperator);
}
@@ -3423,11 +3569,12 @@ int32_t initAggInfo(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInf
}
void initResultSizeInfo(SOperatorInfo* pOperator, int32_t numOfRows) {
+ ASSERT(numOfRows != 0);
pOperator->resultInfo.capacity = numOfRows;
pOperator->resultInfo.threshold = numOfRows * 0.75;
if (pOperator->resultInfo.threshold == 0) {
- pOperator->resultInfo.capacity = numOfRows;
+ pOperator->resultInfo.threshold = numOfRows;
}
}
@@ -3436,6 +3583,25 @@ void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock) {
initResultRowInfo(&pInfo->resultRowInfo);
}
+static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
+ if (pCtx == NULL) {
+ return NULL;
+ }
+
+ for (int32_t i = 0; i < numOfOutput; ++i) {
+ for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) {
+ taosVariantDestroy(&pCtx[i].param[j].param);
+ }
+
+ taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx);
+ taosMemoryFree(pCtx[i].input.pData);
+ taosMemoryFree(pCtx[i].input.pColumnDataAgg);
+ }
+
+ taosMemoryFreeClear(pCtx);
+ return NULL;
+}
+
int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr) {
pSup->pExprInfo = pExprInfo;
pSup->numOfExprs = numOfExpr;
@@ -3449,8 +3615,18 @@ int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr) {
return TSDB_CODE_SUCCESS;
}
+void cleanupExprSupp(SExprSupp* pSupp) {
+ destroySqlFunctionCtx(pSupp->pCtx, pSupp->numOfExprs);
+ if (pSupp->pExprInfo != NULL) {
+ destroyExprInfo(pSupp->pExprInfo, pSupp->numOfExprs);
+ }
+
+ taosMemoryFreeClear(pSupp->pExprInfo);
+ taosMemoryFree(pSupp->rowEntryInfoOffset);
+}
+
SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
- SSDataBlock* pResultBlock, SExprInfo* pScalarExprInfo,
+ SSDataBlock* pResultBlock, SNode* pCondition, SExprInfo* pScalarExprInfo,
int32_t numOfScalarExpr, SExecTaskInfo* pTaskInfo) {
SAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAggOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
@@ -3474,6 +3650,7 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo*
}
pInfo->groupId = INT32_MIN;
+ pInfo->pCondition = pCondition;
pOperator->name = "TableAggregate";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_HASH_AGG;
pOperator->blocking = true;
@@ -3498,25 +3675,6 @@ _error:
return NULL;
}
-static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
- if (pCtx == NULL) {
- return NULL;
- }
-
- for (int32_t i = 0; i < numOfOutput; ++i) {
- for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) {
- taosVariantDestroy(&pCtx[i].param[j].param);
- }
-
- taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx);
- taosMemoryFree(pCtx[i].input.pData);
- taosMemoryFree(pCtx[i].input.pColumnDataAgg);
- }
-
- taosMemoryFreeClear(pCtx);
- return NULL;
-}
-
void cleanupBasicInfo(SOptrBasicInfo* pInfo) {
assert(pInfo != NULL);
cleanupResultRowInfo(&pInfo->resultRowInfo);
@@ -3526,11 +3684,25 @@ void cleanupBasicInfo(SOptrBasicInfo* pInfo) {
void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) {
SOptrBasicInfo* pInfo = (SOptrBasicInfo*)param;
cleanupBasicInfo(pInfo);
+
+ taosMemoryFreeClear(param);
+}
+
+
+static void freeItem(void* pItem) {
+ void** p = pItem;
+ if (*p != NULL) {
+ taosMemoryFreeClear(*p);
+ }
}
void destroyAggOperatorInfo(void* param, int32_t numOfOutput) {
SAggOperatorInfo* pInfo = (SAggOperatorInfo*)param;
cleanupBasicInfo(&pInfo->binfo);
+
+ cleanupAggSup(&pInfo->aggSup);
+ taosArrayDestroyEx(pInfo->groupResInfo.pRows, freeItem);
+ taosMemoryFreeClear(param);
}
void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
@@ -3538,6 +3710,8 @@ void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
pInfo->pRes = blockDataDestroy(pInfo->pRes);
taosMemoryFreeClear(pInfo->p);
+
+ taosMemoryFreeClear(param);
}
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) {
@@ -3548,13 +3722,8 @@ static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) {
cleanupBasicInfo(&pInfo->binfo);
cleanupAggSup(&pInfo->aggSup);
taosArrayDestroy(pInfo->pPseudoColInfo);
-}
-void cleanupExecSupp(SExprSupp* pSupp) {
- destroySqlFunctionCtx(pSupp->pCtx, pSupp->numOfExprs);
- destroyExprInfo(pSupp->pExprInfo, pSupp->numOfExprs);
-
- taosMemoryFree(pSupp->rowEntryInfoOffset);
+ taosMemoryFreeClear(param);
}
static void destroyIndefinitOperatorInfo(void* param, int32_t numOfOutput) {
@@ -3563,7 +3732,9 @@ static void destroyIndefinitOperatorInfo(void* param, int32_t numOfOutput) {
taosArrayDestroy(pInfo->pPseudoColInfo);
cleanupAggSup(&pInfo->aggSup);
- cleanupExecSupp(&pInfo->scalarSup);
+ cleanupExprSupp(&pInfo->scalarSup);
+
+ taosMemoryFreeClear(param);
}
void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput) {
@@ -3581,6 +3752,8 @@ void doDestroyExchangeOperatorInfo(void* param) {
}
tsem_destroy(&pExInfo->ready);
+
+ taosMemoryFreeClear(param);
}
static SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols) {
@@ -3594,6 +3767,10 @@ static SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols)
return pList;
}
+static int64_t getLimit(SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->limit; }
+
+static int64_t getOffset(SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->offset; }
+
SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhysiNode* pProjPhyNode,
SExecTaskInfo* pTaskInfo) {
SProjectOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SProjectOperatorInfo));
@@ -3606,8 +3783,8 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhys
SExprInfo* pExprInfo = createExprInfo(pProjPhyNode->pProjections, NULL, &numOfCols);
SSDataBlock* pResBlock = createResDataBlock(pProjPhyNode->node.pOutputDataBlockDesc);
- SLimit limit = {.limit = pProjPhyNode->limit, .offset = pProjPhyNode->offset};
- SLimit slimit = {.limit = pProjPhyNode->slimit, .offset = pProjPhyNode->soffset};
+ SLimit limit = {.limit = getLimit(pProjPhyNode->node.pLimit), .offset = getOffset(pProjPhyNode->node.pLimit)};
+ SLimit slimit = {.limit = getLimit(pProjPhyNode->node.pSlimit), .offset = getOffset(pProjPhyNode->node.pSlimit)};
pInfo->limit = limit;
pInfo->slimit = slimit;
@@ -3653,6 +3830,41 @@ _error:
return NULL;
}
+static void doHandleDataBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, SOperatorInfo* downstream,
+ SExecTaskInfo* pTaskInfo) {
+ int32_t order = 0;
+ int32_t scanFlag = 0;
+
+ SIndefOperatorInfo* pIndefInfo = pOperator->info;
+ SOptrBasicInfo* pInfo = &pIndefInfo->binfo;
+ SExprSupp* pSup = &pOperator->exprSupp;
+
+ // the pDataBlock are always the same one, no need to call this again
+ int32_t code = getTableScanInfo(downstream, &order, &scanFlag);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
+
+ // there is an scalar expression that needs to be calculated before apply the group aggregation.
+ SExprSupp* pScalarSup = &pIndefInfo->scalarSup;
+ if (pScalarSup->pExprInfo != NULL) {
+ code = projectApplyFunctions(pScalarSup->pExprInfo, pBlock, pBlock, pScalarSup->pCtx, pScalarSup->numOfExprs,
+ pIndefInfo->pPseudoColInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
+ }
+
+ setInputDataBlock(pOperator, pSup->pCtx, pBlock, order, scanFlag, false);
+ blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);
+
+ code = projectApplyFunctions(pSup->pExprInfo, pInfo->pRes, pBlock, pSup->pCtx, pSup->numOfExprs,
+ pIndefInfo->pPseudoColInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
+}
+
static SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator) {
SIndefOperatorInfo* pIndefInfo = pOperator->info;
SOptrBasicInfo* pInfo = &pIndefInfo->binfo;
@@ -3667,8 +3879,6 @@ static SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator) {
}
int64_t st = 0;
- int32_t order = 0;
- int32_t scanFlag = 0;
if (pOperator->cost.openCost == 0) {
st = taosGetTimestampUs();
@@ -3677,36 +3887,50 @@ static SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator) {
SOperatorInfo* downstream = pOperator->pDownstream[0];
while (1) {
- // The downstream exec may change the value of the newgroup, so use a local variable instead.
- SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
- if (pBlock == NULL) {
- doSetOperatorCompleted(pOperator);
- break;
- }
+ // here we need to handle the existsed group results
+ if (pIndefInfo->pNextGroupRes != NULL) { // todo extract method
+ for (int32_t k = 0; k < pSup->numOfExprs; ++k) {
+ SqlFunctionCtx* pCtx = &pSup->pCtx[k];
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ pResInfo->initialized = false;
+ pCtx->pOutput = NULL;
+ }
- // the pDataBlock are always the same one, no need to call this again
- int32_t code = getTableScanInfo(pOperator->pDownstream[0], &order, &scanFlag);
- if (code != TSDB_CODE_SUCCESS) {
- longjmp(pTaskInfo->env, code);
+ doHandleDataBlock(pOperator, pIndefInfo->pNextGroupRes, downstream, pTaskInfo);
+ pIndefInfo->pNextGroupRes = NULL;
}
- // there is an scalar expression that needs to be calculated before apply the group aggregation.
- SExprSupp* pScalarSup = &pIndefInfo->scalarSup;
- if (pScalarSup->pExprInfo != NULL) {
- code = projectApplyFunctions(pScalarSup->pExprInfo, pBlock, pBlock, pScalarSup->pCtx, pScalarSup->numOfExprs,
- pIndefInfo->pPseudoColInfo);
- if (code != TSDB_CODE_SUCCESS) {
- longjmp(pTaskInfo->env, code);
+ if (pInfo->pRes->info.rows < pOperator->resultInfo.threshold) {
+ while (1) {
+ // The downstream exec may change the value of the newgroup, so use a local variable instead.
+ SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
+ if (pBlock == NULL) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (pIndefInfo->groupId == 0 && pBlock->info.groupId != 0) {
+ pIndefInfo->groupId = pBlock->info.groupId; // this is the initial group result
+ } else {
+ if (pIndefInfo->groupId != pBlock->info.groupId) { // reset output buffer and computing status
+ pIndefInfo->groupId = pBlock->info.groupId;
+ pIndefInfo->pNextGroupRes = pBlock;
+ break;
+ }
+ }
+
+ doHandleDataBlock(pOperator, pBlock, downstream, pTaskInfo);
+ if (pInfo->pRes->info.rows >= pOperator->resultInfo.threshold) {
+ break;
+ }
}
}
- setInputDataBlock(pOperator, pSup->pCtx, pBlock, order, scanFlag, false);
- blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);
-
- code = projectApplyFunctions(pOperator->exprSupp.pExprInfo, pInfo->pRes, pBlock, pSup->pCtx,
- pOperator->exprSupp.numOfExprs, pIndefInfo->pPseudoColInfo);
- if (code != TSDB_CODE_SUCCESS) {
- longjmp(pTaskInfo->env, code);
+ doFilter(pIndefInfo->pCondition, pInfo->pRes);
+ size_t rows = pInfo->pRes->info.rows;
+ if (rows >= 0) {
+ break;
}
}
@@ -3736,9 +3960,9 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy
SExprInfo* pExprInfo = createExprInfo(pPhyNode->pFuncs, NULL, &numOfExpr);
if (pPhyNode->pExprs != NULL) {
- int32_t num = 0;
+ int32_t num = 0;
SExprInfo* pSExpr = createExprInfo(pPhyNode->pExprs, NULL, &num);
- int32_t code = initExprSupp(&pInfo->scalarSup, pSExpr, num);
+ int32_t code = initExprSupp(&pInfo->scalarSup, pSExpr, num);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
@@ -3754,22 +3978,23 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy
if (numOfRows * pResBlock->info.rowSize > TWOMB) {
numOfRows = TWOMB / pResBlock->info.rowSize;
}
+
initResultSizeInfo(pOperator, numOfRows);
- initAggInfo(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfExpr, keyBufSize, pTaskInfo->id.str);
+ initAggInfo(pSup, &pInfo->aggSup, pExprInfo, numOfExpr, keyBufSize, pTaskInfo->id.str);
initBasicInfo(&pInfo->binfo, pResBlock);
setFunctionResultOutput(pOperator, &pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfExpr);
- pInfo->binfo.pRes = pResBlock;
- pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr);
+ pInfo->binfo.pRes = pResBlock;
+ pInfo->pCondition = pPhyNode->node.pConditions;
+ pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr);
pOperator->name = "IndefinitOperator";
- pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
- pOperator->exprSupp.numOfExprs = numOfExpr;
+ pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doApplyIndefinitFunction, NULL, NULL,
@@ -3795,11 +4020,15 @@ static int32_t initFillInfo(SFillOperatorInfo* pInfo, SExprInfo* pExpr, int32_t
STimeWindow w = TSWINDOW_INITIALIZER;
getAlignQueryTimeWindow(pInterval, pInterval->precision, win.skey, &w);
+ w = getFirstQualifiedTimeWindow(win.skey, &w, pInterval, TSDB_ORDER_ASC);
int32_t order = TSDB_ORDER_ASC;
- pInfo->pFillInfo = taosCreateFillInfo(order, w.skey, 0, capacity, numOfCols, pInterval, fillType, pColInfo, id);
+ pInfo->pFillInfo = taosCreateFillInfo(order, w.skey, 0, capacity, numOfCols, pInterval,
+ fillType, pColInfo, pInfo->primaryTsCol, id);
+ pInfo->win = win;
pInfo->p = taosMemoryCalloc(numOfCols, POINTER_BYTES);
+
if (pInfo->pFillInfo == NULL || pInfo->p == NULL) {
taosMemoryFree(pInfo->pFillInfo);
taosMemoryFree(pInfo->p);
@@ -3820,11 +4049,20 @@ SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode*
int32_t num = 0;
SSDataBlock* pResBlock = createResDataBlock(pPhyFillNode->node.pOutputDataBlockDesc);
SExprInfo* pExprInfo = createExprInfo(pPhyFillNode->pTargets, NULL, &num);
- SInterval* pInterval = &((SIntervalAggOperatorInfo*)downstream->info)->interval;
- int32_t type = convertFillType(pPhyFillNode->mode);
+ SInterval* pInterval =
+ QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL == downstream->operatorType
+ ? &((SMergeAlignedIntervalAggOperatorInfo*)downstream->info)->intervalAggOperatorInfo->interval
+ : &((SIntervalAggOperatorInfo*)downstream->info)->interval;
+
+ int32_t type = convertFillType(pPhyFillNode->mode);
SResultInfo* pResultInfo = &pOperator->resultInfo;
initResultSizeInfo(pOperator, 4096);
+ pInfo->primaryTsCol = ((SColumnNode*)pPhyFillNode->pWStartTs)->slotId;
+
+ int32_t numOfOutputCols = 0;
+ SArray* pColMatchColInfo = extractColMatchInfo(pPhyFillNode->pTargets, pPhyFillNode->node.pOutputDataBlockDesc,
+ &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
int32_t code = initFillInfo(pInfo, pExprInfo, num, (SNodeListNode*)pPhyFillNode->pValues, pPhyFillNode->timeRange,
pResultInfo->capacity, pTaskInfo->id.str, pInterval, type);
@@ -3834,14 +4072,16 @@ SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode*
pInfo->pRes = pResBlock;
pInfo->multigroupResult = multigroupResult;
+ pInfo->pCondition = pPhyFillNode->node.pConditions;
+ pInfo->pColMatchColInfo = pColMatchColInfo;
pOperator->name = "FillOperator";
pOperator->blocking = false;
pOperator->status = OP_NOT_OPENED;
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_FILL;
- pOperator->exprSupp.pExprInfo = pExprInfo;
- pOperator->exprSupp.numOfExprs = num;
- pOperator->info = pInfo;
- pOperator->pTaskInfo = pTaskInfo;
+ pOperator->exprSupp.pExprInfo = pExprInfo;
+ pOperator->exprSupp.numOfExprs = num;
+ pOperator->info = pInfo;
+ pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet =
createOperatorFpSet(operatorDummyOpenFn, doFill, NULL, NULL, destroySFillOperatorInfo, NULL, NULL, NULL);
@@ -3871,42 +4111,111 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPT
return pTaskInfo;
}
-static tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
- STableListInfo* pTableListInfo, uint64_t queryId, uint64_t taskId,
- SNode* pTagCond);
+static STsdbReader* doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
+ STableListInfo* pTableListInfo, const char* idstr);
static SArray* extractColumnInfo(SNodeList* pNodeList);
-int32_t extractTableSchemaVersion(SReadHandle* pHandle, uint64_t uid, SExecTaskInfo* pTaskInfo) {
+int32_t extractTableSchemaInfo(SReadHandle* pHandle, uint64_t uid, SExecTaskInfo* pTaskInfo) {
SMetaReader mr = {0};
metaReaderInit(&mr, pHandle->meta, 0);
int32_t code = metaGetTableEntryByUid(&mr, uid);
- if (code) {
+ if (code != TSDB_CODE_SUCCESS) {
metaReaderClear(&mr);
- return code;
+ return terrno;
}
pTaskInfo->schemaVer.tablename = strdup(mr.me.name);
if (mr.me.type == TSDB_SUPER_TABLE) {
- pTaskInfo->schemaVer.sversion = mr.me.stbEntry.schemaRow.version;
+ pTaskInfo->schemaVer.sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow);
pTaskInfo->schemaVer.tversion = mr.me.stbEntry.schemaTag.version;
} else if (mr.me.type == TSDB_CHILD_TABLE) {
+ tDecoderClear(&mr.coder);
+
tb_uid_t suid = mr.me.ctbEntry.suid;
metaGetTableEntryByUid(&mr, suid);
- pTaskInfo->schemaVer.sversion = mr.me.stbEntry.schemaRow.version;
+ pTaskInfo->schemaVer.sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow);
pTaskInfo->schemaVer.tversion = mr.me.stbEntry.schemaTag.version;
} else {
- pTaskInfo->schemaVer.sversion = mr.me.ntbEntry.schemaRow.version;
+ pTaskInfo->schemaVer.sw = tCloneSSchemaWrapper(&mr.me.ntbEntry.schemaRow);
}
metaReaderClear(&mr);
-
return TSDB_CODE_SUCCESS;
}
-int32_t generateGroupIdMap(STableListInfo* pTableListInfo, SReadHandle* pHandle, SArray* groupKey) {
- if (groupKey == NULL) {
+static void cleanupTableSchemaInfo(SExecTaskInfo* pTaskInfo) {
+ taosMemoryFreeClear(pTaskInfo->schemaVer.dbname);
+ if (pTaskInfo->schemaVer.sw == NULL) {
+ return;
+ }
+
+ taosMemoryFree(pTaskInfo->schemaVer.sw->pSchema);
+ taosMemoryFree(pTaskInfo->schemaVer.sw);
+ taosMemoryFree(pTaskInfo->schemaVer.tablename);
+}
+
+static int32_t sortTableGroup(STableListInfo* pTableListInfo, int32_t groupNum) {
+ taosArrayClear(pTableListInfo->pGroupList);
+ SArray* sortSupport = taosArrayInit(groupNum, sizeof(uint64_t));
+ if (sortSupport == NULL) return TSDB_CODE_OUT_OF_MEMORY;
+ for (int32_t i = 0; i < taosArrayGetSize(pTableListInfo->pTableList); i++) {
+ STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
+ uint64_t* groupId = taosHashGet(pTableListInfo->map, &info->uid, sizeof(uint64_t));
+
+ int32_t index = taosArraySearchIdx(sortSupport, groupId, compareUint64Val, TD_EQ);
+ if (index == -1) {
+ void* p = taosArraySearch(sortSupport, groupId, compareUint64Val, TD_GT);
+ SArray* tGroup = taosArrayInit(8, sizeof(STableKeyInfo));
+ if (tGroup == NULL) {
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ if (taosArrayPush(tGroup, info) == NULL) {
+ qError("taos push info array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ if (p == NULL) {
+ if (taosArrayPush(sortSupport, groupId) == NULL) {
+ qError("taos push support array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ if (taosArrayPush(pTableListInfo->pGroupList, &tGroup) == NULL) {
+ qError("taos push group array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ } else {
+ int32_t pos = TARRAY_ELEM_IDX(sortSupport, p);
+ if (taosArrayInsert(sortSupport, pos, groupId) == NULL) {
+ qError("taos insert support array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ if (taosArrayInsert(pTableListInfo->pGroupList, pos, &tGroup) == NULL) {
+ qError("taos insert group array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ }
+ } else {
+ SArray* tGroup = (SArray*)taosArrayGetP(pTableListInfo->pGroupList, index);
+ if (taosArrayPush(tGroup, info) == NULL) {
+ qError("taos push uid array error");
+ taosArrayDestroy(sortSupport);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ }
+ }
+ taosArrayDestroy(sortSupport);
+ return TDB_CODE_SUCCESS;
+}
+
+int32_t generateGroupIdMap(STableListInfo* pTableListInfo, SReadHandle* pHandle, SNodeList* group) {
+ if (group == NULL) {
return TDB_CODE_SUCCESS;
}
@@ -3916,13 +4225,14 @@ int32_t generateGroupIdMap(STableListInfo* pTableListInfo, SReadHandle* pHandle,
}
int32_t keyLen = 0;
void* keyBuf = NULL;
- int32_t numOfGroupCols = taosArrayGetSize(groupKey);
- for (int32_t j = 0; j < numOfGroupCols; ++j) {
- SColumn* pCol = taosArrayGet(groupKey, j);
- keyLen += pCol->bytes; // actual data + null_flag
+
+ SNode* node;
+ FOREACH(node, group) {
+ SExprNode* pExpr = (SExprNode*)node;
+ keyLen += pExpr->resType.bytes;
}
- int32_t nullFlagSize = sizeof(int8_t) * numOfGroupCols;
+ int32_t nullFlagSize = sizeof(int8_t) * LIST_LENGTH(group);
keyLen += nullFlagSize;
keyBuf = taosMemoryCalloc(1, keyLen);
@@ -3930,156 +4240,155 @@ int32_t generateGroupIdMap(STableListInfo* pTableListInfo, SReadHandle* pHandle,
return TSDB_CODE_OUT_OF_MEMORY;
}
+ int32_t groupNum = 0;
for (int32_t i = 0; i < taosArrayGetSize(pTableListInfo->pTableList); i++) {
STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
SMetaReader mr = {0};
metaReaderInit(&mr, pHandle->meta, 0);
metaGetTableEntryByUid(&mr, info->uid);
+ SNodeList* groupNew = nodesCloneList(group);
+
+ nodesRewriteExprsPostOrder(groupNew, doTranslateTagExpr, &mr);
char* isNull = (char*)keyBuf;
- char* pStart = (char*)keyBuf + sizeof(int8_t) * numOfGroupCols;
- for (int32_t j = 0; j < numOfGroupCols; ++j) {
- SColumn* pCol = taosArrayGet(groupKey, j);
-
- if (strcmp(pCol->name, "tbname") == 0) {
- isNull[i] = 0;
- memcpy(pStart, mr.me.name, strlen(mr.me.name));
- pStart += strlen(mr.me.name);
+ char* pStart = (char*)keyBuf + nullFlagSize;
+
+ SNode* pNode;
+ int32_t index = 0;
+ FOREACH(pNode, groupNew) {
+ SNode* pNew = NULL;
+ int32_t code = scalarCalculateConstants(pNode, &pNew);
+ if (TSDB_CODE_SUCCESS == code) {
+ REPLACE_NODE(pNew);
} else {
- STagVal tagVal = {0};
- tagVal.cid = pCol->colId;
- const char* p = metaGetTableTagVal(&mr.me, pCol->type, &tagVal);
- if (p == NULL) {
- isNull[j] = 1;
- continue;
- }
- isNull[i] = 0;
- if (pCol->type == TSDB_DATA_TYPE_JSON) {
- // int32_t dataLen = getJsonValueLen(pkey->pData);
- // memcpy(pStart, (pkey->pData), dataLen);
- // pStart += dataLen;
- } else if (IS_VAR_DATA_TYPE(pCol->type)) {
- memcpy(pStart, tagVal.pData, tagVal.nData);
- pStart += tagVal.nData;
- ASSERT(tagVal.nData <= pCol->bytes);
+ taosMemoryFree(keyBuf);
+ nodesClearList(groupNew);
+ metaReaderClear(&mr);
+ return code;
+ }
+
+ ASSERT(nodeType(pNew) == QUERY_NODE_VALUE);
+ SValueNode* pValue = (SValueNode*)pNew;
+
+ if (pValue->node.resType.type == TSDB_DATA_TYPE_NULL || pValue->isNull) {
+ isNull[index++] = 1;
+ continue;
+ } else {
+ isNull[index++] = 0;
+ char* data = nodesGetValueFromNode(pValue);
+ if (pValue->node.resType.type == TSDB_DATA_TYPE_JSON) {
+ if (tTagIsJson(data)) {
+ terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
+ taosMemoryFree(keyBuf);
+ nodesClearList(groupNew);
+ metaReaderClear(&mr);
+ return terrno;
+ }
+ int32_t len = getJsonValueLen(data);
+ memcpy(pStart, data, len);
+ pStart += len;
+ } else if (IS_VAR_DATA_TYPE(pValue->node.resType.type)) {
+ memcpy(pStart, data, varDataTLen(data));
+ pStart += varDataTLen(data);
} else {
- memcpy(pStart, &(tagVal.i64), pCol->bytes);
- pStart += pCol->bytes;
+ memcpy(pStart, data, pValue->node.resType.bytes);
+ pStart += pValue->node.resType.bytes;
}
}
}
+ int32_t len = (int32_t)(pStart - (char*)keyBuf);
+ uint64_t groupId = calcGroupId(keyBuf, len);
+ taosHashPut(pTableListInfo->map, &(info->uid), sizeof(uint64_t), &groupId, sizeof(uint64_t));
+ info->groupId = groupId;
+ groupNum++;
- int32_t len = (int32_t)(pStart - (char*)keyBuf);
- uint64_t* groupId = taosHashGet(pTableListInfo->map, keyBuf, len);
- if (groupId) {
- taosHashPut(pTableListInfo->map, &(info->uid), sizeof(uint64_t), groupId, sizeof(uint64_t));
- } else {
- uint64_t tmpId = calcGroupId(keyBuf, len);
- taosHashPut(pTableListInfo->map, &(info->uid), sizeof(uint64_t), &tmpId, sizeof(uint64_t));
- }
-
+ nodesClearList(groupNew);
metaReaderClear(&mr);
}
taosMemoryFree(keyBuf);
+
+ if (pTableListInfo->needSortTableByGroupId) {
+ return sortTableGroup(pTableListInfo, groupNum);
+ }
+
return TDB_CODE_SUCCESS;
}
SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
- uint64_t queryId, uint64_t taskId, STableListInfo* pTableListInfo, SNode* pTagCond) {
+ uint64_t queryId, uint64_t taskId, STableListInfo* pTableListInfo,
+ const char* pUser) {
int32_t type = nodeType(pPhyNode);
if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) {
if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == type) {
STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
- tsdbReaderT pDataReader =
- doCreateDataReader(pTableScanNode, pHandle, pTableListInfo, (uint64_t)queryId, taskId, pTagCond);
- if (pDataReader == NULL && terrno != 0) {
- pTaskInfo->code = terrno;
- return NULL;
- }
-
- int32_t code = extractTableSchemaVersion(pHandle, pTableScanNode->scan.uid, pTaskInfo);
+ int32_t code = createScanTableListInfo(pTableScanNode, pHandle, pTableListInfo, queryId, taskId);
if (code) {
- tsdbCleanupReadHandle(pDataReader);
- pTaskInfo->code = terrno;
+ pTaskInfo->code = code;
return NULL;
}
- SArray* groupKeys = extractPartitionColInfo(pTableScanNode->pPartitionTags);
- code = generateGroupIdMap(pTableListInfo, pHandle, groupKeys); // todo for json
- taosArrayDestroy(groupKeys);
+ code = extractTableSchemaInfo(pHandle, pTableScanNode->scan.uid, pTaskInfo);
if (code) {
- tsdbCleanupReadHandle(pDataReader);
pTaskInfo->code = terrno;
return NULL;
}
- SOperatorInfo* pOperator = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
+ SOperatorInfo* pOperator = createTableScanOperatorInfo(pTableScanNode, pHandle, pTaskInfo);
STableScanInfo* pScanInfo = pOperator->info;
pTaskInfo->cost.pRecoder = &pScanInfo->readRecorder;
return pOperator;
+
} else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN == type) {
STableMergeScanPhysiNode* pTableScanNode = (STableMergeScanPhysiNode*)pPhyNode;
+ int32_t code = createScanTableListInfo(pTableScanNode, pHandle, pTableListInfo, queryId, taskId);
+ if (code) {
+ pTaskInfo->code = code;
+ return NULL;
+ }
+
+ code = extractTableSchemaInfo(pHandle, pTableScanNode->scan.uid, pTaskInfo);
+ if (code) {
+ pTaskInfo->code = terrno;
+ return NULL;
+ }
+
+ SOperatorInfo* pOperator =
+ createTableMergeScanOperatorInfo(pTableScanNode, pTableListInfo, pHandle, pTaskInfo, queryId, taskId);
- SArray* dataReaders = taosArrayInit(8, POINTER_BYTES);
- createMultipleDataReaders(pTableScanNode, pHandle, pTableListInfo, dataReaders, queryId, taskId, pTagCond);
- extractTableSchemaVersion(pHandle, pTableScanNode->scan.uid, pTaskInfo);
- SArray* groupKeys = extractPartitionColInfo(pTableScanNode->pPartitionTags);
- generateGroupIdMap(pTableListInfo, pHandle, groupKeys); // todo for json
- taosArrayDestroy(groupKeys);
- SOperatorInfo* pOperator = createTableMergeScanOperatorInfo(pTableScanNode, dataReaders, pHandle, pTaskInfo);
STableScanInfo* pScanInfo = pOperator->info;
pTaskInfo->cost.pRecoder = &pScanInfo->readRecorder;
return pOperator;
+
} else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == type) {
return createExchangeOperatorInfo(pHandle->pMsgCb->clientRpc, (SExchangePhysiNode*)pPhyNode, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) {
- SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; // simple child table.
STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
STimeWindowAggSupp twSup = {
.waterMark = pTableScanNode->watermark,
.calTrigger = pTableScanNode->triggerType,
.maxTs = INT64_MIN,
};
- tsdbReaderT pDataReader = NULL;
-
if (pHandle) {
- if (pHandle->vnode) {
- // for stram
- pDataReader =
- doCreateDataReader(pTableScanNode, pHandle, pTableListInfo, (uint64_t)queryId, taskId, pTagCond);
- } else {
- // for tq
- getTableList(pHandle->meta, pScanPhyNode, pTableListInfo, pTagCond);
+ int32_t code = createScanTableListInfo(pTableScanNode, pHandle, pTableListInfo, queryId, taskId);
+ if (code) {
+ pTaskInfo->code = code;
+ return NULL;
}
}
- if (pDataReader == NULL && terrno != 0) {
- qDebug("%s pDataReader is NULL", GET_TASKID(pTaskInfo));
- // return NULL;
- } else {
- qDebug("%s pDataReader is not NULL", GET_TASKID(pTaskInfo));
- }
-
- SArray* groupKeys = extractPartitionColInfo(pTableScanNode->pPartitionTags);
- int32_t code = generateGroupIdMap(pTableListInfo, pHandle, groupKeys); // todo for json
- taosArrayDestroy(groupKeys);
- if (code) {
- tsdbCleanupReadHandle(pDataReader);
- return NULL;
- }
-
- SOperatorInfo* pOperator = createStreamScanOperatorInfo(pDataReader, pHandle, pTableScanNode, pTaskInfo, &twSup);
-
+ SOperatorInfo* pOperator =
+ createStreamScanOperatorInfo(pHandle, pTableScanNode, pTaskInfo, &twSup, queryId, taskId);
return pOperator;
+
} else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode;
- return createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pTaskInfo);
+ return createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pUser, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) {
STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode;
- int32_t code = getTableList(pHandle->meta, pScanPhyNode, pTableListInfo, pScanPhyNode->node.pConditions);
+ int32_t code = getTableList(pHandle->meta, pHandle->vnode, pScanPhyNode, pTableListInfo);
if (code != TSDB_CODE_SUCCESS) {
pTaskInfo->code = terrno;
return NULL;
@@ -4087,17 +4396,17 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
return createTagScanOperatorInfo(pHandle, pScanPhyNode, pTableListInfo, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN == type) {
- SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*) pPhyNode;
+ SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*)pPhyNode;
pTableListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
if (pBlockNode->tableType == TSDB_SUPER_TABLE) {
- int32_t code = tsdbGetAllTableList(pHandle->meta, pBlockNode->uid, pTableListInfo->pTableList);
+ int32_t code = vnodeGetAllTableList(pHandle->vnode, pBlockNode->uid, pTableListInfo->pTableList);
if (code != TSDB_CODE_SUCCESS) {
pTaskInfo->code = terrno;
return NULL;
}
} else { // Create one table group.
- STableKeyInfo info = {.lastKey = 0, .uid = pBlockNode->uid};
+ STableKeyInfo info = {.lastKey = 0, .uid = pBlockNode->uid, .groupId = 0};
taosArrayPush(pTableListInfo->pTableList, &info);
}
@@ -4116,16 +4425,44 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
cond.colList->type = TSDB_DATA_TYPE_TIMESTAMP;
cond.colList->bytes = sizeof(TSKEY);
- cond.numOfTWindows = 1;
- cond.twindows = taosMemoryCalloc(1, sizeof(STimeWindow));
- cond.twindows[0] = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
+ cond.twindows = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
cond.suid = pBlockNode->suid;
- cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
+ cond.type = BLOCK_LOAD_OFFSET_ORDER;
}
- tsdbReaderT* pReader = tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo, queryId, taskId);
+
+ STsdbReader* pReader = NULL;
+ tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo->pTableList, &pReader, "");
cleanupQueryTableDataCond(&cond);
return createDataBlockInfoScanOperator(pReader, pHandle, cond.suid, pBlockNode, pTaskInfo);
+ } else if (QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN == type) {
+ SLastRowScanPhysiNode* pScanNode = (SLastRowScanPhysiNode*)pPhyNode;
+
+ // int32_t code = createScanTableListInfo(pTableScanNode, pHandle, pTableListInfo, queryId, taskId);
+ // if (code) {
+ // pTaskInfo->code = code;
+ // return NULL;
+ // }
+
+ int32_t code = extractTableSchemaInfo(pHandle, pScanNode->uid, pTaskInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ pTaskInfo->code = code;
+ return NULL;
+ }
+
+ pTableListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
+ if (pScanNode->tableType == TSDB_SUPER_TABLE) {
+ code = vnodeGetAllTableList(pHandle->vnode, pScanNode->uid, pTableListInfo->pTableList);
+ if (code != TSDB_CODE_SUCCESS) {
+ pTaskInfo->code = terrno;
+ return NULL;
+ }
+ } else { // Create one table group.
+ STableKeyInfo info = {.lastKey = 0, .uid = pScanNode->uid, .groupId = 0};
+ taosArrayPush(pTableListInfo->pTableList, &info);
+ }
+
+ return createLastrowScanOperator(pScanNode, pHandle, pTableListInfo->pTableList, pTaskInfo);
} else {
ASSERT(0);
}
@@ -4137,7 +4474,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
SOperatorInfo** ops = taosMemoryCalloc(size, POINTER_BYTES);
for (int32_t i = 0; i < size; ++i) {
SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i);
- ops[i] = createOperatorTree(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableListInfo, pTagCond);
+ ops[i] = createOperatorTree(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableListInfo, pUser);
if (ops[i] == NULL) {
return NULL;
}
@@ -4162,8 +4499,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
pOptr = createGroupOperatorInfo(ops[0], pExprInfo, num, pResBlock, pColList, pAggNode->node.pConditions,
pScalarExprInfo, numOfScalarExpr, pTaskInfo);
} else {
- pOptr =
- createAggregateOperatorInfo(ops[0], pExprInfo, num, pResBlock, pScalarExprInfo, numOfScalarExpr, pTaskInfo);
+ pOptr = createAggregateOperatorInfo(ops[0], pExprInfo, num, pResBlock, pAggNode->node.pConditions,
+ pScalarExprInfo, numOfScalarExpr, pTaskInfo);
}
} else if (QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL == type || QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type) {
SIntervalPhysiNode* pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
@@ -4187,9 +4524,25 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
int32_t tsSlotId = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
bool isStream = (QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type);
- pOptr =
- createIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, &as, pTaskInfo, isStream);
+ pOptr = createIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, &as, pIntervalPhyNode,
+ pTaskInfo, isStream);
+
+ } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL == type) {
+ SMergeAlignedIntervalPhysiNode* pIntervalPhyNode = (SMergeAlignedIntervalPhysiNode*)pPhyNode;
+
+ SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
+ SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
+ SInterval interval = {.interval = pIntervalPhyNode->interval,
+ .sliding = pIntervalPhyNode->sliding,
+ .intervalUnit = pIntervalPhyNode->intervalUnit,
+ .slidingUnit = pIntervalPhyNode->slidingUnit,
+ .offset = pIntervalPhyNode->offset,
+ .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision};
+
+ int32_t tsSlotId = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
+ pOptr = createMergeAlignedIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId,
+ pPhyNode->pConditions, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL == type) {
SMergeIntervalPhysiNode* pIntervalPhyNode = (SMergeIntervalPhysiNode*)pPhyNode;
@@ -4213,19 +4566,11 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
pOptr = createStreamFinalIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo, children);
} else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) {
pOptr = createSortOperatorInfo(ops[0], (SSortPhysiNode*)pPhyNode, pTaskInfo);
+ } else if (QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT == type) {
+ pOptr = createGroupSortOperatorInfo(ops[0], (SGroupSortPhysiNode*)pPhyNode, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE == type) {
SMergePhysiNode* pMergePhyNode = (SMergePhysiNode*)pPhyNode;
-
- SDataBlockDescNode* pDescNode = pPhyNode->pOutputDataBlockDesc;
- SSDataBlock* pResBlock = createResDataBlock(pDescNode);
-
- SArray* sortInfo = createSortInfo(pMergePhyNode->pMergeKeys);
- int32_t numOfOutputCols = 0;
- SArray* pColList =
- extractColMatchInfo(pMergePhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
- SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, 0);
- SSDataBlock* pInputDataBlock = createResDataBlock(pChildNode->pOutputDataBlockDesc);
- pOptr = createMultiwaySortMergeOperatorInfo(ops, size, pInputDataBlock, pResBlock, sortInfo, pColList, pTaskInfo);
+ pOptr = createMultiwayMergeOperatorInfo(ops, size, pMergePhyNode, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION == type) {
SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
@@ -4236,8 +4581,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
int32_t tsSlotId = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
- pOptr =
- createSessionAggOperatorInfo(ops[0], pExprInfo, num, pResBlock, pSessionNode->gap, tsSlotId, &as, pTaskInfo);
+ pOptr = createSessionAggOperatorInfo(ops[0], pExprInfo, num, pResBlock, pSessionNode->gap, tsSlotId, &as,
+ pPhyNode->pConditions, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION == type) {
pOptr = createStreamSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION == type) {
@@ -4259,7 +4604,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
SColumnNode* pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
SColumn col = extractColumnFromColumnNode(pColNode);
- pOptr = createStatewindowOperatorInfo(ops[0], pExprInfo, num, pResBlock, &as, tsSlotId, &col, pTaskInfo);
+ pOptr = createStatewindowOperatorInfo(ops[0], pExprInfo, num, pResBlock, &as, tsSlotId, &col, pPhyNode->pConditions,
+ pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE == type) {
pOptr = createStreamStateAggOperatorInfo(ops[0], pPhyNode, pTaskInfo);
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN == type) {
@@ -4278,18 +4624,6 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
return pOptr;
}
-int32_t compareTimeWindow(const void* p1, const void* p2, const void* param) {
- const SQueryTableDataCond* pCond = param;
- const STimeWindow* pWin1 = p1;
- const STimeWindow* pWin2 = p2;
- if (pCond->order == TSDB_ORDER_ASC) {
- return pWin1->skey - pWin2->skey;
- } else if (pCond->order == TSDB_ORDER_DESC) {
- return pWin2->skey - pWin1->skey;
- }
- return 0;
-}
-
SArray* extractColumnInfo(SNodeList* pNodeList) {
size_t numOfCols = LIST_LENGTH(pNodeList);
SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
@@ -4323,16 +4657,16 @@ SArray* extractColumnInfo(SNodeList* pNodeList) {
return pList;
}
-tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
- STableListInfo* pTableListInfo, uint64_t queryId, uint64_t taskId, SNode* pTagCond) {
- int32_t code = getTableList(pHandle->meta, &pTableScanNode->scan, pTableListInfo, pTagCond);
+STsdbReader* doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
+ STableListInfo* pTableListInfo, const char* idstr) {
+ int32_t code = getTableList(pHandle->meta, pHandle->vnode, &pTableScanNode->scan, pTableListInfo);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
if (taosArrayGetSize(pTableListInfo->pTableList) == 0) {
code = 0;
- qDebug("no table qualified for query, TID:0x%" PRIx64 ", QID:0x%" PRIx64, taskId, queryId);
+ qDebug("no table qualified for query, %s", idstr);
goto _error;
}
@@ -4342,7 +4676,12 @@ tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle*
goto _error;
}
- tsdbReaderT* pReader = tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo, queryId, taskId);
+ STsdbReader* pReader;
+ code = tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo->pTableList, &pReader, idstr);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+
cleanupQueryTableDataCond(&cond);
return pReader;
@@ -4352,12 +4691,78 @@ _error:
return NULL;
}
-int32_t encodeOperator(SOperatorInfo* ops, char** result, int32_t* length) {
+static int32_t extractTbscanInStreamOpTree(SOperatorInfo* pOperator, STableScanInfo** ppInfo) {
+ if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
+ if (pOperator->numOfDownstream == 0) {
+ qError("failed to find stream scan operator");
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+
+ if (pOperator->numOfDownstream > 1) {
+ qError("join not supported for stream block scan");
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ return extractTbscanInStreamOpTree(pOperator->pDownstream[0], ppInfo);
+ } else {
+ SStreamScanInfo* pInfo = pOperator->info;
+ ASSERT(pInfo->pTableScanOp->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN);
+ *ppInfo = pInfo->pTableScanOp->info;
+ return 0;
+ }
+}
+
+int32_t extractTableScanNode(SPhysiNode* pNode, STableScanPhysiNode** ppNode) {
+ if (pNode->pChildren == NULL || LIST_LENGTH(pNode->pChildren) == 0) {
+ if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == pNode->type) {
+ *ppNode = (STableScanPhysiNode*)pNode;
+ return 0;
+ } else {
+ ASSERT(0);
+ terrno = TSDB_CODE_QRY_APP_ERROR;
+ return -1;
+ }
+ } else {
+ if (LIST_LENGTH(pNode->pChildren) != 1) {
+ ASSERT(0);
+ terrno = TSDB_CODE_QRY_APP_ERROR;
+ return -1;
+ }
+ SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pNode->pChildren, 0);
+ return extractTableScanNode(pChildNode, ppNode);
+ }
+ return -1;
+}
+
+int32_t rebuildReader(SOperatorInfo* pOperator, SSubplan* plan, SReadHandle* pHandle, int64_t uid, int64_t ts) {
+ STableScanInfo* pTableScanInfo = NULL;
+ if (extractTbscanInStreamOpTree(pOperator, &pTableScanInfo) < 0) {
+ return -1;
+ }
+
+ STableScanPhysiNode* pNode = NULL;
+ if (extractTableScanNode(plan->pNode, &pNode) < 0) {
+ ASSERT(0);
+ }
+
+ tsdbReaderClose(pTableScanInfo->dataReader);
+
+ STableListInfo info = {0};
+ pTableScanInfo->dataReader = doCreateDataReader(pNode, pHandle, &info, NULL);
+ if (pTableScanInfo->dataReader == NULL) {
+ ASSERT(0);
+ qError("failed to create data reader");
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
+ // TODO: set uid and ts to data reader
+ return 0;
+}
+
+int32_t encodeOperator(SOperatorInfo* ops, char** result, int32_t* length, int32_t* nOptrWithVal) {
int32_t code = TDB_CODE_SUCCESS;
char* pCurrent = NULL;
int32_t currLength = 0;
if (ops->fpSet.encodeResultRow) {
- if (result == NULL || length == NULL) {
+ if (result == NULL || length == NULL || nOptrWithVal == NULL) {
return TSDB_CODE_TSC_INVALID_INPUT;
}
code = ops->fpSet.encodeResultRow(ops, &pCurrent, &currLength);
@@ -4368,8 +4773,15 @@ int32_t encodeOperator(SOperatorInfo* ops, char** result, int32_t* length) {
*result = NULL;
}
return code;
+ } else if (currLength == 0) {
+ ASSERT(!pCurrent);
+ goto _downstream;
}
+ ++(*nOptrWithVal);
+
+ ASSERT(currLength >= 0);
+
if (*result == NULL) {
*result = (char*)taosMemoryCalloc(1, currLength + sizeof(int32_t));
if (*result == NULL) {
@@ -4395,8 +4807,9 @@ int32_t encodeOperator(SOperatorInfo* ops, char** result, int32_t* length) {
*length = *(int32_t*)(*result);
}
+_downstream:
for (int32_t i = 0; i < ops->numOfDownstream; ++i) {
- code = encodeOperator(ops->pDownstream[i], result, length);
+ code = encodeOperator(ops->pDownstream[i], result, length, nOptrWithVal);
if (code != TDB_CODE_SUCCESS) {
return code;
}
@@ -4441,16 +4854,27 @@ int32_t decodeOperator(SOperatorInfo* ops, const char* result, int32_t length) {
return TDB_CODE_SUCCESS;
}
-int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, qTaskInfo_t* pTaskInfo) {
+int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, qTaskInfo_t* pTaskInfo, SReadHandle* readHandle) {
SExecTaskInfo* pTask = *(SExecTaskInfo**)pTaskInfo;
switch (pNode->type) {
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: {
+ SInserterParam* pInserterParam = taosMemoryCalloc(1, sizeof(SInserterParam));
+ if (NULL == pInserterParam) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ pInserterParam->readHandle = readHandle;
+
+ *pParam = pInserterParam;
+ break;
+ }
case QUERY_NODE_PHYSICAL_PLAN_DELETE: {
SDeleterParam* pDeleterParam = taosMemoryCalloc(1, sizeof(SDeleterParam));
if (NULL == pDeleterParam) {
return TSDB_CODE_OUT_OF_MEMORY;
}
int32_t tbNum = taosArrayGetSize(pTask->tableqinfoList.pTableList);
+ pDeleterParam->suid = pTask->tableqinfoList.suid;
pDeleterParam->pUidList = taosArrayInit(tbNum, sizeof(uint64_t));
if (NULL == pDeleterParam->pUidList) {
taosMemoryFree(pDeleterParam);
@@ -4483,18 +4907,16 @@ int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SRead
}
(*pTaskInfo)->sql = sql;
+ (*pTaskInfo)->tableqinfoList.pTagCond = pPlan->pTagCond;
+ (*pTaskInfo)->tableqinfoList.pTagIndexCond = pPlan->pTagIndexCond;
(*pTaskInfo)->pRoot = createOperatorTree(pPlan->pNode, *pTaskInfo, pHandle, queryId, taskId,
- &(*pTaskInfo)->tableqinfoList, pPlan->pTagCond);
+ &(*pTaskInfo)->tableqinfoList, pPlan->user);
+
if (NULL == (*pTaskInfo)->pRoot) {
code = (*pTaskInfo)->code;
goto _complete;
}
- if ((*pTaskInfo)->pRoot == NULL) {
- code = TSDB_CODE_QRY_OUT_OF_MEMORY;
- goto _complete;
- }
-
return code;
_complete:
@@ -4506,6 +4928,13 @@ _complete:
static void doDestroyTableList(STableListInfo* pTableqinfoList) {
taosArrayDestroy(pTableqinfoList->pTableList);
taosHashCleanup(pTableqinfoList->map);
+ if (pTableqinfoList->needSortTableByGroupId) {
+ for (int32_t i = 0; i < taosArrayGetSize(pTableqinfoList->pGroupList); i++) {
+ SArray* tmp = taosArrayGetP(pTableqinfoList->pGroupList, i);
+ taosArrayDestroy(tmp);
+ }
+ }
+ taosArrayDestroy(pTableqinfoList->pGroupList);
pTableqinfoList->pTableList = NULL;
pTableqinfoList->map = NULL;
@@ -4516,11 +4945,8 @@ void doDestroyTask(SExecTaskInfo* pTaskInfo) {
doDestroyTableList(&pTaskInfo->tableqinfoList);
destroyOperatorInfo(pTaskInfo->pRoot);
- // taosArrayDestroy(pTaskInfo->summary.queryProfEvents);
- // taosHashCleanup(pTaskInfo->summary.operatorProfResults);
+ cleanupTableSchemaInfo(pTaskInfo);
- taosMemoryFree(pTaskInfo->schemaVer.dbname);
- taosMemoryFree(pTaskInfo->schemaVer.tablename);
taosMemoryFreeClear(pTaskInfo->sql);
taosMemoryFreeClear(pTaskInfo->id.str);
taosMemoryFreeClear(pTaskInfo);
diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c
index 064a36df1c08b7282691f124b7c3e6c70c4e6c8f..ee20bc7ba666e27de27f235a6503670d337b50b9 100644
--- a/source/libs/executor/src/groupoperator.c
+++ b/source/libs/executor/src/groupoperator.c
@@ -37,7 +37,9 @@ static void destroyGroupOperatorInfo(void* param, int32_t numOfOutput) {
taosMemoryFreeClear(pInfo->keyBuf);
taosArrayDestroy(pInfo->pGroupCols);
taosArrayDestroy(pInfo->pGroupColVals);
- cleanupExecSupp(&pInfo->scalarSup);
+ cleanupExprSupp(&pInfo->scalarSup);
+
+ taosMemoryFreeClear(param);
}
static int32_t initGroupOptrInfo(SArray** pGroupColVals, int32_t* keyLen, char** keyBuf, const SArray* pGroupColList) {
@@ -141,6 +143,10 @@ static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSData
pkey->isNull = false;
char* val = colDataGetData(pColInfoData, rowIndex);
if (pkey->type == TSDB_DATA_TYPE_JSON) {
+ if(tTagIsJson(val)){
+ terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
+ return;
+ }
int32_t dataLen = getJsonValueLen(val);
memcpy(pkey->pData, val, dataLen);
} else if (IS_VAR_DATA_TYPE(pkey->type)) {
@@ -227,11 +233,15 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
int32_t len = 0;
STimeWindow w = TSWINDOW_INITIALIZER;
+ terrno = TSDB_CODE_SUCCESS;
int32_t num = 0;
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
// Compare with the previous row of this column, and do not set the output buffer again if they are identical.
if (!pInfo->isInit) {
recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
+ if (terrno != TSDB_CODE_SUCCESS) { // group by json error
+ longjmp(pTaskInfo->env, terrno);
+ }
pInfo->isInit = true;
num++;
continue;
@@ -247,6 +257,9 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
if (j == 0) {
num++;
recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
+ if (terrno != TSDB_CODE_SUCCESS) { // group by json error
+ longjmp(pTaskInfo->env, terrno);
+ }
continue;
}
@@ -291,14 +304,21 @@ static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) {
SSDataBlock* pRes = pInfo->binfo.pRes;
if (pOperator->status == OP_RES_TO_RETURN) {
- doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ while(1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pRes);
+
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
- size_t rows = pRes->info.rows;
- if (rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
+ if (pRes->info.rows > 0) {
+ break;
+ }
}
-
- pOperator->resultInfo.totalRows += rows;
+ pOperator->resultInfo.totalRows += pRes->info.rows;
return (pRes->info.rows == 0)? NULL:pRes;
}
@@ -559,8 +579,8 @@ uint64_t calcGroupId(char* pData, int32_t len) {
}
int32_t* setupColumnOffset(const SSDataBlock* pBlock, int32_t rowCapacity) {
- size_t numOfCols = pBlock->info.numOfCols;
- int32_t* offset = taosMemoryCalloc(pBlock->info.numOfCols, sizeof(int32_t));
+ size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ int32_t* offset = taosMemoryCalloc(numOfCols, sizeof(int32_t));
offset[0] = sizeof(int32_t) + sizeof(uint64_t); // the number of rows in current page, ref to SSDataBlock paged serialization format
@@ -617,6 +637,7 @@ static SSDataBlock* buildPartitionResult(SOperatorInfo* pOperator) {
int32_t* pageId = taosArrayGet(pGroupInfo->pPageList, pInfo->pageIndex);
void* page = getBufPage(pInfo->pBuf, *pageId);
+ blockDataEnsureCapacity(pInfo->binfo.pRes, pInfo->rowCapacity);
blockDataFromBuf1(pInfo->binfo.pRes, page, pInfo->rowCapacity);
pInfo->pageIndex += 1;
@@ -661,7 +682,11 @@ static SSDataBlock* hashPartition(SOperatorInfo* pOperator) {
}
}
+ terrno = TSDB_CODE_SUCCESS;
doHashPartition(pOperator, pBlock);
+ if (terrno != TSDB_CODE_SUCCESS) { // group by json error
+ longjmp(pTaskInfo->env, terrno);
+ }
}
SArray* groupArray = taosArrayInit(taosHashGetSize(pInfo->pGroupSet), sizeof(SDataGroupInfo));
@@ -701,7 +726,9 @@ static void destroyPartitionOperatorInfo(void* param, int32_t numOfOutput) {
taosHashCleanup(pInfo->pGroupSet);
taosMemoryFree(pInfo->columnOffset);
- cleanupExecSupp(&pInfo->scalarSup);
+ cleanupExprSupp(&pInfo->scalarSup);
+
+ taosMemoryFreeClear(param);
}
SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo) {
@@ -784,4 +811,4 @@ int32_t setGroupResultOutputBuf(SOperatorInfo* pOperator, SOptrBasicInfo* binfo,
setResultRowInitCtx(pResultRow, pCtx, numOfCols, pOperator->exprSupp.rowEntryInfoOffset);
return TSDB_CODE_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/source/libs/executor/src/joinoperator.c b/source/libs/executor/src/joinoperator.c
index 6fbda778087b345c7aeef19e068f582451eab006..b864fae47f236955fd89a2ce60fd4b6d3d3f65e3 100644
--- a/source/libs/executor/src/joinoperator.c
+++ b/source/libs/executor/src/joinoperator.c
@@ -53,13 +53,28 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t
pOperator->info = pInfo;
pOperator->pTaskInfo = pTaskInfo;
- SNode* pOnCondition = pJoinNode->pOnConditions;
- if (nodeType(pOnCondition) == QUERY_NODE_OPERATOR) {
- SOperatorNode* pNode = (SOperatorNode*)pOnCondition;
+ SNode* pMergeCondition = pJoinNode->pMergeCondition;
+ if (nodeType(pMergeCondition) == QUERY_NODE_OPERATOR) {
+ SOperatorNode* pNode = (SOperatorNode*)pMergeCondition;
setJoinColumnInfo(&pInfo->leftCol, (SColumnNode*)pNode->pLeft);
setJoinColumnInfo(&pInfo->rightCol, (SColumnNode*)pNode->pRight);
- } else if (nodeType(pOnCondition) == QUERY_NODE_LOGIC_CONDITION) {
- extractTimeCondition(pInfo, (SLogicConditionNode*)pOnCondition);
+ } else {
+ ASSERT(false);
+ }
+
+ if (pJoinNode->pOnConditions != NULL && pJoinNode->node.pConditions != NULL) {
+ pInfo->pCondAfterMerge = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION);
+ SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(pInfo->pCondAfterMerge);
+ pLogicCond->pParameterList = nodesMakeList();
+ nodesListMakeAppend(&pLogicCond->pParameterList, nodesCloneNode(pJoinNode->pOnConditions));
+ nodesListMakeAppend(&pLogicCond->pParameterList, nodesCloneNode(pJoinNode->node.pConditions));
+ pLogicCond->condType = LOGIC_COND_TYPE_AND;
+ } else if (pJoinNode->pOnConditions != NULL) {
+ pInfo->pCondAfterMerge = nodesCloneNode(pJoinNode->pOnConditions);
+ } else if (pJoinNode->node.pConditions != NULL) {
+ pInfo->pCondAfterMerge = nodesCloneNode(pJoinNode->node.pConditions);
+ } else {
+ pInfo->pCondAfterMerge = NULL;
}
pOperator->fpSet =
@@ -88,15 +103,14 @@ void setJoinColumnInfo(SColumnInfo* pColumn, const SColumnNode* pColumnNode) {
void destroyMergeJoinOperator(void* param, int32_t numOfOutput) {
SJoinOperatorInfo* pJoinOperator = (SJoinOperatorInfo*)param;
+ nodesDestroyNode(pJoinOperator->pCondAfterMerge);
+
+ taosMemoryFreeClear(param);
}
-SSDataBlock* doMergeJoin(struct SOperatorInfo* pOperator) {
+static void doMergeJoinImpl(struct SOperatorInfo* pOperator, SSDataBlock* pRes) {
SJoinOperatorInfo* pJoinInfo = pOperator->info;
- SSDataBlock* pRes = pJoinInfo->pRes;
- blockDataCleanup(pRes);
- blockDataEnsureCapacity(pRes, 4096);
-
int32_t nrows = 0;
while (1) {
@@ -181,7 +195,28 @@ SSDataBlock* doMergeJoin(struct SOperatorInfo* pOperator) {
break;
}
}
+}
+
+SSDataBlock* doMergeJoin(struct SOperatorInfo* pOperator) {
+ SJoinOperatorInfo* pJoinInfo = pOperator->info;
+ SSDataBlock* pRes = pJoinInfo->pRes;
+ blockDataCleanup(pRes);
+ blockDataEnsureCapacity(pRes, 4096);
+ while (true) {
+ int32_t numOfRowsBefore = pRes->info.rows;
+ doMergeJoinImpl(pOperator, pRes);
+ int32_t numOfNewRows = pRes->info.rows - numOfRowsBefore;
+ if (numOfNewRows == 0) {
+ break;
+ }
+ if (pJoinInfo->pCondAfterMerge != NULL) {
+ doFilter(pJoinInfo->pCondAfterMerge, pRes);
+ }
+ if (pRes->info.rows >= pOperator->resultInfo.threshold) {
+ break;
+ }
+ }
return (pRes->info.rows > 0) ? pRes : NULL;
}
diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c
index 788464ac66cd178193c0c51d9a037f988c9cfde4..7b274e5af8c4081e206d1c6bc7ec056cb23e93a4 100644
--- a/source/libs/executor/src/scanoperator.c
+++ b/source/libs/executor/src/scanoperator.c
@@ -13,14 +13,12 @@
* along with this program. If not, see .
*/
-#include
-#include "filter.h"
+#include "executorimpl.h"
#include "function.h"
#include "functionMgt.h"
#include "os.h"
#include "querynodes.h"
#include "systable.h"
-#include "tglobal.h"
#include "tname.h"
#include "ttime.h"
@@ -34,8 +32,6 @@
#include "ttypes.h"
#include "vnode.h"
-#include "executorInt.h"
-
#define SET_REVERSE_SCAN_FLAG(_info) ((_info)->scanFlag = REVERSE_SCAN)
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
@@ -43,9 +39,7 @@ static int32_t buildSysDbTableInfo(const SSysTableScanInfo* pInfo, int32_t capac
static int32_t buildDbTableInfoBlock(const SSDataBlock* p, const SSysTableMeta* pSysDbTableMeta, size_t size,
const char* dbName);
-static void addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr,
- SSDataBlock* pBlock);
-static bool processBlockWithProbability(const SSampleExecInfo* pInfo);
+static bool processBlockWithProbability(const SSampleExecInfo* pInfo);
bool processBlockWithProbability(const SSampleExecInfo* pInfo) {
#if 0
@@ -112,12 +106,12 @@ static void getNextTimeWindow(SInterval* pInterval, STimeWindow* tw, int32_t ord
int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
- tw->skey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pInterval->precision);
+ tw->skey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000LL, TSDB_TIME_PRECISION_MILLI, pInterval->precision);
mon = (int)(mon + interval);
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
- tw->ekey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pInterval->precision);
+ tw->ekey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000LL, TSDB_TIME_PRECISION_MILLI, pInterval->precision);
tw->ekey -= 1;
}
@@ -202,29 +196,27 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca
pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
pCost->skipBlocks += 1;
- // clear all data in pBlock that are set when handing the previous block
- for (int32_t i = 0; i < pBlockInfo->numOfCols; ++i) {
- SColumnInfoData* pcol = taosArrayGet(pBlock->pDataBlock, i);
- pcol->pData = NULL;
- }
-
return TSDB_CODE_SUCCESS;
} else if (*status == FUNC_DATA_REQUIRED_STATIS_LOAD) {
pCost->loadBlockStatis += 1;
bool allColumnsHaveAgg = true;
SColumnDataAgg** pColAgg = NULL;
- tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->dataReader, &pColAgg, &allColumnsHaveAgg);
+
+ int32_t code = tsdbRetrieveDatablockSMA(pTableScanInfo->dataReader, &pColAgg, &allColumnsHaveAgg);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
if (allColumnsHaveAgg == true) {
- int32_t numOfCols = pBlock->info.numOfCols;
+ int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
// todo create this buffer during creating operator
if (pBlock->pBlockAgg == NULL) {
pBlock->pBlockAgg = taosMemoryCalloc(numOfCols, POINTER_BYTES);
}
- for (int32_t i = 0; i < numOfCols; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pTableScanInfo->pColMatchInfo); ++i) {
SColMatchInfo* pColMatchInfo = taosArrayGet(pTableScanInfo->pColMatchInfo, i);
if (!pColMatchInfo->output) {
continue;
@@ -264,7 +256,12 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca
// currently only the tbname pseudo column
if (pTableScanInfo->pseudoSup.numOfExprs > 0) {
SExprSupp* pSup = &pTableScanInfo->pseudoSup;
- addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock);
+
+ int32_t code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock,
+ GET_TASKID(pTaskInfo));
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
}
int64_t st = taosGetTimestampMs();
@@ -289,25 +286,25 @@ static void prepareForDescendingScan(STableScanInfo* pTableScanInfo, SqlFunction
// setupQueryRangeForReverseScan(pTableScanInfo);
pTableScanInfo->cond.order = TSDB_ORDER_DESC;
- for (int32_t i = 0; i < pTableScanInfo->cond.numOfTWindows; ++i) {
- STimeWindow* pTWindow = &pTableScanInfo->cond.twindows[i];
- TSWAP(pTWindow->skey, pTWindow->ekey);
- }
-
- SQueryTableDataCond* pCond = &pTableScanInfo->cond;
- taosqsort(pCond->twindows, pCond->numOfTWindows, sizeof(STimeWindow), pCond, compareTimeWindow);
+ STimeWindow* pTWindow = &pTableScanInfo->cond.twindows;
+ TSWAP(pTWindow->skey, pTWindow->ekey);
}
-void addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr,
- SSDataBlock* pBlock) {
+int32_t addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr,
+ SSDataBlock* pBlock, const char* idStr) {
// currently only the tbname pseudo column
if (numOfPseudoExpr == 0) {
- return;
+ return TSDB_CODE_SUCCESS;
}
SMetaReader mr = {0};
metaReaderInit(&mr, pHandle->meta, 0);
- metaGetTableEntryByUid(&mr, pBlock->info.uid);
+ int32_t code = metaGetTableEntryByUid(&mr, pBlock->info.uid);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.uid, tstrerror(terrno), idStr);
+ metaReaderClear(&mr);
+ return terrno;
+ }
for (int32_t j = 0; j < numOfPseudoExpr; ++j) {
SExprInfo* pExpr = &pPseudoExpr[j];
@@ -315,8 +312,6 @@ void addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_
int32_t dstSlotId = pExpr->base.resSchema.slotId;
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId);
-
- colInfoDataEnsureCapacity(pColInfoData, 0, pBlock->info.rows);
colInfoDataCleanup(pColInfoData, pBlock->info.rows);
int32_t functionId = pExpr->pExpr->_function.functionId;
@@ -337,7 +332,8 @@ void addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_
}
for (int32_t i = 0; i < pBlock->info.rows; ++i) {
- colDataAppend(pColInfoData, i, data, (data == NULL));
+ colDataAppend(pColInfoData, i, data,
+ (data == NULL) || (pColInfoData->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
}
if (data && (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) && p != NULL &&
@@ -348,16 +344,15 @@ void addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_
}
metaReaderClear(&mr);
+ return TSDB_CODE_SUCCESS;
}
void setTbNameColData(void* pMeta, const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId) {
struct SScalarFuncExecFuncs fpSet = {0};
fmGetScalarFuncExecFuncs(functionId, &fpSet);
- SColumnInfoData infoData = {0};
- infoData.info.type = TSDB_DATA_TYPE_BIGINT;
- infoData.info.bytes = sizeof(uint64_t);
- colInfoDataEnsureCapacity(&infoData, 0, 1);
+ SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_BIGINT, sizeof(uint64_t), 1);
+ colInfoDataEnsureCapacity(&infoData, 1);
colDataAppendInt64(&infoData, 0, (int64_t*)&pBlock->info.uid);
SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .param = pMeta, .columnData = &infoData};
@@ -384,7 +379,15 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) {
continue;
}
- tsdbRetrieveDataBlockInfo(pTableScanInfo->dataReader, &pBlock->info);
+ blockDataCleanup(pBlock);
+
+ SDataBlockInfo binfo = pBlock->info;
+ tsdbRetrieveDataBlockInfo(pTableScanInfo->dataReader, &binfo);
+
+ binfo.capacity = binfo.rows;
+ blockDataEnsureCapacity(pBlock, binfo.rows);
+ pBlock->info = binfo;
+ ASSERT(binfo.uid != 0);
uint32_t status = 0;
int32_t code = loadDataBlock(pOperator, pTableScanInfo, pBlock, &status);
@@ -407,12 +410,21 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) {
pTableScanInfo->readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
pOperator->cost.totalCost = pTableScanInfo->readRecorder.elapsedTime;
+
+ // todo refactor
+ /*pTableScanInfo->lastStatus.uid = pBlock->info.uid;*/
+ /*pTableScanInfo->lastStatus.ts = pBlock->info.window.ekey;*/
+ pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_DATA;
+ pTaskInfo->streamInfo.lastStatus.uid = pBlock->info.uid;
+ pTaskInfo->streamInfo.lastStatus.ts = pBlock->info.window.ekey;
+
+ ASSERT(pBlock->info.uid != 0);
return pBlock;
}
return NULL;
}
-static SSDataBlock* doTableScan(SOperatorInfo* pOperator) {
+static SSDataBlock* doTableScanGroup(SOperatorInfo* pOperator) {
STableScanInfo* pTableScanInfo = pOperator->info;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
@@ -423,15 +435,10 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) {
// do the ascending order traverse in the first place.
while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
- while (pTableScanInfo->curTWinIdx < pTableScanInfo->cond.numOfTWindows) {
- SSDataBlock* p = doTableScanImpl(pOperator);
- if (p != NULL) {
- return p;
- }
- pTableScanInfo->curTWinIdx += 1;
- if (pTableScanInfo->curTWinIdx < pTableScanInfo->cond.numOfTWindows) {
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, pTableScanInfo->curTWinIdx);
- }
+ SSDataBlock* p = doTableScanImpl(pOperator);
+ if (p != NULL) {
+ ASSERT(p->info.uid != 0);
+ return p;
}
pTableScanInfo->scanTimes += 1;
@@ -440,40 +447,25 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) {
setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
pTableScanInfo->scanFlag = REPEAT_SCAN;
qDebug("%s start to repeat ascending order scan data blocks due to query func required", GET_TASKID(pTaskInfo));
- for (int32_t i = 0; i < pTableScanInfo->cond.numOfTWindows; ++i) {
- STimeWindow* pWin = &pTableScanInfo->cond.twindows[i];
- qDebug("%s\t qrange:%" PRId64 "-%" PRId64, GET_TASKID(pTaskInfo), pWin->skey, pWin->ekey);
- }
+
// do prepare for the next round table scan operation
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, 0);
- pTableScanInfo->curTWinIdx = 0;
+ tsdbReaderReset(pTableScanInfo->dataReader, &pTableScanInfo->cond);
}
}
int32_t total = pTableScanInfo->scanInfo.numOfAsc + pTableScanInfo->scanInfo.numOfDesc;
if (pTableScanInfo->scanTimes < total) {
if (pTableScanInfo->cond.order == TSDB_ORDER_ASC) {
- prepareForDescendingScan(pTableScanInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, 0);
- pTableScanInfo->curTWinIdx = 0;
+ prepareForDescendingScan(pTableScanInfo, pOperator->exprSupp.pCtx, 0);
+ tsdbReaderReset(pTableScanInfo->dataReader, &pTableScanInfo->cond);
}
qDebug("%s start to descending order scan data blocks due to query func required", GET_TASKID(pTaskInfo));
- for (int32_t i = 0; i < pTableScanInfo->cond.numOfTWindows; ++i) {
- STimeWindow* pWin = &pTableScanInfo->cond.twindows[i];
- qDebug("%s\t qrange:%" PRId64 "-%" PRId64, GET_TASKID(pTaskInfo), pWin->skey, pWin->ekey);
- }
while (pTableScanInfo->scanTimes < total) {
- while (pTableScanInfo->curTWinIdx < pTableScanInfo->cond.numOfTWindows) {
- SSDataBlock* p = doTableScanImpl(pOperator);
- if (p != NULL) {
- return p;
- }
- pTableScanInfo->curTWinIdx += 1;
- if (pTableScanInfo->curTWinIdx < pTableScanInfo->cond.numOfTWindows) {
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, pTableScanInfo->curTWinIdx);
- }
+ SSDataBlock* p = doTableScanImpl(pOperator);
+ if (p != NULL) {
+ return p;
}
pTableScanInfo->scanTimes += 1;
@@ -484,16 +476,74 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) {
qDebug("%s start to repeat descending order scan data blocks due to query func required",
GET_TASKID(pTaskInfo));
- for (int32_t i = 0; i < pTableScanInfo->cond.numOfTWindows; ++i) {
- STimeWindow* pWin = &pTableScanInfo->cond.twindows[i];
- qDebug("%s\t qrange:%" PRId64 "-%" PRId64, GET_TASKID(pTaskInfo), pWin->skey, pWin->ekey);
- }
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, 0);
- pTableScanInfo->curTWinIdx = 0;
+ tsdbReaderReset(pTableScanInfo->dataReader, &pTableScanInfo->cond);
}
}
}
+ return NULL;
+}
+
+static SSDataBlock* doTableScan(SOperatorInfo* pOperator) {
+ STableScanInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ // if scan table by table
+ if (pInfo->scanMode == TABLE_SCAN__TABLE_ORDER) {
+ if (pInfo->noTable) return NULL;
+ while (1) {
+ SSDataBlock* result = doTableScanGroup(pOperator);
+ if (result) {
+ return result;
+ }
+ // if no data, switch to next table and continue scan
+ pInfo->currentTable++;
+ if (pInfo->currentTable >= taosArrayGetSize(pTaskInfo->tableqinfoList.pTableList)) {
+ return NULL;
+ }
+ STableKeyInfo* pTableInfo = taosArrayGet(pTaskInfo->tableqinfoList.pTableList, pInfo->currentTable);
+ tsdbSetTableId(pInfo->dataReader, pTableInfo->uid);
+ tsdbReaderReset(pInfo->dataReader, &pInfo->cond);
+ pInfo->scanTimes = 0;
+ }
+ }
+
+ if (pInfo->currentGroupId == -1) {
+ pInfo->currentGroupId++;
+ if (pInfo->currentGroupId >= taosArrayGetSize(pTaskInfo->tableqinfoList.pGroupList)) {
+ setTaskStatus(pTaskInfo, TASK_COMPLETED);
+ return NULL;
+ }
+
+ SArray* tableList = taosArrayGetP(pTaskInfo->tableqinfoList.pGroupList, pInfo->currentGroupId);
+ tsdbReaderClose(pInfo->dataReader);
+
+ int32_t code = tsdbReaderOpen(pInfo->readHandle.vnode, &pInfo->cond, tableList, (STsdbReader**)&pInfo->dataReader,
+ GET_TASKID(pTaskInfo));
+ }
+
+ SSDataBlock* result = doTableScanGroup(pOperator);
+ if (result) {
+ return result;
+ }
+
+ pInfo->currentGroupId++;
+ if (pInfo->currentGroupId >= taosArrayGetSize(pTaskInfo->tableqinfoList.pGroupList)) {
+ setTaskStatus(pTaskInfo, TASK_COMPLETED);
+ return NULL;
+ }
+
+ SArray* tableList = taosArrayGetP(pTaskInfo->tableqinfoList.pGroupList, pInfo->currentGroupId);
+ // tsdbSetTableList(pInfo->dataReader, tableList);
+
+ tsdbReaderReset(pInfo->dataReader, &pInfo->cond);
+ pInfo->scanTimes = 0;
+
+ result = doTableScanGroup(pOperator);
+ if (result) {
+ return result;
+ }
+
setTaskStatus(pTaskInfo, TASK_COMPLETED);
return NULL;
}
@@ -512,26 +562,26 @@ static void destroyTableScanOperatorInfo(void* param, int32_t numOfOutput) {
blockDataDestroy(pTableScanInfo->pResBlock);
cleanupQueryTableDataCond(&pTableScanInfo->cond);
- tsdbCleanupReadHandle(pTableScanInfo->dataReader);
+ tsdbReaderClose(pTableScanInfo->dataReader);
if (pTableScanInfo->pColMatchInfo != NULL) {
taosArrayDestroy(pTableScanInfo->pColMatchInfo);
}
+
+ cleanupExprSupp(&pTableScanInfo->pseudoSup);
+ taosMemoryFreeClear(param);
}
-SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, tsdbReaderT pDataReader,
- SReadHandle* readHandle, SExecTaskInfo* pTaskInfo) {
+SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
+ SExecTaskInfo* pTaskInfo) {
STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
goto _error;
}
- // taosSsleep(20);
-
SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
-
- int32_t numOfCols = 0;
+ int32_t numOfCols = 0;
SArray* pColList = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID);
int32_t code = initQueryTableDataCond(&pInfo->cond, pTableScanNode);
@@ -556,10 +606,9 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
pInfo->dataBlockLoadFlag = pTableScanNode->dataRequired;
pInfo->pResBlock = createResDataBlock(pDescNode);
pInfo->pFilterNode = pTableScanNode->scan.node.pConditions;
- pInfo->dataReader = pDataReader;
pInfo->scanFlag = MAIN_SCAN;
pInfo->pColMatchInfo = pColList;
- pInfo->curTWinIdx = 0;
+ pInfo->currentGroupId = -1;
pOperator->name = "TableScanOperator"; // for debug purpose
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN;
@@ -591,45 +640,57 @@ SOperatorInfo* createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo*
pInfo->dataReader = pReadHandle;
// pInfo->prevGroupId = -1;
- pOperator->name = "TableSeqScanOperator";
+ pOperator->name = "TableSeqScanOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
- pOperator->pTaskInfo = pTaskInfo;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doTableScanImpl, NULL, NULL, NULL, NULL, NULL, NULL);
return pOperator;
}
-static int32_t doGetTableRowSize(void* pMeta, uint64_t uid) {
- int32_t rowLen = 0;
+static int32_t doGetTableRowSize(void* pMeta, uint64_t uid, int32_t* rowLen, const char* idstr) {
+ *rowLen = 0;
SMetaReader mr = {0};
metaReaderInit(&mr, pMeta, 0);
- metaGetTableEntryByUid(&mr, uid);
+ int32_t code = metaGetTableEntryByUid(&mr, uid);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", uid, tstrerror(terrno), idstr);
+ metaReaderClear(&mr);
+ return terrno;
+ }
+
if (mr.me.type == TSDB_SUPER_TABLE) {
int32_t numOfCols = mr.me.stbEntry.schemaRow.nCols;
- for(int32_t i = 0; i < numOfCols; ++i) {
- rowLen += mr.me.stbEntry.schemaRow.pSchema[i].bytes;
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ (*rowLen) += mr.me.stbEntry.schemaRow.pSchema[i].bytes;
}
} else if (mr.me.type == TSDB_CHILD_TABLE) {
uint64_t suid = mr.me.ctbEntry.suid;
- metaGetTableEntryByUid(&mr, suid);
+ code = metaGetTableEntryByUid(&mr, suid);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", suid, tstrerror(terrno), idstr);
+ metaReaderClear(&mr);
+ return terrno;
+ }
+
int32_t numOfCols = mr.me.stbEntry.schemaRow.nCols;
- for(int32_t i = 0; i < numOfCols; ++i) {
- rowLen += mr.me.stbEntry.schemaRow.pSchema[i].bytes;
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ (*rowLen) += mr.me.stbEntry.schemaRow.pSchema[i].bytes;
}
} else if (mr.me.type == TSDB_NORMAL_TABLE) {
int32_t numOfCols = mr.me.ntbEntry.schemaRow.nCols;
- for(int32_t i = 0; i < numOfCols; ++i) {
- rowLen += mr.me.ntbEntry.schemaRow.pSchema[i].bytes;
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ (*rowLen) += mr.me.ntbEntry.schemaRow.pSchema[i].bytes;
}
}
metaReaderClear(&mr);
- return rowLen;
+ return TSDB_CODE_SUCCESS;
}
static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) {
@@ -638,16 +699,21 @@ static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) {
}
SBlockDistInfo* pBlockScanInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
STableBlockDistInfo blockDistInfo = {.minRows = INT_MAX, .maxRows = INT_MIN};
- blockDistInfo.rowSize = doGetTableRowSize(pBlockScanInfo->readHandle.meta, pBlockScanInfo->uid);
+ int32_t code = doGetTableRowSize(pBlockScanInfo->readHandle.meta, pBlockScanInfo->uid, &blockDistInfo.rowSize,
+ GET_TASKID(pTaskInfo));
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
tsdbGetFileBlocksDistInfo(pBlockScanInfo->pHandle, &blockDistInfo);
blockDistInfo.numOfInmemRows = (int32_t)tsdbGetNumOfRowsInMemTable(pBlockScanInfo->pHandle);
SSDataBlock* pBlock = pBlockScanInfo->pResBlock;
- int32_t slotId = pOperator->exprSupp.pExprInfo->base.resSchema.slotId;
+ int32_t slotId = pOperator->exprSupp.pExprInfo->base.resSchema.slotId;
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, slotId);
int32_t len = tSerializeBlockDistInfo(NULL, 0, &blockDistInfo);
@@ -668,6 +734,8 @@ static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) {
static void destroyBlockDistScanOperatorInfo(void* param, int32_t numOfOutput) {
SBlockDistInfo* pDistInfo = (SBlockDistInfo*)param;
blockDataDestroy(pDistInfo->pResBlock);
+
+ taosMemoryFreeClear(param);
}
SOperatorInfo* createDataBlockInfoScanOperator(void* dataReader, SReadHandle* readHandle, uint64_t uid,
@@ -679,23 +747,23 @@ SOperatorInfo* createDataBlockInfoScanOperator(void* dataReader, SReadHandle* re
goto _error;
}
- pInfo->pHandle = dataReader;
+ pInfo->pHandle = dataReader;
pInfo->readHandle = *readHandle;
- pInfo->uid = uid;
- pInfo->pResBlock = createResDataBlock(pBlockScanNode->node.pOutputDataBlockDesc);
+ pInfo->uid = uid;
+ pInfo->pResBlock = createResDataBlock(pBlockScanNode->node.pOutputDataBlockDesc);
- int32_t numOfCols = 0;
+ int32_t numOfCols = 0;
SExprInfo* pExprInfo = createExprInfo(pBlockScanNode->pScanPseudoCols, NULL, &numOfCols);
- int32_t code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfCols);
+ int32_t code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfCols);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
- pOperator->name = "DataBlockDistScanOperator";
+ pOperator->name = "DataBlockDistScanOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doBlockInfoScan, NULL, NULL,
@@ -708,7 +776,7 @@ _error:
return NULL;
}
-static void doClearBufferedBlocks(SStreamBlockScanInfo* pInfo) {
+static void doClearBufferedBlocks(SStreamScanInfo* pInfo) {
size_t total = taosArrayGetSize(pInfo->pBlockLists);
pInfo->validBlockIndex = 0;
@@ -719,23 +787,123 @@ static void doClearBufferedBlocks(SStreamBlockScanInfo* pInfo) {
taosArrayClear(pInfo->pBlockLists);
}
-static bool isSessionWindow(SStreamBlockScanInfo* pInfo) {
- return pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION;
+static bool isSessionWindow(SStreamScanInfo* pInfo) {
+ return pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION ||
+ pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION;
}
-static bool isStateWindow(SStreamBlockScanInfo* pInfo) {
+static bool isStateWindow(SStreamScanInfo* pInfo) {
return pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE;
}
-static bool prepareDataScan(SStreamBlockScanInfo* pInfo) {
- SSDataBlock* pSDB = pInfo->pUpdateRes;
- STimeWindow win = {
- .skey = INT64_MIN,
- .ekey = INT64_MAX,
+static bool isIntervalWindow(SStreamScanInfo* pInfo) {
+ return pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL ||
+ pInfo->sessionSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL;
+}
+
+static uint64_t getGroupId(SOperatorInfo* pOperator, uint64_t uid) {
+ uint64_t* groupId = taosHashGet(pOperator->pTaskInfo->tableqinfoList.map, &uid, sizeof(int64_t));
+ if (groupId) {
+ return *groupId;
+ }
+ return 0;
+ /* Todo(liuyao) for partition by column
+ recordNewGroupKeys(pTableScanInfo->pGroupCols, pTableScanInfo->pGroupColVals, pBlock, rowId);
+ int32_t len = buildGroupKeys(pTableScanInfo->keyBuf, pTableScanInfo->pGroupColVals);
+ uint64_t resId = 0;
+ uint64_t* groupId = taosHashGet(pTableScanInfo->pGroupSet, pTableScanInfo->keyBuf, len);
+ if (groupId) {
+ return *groupId;
+ } else if (len != 0) {
+ resId = calcGroupId(pTableScanInfo->keyBuf, len);
+ taosHashPut(pTableScanInfo->pGroupSet, pTableScanInfo->keyBuf, len, &resId, sizeof(uint64_t));
+ }
+ return resId;
+ */
+}
+
+static void setGroupId(SStreamScanInfo* pInfo, SSDataBlock* pBlock, int32_t groupColIndex, int32_t rowIndex) {
+ ASSERT(rowIndex < pBlock->info.rows);
+ switch (pBlock->info.type) {
+ case STREAM_DELETE_DATA:
+ case STREAM_RETRIEVE: {
+ SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, groupColIndex);
+ uint64_t* groupCol = (uint64_t*)pColInfo->pData;
+ pInfo->groupId = groupCol[rowIndex];
+ } break;
+ default:
+ break;
+ }
+}
+
+void resetTableScanInfo(STableScanInfo* pTableScanInfo, STimeWindow* pWin) {
+ pTableScanInfo->cond.twindows = *pWin;
+ pTableScanInfo->scanTimes = 0;
+ pTableScanInfo->currentGroupId = -1;
+}
+
+static bool prepareRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pBlock, int32_t* pRowIndex) {
+ if ((*pRowIndex) == pBlock->info.rows) {
+ return false;
+ }
+
+ ASSERT(taosArrayGetSize(pBlock->pDataBlock) >= 3);
+ SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* startData = (TSKEY*)pStartTsCol->pData;
+ SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
+ TSKEY* endData = (TSKEY*)pEndTsCol->pData;
+ STimeWindow win = {.skey = startData[*pRowIndex], .ekey = endData[*pRowIndex]};
+ setGroupId(pInfo, pBlock, GROUPID_COLUMN_INDEX, *pRowIndex);
+ (*pRowIndex)++;
+
+ for (; *pRowIndex < pBlock->info.rows; (*pRowIndex)++) {
+ if (win.skey == startData[*pRowIndex]) {
+ win.ekey = TMAX(win.ekey, endData[*pRowIndex]);
+ continue;
+ }
+ if (win.skey == endData[*pRowIndex]) {
+ win.skey = TMIN(win.skey, startData[*pRowIndex]);
+ continue;
+ }
+ ASSERT((win.skey > startData[*pRowIndex] && win.ekey < endData[*pRowIndex]) ||
+ (isInTimeWindow(&win, startData[*pRowIndex], 0) || isInTimeWindow(&win, endData[*pRowIndex], 0)));
+ break;
+ }
+
+ resetTableScanInfo(pInfo->pTableScanOp->info, &win);
+ return true;
+}
+
+static STimeWindow getSlidingWindow(TSKEY* tsCol, SInterval* pInterval, SDataBlockInfo* pDataBlockInfo, int32_t* pRowIndex) {
+ SResultRowInfo dumyInfo;
+ dumyInfo.cur.pageId = -1;
+ STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, tsCol[*pRowIndex], pInterval,
+ TSDB_ORDER_ASC);
+ STimeWindow endWin = win;
+ STimeWindow preWin = win;
+ while (1) {
+ (*pRowIndex) += getNumOfRowsInTimeWindow(pDataBlockInfo, tsCol, *pRowIndex, endWin.ekey,
+ binarySearchForKey, NULL, TSDB_ORDER_ASC);
+ do {
+ preWin = endWin;
+ getNextTimeWindow(pInterval, &endWin, TSDB_ORDER_ASC);
+ } while (tsCol[(*pRowIndex) - 1] >= endWin.skey);
+ endWin = preWin;
+ if (win.ekey == endWin.ekey || (*pRowIndex) == pDataBlockInfo->rows ) {
+ win.ekey = endWin.ekey;
+ return win;
+ }
+ win.ekey = endWin.ekey;
+ }
+}
+static bool prepareDataScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32_t tsColIndex, int32_t* pRowIndex) {
+ STimeWindow win = {
+ .skey = INT64_MIN,
+ .ekey = INT64_MAX,
};
bool needRead = false;
- if (!isStateWindow(pInfo) && pInfo->updateResIndex < pSDB->info.rows) {
- SColumnInfoData* pColDataInfo = taosArrayGet(pSDB->pDataBlock, pInfo->primaryTsIndex);
+ if (!isStateWindow(pInfo) && (*pRowIndex) < pSDB->info.rows) {
+ SColumnInfoData* pColDataInfo = taosArrayGet(pSDB->pDataBlock, tsColIndex);
TSKEY* tsCols = (TSKEY*)pColDataInfo->pData;
SResultRowInfo dumyInfo;
dumyInfo.cur.pageId = -1;
@@ -744,15 +912,18 @@ static bool prepareDataScan(SStreamBlockScanInfo* pInfo) {
int64_t gap = pInfo->sessionSup.gap;
int32_t winIndex = 0;
SResultWindowInfo* pCurWin =
- getSessionTimeWindow(pAggSup, tsCols[pInfo->updateResIndex], INT64_MIN, pSDB->info.groupId, gap, &winIndex);
+ getSessionTimeWindow(pAggSup, tsCols[*pRowIndex], INT64_MIN, pSDB->info.groupId, gap, &winIndex);
win = pCurWin->win;
- pInfo->updateResIndex +=
- updateSessionWindowInfo(pCurWin, tsCols, NULL, pSDB->info.rows, pInfo->updateResIndex, gap, NULL);
+ setGroupId(pInfo, pSDB, GROUPID_COLUMN_INDEX, *pRowIndex);
+ (*pRowIndex) += updateSessionWindowInfo(pCurWin, tsCols, NULL, pSDB->info.rows, *pRowIndex, gap, NULL);
} else {
- win = getActiveTimeWindow(NULL, &dumyInfo, tsCols[pInfo->updateResIndex], &pInfo->interval,
- pInfo->interval.precision, NULL);
- pInfo->updateResIndex += getNumOfRowsInTimeWindow(&pSDB->info, tsCols, pInfo->updateResIndex, win.ekey,
- binarySearchForKey, NULL, TSDB_ORDER_ASC);
+ setGroupId(pInfo, pSDB, GROUPID_COLUMN_INDEX, *pRowIndex);
+ pInfo->updateWin.skey = tsCols[*pRowIndex];
+ win = getSlidingWindow(tsCols, &pInfo->interval, &pSDB->info, pRowIndex);
+ pInfo->updateWin.ekey = tsCols[*pRowIndex - 1];
+ // win = getActiveTimeWindow(NULL, &dumyInfo, tsCols[*pRowIndex], &pInfo->interval, TSDB_ORDER_ASC);
+ // (*pRowIndex) +=
+ // getNumOfRowsInTimeWindow(&pSDB->info, tsCols, *pRowIndex, win.ekey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
}
needRead = true;
} else if (isStateWindow(pInfo)) {
@@ -770,16 +941,12 @@ static bool prepareDataScan(SStreamBlockScanInfo* pInfo) {
if (!needRead) {
return false;
}
- STableScanInfo* pTableScanInfo = pInfo->pOperatorDumy->info;
- pTableScanInfo->cond.twindows[0] = win;
- pTableScanInfo->curTWinIdx = 0;
- tsdbResetReadHandle(pTableScanInfo->dataReader, &pTableScanInfo->cond, 0);
- pTableScanInfo->scanTimes = 0;
+ resetTableScanInfo(pInfo->pTableScanOp->info, &win);
return true;
}
static void copyOneRow(SSDataBlock* dest, SSDataBlock* source, int32_t sourceRowId) {
- for (int32_t j = 0; j < source->info.numOfCols; j++) {
+ for (int32_t j = 0; j < taosArrayGetSize(source->pDataBlock); j++) {
SColumnInfoData* pDestCol = (SColumnInfoData*)taosArrayGet(dest->pDataBlock, j);
SColumnInfoData* pSourceCol = (SColumnInfoData*)taosArrayGet(source->pDataBlock, j);
if (colDataIsNull_s(pSourceCol, sourceRowId)) {
@@ -791,42 +958,43 @@ static void copyOneRow(SSDataBlock* dest, SSDataBlock* source, int32_t sourceRow
dest->info.rows++;
}
-static uint64_t getGroupId(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t rowId) {
- uint64_t* groupId = taosHashGet(pOperator->pTaskInfo->tableqinfoList.map, &pBlock->info.uid, sizeof(int64_t));
- if (groupId) {
- return *groupId;
- }
- return 0;
- /* Todo(liuyao) for partition by column
- recordNewGroupKeys(pTableScanInfo->pGroupCols, pTableScanInfo->pGroupColVals, pBlock, rowId);
- int32_t len = buildGroupKeys(pTableScanInfo->keyBuf, pTableScanInfo->pGroupColVals);
- uint64_t resId = 0;
- uint64_t* groupId = taosHashGet(pTableScanInfo->pGroupSet, pTableScanInfo->keyBuf, len);
- if (groupId) {
- return *groupId;
- } else if (len != 0) {
- resId = calcGroupId(pTableScanInfo->keyBuf, len);
- taosHashPut(pTableScanInfo->pGroupSet, pTableScanInfo->keyBuf, len, &resId, sizeof(uint64_t));
+static SSDataBlock* doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32_t tsColIndex, int32_t* pRowIndex) {
+ while (1) {
+ SSDataBlock* pResult = NULL;
+ pResult = doTableScan(pInfo->pTableScanOp);
+ if (!pResult && prepareRangeScan(pInfo, pSDB, pRowIndex)) {
+ // scan next window data
+ pResult = doTableScan(pInfo->pTableScanOp);
+ }
+ if (!pResult) {
+ blockDataCleanup(pSDB);
+ *pRowIndex = 0;
+ return NULL;
+ }
+
+ if (pResult->info.groupId == pInfo->groupId) {
+ return pResult;
+ }
}
- return resId;
- */
}
-static SSDataBlock* doDataScan(SStreamBlockScanInfo* pInfo) {
+static SSDataBlock* doDataScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32_t tsColIndex, int32_t* pRowIndex) {
while (1) {
SSDataBlock* pResult = NULL;
- pResult = doTableScan(pInfo->pOperatorDumy);
+ pResult = doTableScan(pInfo->pTableScanOp);
if (pResult == NULL) {
- if (prepareDataScan(pInfo)) {
+ if (prepareDataScan(pInfo, pSDB, tsColIndex, pRowIndex)) {
// scan next window data
- pResult = doTableScan(pInfo->pOperatorDumy);
+ pResult = doTableScan(pInfo->pTableScanOp);
}
}
if (!pResult) {
+ pInfo->updateWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
return NULL;
}
if (pResult->info.groupId == pInfo->groupId) {
+ pResult->info.calWin = pInfo->updateWin;
return pResult;
}
}
@@ -835,7 +1003,7 @@ static SSDataBlock* doDataScan(SStreamBlockScanInfo* pInfo) {
SSDataBlock* pBlock = createOneDataBlock(pResult, true);
blockDataCleanup(pResult);
for (int32_t i = 0; i < pBlock->info.rows; i++) {
- uint64_t id = getGroupId(pInfo->pOperatorDumy, pBlock, i);
+ uint64_t id = getGroupId(pInfo->pOperatorDumy, pBlock->info.uid);
if (id == pInfo->groupId) {
copyOneRow(pResult, pBlock, i);
}
@@ -843,22 +1011,94 @@ static SSDataBlock* doDataScan(SStreamBlockScanInfo* pInfo) {
return pResult;
*/
}
+static void generateIntervalTs(SStreamScanInfo* pInfo, SSDataBlock* pDelBlock, SOperatorInfo* pOperator,
+ SSDataBlock* pUpdateRes) {
+ if (pDelBlock->info.rows == 0) {
+ return;
+ }
+ blockDataCleanup(pUpdateRes);
+ blockDataEnsureCapacity(pUpdateRes, 64);
+ ASSERT(taosArrayGetSize(pDelBlock->pDataBlock) >= 3);
+ SColumnInfoData* pStartTsCol = taosArrayGet(pDelBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* startData = (TSKEY*)pStartTsCol->pData;
+ SColumnInfoData* pEndTsCol = taosArrayGet(pDelBlock->pDataBlock, END_TS_COLUMN_INDEX);
+ TSKEY* endData = (TSKEY*)pEndTsCol->pData;
+ SColumnInfoData* pGpCol = taosArrayGet(pDelBlock->pDataBlock, UID_COLUMN_INDEX);
+ uint64_t* uidCol = (uint64_t*)pGpCol->pData;
+
+ SColumnInfoData* pDestTsCol = taosArrayGet(pUpdateRes->pDataBlock, START_TS_COLUMN_INDEX);
+ SColumnInfoData* pDestGpCol = taosArrayGet(pUpdateRes->pDataBlock, GROUPID_COLUMN_INDEX);
+ for (int32_t i = pInfo->deleteDataIndex;
+ i < pDelBlock->info.rows &&
+ i < pDelBlock->info.capacity - (endData[i] - startData[i]) / pInfo->interval.interval - 1;
+ i++) {
+ uint64_t groupId = getGroupId(pOperator, uidCol[i]);
+ for (TSKEY startTs = startData[i]; startTs <= endData[i];) {
+ colDataAppend(pDestTsCol, pUpdateRes->info.rows, (const char*)&startTs, false);
+ colDataAppend(pDestGpCol, pUpdateRes->info.rows, (const char*)&groupId, false);
+ pUpdateRes->info.rows++;
+ startTs = taosTimeAdd(startTs, pInfo->interval.interval, pInfo->interval.intervalUnit, pInfo->interval.precision);
+ }
+ pInfo->deleteDataIndex++;
+ }
+
+ if (pInfo->deleteDataIndex > 0 && pInfo->deleteDataIndex == pDelBlock->info.rows) {
+ blockDataCleanup(pDelBlock);
+ pInfo->deleteDataIndex = 0;
+ }
+}
-static void setUpdateData(SStreamBlockScanInfo* pInfo, SSDataBlock* pBlock, SSDataBlock* pUpdateBlock) {
+static void generateScanRange(SStreamScanInfo* pInfo, SSDataBlock* pBlock, SOperatorInfo* pOperator,
+ SSDataBlock* pUpdateRes) {
+ if (pBlock->info.rows == 0) {
+ return;
+ }
+ blockDataCleanup(pUpdateRes);
+ blockDataEnsureCapacity(pUpdateRes, pBlock->info.rows);
+ ASSERT(taosArrayGetSize(pBlock->pDataBlock) >= 3);
+ SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* startData = (TSKEY*)pStartTsCol->pData;
+ SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
+ TSKEY* endData = (TSKEY*)pEndTsCol->pData;
+ SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
+ uint64_t* uidCol = (uint64_t*)pGpCol->pData;
+
+ SColumnInfoData* pDestStartCol = taosArrayGet(pUpdateRes->pDataBlock, START_TS_COLUMN_INDEX);
+ SColumnInfoData* pDestEndCol = taosArrayGet(pUpdateRes->pDataBlock, END_TS_COLUMN_INDEX);
+ SColumnInfoData* pDestGpCol = taosArrayGet(pUpdateRes->pDataBlock, GROUPID_COLUMN_INDEX);
+ int32_t dummy = 0;
+ for (int32_t i = 0; i < pBlock->info.rows; i++) {
+ uint64_t groupId = getGroupId(pOperator, uidCol[i]);
+ // gap must be 0.
+ SResultWindowInfo* pStartWin =
+ getCurSessionWindow(pInfo->sessionSup.pStreamAggSup, startData[i], endData[i], groupId, 0, &dummy);
+ if (!pStartWin) {
+ // window has been closed.
+ continue;
+ }
+ SResultWindowInfo* pEndWin =
+ getCurSessionWindow(pInfo->sessionSup.pStreamAggSup, endData[i], endData[i], groupId, 0, &dummy);
+ ASSERT(pEndWin);
+ colDataAppend(pDestStartCol, i, (const char*)&pStartWin->win.skey, false);
+ colDataAppend(pDestEndCol, i, (const char*)&pEndWin->win.ekey, false);
+ colDataAppend(pDestGpCol, i, (const char*)&groupId, false);
+ pUpdateRes->info.rows++;
+ }
+}
+static void setUpdateData(SStreamScanInfo* pInfo, SSDataBlock* pBlock, SSDataBlock* pUpdateBlock) {
blockDataCleanup(pUpdateBlock);
int32_t size = taosArrayGetSize(pInfo->tsArray);
if (pInfo->tsArrayIndex < size) {
SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pUpdateBlock->pDataBlock, pInfo->primaryTsIndex);
ASSERT(pCol->info.type == TSDB_DATA_TYPE_TIMESTAMP);
blockDataEnsureCapacity(pUpdateBlock, size);
- ASSERT(pBlock->info.numOfCols == pUpdateBlock->info.numOfCols);
int32_t rowId = *(int32_t*)taosArrayGet(pInfo->tsArray, pInfo->tsArrayIndex);
- pInfo->groupId = getGroupId(pInfo->pOperatorDumy, pBlock, rowId);
+ pInfo->groupId = getGroupId(pInfo->pTableScanOp, pBlock->info.uid);
int32_t i = 0;
for (; i < size; i++) {
rowId = *(int32_t*)taosArrayGet(pInfo->tsArray, i + pInfo->tsArrayIndex);
- uint64_t id = getGroupId(pInfo->pOperatorDumy, pBlock, rowId);
+ uint64_t id = getGroupId(pInfo->pTableScanOp, pBlock->info.uid);
if (pInfo->groupId != id) {
break;
}
@@ -867,7 +1107,7 @@ static void setUpdateData(SStreamBlockScanInfo* pInfo, SSDataBlock* pBlock, SSDa
pUpdateBlock->info.rows = i;
pInfo->tsArrayIndex += i;
pUpdateBlock->info.groupId = pInfo->groupId;
- pUpdateBlock->info.type = STREAM_REPROCESS;
+ pUpdateBlock->info.type = STREAM_CLEAR;
blockDataUpdateTsWindow(pUpdateBlock, 0);
}
// all rows have same group id
@@ -875,178 +1115,285 @@ static void setUpdateData(SStreamBlockScanInfo* pInfo, SSDataBlock* pBlock, SSDa
if (size > 0 && pInfo->tsArrayIndex == size) {
taosArrayClear(pInfo->tsArray);
}
+
+ if (size == 0) {
+ generateIntervalTs(pInfo, pInfo->pDeleteDataRes, pInfo->pTableScanOp, pUpdateBlock);
+ }
}
-static void getUpdateDataBlock(SStreamBlockScanInfo* pInfo, bool invertible, SSDataBlock* pBlock,
- SSDataBlock* pUpdateBlock) {
+static void checkUpdateData(SStreamScanInfo* pInfo, bool invertible, SSDataBlock* pBlock, bool out) {
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
ASSERT(pColDataInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP);
TSKEY* ts = (TSKEY*)pColDataInfo->pData;
for (int32_t rowId = 0; rowId < pBlock->info.rows; rowId++) {
- if (updateInfoIsUpdated(pInfo->pUpdateInfo, pBlock->info.uid, ts[rowId])) {
+ if (updateInfoIsUpdated(pInfo->pUpdateInfo, pBlock->info.uid, ts[rowId]) && out) {
taosArrayPush(pInfo->tsArray, &rowId);
}
}
- if (!pUpdateBlock) {
- taosArrayClear(pInfo->tsArray);
- return;
+}
+
+static void setBlockGroupId(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t uidColIndex) {
+ ASSERT(taosArrayGetSize(pBlock->pDataBlock) >= 3);
+ SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, uidColIndex);
+ uint64_t* uidCol = (uint64_t*)pColDataInfo->pData;
+ ASSERT(pBlock->info.rows > 0);
+ for (int32_t i = 0; i < pBlock->info.rows; i++) {
+ uidCol[i] = getGroupId(pOperator, uidCol[i]);
+ }
+}
+
+static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock) {
+ SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
+ SOperatorInfo* pOperator = pInfo->pStreamScanOp;
+ SExecTaskInfo* pTaskInfo = pInfo->pStreamScanOp->pTaskInfo;
+
+ blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
+
+ pInfo->pRes->info.rows = pBlock->info.rows;
+ pInfo->pRes->info.uid = pBlock->info.uid;
+ pInfo->pRes->info.type = STREAM_NORMAL;
+
+ uint64_t* groupIdPre = taosHashGet(pOperator->pTaskInfo->tableqinfoList.map, &pBlock->info.uid, sizeof(int64_t));
+ if (groupIdPre) {
+ pInfo->pRes->info.groupId = *groupIdPre;
+ } else {
+ pInfo->pRes->info.groupId = 0;
+ }
+
+ // for generating rollup SMA result, each time is an independent time serie.
+ // TODO temporarily used, when the statement of "partition by tbname" is ready, remove this
+ if (pInfo->assignBlockUid) {
+ pInfo->pRes->info.groupId = pBlock->info.uid;
+ }
+
+ // todo extract method
+ for (int32_t i = 0; i < taosArrayGetSize(pInfo->pColMatchInfo); ++i) {
+ SColMatchInfo* pColMatchInfo = taosArrayGet(pInfo->pColMatchInfo, i);
+ if (!pColMatchInfo->output) {
+ continue;
+ }
+
+ bool colExists = false;
+ for (int32_t j = 0; j < blockDataGetNumOfCols(pBlock); ++j) {
+ SColumnInfoData* pResCol = bdGetColumnInfoData(pBlock, j);
+ if (pResCol->info.colId == pColMatchInfo->colId) {
+
+ SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->targetSlotId);
+ colDataAssign(pDst, pResCol, pBlock->info.rows, &pInfo->pRes->info);
+// taosArraySet(pInfo->pRes->pDataBlock, pColMatchInfo->targetSlotId, pResCol);
+ colExists = true;
+ break;
+ }
+ }
+
+ // the required column does not exists in submit block, let's set it to be all null value
+ if (!colExists) {
+ SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->targetSlotId);
+ colDataAppendNNULL(pDst, 0, pBlockInfo->rows);
+ }
+ }
+
+ ASSERT(pInfo->pRes->pDataBlock != NULL);
+
+ // currently only the tbname pseudo column
+ if (pInfo->numOfPseudoExpr > 0) {
+ int32_t code = addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes,
+ GET_TASKID(pTaskInfo));
+ if (code != TSDB_CODE_SUCCESS) {
+ blockDataFreeRes((SSDataBlock*) pBlock);
+ longjmp(pTaskInfo->env, code);
+ }
}
- setUpdateData(pInfo, pBlock, pUpdateBlock);
- // Todo(liuyao) get from tsdb
- // SSDataBlock* p = createOneDataBlock(pBlock, true);
- // p->info.type = STREAM_INVERT;
- // taosArrayClear(pInfo->tsArray);
- // return p;
+
+ doFilter(pInfo->pCondition, pInfo->pRes);
+ blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
+ blockDataFreeRes((SSDataBlock*) pBlock);
+ return 0;
}
-static SSDataBlock* doStreamBlockScan(SOperatorInfo* pOperator) {
+static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) {
// NOTE: this operator does never check if current status is done or not
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SStreamBlockScanInfo* pInfo = pOperator->info;
- int32_t rows = 0;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SStreamScanInfo* pInfo = pOperator->info;
- pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
- if (pTaskInfo->code != TSDB_CODE_SUCCESS || pOperator->status == OP_EXEC_DONE) {
+ qDebug("stream scan called");
+ if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__LOG) {
+ while (1) {
+ SFetchRet ret = {0};
+ tqNextBlock(pInfo->tqReader, &ret);
+ if (ret.fetchType == FETCH_TYPE__DATA) {
+ blockDataCleanup(pInfo->pRes);
+ if (setBlockIntoRes(pInfo, &ret.data) < 0) {
+ ASSERT(0);
+ }
+ // TODO clean data block
+ if (pInfo->pRes->info.rows > 0) {
+ qDebug("stream scan log return %d rows", pInfo->pRes->info.rows);
+ return pInfo->pRes;
+ }
+ } else if (ret.fetchType == FETCH_TYPE__META) {
+ ASSERT(0);
+ pTaskInfo->streamInfo.lastStatus = ret.offset;
+ pTaskInfo->streamInfo.metaBlk = ret.meta;
+ return NULL;
+ } else if (ret.fetchType == FETCH_TYPE__NONE) {
+ pTaskInfo->streamInfo.lastStatus = ret.offset;
+ ASSERT(pTaskInfo->streamInfo.lastStatus.version + 1 >= pTaskInfo->streamInfo.prepareStatus.version);
+ qDebug("stream scan log return null");
+ return NULL;
+ } else {
+ ASSERT(0);
+ }
+ }
+ } else if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_DATA) {
+ SSDataBlock* pResult = doTableScan(pInfo->pTableScanOp);
+ if (pResult && pResult->info.rows > 0) {
+ qDebug("stream scan tsdb return %d rows", pResult->info.rows);
+ return pResult;
+ }
+ qDebug("stream scan tsdb return null");
+ return NULL;
+ } else if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_META) {
+ // TODO scan meta
+ ASSERT(0);
return NULL;
}
size_t total = taosArrayGetSize(pInfo->pBlockLists);
- if (pInfo->blockType == STREAM_DATA_TYPE_SSDATA_BLOCK) {
+ // TODO: refactor
+ if (pInfo->blockType == STREAM_INPUT__DATA_BLOCK) {
if (pInfo->validBlockIndex >= total) {
/*doClearBufferedBlocks(pInfo);*/
- pOperator->status = OP_EXEC_DONE;
+ /*pOperator->status = OP_EXEC_DONE;*/
return NULL;
}
int32_t current = pInfo->validBlockIndex++;
SSDataBlock* pBlock = taosArrayGetP(pInfo->pBlockLists, current);
+ // TODO move into scan
+ pBlock->info.calWin.skey = INT64_MIN;
+ pBlock->info.calWin.ekey = INT64_MAX;
blockDataUpdateTsWindow(pBlock, 0);
+ switch (pBlock->info.type) {
+ case STREAM_NORMAL:
+ case STREAM_GET_ALL:
+ return pBlock;
+ case STREAM_RETRIEVE: {
+ pInfo->blockType = STREAM_INPUT__DATA_SUBMIT;
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RETRIEVE;
+ copyDataBlock(pInfo->pPullDataRes, pBlock);
+ pInfo->pullDataResIndex = 0;
+ prepareDataScan(pInfo, pInfo->pPullDataRes, START_TS_COLUMN_INDEX, &pInfo->pullDataResIndex);
+ updateInfoAddCloseWindowSBF(pInfo->pUpdateInfo);
+ } break;
+ case STREAM_DELETE_DATA: {
+ pInfo->blockType = STREAM_INPUT__DATA_SUBMIT;
+ pInfo->updateResIndex = 0;
+ if (isIntervalWindow(pInfo)) {
+ copyDataBlock(pInfo->pDeleteDataRes, pBlock);
+ generateIntervalTs(pInfo, pInfo->pDeleteDataRes, pInfo->pTableScanOp, pInfo->pUpdateRes);
+ prepareDataScan(pInfo, pInfo->pUpdateRes, START_TS_COLUMN_INDEX, &pInfo->updateResIndex);
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
+ } else {
+ generateScanRange(pInfo, pBlock, pInfo->pTableScanOp, pInfo->pUpdateRes);
+ prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex);
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
+ }
+ pInfo->pUpdateRes->info.type = STREAM_DELETE_DATA;
+ return pInfo->pUpdateRes;
+ } break;
+ default:
+ break;
+ }
return pBlock;
- } else {
+ } else if (pInfo->blockType == STREAM_INPUT__DATA_SUBMIT) {
+ qDebug("scan mode %d", pInfo->scanMode);
if (pInfo->scanMode == STREAM_SCAN_FROM_RES) {
blockDataDestroy(pInfo->pUpdateRes);
pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
return pInfo->pRes;
} else if (pInfo->scanMode == STREAM_SCAN_FROM_UPDATERES) {
- pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
- if (!isStateWindow(pInfo)) {
- prepareDataScan(pInfo);
+ if (isStateWindow(pInfo)) {
+ pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
+ } else {
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
+ prepareDataScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex);
}
return pInfo->pUpdateRes;
- } else {
- if (isStateWindow(pInfo) && taosArrayGetSize(pInfo->sessionSup.pStreamAggSup->pScanWindow) > 0) {
- pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
- pInfo->updateResIndex = pInfo->pUpdateRes->info.rows;
- prepareDataScan(pInfo);
+ } else if (pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER_RETRIEVE) {
+ SSDataBlock* pSDB = doDataScan(pInfo, pInfo->pPullDataRes, 0, &pInfo->pullDataResIndex);
+ if (pSDB != NULL) {
+ checkUpdateData(pInfo, true, pSDB, false);
+ pSDB->info.type = STREAM_PULL_DATA;
+ return pSDB;
}
- if (pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER) {
- SSDataBlock* pSDB = doDataScan(pInfo);
- if (pSDB == NULL) {
- setUpdateData(pInfo, pInfo->pRes, pInfo->pUpdateRes);
- if (pInfo->pUpdateRes->info.rows > 0) {
- if (!isStateWindow(pInfo)) {
- prepareDataScan(pInfo);
- }
- return pInfo->pUpdateRes;
- } else {
- pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
- }
- } else {
- getUpdateDataBlock(pInfo, true, pSDB, NULL);
- return pSDB;
- }
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
+ } else if (pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER) {
+ SSDataBlock* pSDB = doDataScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex);
+ if (pSDB) {
+ pSDB->info.type = STREAM_NORMAL;
+ checkUpdateData(pInfo, true, pSDB, false);
+ return pSDB;
+ }
+ setUpdateData(pInfo, pInfo->pRes, pInfo->pUpdateRes);
+ if (pInfo->pUpdateRes->info.rows > 0) {
+ prepareDataScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex);
+ return pInfo->pUpdateRes;
+ }
+ pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
+ } else if (pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER_RANGE) {
+ SSDataBlock* pSDB = doRangeScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex);
+ if (pSDB) {
+ pSDB->info.type = STREAM_NORMAL;
+ checkUpdateData(pInfo, true, pSDB, false);
+ return pSDB;
}
+ pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
+ } else if (isStateWindow(pInfo)) {
+ pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER;
+ pInfo->updateResIndex = pInfo->pUpdateRes->info.rows;
+ if (prepareDataScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex)) {
+ blockDataCleanup(pInfo->pUpdateRes);
+ // return empty data blcok
+ return pInfo->pUpdateRes;
+ }
+ pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
}
SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
blockDataCleanup(pInfo->pRes);
- while (tqNextDataBlock(pInfo->streamBlockReader)) {
- SArray* pCols = NULL;
- uint64_t groupId = 0;
- uint64_t uid = 0;
- int32_t numOfRows = 0;
- int16_t outputCol = 0;
+ while (tqNextDataBlock(pInfo->tqReader)) {
+ SSDataBlock block = {0};
- int32_t code = tqRetrieveDataBlock(&pCols, pInfo->streamBlockReader, &groupId, &uid, &numOfRows, &outputCol);
+ // todo refactor
+ int32_t code = tqRetrieveDataBlock(&block, pInfo->tqReader);
- if (code != TSDB_CODE_SUCCESS || numOfRows == 0) {
+ if (code != TSDB_CODE_SUCCESS || block.info.rows == 0) {
pTaskInfo->code = code;
return NULL;
}
- pInfo->pRes->info.groupId = groupId;
- pInfo->pRes->info.rows = numOfRows;
- pInfo->pRes->info.uid = uid;
- pInfo->pRes->info.type = STREAM_NORMAL;
-
- // for generating rollup SMA result, each time is an independent time serie.
- // TODO temporarily used, when the statement of "partition by tbname" is ready, remove this
- if (pInfo->assignBlockUid) {
- pInfo->pRes->info.groupId = uid;
- } else {
- pInfo->pRes->info.groupId = groupId;
- }
-
- uint64_t* groupIdPre = taosHashGet(pOperator->pTaskInfo->tableqinfoList.map, &uid, sizeof(int64_t));
- if (groupIdPre) {
- pInfo->pRes->info.groupId = *groupIdPre;
- }
+ setBlockIntoRes(pInfo, &block);
- for (int32_t i = 0; i < taosArrayGetSize(pInfo->pColMatchInfo); ++i) {
- SColMatchInfo* pColMatchInfo = taosArrayGet(pInfo->pColMatchInfo, i);
- if (!pColMatchInfo->output) {
- continue;
- }
-
- bool colExists = false;
- for (int32_t j = 0; j < taosArrayGetSize(pCols); ++j) {
- SColumnInfoData* pResCol = taosArrayGet(pCols, j);
- if (pResCol->info.colId == pColMatchInfo->colId) {
- taosArraySet(pInfo->pRes->pDataBlock, pColMatchInfo->targetSlotId, pResCol);
- colExists = true;
- break;
- }
- }
-
- // the required column does not exists in submit block, let's set it to be all null value
- if (!colExists) {
- SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->targetSlotId);
- colInfoDataEnsureCapacity(pDst, 0, pBlockInfo->rows);
- colDataAppendNNULL(pDst, 0, pBlockInfo->rows);
- }
- }
-
- if (pInfo->pRes->pDataBlock == NULL) {
- // TODO add log
- pOperator->status = OP_EXEC_DONE;
- pTaskInfo->code = terrno;
- return NULL;
- }
-
- rows = pBlockInfo->rows;
-
- // currently only the tbname pseudo column
- if (pInfo->numOfPseudoExpr > 0) {
- addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes);
+ if (pBlockInfo->rows > 0) {
+ break;
}
-
- doFilter(pInfo->pCondition, pInfo->pRes);
- blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
- break;
}
// record the scan action.
pInfo->numOfExec++;
pOperator->resultInfo.totalRows += pBlockInfo->rows;
- if (rows == 0) {
- pOperator->status = OP_EXEC_DONE;
+ if (pBlockInfo->rows == 0) {
+ updateInfoDestoryColseWinSBF(pInfo->pUpdateInfo);
+ /*pOperator->status = OP_EXEC_DONE;*/
} else if (pInfo->pUpdateInfo) {
pInfo->tsArrayIndex = 0;
- getUpdateDataBlock(pInfo, true, pInfo->pRes, pInfo->pUpdateRes);
+ checkUpdateData(pInfo, true, pInfo->pRes, true);
+ setUpdateData(pInfo, pInfo->pRes, pInfo->pUpdateRes);
if (pInfo->pUpdateRes->info.rows > 0) {
- if (pInfo->pUpdateRes->info.type == STREAM_REPROCESS) {
+ if (pInfo->pUpdateRes->info.type == STREAM_CLEAR) {
pInfo->updateResIndex = 0;
pInfo->scanMode = STREAM_SCAN_FROM_UPDATERES;
} else if (pInfo->pUpdateRes->info.type == STREAM_INVERT) {
@@ -1055,11 +1402,20 @@ static SSDataBlock* doStreamBlockScan(SOperatorInfo* pOperator) {
}
}
}
+ qDebug("scan rows: %d", pBlockInfo->rows);
+ return (pBlockInfo->rows == 0) ? NULL : pInfo->pRes;
- return (rows == 0) ? NULL : pInfo->pRes;
+ } else {
+ ASSERT(0);
+ return NULL;
}
}
+static SSDataBlock* doRawScan(SOperatorInfo* pInfo) {
+ //
+ return NULL;
+}
+
static SArray* extractTableIdList(const STableListInfo* pTableGroupInfo) {
SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t));
@@ -1072,11 +1428,24 @@ static SArray* extractTableIdList(const STableListInfo* pTableGroupInfo) {
return tableIdList;
}
-SOperatorInfo* createStreamScanOperatorInfo(void* pDataReader, SReadHandle* pHandle,
- STableScanPhysiNode* pTableScanNode, SExecTaskInfo* pTaskInfo,
- STimeWindowAggSupp* pTwSup) {
- SStreamBlockScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamBlockScanInfo));
- SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+// for subscribing db or stb (not including column),
+// if this scan is used, meta data can be return
+// and schemas are decided when scanning
+SOperatorInfo* createRawScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode,
+ SExecTaskInfo* pTaskInfo, STimeWindowAggSupp* pTwSup) {
+ // create operator
+ // create tb reader
+ // create meta reader
+ // create tq reader
+
+ return NULL;
+}
+
+SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode,
+ SExecTaskInfo* pTaskInfo, STimeWindowAggSupp* pTwSup, uint64_t queryId,
+ uint64_t taskId) {
+ SStreamScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamScanInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
@@ -1097,7 +1466,7 @@ SOperatorInfo* createStreamScanOperatorInfo(void* pDataReader, SReadHandle* pHan
int16_t colId = id->colId;
taosArrayPush(pColIds, &colId);
- if (id->colId == pTableScanNode->tsColId) {
+ if (id->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
pInfo->primaryTsIndex = id->targetSlotId;
}
}
@@ -1114,25 +1483,46 @@ SOperatorInfo* createStreamScanOperatorInfo(void* pDataReader, SReadHandle* pHan
}
if (pHandle) {
- SOperatorInfo* pTableScanDummy = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
- STableScanInfo* pSTInfo = (STableScanInfo*)pTableScanDummy->info;
- if (pSTInfo->interval.interval > 0) {
- pInfo->pUpdateInfo = updateInfoInitP(&pSTInfo->interval, pTwSup->waterMark);
+ SOperatorInfo* pTableScanOp = createTableScanOperatorInfo(pTableScanNode, pHandle, pTaskInfo);
+ STableScanInfo* pTSInfo = (STableScanInfo*)pTableScanOp->info;
+ if (pHandle->version > 0) {
+ pTSInfo->cond.endVersion = pHandle->version;
+ }
+
+ SArray* tableList = taosArrayGetP(pTaskInfo->tableqinfoList.pGroupList, 0);
+ if (pHandle->initTableReader) {
+ pTSInfo->scanMode = TABLE_SCAN__TABLE_ORDER;
+ pTSInfo->dataReader = NULL;
+ if (tsdbReaderOpen(pHandle->vnode, &pTSInfo->cond, tableList, &pTSInfo->dataReader, NULL) < 0) {
+ ASSERT(0);
+ }
+ }
+
+ if (pHandle->initTqReader) {
+ ASSERT(pHandle->tqReader == NULL);
+ pInfo->tqReader = tqOpenReader(pHandle->vnode);
+ ASSERT(pInfo->tqReader);
+ } else {
+ ASSERT(pHandle->tqReader);
+ pInfo->tqReader = pHandle->tqReader;
+ }
+
+ if (pTSInfo->interval.interval > 0) {
+ pInfo->pUpdateInfo = updateInfoInitP(&pTSInfo->interval, pTwSup->waterMark);
} else {
pInfo->pUpdateInfo = NULL;
}
- pInfo->pOperatorDumy = pTableScanDummy;
- pInfo->interval = pSTInfo->interval;
+
+ pInfo->pTableScanOp = pTableScanOp;
+ pInfo->interval = pTSInfo->interval;
pInfo->readHandle = *pHandle;
- ASSERT(pHandle->reader);
- pInfo->streamBlockReader = pHandle->reader;
pInfo->tableUid = pScanPhyNode->uid;
// set the extract column id to streamHandle
- tqReadHandleSetColIdList((STqReadHandle*)pHandle->reader, pColIds);
+ tqReaderSetColIdList(pInfo->tqReader, pColIds);
SArray* tableIdList = extractTableIdList(&pTaskInfo->tableqinfoList);
- int32_t code = tqReadHandleSetTbUidList(pHandle->reader, tableIdList);
+ int32_t code = tqReaderSetTbUidList(pInfo->tqReader, tableIdList);
if (code != 0) {
taosArrayDestroy(tableIdList);
goto _error;
@@ -1148,21 +1538,25 @@ SOperatorInfo* createStreamScanOperatorInfo(void* pDataReader, SReadHandle* pHan
pInfo->pRes = createResDataBlock(pDescNode);
pInfo->pUpdateRes = createResDataBlock(pDescNode);
pInfo->pCondition = pScanPhyNode->node.pConditions;
- pInfo->pDataReader = pDataReader;
pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
pInfo->sessionSup = (SessionWindowSupporter){.pStreamAggSup = NULL, .gap = -1};
pInfo->groupId = 0;
+ pInfo->pPullDataRes = createPullDataBlock();
+ pInfo->pStreamScanOp = pOperator;
+ pInfo->deleteDataIndex = 0;
+ pInfo->pDeleteDataRes = createPullDataBlock();
+ pInfo->updateWin = (STimeWindow){.skey = INT64_MAX, .ekey = INT64_MAX};
- pOperator->name = "StreamBlockScanOperator";
+ pOperator->name = "StreamScanOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN;
pOperator->blocking = false;
pOperator->status = OP_NOT_OPENED;
pOperator->info = pInfo;
- pOperator->exprSupp.numOfExprs = pInfo->pRes->info.numOfCols;
+ pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock);
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet =
- createOperatorFpSet(operatorDummyOpenFn, doStreamBlockScan, NULL, NULL, operatorDummyCloseFn, NULL, NULL, NULL);
+ createOperatorFpSet(operatorDummyOpenFn, doStreamScan, NULL, NULL, operatorDummyCloseFn, NULL, NULL, NULL);
return pOperator;
@@ -1184,6 +1578,16 @@ static void destroySysScanOperator(void* param, int32_t numOfOutput) {
}
taosArrayDestroy(pInfo->scanCols);
+ taosMemoryFreeClear(pInfo->pUser);
+
+ taosMemoryFreeClear(param);
+}
+
+static int32_t getSysTableDbNameColId(const char* pTable) {
+ // if (0 == strcmp(TSDB_INS_TABLE_USER_INDEXES, pTable)) {
+ // return 1;
+ // }
+ return TSDB_INS_USER_STABLES_DBNAME_COLID;
}
EDealRes getDBNameFromConditionWalker(SNode* pNode, void* pContext) {
@@ -1207,7 +1611,7 @@ EDealRes getDBNameFromConditionWalker(SNode* pNode, void* pContext) {
}
SColumnNode* node = (SColumnNode*)pNode;
- if (TSDB_INS_USER_STABLES_DBNAME_COLID == node->colId) {
+ if (getSysTableDbNameColId(node->tableName) == node->colId) {
*(int32_t*)pContext = 2;
return DEAL_RES_CONTINUE;
}
@@ -1239,7 +1643,7 @@ static void getDBNameFromCondition(SNode* pCondition, const char* dbName) {
nodesWalkExpr(pCondition, getDBNameFromConditionWalker, (char*)dbName);
}
-static int32_t loadSysTableCallback(void* param, const SDataBuf* pMsg, int32_t code) {
+static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code) {
SOperatorInfo* operator=(SOperatorInfo*) param;
SSysTableScanInfo* pScanResInfo = (SSysTableScanInfo*)operator->info;
if (TSDB_CODE_SUCCESS == code) {
@@ -1286,7 +1690,7 @@ static SSDataBlock* doFilterResult(SSysTableScanInfo* pInfo) {
SColumnInfoData* pSrc = taosArrayGet(pInfo->pRes->pDataBlock, i);
if (keep) {
- colDataAssign(pDest, pSrc, pInfo->pRes->info.rows);
+ colDataAssign(pDest, pSrc, pInfo->pRes->info.rows, &px->info);
numOfRow = pInfo->pRes->info.rows;
} else if (NULL != rowRes) {
numOfRow = 0;
@@ -1316,8 +1720,6 @@ static SSDataBlock* doFilterResult(SSysTableScanInfo* pInfo) {
}
static SSDataBlock* buildSysTableMetaBlock() {
- SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
-
size_t size = 0;
const SSysTableMeta* pMeta = NULL;
getInfosDbMeta(&pMeta, &size);
@@ -1330,19 +1732,13 @@ static SSDataBlock* buildSysTableMetaBlock() {
}
}
- pBlock->pDataBlock = taosArrayInit(pBlock->info.numOfCols, sizeof(SColumnInfoData));
-
+ SSDataBlock* pBlock = createDataBlock();
for (int32_t i = 0; i < pMeta[index].colNum; ++i) {
- SColumnInfoData colInfoData = {0};
- colInfoData.info.colId = i + 1;
- colInfoData.info.type = pMeta[index].schema[i].type;
- colInfoData.info.bytes = pMeta[index].schema[i].bytes;
- taosArrayPush(pBlock->pDataBlock, &colInfoData);
+ SColumnInfoData colInfoData =
+ createColumnInfoData(pMeta[index].schema[i].type, pMeta[index].schema[i].bytes, i + 1);
+ blockDataAppendColInfo(pBlock, &colInfoData);
}
- pBlock->info.numOfCols = pMeta[index].colNum;
- pBlock->info.hasVarCol = true;
-
return pBlock;
}
@@ -1373,7 +1769,6 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
}
blockDataCleanup(pInfo->pRes);
-
int32_t numOfRows = 0;
const char* db = NULL;
@@ -1417,7 +1812,17 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
SMetaReader mr = {0};
metaReaderInit(&mr, pInfo->readHandle.meta, 0);
- metaGetTableEntryByUid(&mr, pInfo->pCur->mr.me.ctbEntry.suid);
+
+ uint64_t suid = pInfo->pCur->mr.me.ctbEntry.suid;
+ int32_t code = metaGetTableEntryByUid(&mr, suid);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get super table meta, uid:0x%" PRIx64 ", code:%s, %s", suid, tstrerror(terrno),
+ GET_TASKID(pTaskInfo));
+ metaReaderClear(&mr);
+ metaCloseTbCursor(pInfo->pCur);
+ pInfo->pCur = NULL;
+ longjmp(pTaskInfo->env, terrno);
+ }
// number of columns
pColInfoData = taosArrayGet(p->pDataBlock, 3);
@@ -1524,6 +1929,7 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
while (1) {
int64_t startTs = taosGetTimestampUs();
strncpy(pInfo->req.tb, tNameGetTableName(&pInfo->name), tListLen(pInfo->req.tb));
+ strcpy(pInfo->req.user, pInfo->pUser);
if (pInfo->showRewrite) {
char dbName[TSDB_DB_NAME_LEN] = {0};
@@ -1543,11 +1949,15 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
return NULL;
}
+ int32_t msgType = (strcasecmp(name, TSDB_INS_TABLE_DNODE_VARIABLES) == 0) ? TDMT_DND_SYSTABLE_RETRIEVE
+ : TDMT_MND_SYSTABLE_RETRIEVE;
+
pMsgSendInfo->param = pOperator;
pMsgSendInfo->msgInfo.pData = buf1;
pMsgSendInfo->msgInfo.len = contLen;
- pMsgSendInfo->msgType = TDMT_MND_SYSTABLE_RETRIEVE;
+ pMsgSendInfo->msgType = msgType;
pMsgSendInfo->fp = loadSysTableCallback;
+ pMsgSendInfo->requestId = pTaskInfo->id.queryId;
int64_t transporterId = 0;
int32_t code =
@@ -1565,7 +1975,7 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
if (pRsp->numOfRows == 0 || pRsp->completed) {
pOperator->status = OP_EXEC_DONE;
- qDebug("%s load meta data from mnode completed, rowsOfSource:%d, totalRows:%" PRIu64 " ", GET_TASKID(pTaskInfo),
+ qDebug("%s load meta data from mnode completed, rowsOfSource:%d, totalRows:%" PRIu64, GET_TASKID(pTaskInfo),
pRsp->numOfRows, pInfo->loadInfo.totalRows);
if (pRsp->numOfRows == 0) {
@@ -1582,6 +1992,8 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
taosMemoryFree(pRsp);
if (pInfo->pRes->info.rows > 0) {
return pInfo->pRes;
+ } else if (pOperator->status == OP_EXEC_DONE) {
+ return NULL;
}
}
}
@@ -1600,8 +2012,8 @@ int32_t buildSysDbTableInfo(const SSysTableScanInfo* pInfo, int32_t capacity) {
getPerfDbMeta(&pSysDbTableMeta, &size);
p->info.rows = buildDbTableInfoBlock(p, pSysDbTableMeta, size, TSDB_PERFORMANCE_SCHEMA_DB);
- relocateColumnData(pInfo->pRes, pInfo->scanCols, p->pDataBlock, false);
pInfo->pRes->info.rows = p->info.rows;
+ relocateColumnData(pInfo->pRes, pInfo->scanCols, p->pDataBlock, false);
blockDataDestroy(p);
return pInfo->pRes->info.rows;
@@ -1650,7 +2062,7 @@ int32_t buildDbTableInfoBlock(const SSDataBlock* p, const SSysTableMeta* pSysDbT
}
SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode,
- SExecTaskInfo* pTaskInfo) {
+ const char* pUser, SExecTaskInfo* pTaskInfo) {
SSysTableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SSysTableScanInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -1666,6 +2078,7 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan
SArray* colList = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &num, COL_MATCH_FROM_COL_ID);
pInfo->accountId = pScanPhyNode->accountId;
+ pInfo->pUser = taosMemoryStrDup((void*)pUser);
pInfo->showRewrite = pScanPhyNode->showRewrite;
pInfo->pRes = pResBlock;
pInfo->pCondition = pScanNode->node.pConditions;
@@ -1690,7 +2103,7 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan
pOperator->blocking = false;
pOperator->status = OP_NOT_OPENED;
pOperator->info = pInfo;
- pOperator->exprSupp.numOfExprs = pResBlock->info.numOfCols;
+ pOperator->exprSupp.numOfExprs = taosArrayGetSize(pResBlock->pDataBlock);
pOperator->pTaskInfo = pTaskInfo;
pOperator->fpSet =
@@ -1804,7 +2217,13 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
while (pInfo->curPos < size && count < pOperator->resultInfo.capacity) {
STableKeyInfo* item = taosArrayGet(pInfo->pTableList->pTableList, pInfo->curPos);
- metaGetTableEntryByUid(&mr, item->uid);
+ int32_t code = metaGetTableEntryByUid(&mr, item->uid);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
+ GET_TASKID(pTaskInfo));
+ metaReaderClear(&mr);
+ longjmp(pTaskInfo->env, terrno);
+ }
for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
@@ -1824,7 +2243,8 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
} else {
data = (char*)p;
}
- colDataAppend(pDst, count, data, (data == NULL));
+ colDataAppend(pDst, count, data,
+ (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
data != NULL) {
@@ -1847,9 +2267,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
}
pRes->info.rows = count;
- doFilter(pInfo->pFilterNode, pRes);
-
- pOperator->resultInfo.totalRows += pRes->info.rows;
+ pOperator->resultInfo.totalRows += count;
return (pRes->info.rows == 0) ? NULL : pInfo->pRes;
}
@@ -1857,6 +2275,8 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
STagScanInfo* pInfo = (STagScanInfo*)param;
pInfo->pRes = blockDataDestroy(pInfo->pRes);
+
+ taosMemoryFreeClear(param);
}
SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode,
@@ -1874,26 +2294,24 @@ SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysi
SExprInfo* pExprInfo = createExprInfo(pPhyNode->pScanPseudoCols, NULL, &numOfExprs);
SArray* colList = extractColMatchInfo(pPhyNode->pScanPseudoCols, pDescNode, &num, COL_MATCH_FROM_COL_ID);
-
int32_t code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfExprs);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
- pInfo->pTableList = pTableListInfo;
- pInfo->pColMatchInfo = colList;
- pInfo->pRes = createResDataBlock(pDescNode);
- pInfo->readHandle = *pReadHandle;
- pInfo->curPos = 0;
- pInfo->pFilterNode = pPhyNode->node.pConditions;
+ pInfo->pTableList = pTableListInfo;
+ pInfo->pColMatchInfo = colList;
+ pInfo->pRes = createResDataBlock(pDescNode);
+ pInfo->readHandle = *pReadHandle;
+ pInfo->curPos = 0;
pOperator->name = "TagScanOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
- pOperator->pTaskInfo = pTaskInfo;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->pTaskInfo = pTaskInfo;
initResultSizeInfo(pOperator, 4096);
blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
@@ -1911,6 +2329,12 @@ _error:
}
typedef struct STableMergeScanInfo {
+ STableListInfo* tableListInfo;
+ int32_t tableStartIndex;
+ int32_t tableEndIndex;
+ bool hasGroupId;
+ uint64_t groupId;
+
SArray* dataReaders; // array of tsdbReaderT*
SReadHandle readHandle;
@@ -1923,11 +2347,9 @@ typedef struct STableMergeScanInfo {
SSDataBlock* pSortInputBlock;
int64_t startTs; // sort start time
- bool hasGroupId;
- uint64_t groupId;
- STupleHandle* prefetchedTuple;
-
- SArray* sortSourceParams;
+ SArray* sortSourceParams;
+ uint64_t queryId;
+ uint64_t taskId;
SFileBlockLoadRecorder readRecorder;
int64_t numOfRows;
@@ -1955,48 +2377,46 @@ typedef struct STableMergeScanInfo {
// window to check if current data block needs to be loaded.
SSampleExecInfo sample; // sample execution info
- int32_t curTWinIdx;
-
} STableMergeScanInfo;
-int32_t createMultipleDataReaders(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
- STableListInfo* pTableListInfo, SArray* arrayReader, uint64_t queryId,
- uint64_t taskId, SNode* pTagCond) {
- int32_t code = getTableList(pHandle->meta, &pTableScanNode->scan, pTableListInfo, pTagCond);
+int32_t createScanTableListInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
+ STableListInfo* pTableListInfo, uint64_t queryId, uint64_t taskId) {
+ int32_t code = getTableList(pHandle->meta, pHandle->vnode, &pTableScanNode->scan, pTableListInfo);
if (code != TSDB_CODE_SUCCESS) {
- goto _error;
+ return code;
}
if (taosArrayGetSize(pTableListInfo->pTableList) == 0) {
qDebug("no table qualified for query, TID:0x%" PRIx64 ", QID:0x%" PRIx64, taskId, queryId);
- goto _error;
+ return TSDB_CODE_SUCCESS;
}
- SQueryTableDataCond cond = {0};
- code = initQueryTableDataCond(&cond, pTableScanNode);
+ pTableListInfo->needSortTableByGroupId = pTableScanNode->groupSort;
+ code = generateGroupIdMap(pTableListInfo, pHandle, pTableScanNode->pGroupTags);
if (code != TSDB_CODE_SUCCESS) {
- goto _error;
+ return code;
}
- // TODO: free the sublist info and the table list in it
- for (int32_t i = 0; i < taosArrayGetSize(pTableListInfo->pTableList); ++i) {
- STableListInfo* subListInfo = taosMemoryCalloc(1, sizeof(subListInfo));
- subListInfo->pTableList = taosArrayInit(1, sizeof(STableKeyInfo));
- taosArrayPush(subListInfo->pTableList, taosArrayGet(pTableListInfo->pTableList, i));
- tsdbReaderT* pReader = tsdbReaderOpen(pHandle->vnode, &cond, subListInfo, queryId, taskId);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t createMultipleDataReaders(SQueryTableDataCond* pQueryCond, SReadHandle* pHandle, STableListInfo* pTableListInfo,
+ int32_t tableStartIdx, int32_t tableEndIdx, SArray* arrayReader, const char* idstr) {
+ for (int32_t i = tableStartIdx; i <= tableEndIdx; ++i) {
+ SArray* subTableList = taosArrayInit(1, sizeof(STableKeyInfo));
+ taosArrayPush(subTableList, taosArrayGet(pTableListInfo->pTableList, i));
+
+ STsdbReader* pReader = NULL;
+ tsdbReaderOpen(pHandle->vnode, pQueryCond, subTableList, &pReader, idstr);
taosArrayPush(arrayReader, &pReader);
- taosArrayDestroy(subListInfo->pTableList);
- taosMemoryFree(subListInfo);
+ taosArrayDestroy(subTableList);
}
- cleanupQueryTableDataCond(&cond);
- return 0;
-
-_error:
- return code;
+ return TSDB_CODE_SUCCESS;
}
+// todo refactor
static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeScanInfo* pTableScanInfo,
int32_t readerIdx, SSDataBlock* pBlock, uint32_t* status) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
@@ -2027,7 +2447,7 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc
pCost->skipBlocks += 1;
// clear all data in pBlock that are set when handing the previous block
- for (int32_t i = 0; i < pBlockInfo->numOfCols; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
SColumnInfoData* pcol = taosArrayGet(pBlock->pDataBlock, i);
pcol->pData = NULL;
}
@@ -2038,11 +2458,11 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc
bool allColumnsHaveAgg = true;
SColumnDataAgg** pColAgg = NULL;
- tsdbReaderT* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
- tsdbRetrieveDataBlockStatisInfo(reader, &pColAgg, &allColumnsHaveAgg);
+ STsdbReader* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
+ tsdbRetrieveDatablockSMA(reader, &pColAgg, &allColumnsHaveAgg);
if (allColumnsHaveAgg == true) {
- int32_t numOfCols = pBlock->info.numOfCols;
+ int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
// todo create this buffer during creating operator
if (pBlock->pBlockAgg == NULL) {
@@ -2079,7 +2499,7 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc
pCost->totalCheckedRows += pBlock->info.rows;
pCost->loadBlocks += 1;
- tsdbReaderT* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
+ STsdbReader* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
SArray* pCols = tsdbRetrieveDataBlock(reader, NULL);
if (pCols == NULL) {
return terrno;
@@ -2089,8 +2509,11 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc
// currently only the tbname pseudo column
if (pTableScanInfo->numOfPseudoExpr > 0) {
- addTagPseudoColumnData(&pTableScanInfo->readHandle, pTableScanInfo->pPseudoExpr, pTableScanInfo->numOfPseudoExpr,
- pBlock);
+ int32_t code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pTableScanInfo->pPseudoExpr,
+ pTableScanInfo->numOfPseudoExpr, pBlock, GET_TASKID(pTaskInfo));
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
}
int64_t st = taosGetTimestampMs();
@@ -2125,7 +2548,7 @@ static SSDataBlock* getTableDataBlock(void* param) {
blockDataCleanup(pBlock);
- tsdbReaderT* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
+ STsdbReader* reader = taosArrayGetP(pTableScanInfo->dataReaders, readerIdx);
while (tsdbNextDataBlock(reader)) {
if (isTaskKilled(pOperator->pTaskInfo)) {
longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_QUERY_CANCELLED);
@@ -2137,7 +2560,15 @@ static SSDataBlock* getTableDataBlock(void* param) {
continue;
}
- tsdbRetrieveDataBlockInfo(reader, &pBlock->info);
+ blockDataCleanup(pBlock);
+ SDataBlockInfo binfo = pBlock->info;
+ tsdbRetrieveDataBlockInfo(reader, &binfo);
+
+ blockDataEnsureCapacity(pBlock, binfo.rows);
+ pBlock->info.type = binfo.type;
+ pBlock->info.uid = binfo.uid;
+ pBlock->info.window = binfo.window;
+ pBlock->info.rows = binfo.rows;
uint32_t status = 0;
int32_t code = loadDataBlockFromOneTable(pOperator, pTableScanInfo, readerIdx, pBlock, &status);
@@ -2164,11 +2595,19 @@ static SSDataBlock* getTableDataBlock(void* param) {
return NULL;
}
-SArray* generateSortByTsInfo(int32_t order) {
+SArray* generateSortByTsInfo(SArray* colMatchInfo, int32_t order) {
+ int32_t tsTargetSlotId = 0;
+ for (int32_t i = 0; i < taosArrayGetSize(colMatchInfo); ++i) {
+ SColMatchInfo* colInfo = taosArrayGet(colMatchInfo, i);
+ if (colInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
+ tsTargetSlotId = colInfo->targetSlotId;
+ }
+ }
+
SArray* pList = taosArrayInit(1, sizeof(SBlockOrderInfo));
SBlockOrderInfo bi = {0};
bi.order = order;
- bi.slotId = 0;
+ bi.slotId = tsTargetSlotId;
bi.nullFirst = NULL_ORDER_FIRST;
taosArrayPush(pList, &bi);
@@ -2176,22 +2615,47 @@ SArray* generateSortByTsInfo(int32_t order) {
return pList;
}
-int32_t doOpenTableMergeScanOperator(SOperatorInfo* pOperator) {
+int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) {
STableMergeScanInfo* pInfo = pOperator->info;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- if (OPTR_IS_OPENED(pOperator)) {
- return TSDB_CODE_SUCCESS;
+ {
+ size_t tableListSize = taosArrayGetSize(pInfo->tableListInfo->pTableList);
+ int32_t i = pInfo->tableStartIndex + 1;
+ for (; i < tableListSize; ++i) {
+ STableKeyInfo* tableKeyInfo = taosArrayGet(pInfo->tableListInfo->pTableList, i);
+ if (tableKeyInfo->groupId != pInfo->groupId) {
+ break;
+ }
+ }
+ pInfo->tableEndIndex = i - 1;
}
- int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
+ int32_t tableStartIdx = pInfo->tableStartIndex;
+ int32_t tableEndIdx = pInfo->tableEndIndex;
+ STableListInfo* tableListInfo = pInfo->tableListInfo;
+ createMultipleDataReaders(&pInfo->cond, &pInfo->readHandle, tableListInfo, tableStartIdx, tableEndIdx,
+ pInfo->dataReaders, GET_TASKID(pTaskInfo));
+
+ // todo the total available buffer should be determined by total capacity of buffer of this task.
+ // the additional one is reserved for merge result
+ pInfo->sortBufSize = pInfo->bufPageSize * (tableEndIdx - tableStartIdx + 1 + 1);
+ int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_MULTISOURCE_MERGE, pInfo->bufPageSize, numOfBufPage,
pInfo->pSortInputBlock, pTaskInfo->id.str);
tsortSetFetchRawDataFp(pInfo->pSortHandle, getTableDataBlock, NULL, NULL);
size_t numReaders = taosArrayGetSize(pInfo->dataReaders);
+ for (int32_t i = 0; i < numReaders; ++i) {
+ STableMergeScanSortSourceParam param = {0};
+ param.readerIdx = i;
+ param.pOperator = pOperator;
+ param.inputBlock = createOneDataBlock(pInfo->pResBlock, false);
+ taosArrayPush(pInfo->sortSourceParams, ¶m);
+ }
+
for (int32_t i = 0; i < numReaders; ++i) {
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
STableMergeScanSortSourceParam* param = taosArrayGet(pInfo->sortSourceParams, i);
@@ -2205,9 +2669,23 @@ int32_t doOpenTableMergeScanOperator(SOperatorInfo* pOperator) {
longjmp(pTaskInfo->env, terrno);
}
- pOperator->status = OP_RES_TO_RETURN;
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t stopGroupTableMergeScan(SOperatorInfo* pOperator) {
+ STableMergeScanInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- OPTR_SET_OPENED(pOperator);
+ tsortDestroySortHandle(pInfo->pSortHandle);
+ taosArrayClear(pInfo->sortSourceParams);
+
+ for (int32_t i = 0; i < taosArrayGetSize(pInfo->dataReaders); ++i) {
+ STsdbReader* reader = taosArrayGetP(pInfo->dataReaders, i);
+ tsdbReaderClose(reader);
+ }
+
+ taosArrayDestroy(pInfo->dataReaders);
+ pInfo->dataReaders = NULL;
return TSDB_CODE_SUCCESS;
}
@@ -2250,14 +2728,38 @@ SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) {
if (code != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, code);
}
+ size_t tableListSize = taosArrayGetSize(pInfo->tableListInfo->pTableList);
+ if (!pInfo->hasGroupId) {
+ pInfo->hasGroupId = true;
- SSDataBlock* pBlock = getSortedTableMergeScanBlockData(pInfo->pSortHandle, pOperator->resultInfo.capacity, pOperator);
-
- if (pBlock != NULL) {
- pOperator->resultInfo.totalRows += pBlock->info.rows;
- } else {
- doSetOperatorCompleted(pOperator);
+ if (tableListSize == 0) {
+ doSetOperatorCompleted(pOperator);
+ return NULL;
+ }
+ pInfo->tableStartIndex = 0;
+ pInfo->groupId = ((STableKeyInfo*)taosArrayGet(pInfo->tableListInfo->pTableList, pInfo->tableStartIndex))->groupId;
+ startGroupTableMergeScan(pOperator);
+ }
+ SSDataBlock* pBlock = NULL;
+ while (pInfo->tableStartIndex < tableListSize) {
+ pBlock = getSortedTableMergeScanBlockData(pInfo->pSortHandle, pOperator->resultInfo.capacity, pOperator);
+ if (pBlock != NULL) {
+ pBlock->info.groupId = pInfo->groupId;
+ pOperator->resultInfo.totalRows += pBlock->info.rows;
+ return pBlock;
+ } else {
+ stopGroupTableMergeScan(pOperator);
+ if (pInfo->tableEndIndex >= tableListSize - 1) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+ pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
+ pInfo->groupId =
+ ((STableKeyInfo*)taosArrayGet(pInfo->tableListInfo->pTableList, pInfo->tableStartIndex))->groupId;
+ startGroupTableMergeScan(pOperator);
+ }
}
+
return pBlock;
}
@@ -2266,8 +2768,8 @@ void destroyTableMergeScanOperatorInfo(void* param, int32_t numOfOutput) {
cleanupQueryTableDataCond(&pTableScanInfo->cond);
for (int32_t i = 0; i < taosArrayGetSize(pTableScanInfo->dataReaders); ++i) {
- tsdbReaderT* reader = taosArrayGetP(pTableScanInfo->dataReaders, i);
- tsdbCleanupReadHandle(reader);
+ STsdbReader* reader = taosArrayGetP(pTableScanInfo->dataReaders, i);
+ tsdbReaderClose(reader);
}
taosArrayDestroy(pTableScanInfo->dataReaders);
@@ -2275,11 +2777,12 @@ void destroyTableMergeScanOperatorInfo(void* param, int32_t numOfOutput) {
taosArrayDestroy(pTableScanInfo->pColMatchInfo);
}
- taosArrayDestroy(pTableScanInfo->sortSourceParams);
pTableScanInfo->pResBlock = blockDataDestroy(pTableScanInfo->pResBlock);
pTableScanInfo->pSortInputBlock = blockDataDestroy(pTableScanInfo->pSortInputBlock);
taosArrayDestroy(pTableScanInfo->pSortInfo);
+
+ taosMemoryFreeClear(param);
}
typedef struct STableMergeScanExecInfo {
@@ -2301,13 +2804,23 @@ int32_t getTableMergeScanExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExpla
return TSDB_CODE_SUCCESS;
}
-SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SArray* dataReaders,
- SReadHandle* readHandle, SExecTaskInfo* pTaskInfo) {
+int32_t compareTableKeyInfoByGid(const void* p1, const void* p2) {
+ const STableKeyInfo* info1 = p1;
+ const STableKeyInfo* info2 = p2;
+ return info1->groupId - info2->groupId;
+}
+
+SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, STableListInfo* pTableListInfo,
+ SReadHandle* readHandle, SExecTaskInfo* pTaskInfo, uint64_t queryId,
+ uint64_t taskId) {
STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
goto _error;
}
+ if (pTableScanNode->pGroupTags) {
+ taosArraySort(pTableListInfo->pTableList, compareTableKeyInfoByGid);
+ }
SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
@@ -2332,37 +2845,24 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN
pInfo->sample.seed = taosGetTimestampSec();
pInfo->dataBlockLoadFlag = pTableScanNode->dataRequired;
pInfo->pFilterNode = pTableScanNode->scan.node.pConditions;
- pInfo->dataReaders = dataReaders;
+ pInfo->tableListInfo = pTableListInfo;
pInfo->scanFlag = MAIN_SCAN;
pInfo->pColMatchInfo = pColList;
- pInfo->curTWinIdx = 0;
pInfo->pResBlock = createResDataBlock(pDescNode);
+ pInfo->dataReaders = taosArrayInit(64, POINTER_BYTES);
+ pInfo->queryId = queryId;
+ pInfo->taskId = taskId;
- pInfo->sortSourceParams = taosArrayInit(taosArrayGetSize(dataReaders), sizeof(STableMergeScanSortSourceParam));
- for (int32_t i = 0; i < taosArrayGetSize(dataReaders); ++i) {
- STableMergeScanSortSourceParam* param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
- param->readerIdx = i;
- param->pOperator = pOperator;
- param->inputBlock = createOneDataBlock(pInfo->pResBlock, false);
- taosArrayPush(pInfo->sortSourceParams, param);
- taosMemoryFree(param);
- }
+ pInfo->sortSourceParams = taosArrayInit(64, sizeof(STableMergeScanSortSourceParam));
- pInfo->pSortInfo = generateSortByTsInfo(pInfo->cond.order);
+ pInfo->pSortInfo = generateSortByTsInfo(pInfo->pColMatchInfo, pInfo->cond.order);
pInfo->pSortInputBlock = createOneDataBlock(pInfo->pResBlock, false);
int32_t rowSize = pInfo->pResBlock->info.rowSize;
pInfo->bufPageSize = getProperSortPageSize(rowSize);
- // todo the total available buffer should be determined by total capacity of buffer of this task.
- // the additional one is reserved for merge result
- pInfo->sortBufSize = pInfo->bufPageSize * (taosArrayGetSize(dataReaders) + 1);
- pInfo->hasGroupId = false;
- pInfo->prefetchedTuple = NULL;
-
pOperator->name = "TableMergeScanOperator";
- // TODO : change it
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN;
pOperator->blocking = false;
pOperator->status = OP_NOT_OPENED;
@@ -2372,8 +2872,8 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN
initResultSizeInfo(pOperator, 1024);
pOperator->fpSet =
- createOperatorFpSet(doOpenTableMergeScanOperator, doTableMergeScan, NULL, NULL, destroyTableMergeScanOperatorInfo,
- NULL, NULL, getTableMergeScanExplainExecInfo);
+ createOperatorFpSet(operatorDummyOpenFn, doTableMergeScan, NULL, NULL, destroyTableMergeScanOperatorInfo, NULL,
+ NULL, getTableMergeScanExplainExecInfo);
pOperator->cost.openCost = 0;
return pOperator;
@@ -2383,3 +2883,4 @@ _error:
taosMemoryFree(pOperator);
return NULL;
}
+
diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c
index 9d13276e6d68d2aaf380d0ac3111c2214c6f0e75..9795907404f9805b93082c0e41fe13ffe3b41f25 100644
--- a/source/libs/executor/src/sortoperator.c
+++ b/source/libs/executor/src/sortoperator.c
@@ -22,10 +22,11 @@ static int32_t getExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput);
-SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode, SExecTaskInfo* pTaskInfo) {
+SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode,
+ SExecTaskInfo* pTaskInfo) {
SSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
- if (pInfo == NULL || pOperator == NULL/* || rowSize > 100 * 1024 * 1024*/) {
+ if (pInfo == NULL || pOperator == NULL /* || rowSize > 100 * 1024 * 1024*/) {
goto _error;
}
@@ -44,16 +45,17 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode*
initResultSizeInfo(pOperator, 1024);
- pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);;
- pInfo->pColMatchInfo = pColMatchColInfo;
- pOperator->name = "SortOperator";
+ pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);
+ pInfo->pCondition = pSortPhyNode->node.pConditions;
+ pInfo->pColMatchInfo = pColMatchColInfo;
+ pOperator->name = "SortOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT;
- pOperator->blocking = true;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
- pOperator->exprSupp.pExprInfo = pExprInfo;
- pOperator->exprSupp.numOfExprs = numOfCols;
- pOperator->pTaskInfo = pTaskInfo;
+ pOperator->blocking = true;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->exprSupp.pExprInfo = pExprInfo;
+ pOperator->exprSupp.numOfExprs = numOfCols;
+ pOperator->pTaskInfo = pTaskInfo;
// lazy evaluation for the following parameter since the input datablock is not known till now.
// pInfo->bufPageSize = rowSize < 1024 ? 1024 * 2 : rowSize * 2;
@@ -78,7 +80,7 @@ _error:
}
void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle) {
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
bool isNull = tsortIsNullVal(pTupleHandle, i);
if (isNull) {
@@ -118,6 +120,9 @@ SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, i
}
if (p->info.rows > 0) {
+ blockDataEnsureCapacity(pDataBlock, capacity);
+
+ // todo extract function to handle this
int32_t numOfCols = taosArrayGetSize(pColMatchInfo);
for (int32_t i = 0; i < numOfCols; ++i) {
SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, i);
@@ -125,11 +130,10 @@ SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, i
SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId);
SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId);
- colDataAssign(pDst, pSrc, p->info.rows);
+ colDataAssign(pDst, pSrc, p->info.rows, &pDataBlock->info);
}
pDataBlock->info.rows = p->info.rows;
- pDataBlock->info.capacity = p->info.rows;
}
blockDataDestroy(p);
@@ -138,7 +142,8 @@ SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, i
SSDataBlock* loadNextDataBlock(void* param) {
SOperatorInfo* pOperator = (SOperatorInfo*)param;
- return pOperator->fpSet.getNextFn(pOperator);
+ SSDataBlock* pBlock = pOperator->fpSet.getNextFn(pOperator);
+ return pBlock;
}
// todo refactor: merged with fetch fp
@@ -146,8 +151,8 @@ void applyScalarFunction(SSDataBlock* pBlock, void* param) {
SOperatorInfo* pOperator = param;
SSortOperatorInfo* pSort = pOperator->info;
if (pOperator->exprSupp.pExprInfo != NULL) {
- int32_t code =
- projectApplyFunctions(pOperator->exprSupp.pExprInfo, pBlock, pBlock, pOperator->exprSupp.pCtx, pOperator->exprSupp.numOfExprs, NULL);
+ int32_t code = projectApplyFunctions(pOperator->exprSupp.pExprInfo, pBlock, pBlock, pOperator->exprSupp.pCtx,
+ pOperator->exprSupp.numOfExprs, NULL);
if (code != TSDB_CODE_SUCCESS) {
longjmp(pOperator->pTaskInfo->env, code);
}
@@ -165,8 +170,7 @@ int32_t doOpenSortOperator(SOperatorInfo* pOperator) {
pInfo->startTs = taosGetTimestampUs();
// pInfo->binfo.pRes is not equalled to the input datablock.
- pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1,
- NULL, pTaskInfo->id.str);
+ pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1, NULL, pTaskInfo->id.str);
tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock, applyScalarFunction, pOperator);
@@ -201,14 +205,28 @@ SSDataBlock* doSort(SOperatorInfo* pOperator) {
longjmp(pTaskInfo->env, code);
}
- SSDataBlock* pBlock = getSortedBlockData(pInfo->pSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity,
- pInfo->pColMatchInfo, pInfo);
+ SSDataBlock* pBlock = NULL;
+ while (1) {
+ pBlock = getSortedBlockData(pInfo->pSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity,
+ pInfo->pColMatchInfo, pInfo);
+ if (pBlock != NULL) {
+ doFilter(pInfo->pCondition, pBlock);
+ }
+
+ if (pBlock == NULL) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (blockDataGetNumOfRows(pBlock) > 0) {
+ break;
+ }
+ }
if (pBlock != NULL) {
pOperator->resultInfo.totalRows += pBlock->info.rows;
- } else {
- doSetOperatorCompleted(pOperator);
}
+
return pBlock;
}
@@ -218,6 +236,8 @@ void destroyOrderOperatorInfo(void* param, int32_t numOfOutput) {
taosArrayDestroy(pInfo->pSortInfo);
taosArrayDestroy(pInfo->pColMatchInfo);
+
+ taosMemoryFreeClear(param);
}
int32_t getExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
@@ -232,7 +252,267 @@ int32_t getExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t*
return TSDB_CODE_SUCCESS;
}
-typedef struct SMultiwaySortMergeOperatorInfo {
+//=====================================================================================
+// Group Sort Operator
+typedef enum EChildOperatorStatus { CHILD_OP_NEW_GROUP, CHILD_OP_SAME_GROUP, CHILD_OP_FINISHED } EChildOperatorStatus;
+
+typedef struct SGroupSortOperatorInfo {
+ SOptrBasicInfo binfo;
+ SArray* pSortInfo;
+ SArray* pColMatchInfo;
+
+ int64_t startTs;
+ uint64_t sortElapsed;
+ bool hasGroupId;
+ uint64_t currGroupId;
+
+ SSDataBlock* prefetchedSortInput;
+ SSortHandle* pCurrSortHandle;
+ EChildOperatorStatus childOpStatus;
+
+ SSortExecInfo sortExecInfo;
+} SGroupSortOperatorInfo;
+
+SSDataBlock* getGroupSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, int32_t capacity,
+ SArray* pColMatchInfo, SGroupSortOperatorInfo* pInfo) {
+ blockDataCleanup(pDataBlock);
+ blockDataEnsureCapacity(pDataBlock, capacity);
+
+ SSDataBlock* p = tsortGetSortedDataBlock(pHandle);
+ if (p == NULL) {
+ return NULL;
+ }
+
+ blockDataEnsureCapacity(p, capacity);
+
+ while (1) {
+ STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
+ if (pTupleHandle == NULL) {
+ break;
+ }
+
+ appendOneRowToDataBlock(p, pTupleHandle);
+ if (p->info.rows >= capacity) {
+ break;
+ }
+ }
+
+ if (p->info.rows > 0) {
+ int32_t numOfCols = taosArrayGetSize(pColMatchInfo);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, i);
+ ASSERT(pmInfo->matchType == COL_MATCH_FROM_SLOT_ID);
+
+ SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId);
+ SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId);
+ colDataAssign(pDst, pSrc, p->info.rows, &pDataBlock->info);
+ }
+
+ pDataBlock->info.rows = p->info.rows;
+ pDataBlock->info.capacity = p->info.rows;
+ }
+
+ blockDataDestroy(p);
+ return (pDataBlock->info.rows > 0) ? pDataBlock : NULL;
+}
+
+typedef struct SGroupSortSourceParam {
+ SOperatorInfo* childOpInfo;
+ SGroupSortOperatorInfo* grpSortOpInfo;
+} SGroupSortSourceParam;
+
+SSDataBlock* fetchNextGroupSortDataBlock(void* param) {
+ SGroupSortSourceParam* source = param;
+ SGroupSortOperatorInfo* grpSortOpInfo = source->grpSortOpInfo;
+ if (grpSortOpInfo->prefetchedSortInput) {
+ SSDataBlock* block = grpSortOpInfo->prefetchedSortInput;
+ grpSortOpInfo->prefetchedSortInput = NULL;
+ return block;
+ } else {
+ SOperatorInfo* childOp = source->childOpInfo;
+ SSDataBlock* block = childOp->fpSet.getNextFn(childOp);
+ if (block != NULL) {
+ if (block->info.groupId == grpSortOpInfo->currGroupId) {
+ grpSortOpInfo->childOpStatus = CHILD_OP_SAME_GROUP;
+ return block;
+ } else {
+ grpSortOpInfo->childOpStatus = CHILD_OP_NEW_GROUP;
+ grpSortOpInfo->prefetchedSortInput = block;
+ return NULL;
+ }
+ } else {
+ grpSortOpInfo->childOpStatus = CHILD_OP_FINISHED;
+ return NULL;
+ }
+ }
+}
+
+int32_t beginSortGroup(SOperatorInfo* pOperator) {
+ SGroupSortOperatorInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ // pInfo->binfo.pRes is not equalled to the input datablock.
+ pInfo->pCurrSortHandle =
+ tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1, NULL, pTaskInfo->id.str);
+
+ tsortSetFetchRawDataFp(pInfo->pCurrSortHandle, fetchNextGroupSortDataBlock, applyScalarFunction, pOperator);
+
+ SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
+ SGroupSortSourceParam* param = taosMemoryCalloc(1, sizeof(SGroupSortSourceParam));
+ param->childOpInfo = pOperator->pDownstream[0];
+ param->grpSortOpInfo = pInfo;
+ ps->param = param;
+ tsortAddSource(pInfo->pCurrSortHandle, ps);
+
+ int32_t code = tsortOpen(pInfo->pCurrSortHandle);
+ taosMemoryFreeClear(ps);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, terrno);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t finishSortGroup(SOperatorInfo* pOperator) {
+ SGroupSortOperatorInfo* pInfo = pOperator->info;
+
+ SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pCurrSortHandle);
+ pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
+ pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
+ pInfo->sortExecInfo.loops += sortExecInfo.loops;
+ pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
+ pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
+ if (pInfo->pCurrSortHandle != NULL) {
+ tsortDestroySortHandle(pInfo->pCurrSortHandle);
+ }
+ pInfo->pCurrSortHandle = NULL;
+ return TSDB_CODE_SUCCESS;
+}
+
+SSDataBlock* doGroupSort(SOperatorInfo* pOperator) {
+ if (pOperator->status == OP_EXEC_DONE) {
+ return NULL;
+ }
+
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SGroupSortOperatorInfo* pInfo = pOperator->info;
+
+ int32_t code = pOperator->fpSet._openFn(pOperator);
+ if (code != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, code);
+ }
+
+ if (!pInfo->hasGroupId) {
+ pInfo->hasGroupId = true;
+
+ pInfo->prefetchedSortInput = pOperator->pDownstream[0]->fpSet.getNextFn(pOperator->pDownstream[0]);
+ if (pInfo->prefetchedSortInput == NULL) {
+ doSetOperatorCompleted(pOperator);
+ return NULL;
+ }
+ pInfo->currGroupId = pInfo->prefetchedSortInput->info.groupId;
+ pInfo->childOpStatus = CHILD_OP_NEW_GROUP;
+ beginSortGroup(pOperator);
+ }
+
+ SSDataBlock* pBlock = NULL;
+ while (pInfo->pCurrSortHandle != NULL) {
+ // beginSortGroup would fetch all child blocks of pInfo->currGroupId;
+ ASSERT(pInfo->childOpStatus != CHILD_OP_SAME_GROUP);
+ pBlock = getGroupSortedBlockData(pInfo->pCurrSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity,
+ pInfo->pColMatchInfo, pInfo);
+ if (pBlock != NULL) {
+ pBlock->info.groupId = pInfo->currGroupId;
+ pOperator->resultInfo.totalRows += pBlock->info.rows;
+ return pBlock;
+ } else {
+ if (pInfo->childOpStatus == CHILD_OP_NEW_GROUP) {
+ finishSortGroup(pOperator);
+ pInfo->currGroupId = pInfo->prefetchedSortInput->info.groupId;
+ beginSortGroup(pOperator);
+ } else if (pInfo->childOpStatus == CHILD_OP_FINISHED) {
+ finishSortGroup(pOperator);
+ doSetOperatorCompleted(pOperator);
+ return NULL;
+ }
+ }
+ }
+ return NULL;
+}
+
+int32_t getGroupSortExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
+ SGroupSortOperatorInfo* pInfo = (SGroupSortOperatorInfo*)pOptr->info;
+ *pOptrExplain = &pInfo->sortExecInfo;
+ *len = sizeof(SSortExecInfo);
+ return TSDB_CODE_SUCCESS;
+}
+
+void destroyGroupSortOperatorInfo(void* param, int32_t numOfOutput) {
+ SGroupSortOperatorInfo* pInfo = (SGroupSortOperatorInfo*)param;
+ pInfo->binfo.pRes = blockDataDestroy(pInfo->binfo.pRes);
+
+ taosArrayDestroy(pInfo->pSortInfo);
+ taosArrayDestroy(pInfo->pColMatchInfo);
+
+ taosMemoryFreeClear(param);
+}
+
+SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSortPhysiNode* pSortPhyNode,
+ SExecTaskInfo* pTaskInfo) {
+ SGroupSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SGroupSortOperatorInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+ if (pInfo == NULL || pOperator == NULL /* || rowSize > 100 * 1024 * 1024*/) {
+ goto _error;
+ }
+
+ SDataBlockDescNode* pDescNode = pSortPhyNode->node.pOutputDataBlockDesc;
+
+ int32_t numOfCols = 0;
+ SSDataBlock* pResBlock = createResDataBlock(pDescNode);
+ SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols);
+
+ int32_t numOfOutputCols = 0;
+ SArray* pColMatchColInfo =
+ extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
+
+ pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset);
+ pInfo->binfo.pRes = pResBlock;
+
+ initResultSizeInfo(pOperator, 1024);
+
+ pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);
+ ;
+ pInfo->pColMatchInfo = pColMatchColInfo;
+ pOperator->name = "GroupSortOperator";
+ pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->exprSupp.pExprInfo = pExprInfo;
+ pOperator->exprSupp.numOfExprs = numOfCols;
+ pOperator->pTaskInfo = pTaskInfo;
+
+ pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doGroupSort, NULL, NULL, destroyGroupSortOperatorInfo,
+ NULL, NULL, getGroupSortExplainExecInfo);
+
+ int32_t code = appendDownstream(pOperator, &downstream, 1);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+
+ return pOperator;
+
+_error:
+ pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
+ taosMemoryFree(pInfo);
+ taosMemoryFree(pOperator);
+ return NULL;
+}
+
+//=====================================================================================
+// Multiway Sort Merge operator
+typedef struct SMultiwayMergeOperatorInfo {
SOptrBasicInfo binfo;
int32_t bufPageSize;
@@ -242,14 +522,17 @@ typedef struct SMultiwaySortMergeOperatorInfo {
SSortHandle* pSortHandle;
SArray* pColMatchInfo; // for index map from table scan output
- SSDataBlock* pInputBlock;
- int64_t startTs; // sort start time
- uint64_t groupId;
-} SMultiwaySortMergeOperatorInfo;
+ SSDataBlock* pInputBlock;
+ int64_t startTs; // sort start time
+ bool groupSort;
+ bool hasGroupId;
+ uint64_t groupId;
+ STupleHandle* prefetchedTuple;
+} SMultiwayMergeOperatorInfo;
-int32_t doOpenMultiwaySortMergeOperator(SOperatorInfo* pOperator) {
- SMultiwaySortMergeOperatorInfo* pInfo = pOperator->info;
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+int32_t doOpenMultiwayMergeOperator(SOperatorInfo* pOperator) {
+ SMultiwayMergeOperatorInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
if (OPTR_IS_OPENED(pOperator)) {
return TSDB_CODE_SUCCESS;
@@ -259,11 +542,13 @@ int32_t doOpenMultiwaySortMergeOperator(SOperatorInfo* pOperator) {
int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
- pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_MULTISOURCE_MERGE,
- pInfo->bufPageSize, numOfBufPage, pInfo->pInputBlock, pTaskInfo->id.str);
+ pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_MULTISOURCE_MERGE, pInfo->bufPageSize, numOfBufPage,
+ pInfo->pInputBlock, pTaskInfo->id.str);
tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock, NULL, NULL);
+ tsortSetCompareGroupId(pInfo->pSortHandle, pInfo->groupSort);
+
for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
ps->param = pOperator->pDownstream[i];
@@ -285,8 +570,8 @@ int32_t doOpenMultiwaySortMergeOperator(SOperatorInfo* pOperator) {
SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, int32_t capacity,
SArray* pColMatchInfo, SOperatorInfo* pOperator) {
- SMultiwaySortMergeOperatorInfo* pInfo = pOperator->info;
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SMultiwayMergeOperatorInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
blockDataCleanup(pDataBlock);
@@ -298,18 +583,49 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData
blockDataEnsureCapacity(p, capacity);
while (1) {
- STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
+ STupleHandle* pTupleHandle = NULL;
+ if (pInfo->groupSort) {
+ if (pInfo->prefetchedTuple == NULL) {
+ pTupleHandle = tsortNextTuple(pHandle);
+ } else {
+ pTupleHandle = pInfo->prefetchedTuple;
+ pInfo->groupId = tsortGetGroupId(pTupleHandle);
+ pInfo->prefetchedTuple = NULL;
+ }
+ }
+ else {
+ pTupleHandle = tsortNextTuple(pHandle);
+ pInfo->groupId = 0;
+ }
+
if (pTupleHandle == NULL) {
break;
}
- appendOneRowToDataBlock(p, pTupleHandle);
+ if (pInfo->groupSort) {
+ uint64_t tupleGroupId = tsortGetGroupId(pTupleHandle);
+ if (!pInfo->hasGroupId) {
+ pInfo->groupId = tupleGroupId;
+ pInfo->hasGroupId = true;
+ appendOneRowToDataBlock(p, pTupleHandle);
+ } else if (pInfo->groupId == tupleGroupId) {
+ appendOneRowToDataBlock(p, pTupleHandle);
+ } else {
+ pInfo->prefetchedTuple = pTupleHandle;
+ break;
+ }
+ } else {
+ appendOneRowToDataBlock(p, pTupleHandle);
+ }
if (p->info.rows >= capacity) {
break;
}
}
-
- if (p->info.rows > 0) {
+ if (pInfo->groupSort) {
+ pInfo->hasGroupId = false;
+ }
+ if (p->info.rows > 0) { // todo extract method
+ blockDataEnsureCapacity(pDataBlock, p->info.rows);
int32_t numOfCols = taosArrayGetSize(pColMatchInfo);
for (int32_t i = 0; i < numOfCols; ++i) {
SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, i);
@@ -317,11 +633,10 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData
SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId);
SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId);
- colDataAssign(pDst, pSrc, p->info.rows);
+ colDataAssign(pDst, pSrc, p->info.rows, &pDataBlock->info);
}
pDataBlock->info.rows = p->info.rows;
- pDataBlock->info.capacity = p->info.rows;
pDataBlock->info.groupId = pInfo->groupId;
}
@@ -331,13 +646,13 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData
return (pDataBlock->info.rows > 0) ? pDataBlock : NULL;
}
-SSDataBlock* doMultiwaySortMerge(SOperatorInfo* pOperator) {
+SSDataBlock* doMultiwayMerge(SOperatorInfo* pOperator) {
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
}
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SMultiwaySortMergeOperatorInfo* pInfo = pOperator->info;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SMultiwayMergeOperatorInfo* pInfo = pOperator->info;
int32_t code = pOperator->fpSet._openFn(pOperator);
if (code != TSDB_CODE_SUCCESS) {
@@ -346,7 +661,6 @@ SSDataBlock* doMultiwaySortMerge(SOperatorInfo* pOperator) {
SSDataBlock* pBlock = getMultiwaySortedBlockData(pInfo->pSortHandle, pInfo->binfo.pRes,
pOperator->resultInfo.capacity, pInfo->pColMatchInfo, pOperator);
-
if (pBlock != NULL) {
pOperator->resultInfo.totalRows += pBlock->info.rows;
} else {
@@ -355,20 +669,22 @@ SSDataBlock* doMultiwaySortMerge(SOperatorInfo* pOperator) {
return pBlock;
}
-void destroyMultiwaySortMergeOperatorInfo(void* param, int32_t numOfOutput) {
- SMultiwaySortMergeOperatorInfo* pInfo = (SMultiwaySortMergeOperatorInfo*)param;
+void destroyMultiwayMergeOperatorInfo(void* param, int32_t numOfOutput) {
+ SMultiwayMergeOperatorInfo* pInfo = (SMultiwayMergeOperatorInfo*)param;
pInfo->binfo.pRes = blockDataDestroy(pInfo->binfo.pRes);
pInfo->pInputBlock = blockDataDestroy(pInfo->pInputBlock);
taosArrayDestroy(pInfo->pSortInfo);
taosArrayDestroy(pInfo->pColMatchInfo);
+
+ taosMemoryFreeClear(param);
}
-int32_t getMultiwaySortMergeExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
+int32_t getMultiwayMergeExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
ASSERT(pOptr != NULL);
SSortExecInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortExecInfo));
- SMultiwaySortMergeOperatorInfo* pOperatorInfo = (SMultiwaySortMergeOperatorInfo*)pOptr->info;
+ SMultiwayMergeOperatorInfo* pOperatorInfo = (SMultiwayMergeOperatorInfo*)pOptr->info;
*pInfo = tsortGetSortExecInfo(pOperatorInfo->pSortHandle);
*pOptrExplain = pInfo;
@@ -376,39 +692,48 @@ int32_t getMultiwaySortMergeExplainExecInfo(SOperatorInfo* pOptr, void** pOptrEx
return TSDB_CODE_SUCCESS;
}
-SOperatorInfo* createMultiwaySortMergeOperatorInfo(SOperatorInfo** downStreams, int32_t numStreams,
- SSDataBlock* pInputBlock, SSDataBlock* pResBlock, SArray* pSortInfo,
- SArray* pColMatchColInfo, SExecTaskInfo* pTaskInfo) {
- SMultiwaySortMergeOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SMultiwaySortMergeOperatorInfo));
- SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
- int32_t rowSize = pResBlock->info.rowSize;
+SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** downStreams, size_t numStreams,
+ SMergePhysiNode* pMergePhyNode, SExecTaskInfo* pTaskInfo) {
+ SPhysiNode* pPhyNode = (SPhysiNode*)pMergePhyNode;
+
+ SMultiwayMergeOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SMultiwayMergeOperatorInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+ SDataBlockDescNode* pDescNode = pPhyNode->pOutputDataBlockDesc;
+ SSDataBlock* pResBlock = createResDataBlock(pDescNode);
+
+ int32_t rowSize = pResBlock->info.rowSize;
if (pInfo == NULL || pOperator == NULL || rowSize > 100 * 1024 * 1024) {
goto _error;
}
-
+ SArray* pSortInfo = createSortInfo(pMergePhyNode->pMergeKeys);
+ int32_t numOfOutputCols = 0;
+ SArray* pColMatchColInfo =
+ extractColMatchInfo(pMergePhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
+ SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, 0);
+ SSDataBlock* pInputBlock = createResDataBlock(pChildNode->pOutputDataBlockDesc);
initResultSizeInfo(pOperator, 1024);
- pInfo->binfo.pRes = pResBlock;
- pInfo->pSortInfo = pSortInfo;
+ pInfo->groupSort = pMergePhyNode->groupSort;
+ pInfo->binfo.pRes = pResBlock;
+ pInfo->pSortInfo = pSortInfo;
pInfo->pColMatchInfo = pColMatchColInfo;
- pInfo->pInputBlock = pInputBlock;
- pOperator->name = "MultiwaySortMerge";
+ pInfo->pInputBlock = pInputBlock;
+ pOperator->name = "MultiwayMerge";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
pOperator->pTaskInfo = pTaskInfo;
- pInfo->bufPageSize = getProperSortPageSize(rowSize);
+ pInfo->bufPageSize = getProperSortPageSize(rowSize);
// one additional is reserved for merged result.
- pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1);
+ pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1);
- pOperator->fpSet =
- createOperatorFpSet(doOpenMultiwaySortMergeOperator, doMultiwaySortMerge, NULL, NULL,
- destroyMultiwaySortMergeOperatorInfo, NULL, NULL, getMultiwaySortMergeExplainExecInfo);
+ pOperator->fpSet = createOperatorFpSet(doOpenMultiwayMergeOperator, doMultiwayMerge, NULL, NULL,
+ destroyMultiwayMergeOperatorInfo, NULL, NULL, getMultiwayMergeExplainExecInfo);
int32_t code = appendDownstream(pOperator, downStreams, numStreams);
if (code != TSDB_CODE_SUCCESS) {
@@ -421,4 +746,4 @@ _error:
taosMemoryFree(pInfo);
taosMemoryFree(pOperator);
return NULL;
-}
\ No newline at end of file
+}
diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c
index 110c2d6a8f896ee040d03402780564e44df3216b..e0bdcfdc3a6a744c9f67e1d466e05be8bd30c4f5 100644
--- a/source/libs/executor/src/tfill.c
+++ b/source/libs/executor/src/tfill.c
@@ -14,6 +14,7 @@
*/
#include "os.h"
+#include "query.h"
#include "taosdef.h"
#include "tmsg.h"
#include "ttypes.h"
@@ -48,11 +49,15 @@ static void setTagsValue(SFillInfo* pFillInfo, void** data, int32_t genRows) {
}
}
-static void setNullRow(SSDataBlock* pBlock, int32_t numOfCol, int32_t rowIndex) {
+static void setNullRow(SSDataBlock* pBlock, int64_t ts, int32_t rowIndex) {
// the first are always the timestamp column, so start from the second column.
- for (int32_t i = 1; i < pBlock->info.numOfCols; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, i);
- colDataAppendNULL(p, rowIndex);
+ if (p->info.type == TSDB_DATA_TYPE_TIMESTAMP) { // handle timestamp
+ colDataAppend(p, rowIndex, (const char*)&ts, false);
+ } else {
+ colDataAppendNULL(p, rowIndex);
+ }
}
}
@@ -61,70 +66,81 @@ static void setNullRow(SSDataBlock* pBlock, int32_t numOfCol, int32_t rowIndex)
static void doSetVal(SColumnInfoData* pDstColInfoData, int32_t rowIndex, const SGroupKeys* pKey);
-static void doFillOneRowResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* pSrcBlock, int64_t ts,
- bool outOfBound) {
+static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* pSrcBlock, int64_t ts,
+ bool outOfBound) {
SPoint point1, point2, point;
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pFillInfo->order);
- // set the primary timestamp column value
- int32_t index = pFillInfo->numOfCurrent;
- SColumnInfoData* pCol0 = taosArrayGet(pBlock->pDataBlock, 0);
- char* val = colDataGetData(pCol0, index);
-
- *(TSKEY*)val = pFillInfo->currentKey;
+// set the primary timestamp column value
+ int32_t index = pFillInfo->numOfCurrent;
// set the other values
if (pFillInfo->type == TSDB_FILL_PREV) {
SArray* p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->prev : pFillInfo->next;
- for (int32_t i = 1; i < pFillInfo->numOfCols; ++i) {
+ for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
SFillColInfo* pCol = &pFillInfo->pFillCol[i];
if (TSDB_COL_IS_TAG(pCol->flag)) {
continue;
}
- SGroupKeys* pKey = taosArrayGet(p, i);
SColumnInfoData* pDstColInfoData = taosArrayGet(pBlock->pDataBlock, GET_DEST_SLOT_ID(pCol));
- doSetVal(pDstColInfoData, index, pKey);
+
+ if (pDstColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
+ colDataAppend(pDstColInfoData, index, (const char*)&pFillInfo->currentKey, false);
+ } else {
+ SGroupKeys* pKey = taosArrayGet(p, i);
+ doSetVal(pDstColInfoData, index, pKey);
+ }
}
} else if (pFillInfo->type == TSDB_FILL_NEXT) {
SArray* p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->next : pFillInfo->prev;
-
- for (int32_t i = 1; i < pFillInfo->numOfCols; ++i) {
+ // todo refactor: start from 0 not 1
+ for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
SFillColInfo* pCol = &pFillInfo->pFillCol[i];
if (TSDB_COL_IS_TAG(pCol->flag)) {
continue;
}
- SGroupKeys* pKey = taosArrayGet(p, i);
SColumnInfoData* pDstColInfoData = taosArrayGet(pBlock->pDataBlock, GET_DEST_SLOT_ID(pCol));
- doSetVal(pDstColInfoData, index, pKey);
+
+ if (pDstColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
+ colDataAppend(pDstColInfoData, index, (const char*)&pFillInfo->currentKey, false);
+ } else {
+ SGroupKeys* pKey = taosArrayGet(p, i);
+ doSetVal(pDstColInfoData, index, pKey);
+ }
}
} else if (pFillInfo->type == TSDB_FILL_LINEAR) {
// TODO : linear interpolation supports NULL value
if (outOfBound) {
- setNullRow(pBlock, pFillInfo->numOfCols, index);
+ setNullRow(pBlock, pFillInfo->currentKey, index);
} else {
- for (int32_t i = 1; i < pFillInfo->numOfCols; ++i) {
+ for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
SFillColInfo* pCol = &pFillInfo->pFillCol[i];
if (TSDB_COL_IS_TAG(pCol->flag)) {
continue;
}
- int32_t srcSlotId = GET_SRC_SLOT_ID(pCol);
-
int32_t dstSlotId = GET_DEST_SLOT_ID(pCol);
SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
- int16_t type = pCol->pExpr->base.resSchema.type;
+ int16_t type = pDstCol->info.type;
+ if (type == TSDB_DATA_TYPE_TIMESTAMP) {
+ colDataAppend(pDstCol, index, (const char*)&pFillInfo->currentKey, false);
+ continue;
+ }
+
SGroupKeys* pKey = taosArrayGet(pFillInfo->prev, i);
if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || pKey->isNull) {
colDataAppendNULL(pDstCol, index);
continue;
}
- SGroupKeys* pKey1 = taosArrayGet(pFillInfo->prev, 0);
- int64_t prevTs = *(int64_t*)pKey1->pData;
+ SGroupKeys* pKey1 = taosArrayGet(pFillInfo->prev, pFillInfo->tsSlotId);
+
+ int64_t prevTs = *(int64_t*)pKey1->pData;
+ int32_t srcSlotId = GET_SRC_SLOT_ID(pCol);
SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
char* data = colDataGetData(pSrcCol, pFillInfo->index);
@@ -140,9 +156,9 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSData
}
}
} else if (pFillInfo->type == TSDB_FILL_NULL) { // fill with NULL
- setNullRow(pBlock, pFillInfo->numOfCols, index);
+ setNullRow(pBlock, pFillInfo->currentKey, index);
} else { // fill with user specified value for each column
- for (int32_t i = 1; i < pFillInfo->numOfCols; ++i) {
+ for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
SFillColInfo* pCol = &pFillInfo->pFillCol[i];
if (TSDB_COL_IS_TAG(pCol->flag) /* || IS_VAR_DATA_TYPE(pCol->schema.type)*/) {
continue;
@@ -163,6 +179,10 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSData
int64_t v = 0;
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
colDataAppend(pDst, index, (char*)&v, false);
+ } else if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
+ colDataAppend(pDst, index, (const char*)&pFillInfo->currentKey, false);
+ } else { // varchar/nchar data
+ colDataAppendNULL(pDst, index);
}
}
}
@@ -221,8 +241,7 @@ static void copyCurrentRowIntoBuf(SFillInfo* pFillInfo, int32_t rowIndex, SArray
static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t outputRows) {
pFillInfo->numOfCurrent = 0;
- // todo make sure the first column is always the primary timestamp column?
- SColumnInfoData* pTsCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, 0);
+ SColumnInfoData* pTsCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, pFillInfo->tsSlotId);
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pFillInfo->order);
bool ascFill = FILL_IS_ASC_FILL(pFillInfo);
@@ -244,7 +263,7 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t
// fill the gap between two input rows
while (((pFillInfo->currentKey < ts && ascFill) || (pFillInfo->currentKey > ts && !ascFill)) &&
pFillInfo->numOfCurrent < outputRows) {
- doFillOneRowResult(pFillInfo, pBlock, pFillInfo->pSrcBlock, ts, false);
+ doFillOneRow(pFillInfo, pBlock, pFillInfo->pSrcBlock, ts, false);
}
// output buffer is full, abort
@@ -256,9 +275,8 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t
assert(pFillInfo->currentKey == ts);
if (pFillInfo->type == TSDB_FILL_NEXT && (pFillInfo->index + 1) < pFillInfo->numOfRows) {
- ++pFillInfo->index;
- copyCurrentRowIntoBuf(pFillInfo, pFillInfo->index, pFillInfo->next);
- --pFillInfo->index;
+ int32_t nextRowIndex = pFillInfo->index + 1;
+ copyCurrentRowIntoBuf(pFillInfo, nextRowIndex, pFillInfo->next);
}
// assign rows to dst buffer
@@ -340,7 +358,7 @@ static int64_t appendFilledResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, int
*/
pFillInfo->numOfCurrent = 0;
while (pFillInfo->numOfCurrent < resultCapacity) {
- doFillOneRowResult(pFillInfo, pBlock, pFillInfo->pSrcBlock, pFillInfo->start, true);
+ doFillOneRow(pFillInfo, pBlock, pFillInfo->pSrcBlock, pFillInfo->start, true);
}
pFillInfo->numOfTotal += pFillInfo->numOfCurrent;
@@ -405,7 +423,7 @@ static int32_t taosNumOfRemainRows(SFillInfo* pFillInfo) {
}
struct SFillInfo* taosCreateFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int32_t capacity, int32_t numOfCols,
- SInterval* pInterval, int32_t fillType, struct SFillColInfo* pCol,
+ SInterval* pInterval, int32_t fillType, struct SFillColInfo* pCol, int32_t primaryTsSlotId,
const char* id) {
if (fillType == TSDB_FILL_NONE) {
return NULL;
@@ -417,6 +435,8 @@ struct SFillInfo* taosCreateFillInfo(int32_t order, TSKEY skey, int32_t numOfTag
return NULL;
}
+ pFillInfo->tsSlotId = primaryTsSlotId;
+
taosResetFillInfo(pFillInfo, skey);
pFillInfo->order = order;
@@ -586,11 +606,10 @@ int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, SSDataBlock* p, int32_t ca
assert(numOfRes == pFillInfo->numOfCurrent);
}
- // qDebug("fill:%p, generated fill result, src block:%d, index:%d, brange:%"PRId64"-%"PRId64", currentKey:%"PRId64",
- // current:%d, total:%d, %p",
- // pFillInfo, pFillInfo->numOfRows, pFillInfo->index, pFillInfo->start, pFillInfo->end, pFillInfo->currentKey,
- // pFillInfo->numOfCurrent,
- // pFillInfo->numOfTotal, pFillInfo->handle);
+ qDebug("fill:%p, generated fill result, src block:%d, index:%d, brange:%" PRId64 "-%" PRId64 ", currentKey:%" PRId64
+ ", current : % d, total : % d, %s", pFillInfo,
+ pFillInfo->numOfRows, pFillInfo->index, pFillInfo->start, pFillInfo->end, pFillInfo->currentKey,
+ pFillInfo->numOfCurrent, pFillInfo->numOfTotal, pFillInfo->id);
return numOfRes;
}
diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c
index 63285daa3a068fe3e66d39690c7bacf423cb758f..74b5a3dab202bed509fc5fde773ca207fce71285 100644
--- a/source/libs/executor/src/timewindowoperator.c
+++ b/source/libs/executor/src/timewindowoperator.c
@@ -15,9 +15,10 @@
#include "executorimpl.h"
#include "function.h"
#include "functionMgt.h"
+#include "tcompare.h"
#include "tdatablock.h"
-#include "ttime.h"
#include "tfill.h"
+#include "ttime.h"
typedef enum SResultTsInterpType {
RESULT_ROW_START_INTERP = 1,
@@ -26,6 +27,16 @@ typedef enum SResultTsInterpType {
#define IS_FINAL_OP(op) ((op)->isFinal)
+typedef struct SWinRes {
+ TSKEY ts;
+ uint64_t groupId;
+} SWinRes;
+
+typedef struct SPullWindowInfo {
+ STimeWindow window;
+ uint64_t groupId;
+} SPullWindowInfo;
+
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator);
static int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo);
@@ -42,67 +53,12 @@ static void doCloseWindow(SResultRowInfo* pResultRowInfo, const SIntervalAggOper
// * merged during merge stage. In this case, we need the pTableQueryInfo->lastResRows to decide if there
// * is a previous result generated or not.
// */
-//static void setIntervalQueryRange(STableQueryInfo* pTableQueryInfo, TSKEY key, STimeWindow* pQRange) {
+// static void setIntervalQueryRange(STableQueryInfo* pTableQueryInfo, TSKEY key, STimeWindow* pQRange) {
// // do nothing
//}
static TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols) { return tsCols == NULL ? win->skey : tsCols[0]; }
-static void getInitialStartTimeWindow(SInterval* pInterval, int32_t precision, TSKEY ts, STimeWindow* w,
- bool ascQuery) {
- if (ascQuery) {
- getAlignQueryTimeWindow(pInterval, precision, ts, w);
- } else {
- // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
- getAlignQueryTimeWindow(pInterval, precision, ts, w);
-
- int64_t key = w->skey;
- while (key < ts) { // moving towards end
- key = taosTimeAdd(key, pInterval->sliding, pInterval->slidingUnit, precision);
- if (key >= ts) {
- break;
- }
-
- w->skey = key;
- }
- }
-}
-
-// get the correct time window according to the handled timestamp
-STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval,
- int32_t precision, STimeWindow* win) {
- STimeWindow w = {0};
-
- if (pResultRowInfo->cur.pageId == -1) { // the first window, from the previous stored value
- getInitialStartTimeWindow(pInterval, precision, ts, &w, true);
- w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
- } else {
- w = getResultRowByPos(pBuf, &pResultRowInfo->cur)->win;
- }
-
- if (w.skey > ts || w.ekey < ts) {
- if (pInterval->intervalUnit == 'n' || pInterval->intervalUnit == 'y') {
- w.skey = taosTimeTruncate(ts, pInterval, precision);
- w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
- } else {
- int64_t st = w.skey;
-
- if (st > ts) {
- st -= ((st - ts + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
- }
-
- int64_t et = st + pInterval->interval - 1;
- if (et < ts) {
- st += ((ts - et + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
- }
-
- w.skey = st;
- w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
- }
- }
- return w;
-}
-
static int32_t setTimeWindowOutputBuf(SResultRowInfo* pResultRowInfo, STimeWindow* win, bool masterscan,
SResultRow** pResult, int64_t tableGroupId, SqlFunctionCtx* pCtx,
int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup,
@@ -314,18 +270,18 @@ static void getNextTimeWindow(SInterval* pInterval, int32_t precision, int32_t o
int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
- tw->skey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, precision);
+ tw->skey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000LL, TSDB_TIME_PRECISION_MILLI, precision);
mon = (int)(mon + interval);
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
- tw->ekey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, precision);
+ tw->ekey = convertTimePrecision((int64_t)taosMktime(&tm) * 1000LL, TSDB_TIME_PRECISION_MILLI, precision);
tw->ekey -= 1;
}
-void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex,
- TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type, SExprSupp* pSup) {
+void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY curTs,
+ int32_t curRowIndex, TSKEY windowKey, int32_t type, SExprSupp* pSup) {
SqlFunctionCtx* pCtx = pSup->pCtx;
int32_t index = 1;
@@ -405,8 +361,8 @@ static void setNotInterpoWindowKey(SqlFunctionCtx* pCtx, int32_t numOfOutput, in
}
}
-static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, int32_t pos, SSDataBlock* pBlock, const TSKEY* tsCols,
- STimeWindow* win, SExprSupp* pSup) {
+static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, int32_t pos, SSDataBlock* pBlock,
+ const TSKEY* tsCols, STimeWindow* win, SExprSupp* pSup) {
bool ascQuery = (pInfo->order == TSDB_ORDER_ASC);
TSKEY curTs = tsCols[pos];
@@ -434,9 +390,9 @@ static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, i
return true;
}
-static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SExprSupp* pSup,
- int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols,
- TSKEY blockEkey, STimeWindow* win) {
+static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SExprSupp* pSup, int32_t endRowIndex,
+ SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey,
+ STimeWindow* win) {
int32_t order = pInfo->order;
TSKEY actualEndKey = tsCols[endRowIndex];
@@ -463,6 +419,14 @@ static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SEx
return true;
}
+bool inSlidingWindow(SInterval* pInterval, STimeWindow* pWin, SDataBlockInfo* pBlockInfo) {
+ if (pInterval->interval != pInterval->sliding &&
+ (pWin->ekey < pBlockInfo->calWin.skey || pWin->skey > pBlockInfo->calWin.ekey)) {
+ return false;
+ }
+ return true;
+}
+
static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
TSKEY* primaryKeys, int32_t prevPosition, int32_t order) {
bool ascQuery = (order == TSDB_ORDER_ASC);
@@ -476,6 +440,10 @@ static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext,
return -1;
}
+ if (!inSlidingWindow(pInterval, pNext, pDataBlockInfo) && order == TSDB_ORDER_ASC) {
+ return -1;
+ }
+
TSKEY skey = ascQuery ? pNext->skey : pNext->ekey;
int32_t startPos = 0;
@@ -548,8 +516,8 @@ static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) {
}
}
-static void doWindowBorderInterpolation(SIntervalAggOperatorInfo* pInfo, SSDataBlock* pBlock, SResultRow* pResult, STimeWindow* win, int32_t startPos,
- int32_t forwardRows, SExprSupp* pSup) {
+static void doWindowBorderInterpolation(SIntervalAggOperatorInfo* pInfo, SSDataBlock* pBlock, SResultRow* pResult,
+ STimeWindow* win, int32_t startPos, int32_t forwardRows, SExprSupp* pSup) {
if (!pInfo->timeWindowInterpo) {
return;
}
@@ -628,7 +596,7 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
- SExprSupp* pSup = &pOperatorInfo->exprSupp;
+ SExprSupp* pSup = &pOperatorInfo->exprSupp;
int32_t startPos = 0;
int32_t numOfOutput = pSup->numOfExprs;
@@ -655,9 +623,8 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num
}
STimeWindow w = pr->win;
- int32_t ret =
- setTimeWindowOutputBuf(pResultRowInfo, &w, (scanFlag == MAIN_SCAN), &pResult, groupId, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &w, (scanFlag == MAIN_SCAN), &pResult, groupId, pSup->pCtx,
+ numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
@@ -672,8 +639,8 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num
setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
setNotInterpoWindowKey(pSup->pCtx, numOfExprs, RESULT_ROW_START_INTERP);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &w, &pInfo->twAggSup.timeWindowData, startPos, 0, tsCols,
- pBlock->info.rows, numOfExprs, pInfo->order);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &w, &pInfo->twAggSup.timeWindowData, startPos, 0, tsCols, pBlock->info.rows,
+ numOfExprs, pInfo->order);
if (isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) {
closeResultRow(pr);
@@ -685,10 +652,13 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num
}
void printDataBlock(SSDataBlock* pBlock, const char* flag) {
- SArray* blocks = taosArrayInit(1, sizeof(SSDataBlock));
- taosArrayPush(blocks, pBlock);
- blockDebugShowData(blocks, flag);
- taosArrayDestroy(blocks);
+ if (pBlock == NULL) {
+ qDebug("======printDataBlock Block is Null");
+ return;
+ }
+ char* pBuf = NULL;
+ qDebug("%s", dumpBlockData(pBlock, flag, &pBuf));
+ taosMemoryFree(pBuf);
}
typedef int64_t (*__get_value_fn_t)(void* data, int32_t index);
@@ -753,8 +723,7 @@ int64_t getReskey(void* data, int32_t index) {
return *(int64_t*)pos->key;
}
-static int32_t saveResult(int64_t ts, int32_t pageId, int32_t offset, uint64_t groupId,
- SArray* pUpdated) {
+static int32_t saveResult(int64_t ts, int32_t pageId, int32_t offset, uint64_t groupId, SArray* pUpdated) {
int32_t size = taosArrayGetSize(pUpdated);
int32_t index = binarySearch(pUpdated, size, ts, TSDB_ORDER_DESC, getReskey);
if (index == -1) {
@@ -796,17 +765,43 @@ static void removeResult(SArray* pUpdated, TSKEY key) {
static void removeResults(SArray* pWins, SArray* pUpdated) {
int32_t size = taosArrayGetSize(pWins);
for (int32_t i = 0; i < size; i++) {
- STimeWindow* pW = taosArrayGet(pWins, i);
- removeResult(pUpdated, pW->skey);
+ SWinRes* pW = taosArrayGet(pWins, i);
+ removeResult(pUpdated, pW->ts);
+ }
+}
+
+int64_t getWinReskey(void* data, int32_t index) {
+ SArray* res = (SArray*)data;
+ SWinRes* pos = taosArrayGet(res, index);
+ return pos->ts;
+}
+
+static void removeDeleteResults(SArray* pUpdated, SArray* pDelWins) {
+ int32_t upSize = taosArrayGetSize(pUpdated);
+ int32_t delSize = taosArrayGetSize(pDelWins);
+ for (int32_t i = 0; i < upSize; i++) {
+ SResKeyPos* pResKey = taosArrayGetP(pUpdated, i);
+ int64_t key = *(int64_t*)pResKey->key;
+ int32_t index = binarySearch(pDelWins, delSize, key, TSDB_ORDER_DESC, getWinReskey);
+ if (index >= 0 && key == getWinReskey(pDelWins, index)) {
+ taosArrayRemove(pDelWins, index);
+ }
}
}
+bool isOverdue(TSKEY ts, STimeWindowAggSupp* pSup) {
+ ASSERT(pSup->maxTs == INT64_MIN || pSup->maxTs > 0);
+ return pSup->maxTs != INT64_MIN && ts < pSup->maxTs - pSup->waterMark;
+}
+
+bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pSup) { return isOverdue(pWin->ekey, pSup); }
+
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
int32_t scanFlag, SArray* pUpdated) {
SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
- SExprSupp* pSup = &pOperatorInfo->exprSupp;
+ SExprSupp* pSup = &pOperatorInfo->exprSupp;
int32_t startPos = 0;
int32_t numOfOutput = pSup->numOfExprs;
@@ -816,18 +811,17 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
TSKEY ts = getStartTsKey(&pBlock->info.window, tsCols);
SResultRow* pResult = NULL;
- STimeWindow win = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval,
- pInfo->interval.precision, &pInfo->win);
-
- int32_t ret =
- setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
- if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
- longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
+ STimeWindow win = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, pInfo->order);
+ int32_t ret = TSDB_CODE_SUCCESS;
+ if ((!pInfo->ignoreExpiredData || !isCloseWindow(&win, &pInfo->twAggSup)) &&
+ inSlidingWindow(&pInfo->interval, &win, &pBlock->info)) {
+ ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
+ numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
+ longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
- if (pInfo->execModel == OPTR_EXEC_MODEL_STREAM) {
- if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
+ if (pInfo->execModel == OPTR_EXEC_MODEL_STREAM && pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
saveResultRow(pResult, tableGroupId, pUpdated);
}
}
@@ -843,9 +837,8 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);
// restore current time window
- ret =
- setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
+ numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
@@ -854,9 +847,12 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
doWindowBorderInterpolation(pInfo, pBlock, pResult, &win, startPos, forwardRows, pSup);
}
- updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &win, true);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &win, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
- pBlock->info.rows, numOfOutput, pInfo->order);
+ if ((!pInfo->ignoreExpiredData || !isCloseWindow(&win, &pInfo->twAggSup)) &&
+ inSlidingWindow(&pInfo->interval, &win, &pBlock->info)) {
+ updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &win, true);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &win, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pBlock->info.rows, numOfOutput, pInfo->order);
+ }
doCloseWindow(pResultRowInfo, pInfo, pResult);
@@ -867,19 +863,22 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
if (startPos < 0) {
break;
}
+ if (pInfo->ignoreExpiredData && isCloseWindow(&nextWin, &pInfo->twAggSup)) {
+ ekey = ascScan ? nextWin.ekey : nextWin.skey;
+ forwardRows =
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->order);
+ continue;
+ }
// null data, failed to allocate more memory buffer
int32_t code = setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
- pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset,
- &pInfo->aggSup, pTaskInfo);
+ pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- if (pInfo->execModel == OPTR_EXEC_MODEL_STREAM) {
- if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
- saveResultRow(pResult, tableGroupId, pUpdated);
- }
+ if (pInfo->execModel == OPTR_EXEC_MODEL_STREAM && pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
+ saveResultRow(pResult, tableGroupId, pUpdated);
}
ekey = ascScan ? nextWin.ekey : nextWin.skey;
@@ -890,8 +889,8 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
doWindowBorderInterpolation(pInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pSup);
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
- tsCols, pBlock->info.rows, numOfOutput, pInfo->order);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pBlock->info.rows, numOfOutput, pInfo->order);
doCloseWindow(pResultRowInfo, pInfo, pResult);
}
@@ -960,24 +959,14 @@ static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
getTableScanInfo(pOperator, &pInfo->order, &scanFlag);
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
+
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pSup->pCtx, pBlock, pInfo->order, scanFlag, true);
hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, scanFlag, NULL);
-
-#if 0 // test for encode/decode result info
- if(pOperator->fpSet.encodeResultRow){
- char *result = NULL;
- int32_t length = 0;
- SAggSupporter *pSup = &pInfo->aggSup;
- pOperator->fpSet.encodeResultRow(pOperator, &result, &length);
- taosHashClear(pSup->pResultRowHashTable);
- pInfo->binfo.resultRowInfo.size = 0;
- pOperator->fpSet.decodeResultRow(pOperator, result);
- if(result){
- taosMemoryFree(result);
- }
- }
-#endif
}
closeAllResultRows(&pInfo->binfo.resultRowInfo);
@@ -1002,7 +991,7 @@ static bool compareVal(const char* v, const SStateKeys* pKey) {
static void doStateWindowAggImpl(SOperatorInfo* pOperator, SStateWindowOperatorInfo* pInfo, SSDataBlock* pBlock) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SColumnInfoData* pStateColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->stateCol.slotId);
int64_t gid = pBlock->info.groupId;
@@ -1050,9 +1039,8 @@ static void doStateWindowAggImpl(SOperatorInfo* pOperator, SStateWindowOperatorI
STimeWindow window = pRowSup->win;
pRowSup->win.ekey = pRowSup->win.skey;
- int32_t ret =
- setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
+ numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
longjmp(pTaskInfo->env, TSDB_CODE_QRY_APP_ERROR);
}
@@ -1076,9 +1064,8 @@ static void doStateWindowAggImpl(SOperatorInfo* pOperator, SStateWindowOperatorI
SResultRow* pResult = NULL;
pRowSup->win.ekey = tsList[pBlock->info.rows - 1];
- int32_t ret =
- setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid,
+ pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
longjmp(pTaskInfo->env, TSDB_CODE_QRY_APP_ERROR);
}
@@ -1095,19 +1082,28 @@ static SSDataBlock* doStateWindowAgg(SOperatorInfo* pOperator) {
SStateWindowOperatorInfo* pInfo = pOperator->info;
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SExprSupp* pSup = &pOperator->exprSupp;
SOptrBasicInfo* pBInfo = &pInfo->binfo;
if (pOperator->status == OP_RES_TO_RETURN) {
- doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
- if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
- return NULL;
- }
+ while (1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pBInfo->pRes);
- return pBInfo->pRes;
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (pBInfo->pRes->info.rows > 0) {
+ break;
+ }
+ }
+ pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
+ return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
}
int32_t order = TSDB_ORDER_ASC;
@@ -1133,15 +1129,22 @@ static SSDataBlock* doStateWindowAgg(SOperatorInfo* pOperator) {
initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, TSDB_ORDER_ASC);
blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
- doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
- if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
- }
+ while (1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pBInfo->pRes);
- size_t rows = pBInfo->pRes->info.rows;
- pOperator->resultInfo.totalRows += rows;
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
- return (rows == 0) ? NULL : pBInfo->pRes;
+ if (pBInfo->pRes->info.rows > 0) {
+ break;
+ }
+ }
+ pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
+ return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
}
static SSDataBlock* doBuildIntervalResult(SOperatorInfo* pOperator) {
@@ -1163,10 +1166,19 @@ static SSDataBlock* doBuildIntervalResult(SOperatorInfo* pOperator) {
}
blockDataEnsureCapacity(pBlock, pOperator->resultInfo.capacity);
- doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ while (1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pBlock);
- if (pBlock->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (pBlock->info.rows > 0) {
+ break;
+ }
}
size_t rows = pBlock->info.rows;
@@ -1207,7 +1219,7 @@ static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type
}
}
-void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf, SExprSupp *pSup, int32_t numOfOutput) {
+void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf, SExprSupp* pSup, int32_t numOfOutput) {
SResultRow* pResult = getResultRowByPos(pResultBuf, p1);
SqlFunctionCtx* pCtx = pSup->pCtx;
for (int32_t i = 0; i < numOfOutput; ++i) {
@@ -1221,33 +1233,83 @@ void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf, SExprS
pCtx[i].fpSet.init(&pCtx[i], pResInfo);
}
}
+ SFilePage* bufPage = getBufPage(pResultBuf, p1->pageId);
+ setBufPageDirty(bufPage, true);
+ releaseBufPage(pResultBuf, bufPage);
}
-void doClearWindow(SAggSupporter* pAggSup, SExprSupp *pSup, char* pData, int16_t bytes, uint64_t groupId,
+bool doClearWindow(SAggSupporter* pAggSup, SExprSupp* pSup, char* pData, int16_t bytes, uint64_t groupId,
int32_t numOfOutput) {
SET_RES_WINDOW_KEY(pAggSup->keyBuf, pData, bytes, groupId);
SResultRowPosition* p1 =
(SResultRowPosition*)taosHashGet(pAggSup->pResultRowHashTable, pAggSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
if (!p1) {
// window has been closed
- return;
+ return false;
}
doClearWindowImpl(p1, pAggSup->pResultBuf, pSup, numOfOutput);
+ return true;
}
-static void doClearWindows(SAggSupporter* pAggSup, SExprSupp* pSup1, SInterval* pInterval, int32_t tsIndex,
- int32_t numOfOutput, SSDataBlock* pBlock, SArray* pUpWins) {
- SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, tsIndex);
- TSKEY* tsCols = (TSKEY*)pColDataInfo->pData;
- int32_t step = 0;
- for (int32_t i = 0; i < pBlock->info.rows; i += step) {
+bool doDeleteIntervalWindow(SAggSupporter* pAggSup, TSKEY ts, uint64_t groupId) {
+ size_t bytes = sizeof(TSKEY);
+ SET_RES_WINDOW_KEY(pAggSup->keyBuf, &ts, bytes, groupId);
+ SResultRowPosition* p1 =
+ (SResultRowPosition*)taosHashGet(pAggSup->pResultRowHashTable, pAggSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
+ if (!p1) {
+ // window has been closed
+ return false;
+ }
+ // SFilePage* bufPage = getBufPage(pAggSup->pResultBuf, p1->pageId);
+ // dBufSetBufPageRecycled(pAggSup->pResultBuf, bufPage);
+ taosHashRemove(pAggSup->pResultRowHashTable, pAggSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
+ return true;
+}
+
+void doDeleteSpecifyIntervalWindow(SAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* pUpWins, SInterval* pInterval) {
+ SColumnInfoData* pStartCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* tsStarts = (TSKEY*)pStartCol->pData;
+ SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
+ uint64_t* groupIds = (uint64_t*)pGroupCol->pData;
+ for (int32_t i = 0; i < pBlock->info.rows; i++) {
SResultRowInfo dumyInfo;
dumyInfo.cur.pageId = -1;
- STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, tsCols[i], pInterval, pInterval->precision, NULL);
- step = getNumOfRowsInTimeWindow(&pBlock->info, tsCols, i, win.ekey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
- doClearWindow(pAggSup, pSup1, (char*)&win.skey, sizeof(TKEY), pBlock->info.groupId, numOfOutput);
+ STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, tsStarts[i], pInterval, TSDB_ORDER_ASC);
+ doDeleteIntervalWindow(pAggSup, win.skey, groupIds[i]);
if (pUpWins) {
- taosArrayPush(pUpWins, &win);
+ SWinRes winRes = {.ts = win.skey, .groupId = groupIds[i]};
+ taosArrayPush(pUpWins, &winRes);
+ }
+ }
+}
+
+static void doClearWindows(SAggSupporter* pAggSup, SExprSupp* pSup1, SInterval* pInterval, int32_t numOfOutput,
+ SSDataBlock* pBlock, SArray* pUpWins) {
+ SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* tsCols = (TSKEY*)pTsCol->pData;
+ uint64_t* pGpDatas = NULL;
+ if (pBlock->info.type == STREAM_RETRIEVE) {
+ SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
+ pGpDatas = (uint64_t*)pGpCol->pData;
+ }
+ int32_t step = 0;
+ int32_t startPos = 0;
+ SResultRowInfo dumyInfo;
+ dumyInfo.cur.pageId = -1;
+ STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, tsCols[0], pInterval, TSDB_ORDER_ASC);
+ while (1) {
+ step =
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, win.ekey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
+ uint64_t winGpId = pGpDatas ? pGpDatas[startPos] : pBlock->info.groupId;
+ bool res = doClearWindow(pAggSup, pSup1, (char*)&win.skey, sizeof(TSKEY), winGpId, numOfOutput);
+ if (pUpWins && res) {
+ SWinRes winRes = {.ts = win.skey, .groupId = winGpId};
+ taosArrayPush(pUpWins, &winRes);
+ }
+ int32_t prevEndPos = step - 1 + startPos;
+ startPos = getNextQualifiedWindow(pInterval, &win, &pBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
+ if (startPos < 0) {
+ break;
}
}
}
@@ -1259,9 +1321,9 @@ static int32_t getAllIntervalWindow(SHashObj* pHashMap, SArray* resWins) {
void* key = taosHashGetKey(pIte, &keyLen);
uint64_t groupId = *(uint64_t*)key;
ASSERT(keyLen == GET_RES_WINDOW_KEY_LEN(sizeof(TSKEY)));
- TSKEY ts = *(int64_t*)((char*)key + sizeof(uint64_t));
+ TSKEY ts = *(int64_t*)((char*)key + sizeof(uint64_t));
SResultRowPosition* pPos = (SResultRowPosition*)pIte;
- int32_t code = saveResult(ts, pPos->pageId, pPos->offset, groupId, resWins);
+ int32_t code = saveResult(ts, pPos->pageId, pPos->offset, groupId, resWins);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@@ -1269,12 +1331,9 @@ static int32_t getAllIntervalWindow(SHashObj* pHashMap, SArray* resWins) {
return TSDB_CODE_SUCCESS;
}
-bool isCloseWindow(STimeWindow *pWin, STimeWindowAggSupp* pSup) {
- return pWin->ekey < pSup->maxTs - pSup->waterMark;
-}
-
static int32_t closeIntervalWindow(SHashObj* pHashMap, STimeWindowAggSupp* pSup, SInterval* pInterval,
- SArray* closeWins) {
+ SHashObj* pPullDataMap, SArray* closeWins, SArray* pRecyPages,
+ SDiskbasedBuf* pDiscBuf) {
void* pIte = NULL;
size_t keyLen = 0;
while ((pIte = taosHashIterate(pHashMap, pIte)) != NULL) {
@@ -1282,25 +1341,88 @@ static int32_t closeIntervalWindow(SHashObj* pHashMap, STimeWindowAggSupp* pSup,
uint64_t groupId = *(uint64_t*)key;
ASSERT(keyLen == GET_RES_WINDOW_KEY_LEN(sizeof(TSKEY)));
TSKEY ts = *(int64_t*)((char*)key + sizeof(uint64_t));
- SResultRowInfo dumyInfo;
- dumyInfo.cur.pageId = -1;
- STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, ts, pInterval, pInterval->precision, NULL);
+ STimeWindow win;
+ win.skey = ts;
+ win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
+ SWinRes winRe = {
+ .ts = win.skey,
+ .groupId = groupId,
+ };
+ void* chIds = taosHashGet(pPullDataMap, &winRe, sizeof(SWinRes));
if (isCloseWindow(&win, pSup)) {
- char keyBuf[GET_RES_WINDOW_KEY_LEN(sizeof(TSKEY))];
- SET_RES_WINDOW_KEY(keyBuf, &ts, sizeof(TSKEY), groupId);
- taosHashRemove(pHashMap, keyBuf, keyLen);
+ if (chIds && pPullDataMap) {
+ SArray* chAy = *(SArray**)chIds;
+ int32_t size = taosArrayGetSize(chAy);
+ qDebug("window %" PRId64 " wait child size:%d", win.skey, size);
+ for (int32_t i = 0; i < size; i++) {
+ qDebug("window %" PRId64 " wait chid id:%d", win.skey, *(int32_t*)taosArrayGet(chAy, i));
+ }
+ continue;
+ } else if (pPullDataMap) {
+ qDebug("close window %" PRId64, win.skey);
+ }
SResultRowPosition* pPos = (SResultRowPosition*)pIte;
if (pSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
int32_t code = saveResult(ts, pPos->pageId, pPos->offset, groupId, closeWins);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
+ ASSERT(pRecyPages != NULL);
+ taosArrayPush(pRecyPages, &pPos->pageId);
+ } else {
+ // SFilePage* bufPage = getBufPage(pDiscBuf, pPos->pageId);
+ // dBufSetBufPageRecycled(pDiscBuf, bufPage);
}
+ char keyBuf[GET_RES_WINDOW_KEY_LEN(sizeof(TSKEY))];
+ SET_RES_WINDOW_KEY(keyBuf, &ts, sizeof(TSKEY), groupId);
+ taosHashRemove(pHashMap, keyBuf, keyLen);
}
}
return TSDB_CODE_SUCCESS;
}
+static void closeChildIntervalWindow(SArray* pChildren, TSKEY maxTs) {
+ int32_t size = taosArrayGetSize(pChildren);
+ for (int32_t i = 0; i < size; i++) {
+ SOperatorInfo* pChildOp = taosArrayGetP(pChildren, i);
+ SStreamFinalIntervalOperatorInfo* pChInfo = pChildOp->info;
+ ASSERT(pChInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE);
+ pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
+ closeIntervalWindow(pChInfo->aggSup.pResultRowHashTable, &pChInfo->twAggSup, &pChInfo->interval, NULL, NULL, NULL,
+ pChInfo->aggSup.pResultBuf);
+ }
+}
+
+static void freeAllPages(SArray* pageIds, SDiskbasedBuf* pDiskBuf) {
+ int32_t size = taosArrayGetSize(pageIds);
+ for (int32_t i = 0; i < size; i++) {
+ int32_t pageId = *(int32_t*)taosArrayGet(pageIds, i);
+ // SFilePage* bufPage = getBufPage(pDiskBuf, pageId);
+ // dBufSetBufPageRecycled(pDiskBuf, bufPage);
+ }
+ taosArrayClear(pageIds);
+}
+
+static void doBuildDeleteResult(SArray* pWins, int32_t* index, SSDataBlock* pBlock) {
+ blockDataCleanup(pBlock);
+ int32_t size = taosArrayGetSize(pWins);
+ if (*index == size) {
+ *index = 0;
+ taosArrayClear(pWins);
+ return;
+ }
+ blockDataEnsureCapacity(pBlock, size - *index);
+ SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, DELETE_GROUPID_COLUMN_INDEX);
+ for (int32_t i = *index; i < size; i++) {
+ SWinRes* pWin = taosArrayGet(pWins, i);
+ colDataAppend(pTsCol, pBlock->info.rows, (const char*)&pWin->ts, false);
+ colDataAppend(pGroupCol, pBlock->info.rows, (const char*)&pWin->groupId, false);
+ pBlock->info.rows++;
+ (*index)++;
+ }
+}
+
static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
SIntervalAggOperatorInfo* pInfo = pOperator->info;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
@@ -1313,31 +1435,48 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
}
if (pOperator->status == OP_RES_TO_RETURN) {
+ doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
+ if (pInfo->pDelRes->info.rows > 0) {
+ return pInfo->pDelRes;
+ }
+
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
if (pInfo->binfo.pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
pOperator->status = OP_EXEC_DONE;
+ freeAllPages(pInfo->pRecycledPages, pInfo->aggSup.pResultBuf);
}
return pInfo->binfo.pRes->info.rows == 0 ? NULL : pInfo->binfo.pRes;
}
SOperatorInfo* downstream = pOperator->pDownstream[0];
- SArray* pUpdated = taosArrayInit(4, POINTER_BYTES);
+ SArray* pUpdated = taosArrayInit(4, POINTER_BYTES); // SResKeyPos
while (1) {
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
if (pBlock == NULL) {
break;
}
+ printDataBlock(pBlock, "single interval recv");
- if (pBlock->info.type == STREAM_REPROCESS) {
- doClearWindows(&pInfo->aggSup, &pOperator->exprSupp, &pInfo->interval, 0, pOperator->exprSupp.numOfExprs, pBlock, NULL);
+ if (pBlock->info.type == STREAM_CLEAR) {
+ doClearWindows(&pInfo->aggSup, &pOperator->exprSupp, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock,
+ NULL);
qDebug("%s clear existed time window results for updates checked", GET_TASKID(pTaskInfo));
continue;
+ }
+ if (pBlock->info.type == STREAM_DELETE_DATA) {
+ doDeleteSpecifyIntervalWindow(&pInfo->aggSup, pBlock, pInfo->pDelWins, &pInfo->interval);
+ continue;
} else if (pBlock->info.type == STREAM_GET_ALL) {
getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdated);
continue;
}
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
+
// The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
// caller. Note that all the time window are not close till now.
// the pDataBlock are always the same one, no need to call this again
@@ -1349,15 +1488,20 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, MAIN_SCAN, pUpdated);
}
- closeIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, pUpdated);
+ pOperator->status = OP_RES_TO_RETURN;
+ closeIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL, pUpdated,
+ pInfo->pRecycledPages, pInfo->aggSup.pResultBuf);
finalizeUpdatedResult(pOperator->exprSupp.numOfExprs, pInfo->aggSup.pResultBuf, pUpdated, pSup->rowEntryInfoOffset);
initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated);
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
+ removeDeleteResults(pUpdated, pInfo->pDelWins);
+ doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
+ if (pInfo->pDelRes->info.rows > 0) {
+ return pInfo->pDelRes;
+ }
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
-
- pOperator->status = OP_RES_TO_RETURN;
-
+ printDataBlock(pInfo->binfo.pRes, "single interval");
return pInfo->binfo.pRes->info.rows == 0 ? NULL : pInfo->binfo.pRes;
}
@@ -1365,28 +1509,41 @@ static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput) {
SStateWindowOperatorInfo* pInfo = (SStateWindowOperatorInfo*)param;
cleanupBasicInfo(&pInfo->binfo);
taosMemoryFreeClear(pInfo->stateKey.pData);
+
+ taosMemoryFreeClear(param);
}
void destroyIntervalOperatorInfo(void* param, int32_t numOfOutput) {
SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)param;
cleanupBasicInfo(&pInfo->binfo);
cleanupAggSup(&pInfo->aggSup);
+ taosArrayDestroy(pInfo->pRecycledPages);
+
+ taosMemoryFreeClear(param);
}
void destroyStreamFinalIntervalOperatorInfo(void* param, int32_t numOfOutput) {
SStreamFinalIntervalOperatorInfo* pInfo = (SStreamFinalIntervalOperatorInfo*)param;
cleanupBasicInfo(&pInfo->binfo);
cleanupAggSup(&pInfo->aggSup);
+ // it should be empty.
+ taosHashCleanup(pInfo->pPullDataMap);
+ taosArrayDestroy(pInfo->pPullWins);
+ blockDataDestroy(pInfo->pPullDataRes);
+ taosArrayDestroy(pInfo->pRecycledPages);
+
if (pInfo->pChildren) {
int32_t size = taosArrayGetSize(pInfo->pChildren);
for (int32_t i = 0; i < size; i++) {
SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, i);
- destroyIntervalOperatorInfo(pChildOp->info, numOfOutput);
+ destroyStreamFinalIntervalOperatorInfo(pChildOp->info, numOfOutput);
taosMemoryFreeClear(pChildOp->info);
taosMemoryFreeClear(pChildOp);
}
}
nodesDestroyNode((SNode*)pInfo->pPhyNode);
+
+ taosMemoryFreeClear(param);
}
static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
@@ -1443,14 +1600,37 @@ static bool timeWindowinterpNeeded(SqlFunctionCtx* pCtx, int32_t numOfCols, SInt
}
void increaseTs(SqlFunctionCtx* pCtx) {
- if (pCtx[0].pExpr->pExpr->_function.pFunctNode->funcType == FUNCTION_TYPE_WSTARTTS) {
+ if (pCtx[0].pExpr->pExpr->_function.pFunctNode->funcType == FUNCTION_TYPE_WSTART) {
pCtx[0].increase = true;
}
}
+SSDataBlock* createDeleteBlock() {
+ SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ pBlock->info.hasVarCol = false;
+ pBlock->info.groupId = 0;
+ pBlock->info.rows = 0;
+ pBlock->info.type = STREAM_DELETE_RESULT;
+ pBlock->info.rowSize = sizeof(TSKEY) + sizeof(uint64_t);
+
+ pBlock->pDataBlock = taosArrayInit(2, sizeof(SColumnInfoData));
+ SColumnInfoData infoData = {0};
+ infoData.info.type = TSDB_DATA_TYPE_TIMESTAMP;
+ infoData.info.bytes = sizeof(TSKEY);
+ // window start ts
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ infoData.info.type = TSDB_DATA_TYPE_UBIGINT;
+ infoData.info.bytes = sizeof(uint64_t);
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ return pBlock;
+}
+
SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
- STimeWindowAggSupp* pTwAggSupp, SExecTaskInfo* pTaskInfo, bool isStream) {
+ STimeWindowAggSupp* pTwAggSupp, SIntervalPhysiNode* pPhyNode,
+ SExecTaskInfo* pTaskInfo, bool isStream) {
SIntervalAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -1462,6 +1642,17 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo*
pInfo->interval = *pInterval;
pInfo->execModel = pTaskInfo->execModel;
pInfo->twAggSup = *pTwAggSupp;
+ pInfo->ignoreExpiredData = pPhyNode->window.igExpired;
+ pInfo->pCondition = pPhyNode->window.node.pConditions;
+
+ if (pPhyNode->window.pExprs != NULL) {
+ int32_t numOfScalar = 0;
+ SExprInfo* pScalarExprInfo = createExprInfo(pPhyNode->window.pExprs, NULL, &numOfScalar);
+ int32_t code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+ }
pInfo->primaryTsIndex = primaryTsSlotId;
@@ -1490,6 +1681,12 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo*
goto _error;
}
}
+ pInfo->pRecycledPages = taosArrayInit(4, sizeof(int32_t));
+ pInfo->pDelWins = taosArrayInit(4, sizeof(SWinRes));
+ pInfo->delIndex = 0;
+ // pInfo->pDelRes = createPullDataBlock(); todo(liuyao) for delete
+ pInfo->pDelRes = createOneDataBlock(pInfo->binfo.pRes, false); // todo(liuyao) for delete
+ pInfo->pDelRes->info.type = STREAM_DELETE_RESULT; // todo(liuyao) for delete
initResultRowInfo(&pInfo->binfo.resultRowInfo);
@@ -1580,7 +1777,7 @@ _error:
// todo handle multiple tables cases.
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSessionAggOperatorInfo* pInfo, SSDataBlock* pBlock) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
@@ -1617,9 +1814,8 @@ static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSessionAggOperator
STimeWindow window = pRowSup->win;
pRowSup->win.ekey = pRowSup->win.skey;
- int32_t ret =
- setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
+ numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
longjmp(pTaskInfo->env, TSDB_CODE_QRY_APP_ERROR);
}
@@ -1637,9 +1833,8 @@ static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSessionAggOperator
SResultRow* pResult = NULL;
pRowSup->win.ekey = tsList[pBlock->info.rows - 1];
- int32_t ret =
- setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
+ int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid,
+ pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
longjmp(pTaskInfo->env, TSDB_CODE_QRY_APP_ERROR);
}
@@ -1656,16 +1851,25 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
SSessionAggOperatorInfo* pInfo = pOperator->info;
SOptrBasicInfo* pBInfo = &pInfo->binfo;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
if (pOperator->status == OP_RES_TO_RETURN) {
- doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
- if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
- return NULL;
- }
+ while (1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pBInfo->pRes);
- return pBInfo->pRes;
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
+
+ if (pBInfo->pRes->info.rows > 0) {
+ break;
+ }
+ }
+ pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
+ return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
}
int64_t st = taosGetTimestampUs();
@@ -1694,21 +1898,28 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, TSDB_ORDER_ASC);
blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
- doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
- if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
- doSetOperatorCompleted(pOperator);
- }
+ while (1) {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ doFilter(pInfo->pCondition, pBInfo->pRes);
- size_t rows = pBInfo->pRes->info.rows;
- pOperator->resultInfo.totalRows += rows;
+ bool hasRemain = hasDataInGroupInfo(&pInfo->groupResInfo);
+ if (!hasRemain) {
+ doSetOperatorCompleted(pOperator);
+ break;
+ }
- return (rows == 0) ? NULL : pBInfo->pRes;
+ if (pBInfo->pRes->info.rows > 0) {
+ break;
+ }
+ }
+ pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
+ return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
}
static void doKeepPrevRows(STimeSliceOperatorInfo* pSliceInfo, const SSDataBlock* pBlock, int32_t rowIndex) {
int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
- for(int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
// null data should not be kept since it can not be used to perform interpolation
if (!colDataIsNull_s(pColInfoData, i)) {
@@ -1821,7 +2032,7 @@ static int32_t initPrevRowsKeeper(STimeSliceOperatorInfo* pInfo, SSDataBlock* pB
return TSDB_CODE_OUT_OF_MEMORY;
}
- int32_t numOfCols = pBlock->info.numOfCols;
+ int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
@@ -1844,22 +2055,22 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
STimeSliceOperatorInfo* pSliceInfo = pOperator->info;
- SSDataBlock* pResBlock = pSliceInfo->pRes;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SSDataBlock* pResBlock = pSliceInfo->pRes;
+ SExprSupp* pSup = &pOperator->exprSupp;
blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
-// if (pOperator->status == OP_RES_TO_RETURN) {
-// // doBuildResultDatablock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
-// if (pResBlock->info.rows == 0 || !hasDataInGroupInfo(&pSliceInfo->groupResInfo)) {
-// doSetOperatorCompleted(pOperator);
-// }
-//
-// return pResBlock;
-// }
+ // if (pOperator->status == OP_RES_TO_RETURN) {
+ // // doBuildResultDatablock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
+ // if (pResBlock->info.rows == 0 || !hasDataInGroupInfo(&pSliceInfo->groupResInfo)) {
+ // doSetOperatorCompleted(pOperator);
+ // }
+ //
+ // return pResBlock;
+ // }
- int32_t order = TSDB_ORDER_ASC;
- SInterval* pInterval = &pSliceInfo->interval;
+ int32_t order = TSDB_ORDER_ASC;
+ SInterval* pInterval = &pSliceInfo->interval;
SOperatorInfo* downstream = pOperator->pDownstream[0];
int32_t numOfRows = 0;
@@ -1878,14 +2089,14 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
setInputDataBlock(pOperator, pSup->pCtx, pBlock, order, MAIN_SCAN, true);
SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->tsCol.slotId);
- for(int32_t i = 0; i < pBlock->info.rows; ++i) {
- int64_t ts = *(int64_t*) colDataGetData(pTsCol, i);
+ for (int32_t i = 0; i < pBlock->info.rows; ++i) {
+ int64_t ts = *(int64_t*)colDataGetData(pTsCol, i);
if (ts == pSliceInfo->current) {
- for(int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
+ for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[j];
- int32_t dstSlot = pExprInfo->base.resSchema.slotId;
- int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId;
+ int32_t dstSlot = pExprInfo->base.resSchema.slotId;
+ int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId;
SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot);
SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot);
@@ -1897,7 +2108,8 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
pResBlock->info.rows += 1;
doKeepPrevRows(pSliceInfo, pBlock, i);
- pSliceInfo->current = taosTimeAdd(pSliceInfo->current, pInterval->interval, pInterval->intervalUnit, pInterval->precision);
+ pSliceInfo->current =
+ taosTimeAdd(pSliceInfo->current, pInterval->interval, pInterval->intervalUnit, pInterval->precision);
if (pSliceInfo->current > pSliceInfo->win.ekey) {
doSetOperatorCompleted(pOperator);
break;
@@ -1908,7 +2120,7 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
}
} else if (ts < pSliceInfo->current) {
if (i < pBlock->info.rows - 1) {
- int64_t nextTs = *(int64_t*) colDataGetData(pTsCol, i + 1);
+ int64_t nextTs = *(int64_t*)colDataGetData(pTsCol, i + 1);
if (nextTs > pSliceInfo->current) {
while (pSliceInfo->current < nextTs && pSliceInfo->current <= pSliceInfo->win.ekey) {
genInterpolationResult(pSliceInfo, &pOperator->exprSupp, pBlock, i, pResBlock);
@@ -1956,7 +2168,7 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
return pResBlock->info.rows == 0 ? NULL : pResBlock;
}
-SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode *pPhyNode, SExecTaskInfo* pTaskInfo) {
+SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo) {
STimeSliceOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STimeSliceOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pOperator == NULL || pInfo == NULL) {
@@ -1964,17 +2176,17 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode
}
SInterpFuncPhysiNode* pInterpPhyNode = (SInterpFuncPhysiNode*)pPhyNode;
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
- int32_t numOfExprs = 0;
+ int32_t numOfExprs = 0;
SExprInfo* pExprInfo = createExprInfo(pInterpPhyNode->pFuncs, NULL, &numOfExprs);
- int32_t code = initExprSupp(pSup, pExprInfo, numOfExprs);
+ int32_t code = initExprSupp(pSup, pExprInfo, numOfExprs);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
if (pInterpPhyNode->pExprs != NULL) {
- int32_t num = 0;
+ int32_t num = 0;
SExprInfo* pScalarExprInfo = createExprInfo(pInterpPhyNode->pExprs, NULL, &num);
code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, num);
if (code != TSDB_CODE_SUCCESS) {
@@ -1986,21 +2198,21 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode
pInfo->fillType = convertFillType(pInterpPhyNode->fillMode);
initResultSizeInfo(pOperator, 4096);
- pInfo->pFillColInfo = createFillColInfo(pExprInfo, numOfExprs, (SNodeListNode*)pInterpPhyNode->pFillValues);
- pInfo->pRes = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
- pInfo->win = pInterpPhyNode->timeRange;
+ pInfo->pFillColInfo = createFillColInfo(pExprInfo, numOfExprs, (SNodeListNode*)pInterpPhyNode->pFillValues);
+ pInfo->pRes = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
+ pInfo->win = pInterpPhyNode->timeRange;
pInfo->interval.interval = pInterpPhyNode->interval;
- pInfo->current = pInfo->win.skey;
+ pInfo->current = pInfo->win.skey;
- pOperator->name = "TimeSliceOperator";
+ pOperator->name = "TimeSliceOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC;
- pOperator->blocking = false;
- pOperator->status = OP_NOT_OPENED;
- pOperator->info = pInfo;
- pOperator->pTaskInfo = pTaskInfo;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->info = pInfo;
+ pOperator->pTaskInfo = pTaskInfo;
- pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doTimeslice, NULL, NULL, destroyBasicOperatorInfo,
- NULL, NULL, NULL);
+ pOperator->fpSet =
+ createOperatorFpSet(operatorDummyOpenFn, doTimeslice, NULL, NULL, destroyBasicOperatorInfo, NULL, NULL, NULL);
code = appendDownstream(pOperator, &downstream, 1);
return pOperator;
@@ -2014,7 +2226,7 @@ _error:
SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfCols,
SSDataBlock* pResBlock, STimeWindowAggSupp* pTwAggSup, int32_t tsSlotId,
- SColumn* pStateKeyCol, SExecTaskInfo* pTaskInfo) {
+ SColumn* pStateKeyCol, SNode* pCondition, SExecTaskInfo* pTaskInfo) {
SStateWindowOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStateWindowOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -2025,6 +2237,7 @@ SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SExprInf
pInfo->stateKey.type = pInfo->stateCol.type;
pInfo->stateKey.bytes = pInfo->stateCol.bytes;
pInfo->stateKey.pData = taosMemoryCalloc(1, pInfo->stateCol.bytes);
+ pInfo->pCondition = pCondition;
if (pInfo->stateKey.pData == NULL) {
goto _error;
}
@@ -2064,11 +2277,14 @@ _error:
void destroySWindowOperatorInfo(void* param, int32_t numOfOutput) {
SSessionAggOperatorInfo* pInfo = (SSessionAggOperatorInfo*)param;
cleanupBasicInfo(&pInfo->binfo);
+
+ taosMemoryFreeClear(param);
}
SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, int64_t gap, int32_t tsSlotId,
- STimeWindowAggSupp* pTwAggSupp, SExecTaskInfo* pTaskInfo) {
+ STimeWindowAggSupp* pTwAggSupp, SNode* pCondition,
+ SExecTaskInfo* pTaskInfo) {
SSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSessionAggOperatorInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -2094,6 +2310,7 @@ SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SExprInfo
pInfo->binfo.pRes = pResBlock;
pInfo->winSup.prevTs = INT64_MIN;
pInfo->reptScan = false;
+ pInfo->pCondition = pCondition;
pOperator->name = "SessionWindowAggOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION;
pOperator->blocking = true;
@@ -2138,36 +2355,79 @@ void compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int3
}
}
-static void rebuildIntervalWindow(SStreamFinalIntervalOperatorInfo* pInfo, SExprSupp* pSup, SArray* pWinArray, int32_t groupId,
- int32_t numOfOutput, SExecTaskInfo* pTaskInfo) {
+bool hasIntervalWindow(SAggSupporter* pSup, TSKEY ts, uint64_t groupId) {
+ int32_t bytes = sizeof(TSKEY);
+ SET_RES_WINDOW_KEY(pSup->keyBuf, &ts, bytes, groupId);
+ SResultRowPosition* p1 =
+ (SResultRowPosition*)taosHashGet(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
+ return p1 != NULL;
+}
+
+static void rebuildIntervalWindow(SStreamFinalIntervalOperatorInfo* pInfo, SExprSupp* pSup, SArray* pWinArray,
+ int32_t groupId, int32_t numOfOutput, SExecTaskInfo* pTaskInfo, SArray* pUpdated) {
int32_t size = taosArrayGetSize(pWinArray);
- ASSERT(pInfo->pChildren);
+ if (!pInfo->pChildren) {
+ return;
+ }
for (int32_t i = 0; i < size; i++) {
- STimeWindow* pParentWin = taosArrayGet(pWinArray, i);
- SResultRow* pCurResult = NULL;
- setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, pParentWin, true, &pCurResult, 0, pSup->pCtx,
+ SWinRes* pWinRes = taosArrayGet(pWinArray, i);
+ SResultRow* pCurResult = NULL;
+ STimeWindow ParentWin = {.skey = pWinRes->ts, .ekey = pWinRes->ts + 1};
+ setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &ParentWin, true, &pCurResult, pWinRes->groupId, pSup->pCtx,
numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
int32_t numOfChildren = taosArrayGetSize(pInfo->pChildren);
+ bool find = true;
for (int32_t j = 0; j < numOfChildren; j++) {
SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, j);
SIntervalAggOperatorInfo* pChInfo = pChildOp->info;
- SExprSupp* pChildSup = &pChildOp->exprSupp;
-
- SResultRow* pChResult = NULL;
- setTimeWindowOutputBuf(&pChInfo->binfo.resultRowInfo, pParentWin, true, &pChResult, 0, pChildSup->pCtx,
- pChildSup->numOfExprs, pChildSup->rowEntryInfoOffset, &pChInfo->aggSup, pTaskInfo);
+ SExprSupp* pChildSup = &pChildOp->exprSupp;
+ if (!hasIntervalWindow(&pChInfo->aggSup, pWinRes->ts, pWinRes->groupId)) {
+ continue;
+ }
+ find = true;
+ SResultRow* pChResult = NULL;
+ setTimeWindowOutputBuf(&pChInfo->binfo.resultRowInfo, &ParentWin, true, &pChResult, pWinRes->groupId,
+ pChildSup->pCtx, pChildSup->numOfExprs, pChildSup->rowEntryInfoOffset, &pChInfo->aggSup,
+ pTaskInfo);
compactFunctions(pSup->pCtx, pChildSup->pCtx, numOfOutput, pTaskInfo);
}
+ if (find && pUpdated) {
+ saveResultRow(pCurResult, pWinRes->groupId, pUpdated);
+ }
}
}
bool isDeletedWindow(STimeWindow* pWin, uint64_t groupId, SAggSupporter* pSup) {
SET_RES_WINDOW_KEY(pSup->keyBuf, &pWin->skey, sizeof(int64_t), groupId);
- SResultRowPosition* p1 = (SResultRowPosition*)taosHashGet(pSup->pResultRowHashTable,
- pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(sizeof(int64_t)));
+ SResultRowPosition* p1 = (SResultRowPosition*)taosHashGet(pSup->pResultRowHashTable, pSup->keyBuf,
+ GET_RES_WINDOW_KEY_LEN(sizeof(int64_t)));
return p1 == NULL;
}
+int32_t getNexWindowPos(SInterval* pInterval, SDataBlockInfo* pBlockInfo, TSKEY* tsCols, int32_t startPos, TSKEY eKey,
+ STimeWindow* pNextWin) {
+ int32_t forwardRows =
+ getNumOfRowsInTimeWindow(pBlockInfo, tsCols, startPos, eKey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
+ int32_t prevEndPos = forwardRows - 1 + startPos;
+ return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
+}
+
+void addPullWindow(SHashObj* pMap, SWinRes* pWinRes, int32_t size) {
+ SArray* childIds = taosArrayInit(8, sizeof(int32_t));
+ for (int32_t i = 0; i < size; i++) {
+ taosArrayPush(childIds, &i);
+ }
+ taosHashPut(pMap, pWinRes, sizeof(SWinRes), &childIds, sizeof(void*));
+}
+
+static int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
+
+STimeWindow getFinalTimeWindow(int64_t ts, SInterval* pInterval) {
+ STimeWindow w = {.skey = ts, .ekey = INT64_MAX};
+ w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
+ return w;
+}
+
static void doHashInterval(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataBlock, uint64_t tableGroupId,
SArray* pUpdated) {
SStreamFinalIntervalOperatorInfo* pInfo = (SStreamFinalIntervalOperatorInfo*)pOperatorInfo->info;
@@ -2181,42 +2441,86 @@ static void doHashInterval(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataBloc
SResultRow* pResult = NULL;
int32_t forwardRows = 0;
- if (pSDataBlock->pDataBlock != NULL) {
- SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
- tsCols = (int64_t*)pColDataInfo->pData;
- } else {
- return;
- }
+ ASSERT(pSDataBlock->pDataBlock != NULL);
+ SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
+ tsCols = (int64_t*)pColDataInfo->pData;
int32_t startPos = ascScan ? 0 : (pSDataBlock->info.rows - 1);
TSKEY ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
- STimeWindow nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval,
- pInfo->interval.precision, NULL);
+ STimeWindow nextWin = {0};
+ if (IS_FINAL_OP(pInfo)) {
+ nextWin = getFinalTimeWindow(ts, &pInfo->interval);
+ } else {
+ nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, pInfo->order);
+ }
while (1) {
- if (IS_FINAL_OP(pInfo) && isCloseWindow(&nextWin, &pInfo->twAggSup) &&
- isDeletedWindow(&nextWin, tableGroupId, &pInfo->aggSup)) {
- SArray* pUpWins = taosArrayInit(8, sizeof(STimeWindow));
- taosArrayPush(pUpWins, &nextWin);
- rebuildIntervalWindow(pInfo, pSup, pUpWins, pInfo->binfo.pRes->info.groupId, pSup->numOfExprs, pOperatorInfo->pTaskInfo);
- taosArrayDestroy(pUpWins);
+ bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
+ if ((pInfo->ignoreExpiredData && isClosed) || !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
+ startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
+ if (startPos < 0) {
+ break;
+ }
+ continue;
}
+ if (IS_FINAL_OP(pInfo) && isClosed && pInfo->pChildren) {
+ bool ignore = true;
+ SWinRes winRes = {
+ .ts = nextWin.skey,
+ .groupId = tableGroupId,
+ };
+ void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinRes));
+ if (isDeletedWindow(&nextWin, tableGroupId, &pInfo->aggSup) && !chIds) {
+ SPullWindowInfo pull = {.window = nextWin, .groupId = tableGroupId};
+ // add pull data request
+ taosArrayPush(pInfo->pPullWins, &pull);
+ addPullWindow(pInfo->pPullDataMap, &winRes, taosArrayGetSize(pInfo->pChildren));
+ } else {
+ int32_t index = -1;
+ SArray* chArray = NULL;
+ if (chIds) {
+ chArray = *(void**)chIds;
+ int32_t chId = getChildIndex(pSDataBlock);
+ index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
+ }
+ if (index != -1 && pSDataBlock->info.type == STREAM_PULL_DATA) {
+ taosArrayRemove(chArray, index);
+ if (taosArrayGetSize(chArray) == 0) {
+ // pull data is over
+ taosHashRemove(pInfo->pPullDataMap, &winRes, sizeof(SWinRes));
+ }
+ }
+ if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
+ ignore = false;
+ }
+ }
+
+ if (ignore) {
+ startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
+ if (startPos < 0) {
+ break;
+ }
+ continue;
+ }
+ }
+
int32_t code = setTimeWindowOutputBuf(pResultRowInfo, &nextWin, true, &pResult, tableGroupId, pSup->pCtx,
numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- SResKeyPos* pos = taosMemoryMalloc(sizeof(SResKeyPos) + sizeof(uint64_t));
- pos->groupId = tableGroupId;
- pos->pos = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
- *(int64_t*)pos->key = pResult->win.skey;
- forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey, NULL,
- TSDB_ORDER_ASC);
+
+ if (IS_FINAL_OP(pInfo)) {
+ forwardRows = 1;
+ } else {
+ forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
+ NULL, TSDB_ORDER_ASC);
+ }
if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdated) {
saveResultRow(pResult, tableGroupId, pUpdated);
}
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
- tsCols, pSDataBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pSDataBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
int32_t prevEndPos = (forwardRows - 1) * step + startPos;
ASSERT(pSDataBlock->info.window.skey > 0 && pSDataBlock->info.window.ekey > 0);
startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, pInfo->order);
@@ -2233,7 +2537,7 @@ static void clearStreamIntervalOperator(SStreamFinalIntervalOperatorInfo* pInfo)
initResultRowInfo(&pInfo->binfo.resultRowInfo);
}
-static void clearUpdateDataBlock(SSDataBlock* pBlock) {
+static void clearSpecialDataBlock(SSDataBlock* pBlock) {
if (pBlock->info.rows <= 0) {
return;
}
@@ -2241,24 +2545,81 @@ static void clearUpdateDataBlock(SSDataBlock* pBlock) {
}
void copyUpdateDataBlock(SSDataBlock* pDest, SSDataBlock* pSource, int32_t tsColIndex) {
- ASSERT(pDest->info.capacity >= pSource->info.rows);
- clearUpdateDataBlock(pDest);
+ // ASSERT(pDest->info.capacity >= pSource->info.rows);
+ blockDataEnsureCapacity(pDest, pSource->info.rows);
+ clearSpecialDataBlock(pDest);
SColumnInfoData* pDestCol = taosArrayGet(pDest->pDataBlock, 0);
SColumnInfoData* pSourceCol = taosArrayGet(pSource->pDataBlock, tsColIndex);
+
// copy timestamp column
- colDataAssign(pDestCol, pSourceCol, pSource->info.rows);
- for (int32_t i = 1; i < pDest->info.numOfCols; i++) {
+ colDataAssign(pDestCol, pSourceCol, pSource->info.rows, &pDest->info);
+ for (int32_t i = 1; i < taosArrayGetSize(pDest->pDataBlock); i++) {
SColumnInfoData* pCol = taosArrayGet(pDest->pDataBlock, i);
colDataAppendNNULL(pCol, 0, pSource->info.rows);
}
+
pDest->info.rows = pSource->info.rows;
pDest->info.groupId = pSource->info.groupId;
pDest->info.type = pSource->info.type;
blockDataUpdateTsWindow(pDest, 0);
}
-static int32_t getChildIndex(SSDataBlock* pBlock) {
- return pBlock->info.childId;
+static bool needBreak(SStreamFinalIntervalOperatorInfo* pInfo) {
+ int32_t size = taosArrayGetSize(pInfo->pPullWins);
+ if (pInfo->pullIndex < size) {
+ return true;
+ }
+ return false;
+}
+
+static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
+ clearSpecialDataBlock(pBlock);
+ int32_t size = taosArrayGetSize(array);
+ if (size - (*pIndex) == 0) {
+ return;
+ }
+ blockDataEnsureCapacity(pBlock, size - (*pIndex));
+ ASSERT(3 <= taosArrayGetSize(pBlock->pDataBlock));
+ for (; (*pIndex) < size; (*pIndex)++) {
+ SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
+ SColumnInfoData* pStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ colDataAppend(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false);
+
+ SColumnInfoData* pEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
+ colDataAppend(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false);
+
+ SColumnInfoData* pGroupId = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
+ colDataAppend(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false);
+ pBlock->info.rows++;
+ }
+ if ((*pIndex) == size) {
+ *pIndex = 0;
+ taosArrayClear(array);
+ }
+ blockDataUpdateTsWindow(pBlock, 0);
+}
+
+void processPullOver(SSDataBlock* pBlock, SHashObj* pMap) {
+ SColumnInfoData* pStartCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* tsData = (TSKEY*)pStartCol->pData;
+ SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
+ uint64_t* groupIdData = (uint64_t*)pGroupCol->pData;
+ int32_t chId = getChildIndex(pBlock);
+ for (int32_t i = 0; i < pBlock->info.rows; i++) {
+ SWinRes winRes = {.ts = tsData[i], .groupId = groupIdData[i]};
+ void* chIds = taosHashGet(pMap, &winRes, sizeof(SWinRes));
+ if (chIds) {
+ SArray* chArray = *(SArray**)chIds;
+ int32_t index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
+ if (index != -1) {
+ taosArrayRemove(chArray, index);
+ if (taosArrayGetSize(chArray) == 0) {
+ // pull data is over
+ taosHashRemove(pMap, &winRes, sizeof(SWinRes));
+ }
+ }
+ }
+ }
}
static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
@@ -2269,59 +2630,122 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
SExprSupp* pSup = &pOperator->exprSupp;
+ qDebug("interval status %d %s", pOperator->status, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
} else if (pOperator->status == OP_RES_TO_RETURN) {
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
if (pInfo->binfo.pRes->info.rows == 0) {
pOperator->status = OP_EXEC_DONE;
- if (IS_FINAL_OP(pInfo) || pInfo->pUpdateRes->info.rows == 0) {
- if (!IS_FINAL_OP(pInfo)) {
- // semi interval operator clear disk buffer
- clearStreamIntervalOperator(pInfo);
- }
- return NULL;
+ if (!IS_FINAL_OP(pInfo)) {
+ // semi interval operator clear disk buffer
+ clearStreamIntervalOperator(pInfo);
+ } else {
+ freeAllPages(pInfo->pRecycledPages, pInfo->aggSup.pResultBuf);
}
+ return NULL;
+ }
+ printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->binfo.pRes;
+ } else {
+ doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
+ if (pInfo->binfo.pRes->info.rows != 0) {
+ printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->binfo.pRes;
+ }
+ if (pInfo->pUpdateRes->info.rows != 0 && pInfo->returnUpdate) {
+ pInfo->returnUpdate = false;
+ ASSERT(!IS_FINAL_OP(pInfo));
+ printDataBlock(pInfo->pUpdateRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
// process the rest of the data
- pOperator->status = OP_OPENED;
return pInfo->pUpdateRes;
}
- return pInfo->binfo.pRes;
+ doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
+ if (pInfo->pPullDataRes->info.rows != 0) {
+ // process the rest of the data
+ ASSERT(IS_FINAL_OP(pInfo));
+ printDataBlock(pInfo->pPullDataRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->pPullDataRes;
+ }
+ doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
+ if (pInfo->pDelRes->info.rows != 0) {
+ // process the rest of the data
+ printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->pDelRes;
+ }
}
while (1) {
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
if (pBlock == NULL) {
- clearUpdateDataBlock(pInfo->pUpdateRes);
+ clearSpecialDataBlock(pInfo->pUpdateRes);
+ removeDeleteResults(pUpdated, pInfo->pDelWins);
+ pOperator->status = OP_RES_TO_RETURN;
+ qDebug("%s return data", IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
break;
}
+ printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "interval Final recv" : "interval Semi recv");
+ maxTs = TMAX(maxTs, pBlock->info.window.ekey);
- if (pBlock->info.type == STREAM_REPROCESS) {
- SArray* pUpWins = taosArrayInit(8, sizeof(STimeWindow));
- doClearWindows(&pInfo->aggSup, pSup, &pInfo->interval, pInfo->primaryTsIndex, pOperator->exprSupp.numOfExprs,
- pBlock, pUpWins);
+ if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA ||
+ pBlock->info.type == STREAM_INVALID) {
+ pInfo->binfo.pRes->info.type = pBlock->info.type;
+ } else if (pBlock->info.type == STREAM_CLEAR) {
+ SArray* pUpWins = taosArrayInit(8, sizeof(SWinRes));
+ doClearWindows(&pInfo->aggSup, pSup, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, pUpWins);
if (IS_FINAL_OP(pInfo)) {
- int32_t childIndex = getChildIndex(pBlock);
- SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
- SIntervalAggOperatorInfo* pChildInfo = pChildOp->info;
- SExprSupp* pChildSup = &pChildOp->exprSupp;
+ int32_t childIndex = getChildIndex(pBlock);
+ SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
+ SStreamFinalIntervalOperatorInfo* pChildInfo = pChildOp->info;
+ SExprSupp* pChildSup = &pChildOp->exprSupp;
- doClearWindows(&pChildInfo->aggSup, pChildSup, &pChildInfo->interval, pChildInfo->primaryTsIndex,
- pChildSup->numOfExprs, pBlock, NULL);
+ doClearWindows(&pChildInfo->aggSup, pChildSup, &pChildInfo->interval, pChildSup->numOfExprs, pBlock, NULL);
rebuildIntervalWindow(pInfo, pSup, pUpWins, pInfo->binfo.pRes->info.groupId, pOperator->exprSupp.numOfExprs,
- pOperator->pTaskInfo);
+ pOperator->pTaskInfo, NULL);
taosArrayDestroy(pUpWins);
continue;
}
removeResults(pUpWins, pUpdated);
copyUpdateDataBlock(pInfo->pUpdateRes, pBlock, pInfo->primaryTsIndex);
+ pInfo->returnUpdate = true;
taosArrayDestroy(pUpWins);
break;
+ } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT) {
+ doDeleteSpecifyIntervalWindow(&pInfo->aggSup, pBlock, pInfo->pDelWins, &pInfo->interval);
+ if (IS_FINAL_OP(pInfo)) {
+ int32_t childIndex = getChildIndex(pBlock);
+ SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
+ SStreamFinalIntervalOperatorInfo* pChildInfo = pChildOp->info;
+ SExprSupp* pChildSup = &pChildOp->exprSupp;
+ doDeleteSpecifyIntervalWindow(&pChildInfo->aggSup, pBlock, NULL, &pChildInfo->interval);
+ rebuildIntervalWindow(pInfo, pSup, pInfo->pDelWins, pInfo->binfo.pRes->info.groupId,
+ pOperator->exprSupp.numOfExprs, pOperator->pTaskInfo, pUpdated);
+ continue;
+ }
+ removeResults(pInfo->pDelWins, pUpdated);
+ break;
} else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_OP(pInfo)) {
getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdated);
continue;
+ } else if (pBlock->info.type == STREAM_RETRIEVE && !IS_FINAL_OP(pInfo)) {
+ SArray* pUpWins = taosArrayInit(8, sizeof(SWinRes));
+ doClearWindows(&pInfo->aggSup, pSup, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, pUpWins);
+ removeResults(pUpWins, pUpdated);
+ taosArrayDestroy(pUpWins);
+ if (taosArrayGetSize(pUpdated) > 0) {
+ break;
+ }
+ continue;
+ } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_OP(pInfo)) {
+ processPullOver(pBlock, pInfo->pPullDataMap);
+ continue;
}
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
setInputDataBlock(pOperator, pSup->pCtx, pBlock, pInfo->order, MAIN_SCAN, true);
doHashInterval(pOperator, pBlock, pBlock->info.groupId, pUpdated);
if (IS_FINAL_OP(pInfo)) {
@@ -2333,36 +2757,85 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
if (!pChildOp) {
longjmp(pOperator->pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
+ SStreamFinalIntervalOperatorInfo* pTmpInfo = pChildOp->info;
+ pTmpInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
taosArrayPush(pInfo->pChildren, &pChildOp);
}
SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
SStreamFinalIntervalOperatorInfo* pChInfo = pChildOp->info;
setInputDataBlock(pChildOp, pChildOp->exprSupp.pCtx, pBlock, pChInfo->order, MAIN_SCAN, true);
doHashInterval(pChildOp, pBlock, pBlock->info.groupId, NULL);
+
+ if (needBreak(pInfo)) {
+ break;
+ }
}
- maxTs = TMAX(maxTs, pBlock->info.window.ekey);
}
pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
if (IS_FINAL_OP(pInfo)) {
- closeIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, pUpdated);
+ closeIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, pInfo->pPullDataMap,
+ pUpdated, pInfo->pRecycledPages, pInfo->aggSup.pResultBuf);
+ closeChildIntervalWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
}
finalizeUpdatedResult(pOperator->exprSupp.numOfExprs, pInfo->aggSup.pResultBuf, pUpdated, pSup->rowEntryInfoOffset);
initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated);
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
- pOperator->status = OP_RES_TO_RETURN;
- if (pInfo->binfo.pRes->info.rows == 0) {
- pOperator->status = OP_EXEC_DONE;
- if (pInfo->pUpdateRes->info.rows == 0) {
- return NULL;
- }
+ if (pInfo->binfo.pRes->info.rows != 0) {
+ printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->binfo.pRes;
+ }
+
+ if (pInfo->pUpdateRes->info.rows != 0 && pInfo->returnUpdate) {
+ pInfo->returnUpdate = false;
+ ASSERT(!IS_FINAL_OP(pInfo));
+ printDataBlock(pInfo->pUpdateRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
// process the rest of the data
- pOperator->status = OP_OPENED;
return pInfo->pUpdateRes;
}
- return pInfo->binfo.pRes;
+
+ doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
+ if (pInfo->pPullDataRes->info.rows != 0) {
+ // process the rest of the data
+ ASSERT(IS_FINAL_OP(pInfo));
+ printDataBlock(pInfo->pPullDataRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->pPullDataRes;
+ }
+
+ doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
+ if (pInfo->pDelRes->info.rows != 0) {
+ // process the rest of the data
+ printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval Final" : "interval Semi");
+ return pInfo->pDelRes;
+ }
+ // ASSERT(false);
+ return NULL;
+}
+
+SSDataBlock* createPullDataBlock() {
+ SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
+ pBlock->info.hasVarCol = false;
+ pBlock->info.groupId = 0;
+ pBlock->info.rows = 0;
+ pBlock->info.type = STREAM_RETRIEVE;
+ pBlock->info.rowSize = sizeof(TSKEY) + sizeof(TSKEY) + sizeof(uint64_t);
+
+ pBlock->pDataBlock = taosArrayInit(3, sizeof(SColumnInfoData));
+ SColumnInfoData infoData = {0};
+ infoData.info.type = TSDB_DATA_TYPE_TIMESTAMP;
+ infoData.info.bytes = sizeof(TSKEY);
+ // window start ts
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+ // window end ts
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ infoData.info.type = TSDB_DATA_TYPE_UBIGINT;
+ infoData.info.bytes = sizeof(uint64_t);
+ taosArrayPush(pBlock->pDataBlock, &infoData);
+
+ return pBlock;
}
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
@@ -2390,6 +2863,15 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
initResultSizeInfo(pOperator, 4096);
+ if (pIntervalPhyNode->window.pExprs != NULL) {
+ int32_t numOfScalar = 0;
+ SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
+ int32_t code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+ }
+
int32_t numOfCols = 0;
SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
@@ -2406,33 +2888,48 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
initResultRowInfo(&pInfo->binfo.resultRowInfo);
pInfo->pChildren = NULL;
if (numOfChild > 0) {
- pInfo->pChildren = taosArrayInit(numOfChild, sizeof(SOperatorInfo));
+ pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
for (int32_t i = 0; i < numOfChild; i++) {
SOperatorInfo* pChildOp = createStreamFinalIntervalOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
if (pChildOp) {
+ SStreamFinalIntervalOperatorInfo* pChInfo = pChildOp->info;
+ pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
taosArrayPush(pInfo->pChildren, &pChildOp);
continue;
}
goto _error;
}
}
- // semi interval operator does not catch result
pInfo->pUpdateRes = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
- pInfo->pUpdateRes->info.type = STREAM_REPROCESS;
+ pInfo->pUpdateRes->info.type = STREAM_CLEAR;
blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
+ pInfo->returnUpdate = false;
+
pInfo->pPhyNode = (SPhysiNode*)nodesCloneNode((SNode*)pPhyNode);
if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL) {
pInfo->isFinal = true;
pOperator->name = "StreamFinalIntervalOperator";
} else {
+ // semi interval operator does not catch result
pInfo->isFinal = false;
pOperator->name = "StreamSemiIntervalOperator";
}
- if (!IS_FINAL_OP(pInfo)) {
+ if (!IS_FINAL_OP(pInfo) || numOfChild == 0) {
pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
}
+ pInfo->pPullWins = taosArrayInit(8, sizeof(SPullWindowInfo));
+ pInfo->pullIndex = 0;
+ _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
+ pInfo->pPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK);
+ pInfo->pPullDataRes = createPullDataBlock();
+ pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
+ // pInfo->pDelRes = createPullDataBlock(); // todo(liuyao) for delete
+ pInfo->pDelRes = createOneDataBlock(pInfo->binfo.pRes, false); // todo(liuyao) for delete
+ pInfo->pDelRes->info.type = STREAM_DELETE_RESULT; // todo(liuyao) for delete
+ pInfo->delIndex = 0;
+ pInfo->pDelWins = taosArrayInit(4, sizeof(SWinRes));
pOperator->operatorType = pPhyNode->type;
pOperator->blocking = true;
@@ -2463,9 +2960,9 @@ _error:
void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
taosMemoryFreeClear(pSup->pKeyBuf);
- void **pIte = NULL;
+ void** pIte = NULL;
while ((pIte = taosHashIterate(pSup->pResultRows, pIte)) != NULL) {
- SArray *pWins = (SArray *) (*pIte);
+ SArray* pWins = (SArray*)(*pIte);
taosArrayDestroy(pWins);
}
taosHashCleanup(pSup->pResultRows);
@@ -2487,20 +2984,23 @@ void destroyStreamSessionAggOperatorInfo(void* param, int32_t numOfOutput) {
taosMemoryFreeClear(pChInfo);
}
}
+
+ taosMemoryFreeClear(param);
}
-int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols, SSDataBlock* pResultBlock) {
+int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
+ SSDataBlock* pResultBlock) {
int32_t code = initExprSupp(pSup, pExprInfo, numOfCols);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
initBasicInfo(pBasicInfo, pResultBlock);
-
+
for (int32_t i = 0; i < numOfCols; ++i) {
pSup->pCtx[i].pBuf = NULL;
}
-
+
ASSERT(numOfCols > 0);
increaseTs(pSup->pCtx);
return TSDB_CODE_SUCCESS;
@@ -2514,36 +3014,45 @@ void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t num
void initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, int64_t gap, int64_t waterMark,
uint8_t type) {
ASSERT(downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN);
- SStreamBlockScanInfo* pScanInfo = downstream->info;
+ SStreamScanInfo* pScanInfo = downstream->info;
pScanInfo->sessionSup = (SessionWindowSupporter){.pStreamAggSup = pAggSup, .gap = gap, .parentType = type};
pScanInfo->pUpdateInfo = updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, waterMark);
}
-int32_t initSessionAggSupporter(SStreamAggSupporter* pSup, const char* pKey, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
+int32_t initSessionAggSupporter(SStreamAggSupporter* pSup, const char* pKey, SqlFunctionCtx* pCtx,
+ int32_t numOfOutput) {
return initStreamAggSupporter(pSup, pKey, pCtx, numOfOutput, sizeof(SResultWindowInfo));
}
-SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo) {
- SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
- int32_t numOfCols = 0;
- SExprInfo* pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
- SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
- int32_t code = TSDB_CODE_OUT_OF_MEMORY;
+SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
+ SExecTaskInfo* pTaskInfo) {
+ SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
+ int32_t numOfCols = 0;
+ SExprInfo* pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
+ SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
+ int32_t code = TSDB_CODE_OUT_OF_MEMORY;
SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
- SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
goto _error;
}
initResultSizeInfo(pOperator, 4096);
+ if (pSessionNode->window.pExprs != NULL) {
+ int32_t numOfScalar = 0;
+ SExprInfo* pScalarExprInfo = createExprInfo(pSessionNode->window.pExprs, NULL, &numOfScalar);
+ int32_t code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+ }
SExprSupp* pSup = &pOperator->exprSupp;
code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
-
-
+
code = initSessionAggSupporter(&pInfo->streamAggSup, "StreamSessionAggOperatorInfo", pSup->pCtx, numOfCols);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
@@ -2555,10 +3064,8 @@ SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPh
}
initDummyFunction(pInfo->pDummyCtx, pSup->pCtx, numOfCols);
- pInfo->twAggSup = (STimeWindowAggSupp) {
- .waterMark = pSessionNode->window.watermark,
- .calTrigger = pSessionNode->window.triggerType,
- .maxTs = INT64_MIN};
+ pInfo->twAggSup = (STimeWindowAggSupp){
+ .waterMark = pSessionNode->window.watermark, .calTrigger = pSessionNode->window.triggerType, .maxTs = INT64_MIN};
initResultRowInfo(&pInfo->binfo.resultRowInfo);
initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
@@ -2573,11 +3080,14 @@ SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPh
_hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
pInfo->pStDeleted = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
pInfo->pDelIterator = NULL;
- pInfo->pDelRes = createOneDataBlock(pResBlock, false);
- blockDataEnsureCapacity(pInfo->pDelRes, 64);
+ // pInfo->pDelRes = createPullDataBlock();
+ pInfo->pDelRes = createOneDataBlock(pInfo->binfo.pRes, false); // todo(liuyao) for delete
+ pInfo->pDelRes->info.type = STREAM_DELETE_RESULT; // todo(liuyao) for delete
pInfo->pChildren = NULL;
pInfo->isFinal = false;
pInfo->pPhyNode = pPhyNode;
+ pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
+ pInfo->returnDelete = false;
pOperator->name = "StreamSessionWindowAggOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION;
@@ -2612,15 +3122,16 @@ int64_t getSessionWindowEndkey(void* data, int32_t index) {
SResultWindowInfo* pWin = taosArrayGet(pWinInfos, index);
return pWin->win.ekey;
}
-static bool isInWindow(SResultWindowInfo* pWin, TSKEY ts, int64_t gap) {
- int64_t sGap = ts - pWin->win.skey;
- int64_t eGap = pWin->win.ekey - ts;
- if ((sGap < 0 && sGap >= -gap) || (eGap < 0 && eGap >= -gap) || (sGap >= 0 && eGap >= 0)) {
+
+bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
+ if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
return true;
}
return false;
}
+bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) { return isInTimeWindow(&pWinInfo->win, ts, gap); }
+
static SResultWindowInfo* insertNewSessionWindow(SArray* pWinInfos, TSKEY ts, int32_t index) {
SResultWindowInfo win = {.pos.offset = -1, .pos.pageId = -1, .win.skey = ts, .win.ekey = ts, .isOutput = false};
return taosArrayInsert(pWinInfos, index, &win);
@@ -2632,19 +3143,54 @@ static SResultWindowInfo* addNewSessionWindow(SArray* pWinInfos, TSKEY ts) {
}
SArray* getWinInfos(SStreamAggSupporter* pAggSup, uint64_t groupId) {
- void** ite = taosHashGet(pAggSup->pResultRows, &groupId, sizeof(uint64_t));
+ void** ite = taosHashGet(pAggSup->pResultRows, &groupId, sizeof(uint64_t));
SArray* pWinInfos = NULL;
if (ite == NULL) {
pWinInfos = taosArrayInit(1024, pAggSup->valueSize);
- taosHashPut(pAggSup->pResultRows, &groupId, sizeof(uint64_t), &pWinInfos, sizeof(void *));
+ taosHashPut(pAggSup->pResultRows, &groupId, sizeof(uint64_t), &pWinInfos, sizeof(void*));
} else {
pWinInfos = *ite;
}
return pWinInfos;
}
-SResultWindowInfo* getSessionTimeWindow(SStreamAggSupporter* pAggSup, TSKEY startTs,
- TSKEY endTs, uint64_t groupId, int64_t gap, int32_t* pIndex) {
+// don't add new window
+SResultWindowInfo* getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
+ int64_t gap, int32_t* pIndex) {
+ SArray* pWinInfos = getWinInfos(pAggSup, groupId);
+ pAggSup->pCurWins = pWinInfos;
+
+ int32_t size = taosArrayGetSize(pWinInfos);
+ if (size == 0) {
+ return NULL;
+ }
+ // find the first position which is smaller than the key
+ int32_t index = binarySearch(pWinInfos, size, startTs, TSDB_ORDER_DESC, getSessionWindowEndkey);
+ SResultWindowInfo* pWin = NULL;
+ if (index >= 0) {
+ pWin = taosArrayGet(pWinInfos, index);
+ if (isInWindow(pWin, startTs, gap)) {
+ *pIndex = index;
+ return pWin;
+ }
+ }
+
+ if (index + 1 < size) {
+ pWin = taosArrayGet(pWinInfos, index + 1);
+ if (isInWindow(pWin, startTs, gap)) {
+ *pIndex = index + 1;
+ return pWin;
+ } else if (endTs != INT64_MIN && isInWindow(pWin, endTs, gap)) {
+ *pIndex = index + 1;
+ return pWin;
+ }
+ }
+
+ return NULL;
+}
+
+SResultWindowInfo* getSessionTimeWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
+ int64_t gap, int32_t* pIndex) {
SArray* pWinInfos = getWinInfos(pAggSup, groupId);
pAggSup->pCurWins = pWinInfos;
@@ -2683,10 +3229,10 @@ SResultWindowInfo* getSessionTimeWindow(SStreamAggSupporter* pAggSup, TSKEY star
return insertNewSessionWindow(pWinInfos, startTs, index + 1);
}
-int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
- TSKEY* pEndTs, int32_t rows, int32_t start, int64_t gap, SHashObj* pStDeleted) {
+int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs, TSKEY* pEndTs, int32_t rows,
+ int32_t start, int64_t gap, SHashObj* pStDeleted) {
for (int32_t i = start; i < rows; ++i) {
- if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap)) ) {
+ if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
return i - start;
}
if (pWinInfo->win.skey > pStartTs[i]) {
@@ -2742,7 +3288,7 @@ static int32_t doOneWindowAggImpl(int32_t tsColId, SOptrBasicInfo* pBinfo, SStre
SColumnInfoData* pTimeWindowData, SSDataBlock* pSDataBlock,
SResultWindowInfo* pCurWin, SResultRow** pResult, int32_t startIndex, int32_t winRows,
int32_t numOutput, SOperatorInfo* pOperator) {
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, tsColId);
@@ -2755,19 +3301,22 @@ static int32_t doOneWindowAggImpl(int32_t tsColId, SOptrBasicInfo* pBinfo, SStre
updateTimeWindowInfo(pTimeWindowData, &pCurWin->win, false);
doApplyFunctions(pTaskInfo, pSup->pCtx, &pCurWin->win, pTimeWindowData, startIndex, winRows, tsCols,
pSDataBlock->info.rows, numOutput, TSDB_ORDER_ASC);
+ SFilePage* bufPage = getBufPage(pAggSup->pResultBuf, pCurWin->pos.pageId);
+ setBufPageDirty(bufPage, true);
+ releaseBufPage(pAggSup->pResultBuf, bufPage);
return TSDB_CODE_SUCCESS;
}
static int32_t doOneWindowAgg(SStreamSessionAggOperatorInfo* pInfo, SSDataBlock* pSDataBlock,
SResultWindowInfo* pCurWin, SResultRow** pResult, int32_t startIndex, int32_t winRows,
- int32_t numOutput, SOperatorInfo * pOperator) {
+ int32_t numOutput, SOperatorInfo* pOperator) {
return doOneWindowAggImpl(pInfo->primaryTsIndex, &pInfo->binfo, &pInfo->streamAggSup, &pInfo->twAggSup.timeWindowData,
pSDataBlock, pCurWin, pResult, startIndex, winRows, numOutput, pOperator);
}
static int32_t doOneStateWindowAgg(SStreamStateAggOperatorInfo* pInfo, SSDataBlock* pSDataBlock,
SResultWindowInfo* pCurWin, SResultRow** pResult, int32_t startIndex,
- int32_t winRows, int32_t numOutput, SOperatorInfo * pOperator) {
+ int32_t winRows, int32_t numOutput, SOperatorInfo* pOperator) {
return doOneWindowAggImpl(pInfo->primaryTsIndex, &pInfo->binfo, &pInfo->streamAggSup, &pInfo->twAggSup.timeWindowData,
pSDataBlock, pCurWin, pResult, startIndex, winRows, numOutput, pOperator);
}
@@ -2788,7 +3337,7 @@ int32_t getNumCompactWindow(SArray* pWinInfos, int32_t startIndex, int64_t gap)
void compactTimeWindow(SStreamSessionAggOperatorInfo* pInfo, int32_t startIndex, int32_t num, uint64_t groupId,
int32_t numOfOutput, SHashObj* pStUpdated, SHashObj* pStDeleted, SOperatorInfo* pOperator) {
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SResultWindowInfo* pCurWin = taosArrayGet(pInfo->streamAggSup.pCurWins, startIndex);
@@ -2811,16 +3360,17 @@ void compactTimeWindow(SStreamSessionAggOperatorInfo* pInfo, int32_t startIndex,
pWinInfo->isOutput = false;
}
taosArrayRemove(pInfo->streamAggSup.pCurWins, i);
+ SFilePage* tmpPage = getBufPage(pInfo->streamAggSup.pResultBuf, pWinInfo->pos.pageId);
+ releaseBufPage(pInfo->streamAggSup.pResultBuf, tmpPage);
}
+ SFilePage* bufPage = getBufPage(pInfo->streamAggSup.pResultBuf, pCurWin->pos.pageId);
+ ASSERT(num > 0);
+ setBufPageDirty(bufPage, true);
+ releaseBufPage(pInfo->streamAggSup.pResultBuf, bufPage);
}
-typedef struct SWinRes {
- TSKEY ts;
- uint64_t groupId;
-} SWinRes;
-
-static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock,
- SHashObj* pStUpdated, SHashObj* pStDeleted, bool hasEndTs) {
+static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SHashObj* pStUpdated,
+ SHashObj* pStDeleted, bool hasEndTs) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
bool masterScan = true;
@@ -2836,27 +3386,27 @@ static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSData
SResultRow* pResult = NULL;
int32_t winRows = 0;
- if (pSDataBlock->pDataBlock != NULL) {
- SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
- startTsCols = (int64_t*) pStartTsCol->pData;
- SColumnInfoData* pEndTsCol = NULL;
- if (hasEndTs) {
- pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
- } else {
- pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
- }
- endTsCols = (int64_t*) pEndTsCol->pData;
+ ASSERT(pSDataBlock->pDataBlock);
+ SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
+ startTsCols = (int64_t*)pStartTsCol->pData;
+ SColumnInfoData* pEndTsCol = NULL;
+ if (hasEndTs) {
+ pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
} else {
- return;
+ pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
}
+ endTsCols = (int64_t*)pEndTsCol->pData;
SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
for (int32_t i = 0; i < pSDataBlock->info.rows;) {
+ if (pInfo->ignoreExpiredData && isOverdue(endTsCols[i], &pInfo->twAggSup)) {
+ i++;
+ continue;
+ }
int32_t winIndex = 0;
- SResultWindowInfo* pCurWin = getSessionTimeWindow(pAggSup, startTsCols[i],
- endTsCols[i], groupId, gap, &winIndex);
- winRows = updateSessionWindowInfo(pCurWin, startTsCols, endTsCols,
- pSDataBlock->info.rows, i, pInfo->gap, pStDeleted);
+ SResultWindowInfo* pCurWin = getSessionTimeWindow(pAggSup, startTsCols[i], endTsCols[i], groupId, gap, &winIndex);
+ winRows =
+ updateSessionWindowInfo(pCurWin, startTsCols, endTsCols, pSDataBlock->info.rows, i, pInfo->gap, pStDeleted);
code = doOneWindowAgg(pInfo, pSDataBlock, pCurWin, &pResult, i, winRows, numOfOutput, pOperator);
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
@@ -2879,14 +3429,47 @@ static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSData
}
}
-static void doClearSessionWindows(SStreamAggSupporter* pAggSup, SExprSupp* pSup, SSDataBlock* pBlock,
- int32_t tsIndex, int32_t numOfOutput, int64_t gap, SArray* result) {
+void deleteWindow(SArray* pWinInfos, int32_t index) {
+ ASSERT(index >= 0 && index < taosArrayGetSize(pWinInfos));
+ taosArrayRemove(pWinInfos, index);
+}
+
+static void doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, int64_t gap, SArray* result) {
+ SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
+ TSKEY* startDatas = (TSKEY*)pStartTsCol->pData;
+ SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
+ TSKEY* endDatas = (TSKEY*)pEndTsCol->pData;
+ SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
+ uint64_t* gpDatas = (uint64_t*)pGroupCol->pData;
+ for (int32_t i = 0; i < pBlock->info.rows; i++) {
+ int32_t winIndex = 0;
+ while (1) {
+ SResultWindowInfo* pCurWin = getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], gap, &winIndex);
+ if (!pCurWin) {
+ break;
+ }
+ deleteWindow(pAggSup->pCurWins, winIndex);
+ if (result) {
+ taosArrayPush(result, pCurWin);
+ }
+ }
+ }
+}
+
+static void doClearSessionWindows(SStreamAggSupporter* pAggSup, SExprSupp* pSup, SSDataBlock* pBlock, int32_t tsIndex,
+ int32_t numOfOutput, int64_t gap, SArray* result) {
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, tsIndex);
TSKEY* tsCols = (TSKEY*)pColDataInfo->pData;
int32_t step = 0;
for (int32_t i = 0; i < pBlock->info.rows; i += step) {
int32_t winIndex = 0;
- SResultWindowInfo* pCurWin = getSessionTimeWindow(pAggSup, tsCols[i], INT64_MIN, pBlock->info.groupId, gap, &winIndex);
+ SResultWindowInfo* pCurWin =
+ getCurSessionWindow(pAggSup, tsCols[i], INT64_MIN, pBlock->info.groupId, gap, &winIndex);
+ if (!pCurWin || pCurWin->pos.pageId == -1) {
+ // window has been closed.
+ step = 1;
+ continue;
+ }
step = updateSessionWindowInfo(pCurWin, tsCols, NULL, pBlock->info.rows, i, gap, NULL);
ASSERT(isInWindow(pCurWin, tsCols[i], gap));
doClearWindowImpl(&pCurWin->pos, pAggSup->pResultBuf, pSup, numOfOutput);
@@ -2911,16 +3494,22 @@ static int32_t copyUpdateResult(SHashObj* pStUpdated, SArray* pUpdated) {
*(int64_t*)pos->key = ((SWinRes*)pData)->ts;
taosArrayPush(pUpdated, &pos);
}
+ taosArraySort(pUpdated, resultrowComparAsc);
return TSDB_CODE_SUCCESS;
}
void doBuildDeleteDataBlock(SHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
blockDataCleanup(pBlock);
+ int32_t size = taosHashGetSize(pStDeleted);
+ if (size == 0) {
+ return;
+ }
+ blockDataEnsureCapacity(pBlock, size);
size_t keyLen = 0;
while (((*Ite) = taosHashIterate(pStDeleted, *Ite)) != NULL) {
- SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
colDataAppend(pColInfoData, pBlock->info.rows, *Ite, false);
- for (int32_t i = 1; i < pBlock->info.numOfCols; i++) {
+ for (int32_t i = 1; i < taosArrayGetSize(pBlock->pDataBlock); i++) {
pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
colDataAppendNULL(pColInfoData, pBlock->info.rows);
}
@@ -2936,7 +3525,7 @@ void doBuildDeleteDataBlock(SHashObj* pStDeleted, SSDataBlock* pBlock, void** It
static void rebuildTimeWindow(SStreamSessionAggOperatorInfo* pInfo, SArray* pWinArray, int32_t groupId,
int32_t numOfOutput, SOperatorInfo* pOperator) {
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
int32_t size = taosArrayGetSize(pWinArray);
@@ -2955,20 +3544,27 @@ static void rebuildTimeWindow(SStreamSessionAggOperatorInfo* pInfo, SArray* pWin
int32_t chWinSize = taosArrayGetSize(pChWins);
int32_t index = binarySearch(pChWins, chWinSize, pParentWin->win.skey, TSDB_ORDER_DESC, getSessionWindowEndkey);
if (index < 0) {
- index = 0;
+ index = 0;
}
for (int32_t k = index; k < chWinSize; k++) {
- SResultWindowInfo* pcw = taosArrayGet(pChWins, k);
- if (pParentWin->win.skey <= pcw->win.skey && pcw->win.ekey <= pParentWin->win.ekey) {
+ SResultWindowInfo* pChWin = taosArrayGet(pChWins, k);
+ if (pParentWin->win.skey <= pChWin->win.skey && pChWin->win.ekey <= pParentWin->win.ekey) {
SResultRow* pChResult = NULL;
- setWindowOutputBuf(pcw, &pChResult, pChild->exprSupp.pCtx, groupId, numOfOutput,
+ setWindowOutputBuf(pChWin, &pChResult, pChild->exprSupp.pCtx, groupId, numOfOutput,
pChild->exprSupp.rowEntryInfoOffset, &pChInfo->streamAggSup, pTaskInfo);
compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo);
+ SFilePage* bufPage = getBufPage(pChInfo->streamAggSup.pResultBuf, pChWin->pos.pageId);
+ releaseBufPage(pChInfo->streamAggSup.pResultBuf, bufPage);
continue;
+ } else if (!pChWin->isClosed) {
+ break;
}
- break;
}
}
+ SFilePage* bufPage = getBufPage(pInfo->streamAggSup.pResultBuf, pParentWin->pos.pageId);
+ ASSERT(size > 0);
+ setBufPageDirty(bufPage, true);
+ releaseBufPage(pInfo->streamAggSup.pResultBuf, bufPage);
}
}
@@ -2976,25 +3572,33 @@ typedef SResultWindowInfo* (*__get_win_info_)(void*);
SResultWindowInfo* getResWinForSession(void* pData) { return (SResultWindowInfo*)pData; }
SResultWindowInfo* getResWinForState(void* pData) { return &((SStateWindowInfo*)pData)->winInfo; }
-int32_t closeSessionWindow(SHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SArray* pClosed,
- __get_win_info_ fn) {
+int32_t closeSessionWindow(SHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SArray* pClosed, __get_win_info_ fn,
+ bool delete) {
// Todo(liuyao) save window to tdb
- void **pIte = NULL;
+ void** pIte = NULL;
size_t keyLen = 0;
while ((pIte = taosHashIterate(pHashMap, pIte)) != NULL) {
uint64_t* pGroupId = taosHashGetKey(pIte, &keyLen);
- SArray *pWins = (SArray *) (*pIte);
- int32_t size = taosArrayGetSize(pWins);
+ SArray* pWins = (SArray*)(*pIte);
+ int32_t size = taosArrayGetSize(pWins);
for (int32_t i = 0; i < size; i++) {
void* pWin = taosArrayGet(pWins, i);
SResultWindowInfo* pSeWin = fn(pWin);
- if (pSeWin->win.ekey < pTwSup->maxTs - pTwSup->waterMark) {
+ if (isCloseWindow(&pSeWin->win, pTwSup)) {
if (!pSeWin->isClosed) {
pSeWin->isClosed = true;
- if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
+ if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
int32_t code = saveResult(pSeWin->win.skey, pSeWin->pos.pageId, pSeWin->pos.offset, *pGroupId, pClosed);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
pSeWin->isOutput = true;
}
+ if (delete) {
+ deleteWindow(pWins, i);
+ i--;
+ size = taosArrayGetSize(pWins);
+ }
}
continue;
}
@@ -3004,10 +3608,20 @@ int32_t closeSessionWindow(SHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SArra
return TSDB_CODE_SUCCESS;
}
+static void closeChildSessionWindow(SArray* pChildren, TSKEY maxTs, bool delete) {
+ int32_t size = taosArrayGetSize(pChildren);
+ for (int32_t i = 0; i < size; i++) {
+ SOperatorInfo* pChildOp = taosArrayGetP(pChildren, i);
+ SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
+ pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
+ closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL, getResWinForSession, delete);
+ }
+}
+
int32_t getAllSessionWindow(SHashObj* pHashMap, SArray* pClosed, __get_win_info_ fn) {
- void **pIte = NULL;
+ void** pIte = NULL;
while ((pIte = taosHashIterate(pHashMap, pIte)) != NULL) {
- SArray *pWins = (SArray *) (*pIte);
+ SArray* pWins = (SArray*)(*pIte);
int32_t size = taosArrayGetSize(pWins);
for (int32_t i = 0; i < size; i++) {
void* pWin = taosArrayGet(pWins, i);
@@ -3021,6 +3635,14 @@ int32_t getAllSessionWindow(SHashObj* pHashMap, SArray* pClosed, __get_win_info_
return TSDB_CODE_SUCCESS;
}
+static void copyDeleteWindowInfo(SArray* pResWins, SHashObj* pStDeleted) {
+ int32_t size = taosArrayGetSize(pResWins);
+ for (int32_t i = 0; i < size; i++) {
+ SResultWindowInfo* pWinInfo = taosArrayGet(pResWins, i);
+ taosHashPut(pStDeleted, &pWinInfo->pos, sizeof(SResultRowPosition), &pWinInfo->win.skey, sizeof(TSKEY));
+ }
+}
+
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
SExprSupp* pSup = &pOperator->exprSupp;
SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
@@ -3031,12 +3653,14 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
} else if (pOperator->status == OP_RES_TO_RETURN) {
doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
if (pInfo->pDelRes->info.rows > 0) {
+ printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "Final Session" : "Single Session");
return pInfo->pDelRes;
}
doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
doSetOperatorCompleted(pOperator);
}
+ printDataBlock(pBInfo->pRes, IS_FINAL_OP(pInfo) ? "Final Session" : "Single Session");
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
}
@@ -3049,25 +3673,46 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
if (pBlock == NULL) {
break;
}
+ printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "Final Session Recv" : "Single Session Recv");
- if (pBlock->info.type == STREAM_REPROCESS) {
+ if (pBlock->info.type == STREAM_CLEAR) {
SArray* pWins = taosArrayInit(16, sizeof(SResultWindowInfo));
- doClearSessionWindows(&pInfo->streamAggSup, &pOperator->exprSupp, pBlock, 0, pOperator->exprSupp.numOfExprs, pInfo->gap, pWins);
+ doClearSessionWindows(&pInfo->streamAggSup, &pOperator->exprSupp, pBlock, 0, pOperator->exprSupp.numOfExprs, 0,
+ pWins);
if (IS_FINAL_OP(pInfo)) {
int32_t childIndex = getChildIndex(pBlock);
SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
doClearSessionWindows(&pChildInfo->streamAggSup, &pChildOp->exprSupp, pBlock, 0, pChildOp->exprSupp.numOfExprs,
- pChildInfo->gap, NULL);
+ 0, NULL);
rebuildTimeWindow(pInfo, pWins, pBlock->info.groupId, pOperator->exprSupp.numOfExprs, pOperator);
}
taosArrayDestroy(pWins);
continue;
+ } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT) {
+ SArray* pWins = taosArrayInit(16, sizeof(SResultWindowInfo));
+ // gap must be 0
+ doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, 0, pWins);
+ if (IS_FINAL_OP(pInfo)) {
+ int32_t childIndex = getChildIndex(pBlock);
+ SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
+ SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
+ // gap must be 0
+ doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, 0, NULL);
+ rebuildTimeWindow(pInfo, pWins, pBlock->info.groupId, pOperator->exprSupp.numOfExprs, pOperator);
+ }
+ copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
+ taosArrayDestroy(pWins);
+ continue;
} else if (pBlock->info.type == STREAM_GET_ALL) {
getAllSessionWindow(pInfo->streamAggSup.pResultRows, pUpdated, getResWinForSession);
continue;
}
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pSup->pCtx, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
doStreamSessionAggImpl(pOperator, pBlock, pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo));
@@ -3076,13 +3721,14 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
int32_t size = taosArrayGetSize(pInfo->pChildren);
// if chIndex + 1 - size > 0, add new child
for (int32_t i = 0; i < chIndex + 1 - size; i++) {
- SOperatorInfo* pChildOp = createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0);
+ SOperatorInfo* pChildOp =
+ createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0);
if (!pChildOp) {
longjmp(pOperator->pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
taosArrayPush(pInfo->pChildren, &pChildOp);
}
- SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
+ SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
setInputDataBlock(pChildOp, pChildOp->exprSupp.pCtx, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true);
}
@@ -3093,27 +3739,29 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
// restore the value
pOperator->status = OP_RES_TO_RETURN;
- closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pUpdated,
- getResWinForSession);
+ closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pUpdated, getResWinForSession,
+ pInfo->ignoreExpiredData);
+ closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs, pInfo->ignoreExpiredData);
copyUpdateResult(pStUpdated, pUpdated);
taosHashCleanup(pStUpdated);
- finalizeUpdatedResult(pSup->numOfExprs, pInfo->streamAggSup.pResultBuf, pUpdated,
- pSup->rowEntryInfoOffset);
+ finalizeUpdatedResult(pSup->numOfExprs, pInfo->streamAggSup.pResultBuf, pUpdated, pSup->rowEntryInfoOffset);
initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated);
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
if (pInfo->pDelRes->info.rows > 0) {
+ printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "Final Session" : "Single Session");
return pInfo->pDelRes;
}
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
+ printDataBlock(pBInfo->pRes, IS_FINAL_OP(pInfo) ? "Final Session" : "Single Session");
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
}
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
- void **pIte = NULL;
+ void** pIte = NULL;
while ((pIte = taosHashIterate(pInfo->streamAggSup.pResultRows, pIte)) != NULL) {
- SArray *pWins = (SArray *) (*pIte);
+ SArray* pWins = (SArray*)(*pIte);
int32_t size = taosArrayGetSize(pWins);
for (int32_t i = 0; i < size; i++) {
SResultWindowInfo* pWin = (SResultWindowInfo*)taosArrayGet(pWins, i);
@@ -3139,27 +3787,33 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
SOptrBasicInfo* pBInfo = &pInfo->binfo;
TSKEY maxTs = INT64_MIN;
SExprSupp* pSup = &pOperator->exprSupp;
-
+
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
} else if (pOperator->status == OP_RES_TO_RETURN) {
- doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
- if (pInfo->pDelRes->info.rows > 0) {
+ doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
+ if (pBInfo->pRes->info.rows > 0) {
+ printDataBlock(pBInfo->pRes, "Semi Session");
+ return pBInfo->pRes;
+ }
+
+ // doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
+ if (pInfo->pDelRes->info.rows > 0 && !pInfo->returnDelete) {
+ pInfo->returnDelete = true;
+ printDataBlock(pInfo->pDelRes, "Semi Session");
return pInfo->pDelRes;
}
- doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
- if (pInfo->binfo.pRes->info.rows == 0) {
- pOperator->status = OP_EXEC_DONE;
- if (pInfo->pUpdateRes->info.rows == 0) {
- // semi interval operator clear disk buffer
- clearStreamSessionOperator(pInfo);
- return NULL;
- }
+
+ if (pInfo->pUpdateRes->info.rows > 0) {
// process the rest of the data
pOperator->status = OP_OPENED;
+ printDataBlock(pInfo->pUpdateRes, "Semi Session");
return pInfo->pUpdateRes;
}
- return pInfo->binfo.pRes;
+ // semi interval operator clear disk buffer
+ clearStreamSessionOperator(pInfo);
+ pOperator->status = OP_EXEC_DONE;
+ return NULL;
}
_hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
@@ -3169,22 +3823,32 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
while (1) {
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
if (pBlock == NULL) {
- clearUpdateDataBlock(pInfo->pUpdateRes);
+ clearSpecialDataBlock(pInfo->pUpdateRes);
break;
}
- if (pBlock->info.type == STREAM_REPROCESS) {
+ if (pBlock->info.type == STREAM_CLEAR) {
SArray* pWins = taosArrayInit(16, sizeof(SResultWindowInfo));
- doClearSessionWindows(&pInfo->streamAggSup, pSup, pBlock, 0, pSup->numOfExprs, pInfo->gap, pWins);
+ doClearSessionWindows(&pInfo->streamAggSup, pSup, pBlock, 0, pSup->numOfExprs, 0, pWins);
removeSessionResults(pStUpdated, pWins);
taosArrayDestroy(pWins);
copyUpdateDataBlock(pInfo->pUpdateRes, pBlock, pInfo->primaryTsIndex);
break;
+ } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT) {
+ // gap must be 0
+ doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, 0, NULL);
+ copyDataBlock(pInfo->pDelRes, pBlock);
+ pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
+ break;
} else if (pBlock->info.type == STREAM_GET_ALL) {
getAllSessionWindow(pInfo->streamAggSup.pResultRows, pUpdated, getResWinForSession);
continue;
}
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pSup->pCtx, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
doStreamSessionAggImpl(pOperator, pBlock, pStUpdated, pInfo->pStDeleted, false);
@@ -3203,26 +3867,34 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
finalizeUpdatedResult(pOperator->exprSupp.numOfExprs, pInfo->streamAggSup.pResultBuf, pUpdated,
pSup->rowEntryInfoOffset);
initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated);
- blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
- doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
- if (pInfo->pDelRes->info.rows > 0) {
+ blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
+
+ doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
+ if (pBInfo->pRes->info.rows > 0) {
+ printDataBlock(pBInfo->pRes, "Semi Session");
+ return pBInfo->pRes;
+ }
+
+ // doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
+ if (pInfo->pDelRes->info.rows > 0 && !pInfo->returnDelete) {
+ pInfo->returnDelete = true;
+ printDataBlock(pInfo->pDelRes, "Semi Session");
return pInfo->pDelRes;
}
- doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
- if (pInfo->binfo.pRes->info.rows == 0) {
- pOperator->status = OP_EXEC_DONE;
- if (pInfo->pUpdateRes->info.rows == 0) {
- return NULL;
- }
+
+ if (pInfo->pUpdateRes->info.rows > 0) {
// process the rest of the data
pOperator->status = OP_OPENED;
+ printDataBlock(pInfo->pUpdateRes, "Semi Session");
return pInfo->pUpdateRes;
}
- return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
+
+ pOperator->status = OP_EXEC_DONE;
+ return NULL;
}
-SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream,
- SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
+SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
+ SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
int32_t code = TSDB_CODE_OUT_OF_MEMORY;
SOperatorInfo* pOperator = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo);
if (pOperator == NULL) {
@@ -3236,19 +3908,18 @@ SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream
} else {
pInfo->isFinal = false;
pInfo->pUpdateRes = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
- pInfo->pUpdateRes->info.type = STREAM_REPROCESS;
+ pInfo->pUpdateRes->info.type = STREAM_CLEAR;
blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
pOperator->name = "StreamSessionSemiAggOperator";
pOperator->fpSet =
- createOperatorFpSet(operatorDummyOpenFn, doStreamSessionSemiAgg, NULL, NULL, destroyStreamSessionAggOperatorInfo,
- aggEncodeResultRow, aggDecodeResultRow, NULL);
+ createOperatorFpSet(operatorDummyOpenFn, doStreamSessionSemiAgg, NULL, NULL,
+ destroyStreamSessionAggOperatorInfo, aggEncodeResultRow, aggDecodeResultRow, NULL);
}
pOperator->operatorType = pPhyNode->type;
if (numOfChild > 0) {
pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
for (int32_t i = 0; i < numOfChild; i++) {
- SOperatorInfo* pChild =
- createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
+ SOperatorInfo* pChild = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
if (pChild == NULL) {
goto _error;
}
@@ -3283,6 +3954,8 @@ void destroyStreamStateOperatorInfo(void* param, int32_t numOfOutput) {
taosMemoryFreeClear(pChInfo);
}
}
+
+ taosMemoryFreeClear(param);
}
int64_t getStateWinTsKey(void* data, int32_t index) {
@@ -3366,8 +4039,8 @@ SStateWindowInfo* getStateWindowByTs(SStreamAggSupporter* pAggSup, TSKEY ts, uin
return NULL;
}
-SStateWindowInfo* getStateWindow(SStreamAggSupporter* pAggSup, TSKEY ts,
- uint64_t groupId, char* pKeyData, SColumn* pCol, int32_t* pIndex) {
+SStateWindowInfo* getStateWindow(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
+ SColumn* pCol, int32_t* pIndex) {
SArray* pWinInfos = getWinInfos(pAggSup, groupId);
pAggSup->pCurWins = pWinInfos;
int32_t size = taosArrayGetSize(pWinInfos);
@@ -3445,11 +4118,6 @@ int32_t updateStateWindowInfo(SArray* pWinInfos, int32_t winIndex, TSKEY* pTs, S
return rows - start;
}
-void deleteWindow(SArray* pWinInfos, int32_t index) {
- ASSERT(index >= 0 && index < taosArrayGetSize(pWinInfos));
- taosArrayRemove(pWinInfos, index);
-}
-
static void doClearStateWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, int32_t tsIndex, SColumn* pCol,
int32_t keyIndex, SHashObj* pSeUpdated, SHashObj* pSeDeleted) {
SColumnInfoData* pTsColInfo = taosArrayGet(pBlock->pDataBlock, tsIndex);
@@ -3496,14 +4164,17 @@ static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBl
SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
for (int32_t i = 0; i < pSDataBlock->info.rows; i += winRows) {
+ if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup)) {
+ i++;
+ continue;
+ }
char* pKeyData = colDataGetData(pKeyColInfo, i);
int32_t winIndex = 0;
bool allEqual = true;
- SStateWindowInfo* pCurWin =
- getStateWindow(pAggSup, tsCols[i], pSDataBlock->info.groupId, pKeyData,
- &pInfo->stateCol, &winIndex);
- winRows = updateStateWindowInfo(pAggSup->pCurWins, winIndex, tsCols, pKeyColInfo,
- pSDataBlock->info.rows, i, &allEqual, pInfo->pSeDeleted);
+ SStateWindowInfo* pCurWin =
+ getStateWindow(pAggSup, tsCols[i], pSDataBlock->info.groupId, pKeyData, &pInfo->stateCol, &winIndex);
+ winRows = updateStateWindowInfo(pAggSup->pCurWins, winIndex, tsCols, pKeyColInfo, pSDataBlock->info.rows, i,
+ &allEqual, pInfo->pSeDeleted);
if (!allEqual) {
taosArrayPush(pAggSup->pScanWindow, &pCurWin->winInfo.win);
taosHashRemove(pSeUpdated, &pCurWin->winInfo.pos, sizeof(SResultRowPosition));
@@ -3517,8 +4188,7 @@ static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBl
pCurWin->winInfo.isClosed = false;
if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
SWinRes value = {.ts = pCurWin->winInfo.win.skey, .groupId = groupId};
- code = taosHashPut(pSeUpdated, &pCurWin->winInfo.pos, sizeof(SResultRowPosition),
- &value, sizeof(SWinRes));
+ code = taosHashPut(pSeUpdated, &pCurWin->winInfo.pos, sizeof(SResultRowPosition), &value, sizeof(SWinRes));
if (code != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
@@ -3532,18 +4202,20 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
return NULL;
}
- SExprSupp* pSup = &pOperator->exprSupp;
+ SExprSupp* pSup = &pOperator->exprSupp;
SStreamStateAggOperatorInfo* pInfo = pOperator->info;
SOptrBasicInfo* pBInfo = &pInfo->binfo;
if (pOperator->status == OP_RES_TO_RETURN) {
doBuildDeleteDataBlock(pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
if (pInfo->pDelRes->info.rows > 0) {
+ printDataBlock(pInfo->pDelRes, "single state");
return pInfo->pDelRes;
}
doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
doSetOperatorCompleted(pOperator);
}
+ printDataBlock(pBInfo->pRes, "single state");
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
}
@@ -3556,16 +4228,27 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
if (pBlock == NULL) {
break;
}
+ printDataBlock(pBlock, "single state recv");
- if (pBlock->info.type == STREAM_REPROCESS) {
+ if (pBlock->info.type == STREAM_CLEAR) {
doClearStateWindows(&pInfo->streamAggSup, pBlock, pInfo->primaryTsIndex, &pInfo->stateCol, pInfo->stateCol.slotId,
pSeUpdated, pInfo->pSeDeleted);
continue;
+ } else if (pBlock->info.type == STREAM_DELETE_DATA) {
+ SArray* pWins = taosArrayInit(16, sizeof(SResultWindowInfo));
+ doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, 0, pWins);
+ copyDeleteWindowInfo(pWins, pInfo->pSeDeleted);
+ taosArrayDestroy(pWins);
+ continue;
} else if (pBlock->info.type == STREAM_GET_ALL) {
getAllSessionWindow(pInfo->streamAggSup.pResultRows, pUpdated, getResWinForState);
continue;
}
+ if (pInfo->scalarSupp.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pInfo->scalarSupp;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pSup->pCtx, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
doStreamStateAggImpl(pOperator, pBlock, pSeUpdated, pInfo->pSeDeleted);
@@ -3574,8 +4257,9 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
// restore the value
pOperator->status = OP_RES_TO_RETURN;
- closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pUpdated,
- getResWinForState);
+ closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pUpdated, getResWinForState,
+ pInfo->ignoreExpiredData);
+ closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs, pInfo->ignoreExpiredData);
copyUpdateResult(pSeUpdated, pUpdated);
taosHashCleanup(pSeUpdated);
@@ -3585,9 +4269,11 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
doBuildDeleteDataBlock(pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
if (pInfo->pDelRes->info.rows > 0) {
+ printDataBlock(pInfo->pDelRes, "single state");
return pInfo->pDelRes;
}
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
+ printDataBlock(pBInfo->pRes, "single state");
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
}
@@ -3616,6 +4302,15 @@ SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhys
pInfo->stateCol = extractColumnFromColumnNode(pColNode);
initResultSizeInfo(pOperator, 4096);
+ if (pStateNode->window.pExprs != NULL) {
+ int32_t numOfScalar = 0;
+ SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalar);
+ int32_t code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+ }
+
initResultRowInfo(&pInfo->binfo.resultRowInfo);
pInfo->twAggSup = (STimeWindowAggSupp){
.waterMark = pStateNode->window.watermark,
@@ -3645,9 +4340,11 @@ SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhys
_hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
pInfo->pSeDeleted = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
pInfo->pDelIterator = NULL;
- pInfo->pDelRes = createOneDataBlock(pResBlock, false);
- blockDataEnsureCapacity(pInfo->pDelRes, 64);
+ // pInfo->pDelRes = createPullDataBlock(); // todo(liuyao) for delete
+ pInfo->pDelRes = createOneDataBlock(pInfo->binfo.pRes, false); // todo(liuyao) for delete
+ pInfo->pDelRes->info.type = STREAM_DELETE_RESULT; // todo(liuyao) for delete
pInfo->pChildren = NULL;
+ pInfo->ignoreExpiredData = pStateNode->window.igExpired;
pOperator->name = "StreamStateAggOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE;
@@ -3674,48 +4371,41 @@ _error:
return NULL;
}
-typedef struct SMergeIntervalAggOperatorInfo {
- SIntervalAggOperatorInfo intervalAggOperatorInfo;
-
- bool hasGroupId;
- uint64_t groupId;
- SSDataBlock* prefetchedBlock;
- bool inputBlocksFinished;
-} SMergeIntervalAggOperatorInfo;
+void destroyMergeAlignedIntervalOperatorInfo(void* param, int32_t numOfOutput) {
+ SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
+ destroyIntervalOperatorInfo(miaInfo->intervalAggOperatorInfo, numOfOutput);
-void destroyMergeIntervalOperatorInfo(void* param, int32_t numOfOutput) {
- SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
- destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo, numOfOutput);
+ taosMemoryFreeClear(param);
}
-static int32_t outputMergeIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock, TSKEY wstartTs) {
- SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
- SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
- SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
+static int32_t outputMergeAlignedIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId,
+ SSDataBlock* pResultBlock, TSKEY wstartTs) {
+ SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
+ SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
+ SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
SExprSupp* pSup = &pOperatorInfo->exprSupp;
- bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
+ bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
SET_RES_WINDOW_KEY(iaInfo->aggSup.keyBuf, &wstartTs, TSDB_KEYSIZE, tableGroupId);
SResultRowPosition* p1 = (SResultRowPosition*)taosHashGet(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf,
GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
ASSERT(p1 != NULL);
- finalizeResultRowIntoResultDataBlock(iaInfo->aggSup.pResultBuf, p1, pSup->pCtx, pSup->pExprInfo,
- pSup->numOfExprs, pSup->rowEntryInfoOffset, pResultBlock,
- pTaskInfo);
+ finalizeResultRowIntoResultDataBlock(iaInfo->aggSup.pResultBuf, p1, pSup->pCtx, pSup->pExprInfo, pSup->numOfExprs,
+ pSup->rowEntryInfoOffset, pResultBlock, pTaskInfo);
taosHashRemove(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf, GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
return 0;
}
-static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
- int32_t scanFlag, SSDataBlock* pResultBlock) {
- SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
- SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
+static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
+ SSDataBlock* pBlock, int32_t scanFlag, SSDataBlock* pResultBlock) {
+ SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
+ SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
- SExprSupp* pSup = &pOperatorInfo->exprSupp;
+ SExprSupp* pSup = &pOperatorInfo->exprSupp;
int32_t startPos = 0;
int32_t numOfOutput = pSup->numOfExprs;
@@ -3726,18 +4416,18 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
STimeWindow win;
win.skey = blockStartTs;
- win.ekey = taosTimeAdd(win.skey, iaInfo->interval.interval, iaInfo->interval.intervalUnit, iaInfo->interval.precision) - 1;
+ win.ekey =
+ taosTimeAdd(win.skey, iaInfo->interval.interval, iaInfo->interval.intervalUnit, iaInfo->interval.precision) - 1;
- //TODO: remove the hash table usage (groupid + winkey => result row position)
- int32_t ret =
- setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
+ // TODO: remove the hash table (groupid + winkey => result row position)
+ int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
+ pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- TSKEY currTs = blockStartTs;
- TSKEY currPos = startPos;
+ TSKEY currTs = blockStartTs;
+ TSKEY currPos = startPos;
STimeWindow currWin = win;
while (1) {
++currPos;
@@ -3748,27 +4438,327 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
continue;
} else {
updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, true);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos,
- currPos - startPos, tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
+ tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
- outputMergeIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
+ outputMergeAlignedIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
currTs = tsCols[currPos];
currWin.skey = currTs;
- currWin.ekey = taosTimeAdd(currWin.skey, iaInfo->interval.interval, iaInfo->interval.intervalUnit, iaInfo->interval.precision) - 1;
+ currWin.ekey = taosTimeAdd(currWin.skey, iaInfo->interval.interval, iaInfo->interval.intervalUnit,
+ iaInfo->interval.precision) -
+ 1;
startPos = currPos;
- ret = setTimeWindowOutputBuf(pResultRowInfo, &currWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
- numOfOutput, pSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
+ ret = setTimeWindowOutputBuf(pResultRowInfo, &currWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
+ pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
}
}
updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, true);
- doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos,
- currPos - startPos, tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
+ doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
+ tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
+
+ outputMergeAlignedIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
+}
+
+static SSDataBlock* doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperator->info;
+ SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
+ if (pOperator->status == OP_EXEC_DONE) {
+ return NULL;
+ }
+
+ SExprSupp* pSup = &pOperator->exprSupp;
+ SSDataBlock* pRes = iaInfo->binfo.pRes;
+ blockDataCleanup(pRes);
+ blockDataEnsureCapacity(pRes, pOperator->resultInfo.capacity);
+
+ if (!miaInfo->inputBlocksFinished) {
+ SOperatorInfo* downstream = pOperator->pDownstream[0];
+ int32_t scanFlag = MAIN_SCAN;
+ while (1) {
+ SSDataBlock* pBlock = NULL;
+ if (miaInfo->prefetchedBlock == NULL) {
+ pBlock = downstream->fpSet.getNextFn(downstream);
+ } else {
+ pBlock = miaInfo->prefetchedBlock;
+ miaInfo->groupId = pBlock->info.groupId;
+ miaInfo->prefetchedBlock = NULL;
+ }
+
+ if (pBlock == NULL) {
+ miaInfo->inputBlocksFinished = true;
+ break;
+ }
+
+ if (!miaInfo->hasGroupId) {
+ miaInfo->hasGroupId = true;
+ miaInfo->groupId = pBlock->info.groupId;
+ } else if (miaInfo->groupId != pBlock->info.groupId) {
+ miaInfo->prefetchedBlock = pBlock;
+ break;
+ }
+
+ getTableScanInfo(pOperator, &iaInfo->order, &scanFlag);
+ setInputDataBlock(pOperator, pSup->pCtx, pBlock, iaInfo->order, scanFlag, true);
+ doMergeAlignedIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
+ doFilter(miaInfo->pCondition, pRes);
+ if (pRes->info.rows >= pOperator->resultInfo.capacity) {
+ break;
+ }
+ }
+
+ pRes->info.groupId = miaInfo->groupId;
+ }
+ miaInfo->hasGroupId = false;
+
+ if (miaInfo->inputBlocksFinished) {
+ doSetOperatorCompleted(pOperator);
+ }
- outputMergeIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
+ size_t rows = pRes->info.rows;
+ pOperator->resultInfo.totalRows += rows;
+ return (rows == 0) ? NULL : pRes;
+}
+
+SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo,
+ int32_t numOfCols, SSDataBlock* pResBlock, SInterval* pInterval,
+ int32_t primaryTsSlotId, SNode* pCondition,
+ SExecTaskInfo* pTaskInfo) {
+ SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
+ SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
+ if (miaInfo == NULL || pOperator == NULL) {
+ goto _error;
+ }
+
+ miaInfo->intervalAggOperatorInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
+ if (miaInfo->intervalAggOperatorInfo == NULL) {
+ goto _error;
+ }
+
+ SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
+ SExprSupp* pSup = &pOperator->exprSupp;
+
+ miaInfo->pCondition = pCondition;
+ iaInfo->win = pTaskInfo->window;
+ iaInfo->order = TSDB_ORDER_ASC;
+ iaInfo->interval = *pInterval;
+ iaInfo->execModel = pTaskInfo->execModel;
+ iaInfo->primaryTsIndex = primaryTsSlotId;
+
+ size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
+ initResultSizeInfo(pOperator, 4096);
+
+ int32_t code =
+ initAggInfo(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str);
+ initBasicInfo(&iaInfo->binfo, pResBlock);
+
+ initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
+
+ iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, numOfCols, iaInfo);
+ if (iaInfo->timeWindowInterpo) {
+ iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SResultRowPosition));
+ }
+
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+
+ initResultRowInfo(&iaInfo->binfo.resultRowInfo);
+
+ pOperator->name = "TimeMergeAlignedIntervalAggOperator";
+ pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL;
+ pOperator->blocking = false;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->exprSupp.pExprInfo = pExprInfo;
+ pOperator->pTaskInfo = pTaskInfo;
+ pOperator->exprSupp.numOfExprs = numOfCols;
+ pOperator->info = miaInfo;
+
+ pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doMergeAlignedIntervalAgg, NULL, NULL,
+ destroyMergeAlignedIntervalOperatorInfo, NULL, NULL, NULL);
+
+ code = appendDownstream(pOperator, &downstream, 1);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
+
+ return pOperator;
+
+_error:
+ destroyMergeAlignedIntervalOperatorInfo(miaInfo, numOfCols);
+ taosMemoryFreeClear(miaInfo);
+ taosMemoryFreeClear(pOperator);
+ pTaskInfo->code = code;
+ return NULL;
+}
+
+//=====================================================================================================================
+// merge interval operator
+typedef struct SMergeIntervalAggOperatorInfo {
+ SIntervalAggOperatorInfo intervalAggOperatorInfo;
+ SList* groupIntervals;
+ SListIter groupIntervalsIter;
+ bool hasGroupId;
+ uint64_t groupId;
+ SSDataBlock* prefetchedBlock;
+ bool inputBlocksFinished;
+} SMergeIntervalAggOperatorInfo;
+
+typedef struct SGroupTimeWindow {
+ uint64_t groupId;
+ STimeWindow window;
+} SGroupTimeWindow;
+
+void destroyMergeIntervalOperatorInfo(void* param, int32_t numOfOutput) {
+ SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
+ tdListFree(miaInfo->groupIntervals);
+ destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo, numOfOutput);
+
+ taosMemoryFreeClear(param);
+}
+
+static int32_t finalizeWindowResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, STimeWindow* win,
+ SSDataBlock* pResultBlock) {
+ SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
+ SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
+ SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
+ bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
+ SExprSupp* pExprSup = &pOperatorInfo->exprSupp;
+
+ SET_RES_WINDOW_KEY(iaInfo->aggSup.keyBuf, &win->skey, TSDB_KEYSIZE, tableGroupId);
+ SResultRowPosition* p1 = (SResultRowPosition*)taosHashGet(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf,
+ GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
+ ASSERT(p1 != NULL);
+ finalizeResultRowIntoResultDataBlock(iaInfo->aggSup.pResultBuf, p1, pExprSup->pCtx, pExprSup->pExprInfo,
+ pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset, pResultBlock, pTaskInfo);
+ taosHashRemove(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf, GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t outputPrevIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock,
+ STimeWindow* newWin) {
+ SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
+ SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
+ SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
+ bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
+ SExprSupp* pExprSup = &pOperatorInfo->exprSupp;
+
+ SGroupTimeWindow groupTimeWindow = {.groupId = tableGroupId, .window = *newWin};
+ tdListAppend(miaInfo->groupIntervals, &groupTimeWindow);
+
+ SListIter iter = {0};
+ tdListInitIter(miaInfo->groupIntervals, &iter, TD_LIST_FORWARD);
+ SListNode* listNode = NULL;
+ while ((listNode = tdListNext(&iter)) != NULL) {
+ SGroupTimeWindow* prevGrpWin = (SGroupTimeWindow*)listNode->data;
+ if (prevGrpWin->groupId != tableGroupId) {
+ continue;
+ }
+ STimeWindow* prevWin = &prevGrpWin->window;
+ if ((ascScan && newWin->skey > prevWin->ekey) || ((!ascScan) && newWin->skey < prevWin->ekey)) {
+ finalizeWindowResult(pOperatorInfo, tableGroupId, prevWin, pResultBlock);
+ tdListPopNode(miaInfo->groupIntervals, listNode);
+ }
+ }
+
+ return 0;
+}
+
+static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
+ int32_t scanFlag, SSDataBlock* pResultBlock) {
+ SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
+ SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
+
+ SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
+ SExprSupp* pExprSup = &pOperatorInfo->exprSupp;
+
+ int32_t startPos = 0;
+ int32_t numOfOutput = pExprSup->numOfExprs;
+ int64_t* tsCols = extractTsCol(pBlock, iaInfo);
+ uint64_t tableGroupId = pBlock->info.groupId;
+ bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
+ TSKEY blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
+ SResultRow* pResult = NULL;
+
+ STimeWindow win =
+ getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval, iaInfo->order);
+
+ int32_t ret =
+ setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
+ numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
+ if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
+ longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ TSKEY ekey = ascScan ? win.ekey : win.skey;
+ int32_t forwardRows =
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->order);
+ ASSERT(forwardRows > 0);
+
+ // prev time window not interpolation yet.
+ if (iaInfo->timeWindowInterpo) {
+ SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult);
+ doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);
+
+ // restore current time window
+ ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
+ numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ // window start key interpolation
+ doWindowBorderInterpolation(iaInfo, pBlock, pResult, &win, startPos, forwardRows, pExprSup);
+ }
+
+ updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, true);
+ doApplyFunctions(pTaskInfo, pExprSup->pCtx, &win, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pBlock->info.rows, numOfOutput, iaInfo->order);
+ doCloseWindow(pResultRowInfo, iaInfo, pResult);
+
+ // output previous interval results after this interval (&win) is closed
+ outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &win);
+
+ STimeWindow nextWin = win;
+ while (1) {
+ int32_t prevEndPos = forwardRows - 1 + startPos;
+ startPos = getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->order);
+ if (startPos < 0) {
+ break;
+ }
+
+ // null data, failed to allocate more memory buffer
+ int32_t code =
+ setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
+ pExprSup->pCtx, numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
+ if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
+ longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ ekey = ascScan ? nextWin.ekey : nextWin.skey;
+ forwardRows =
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->order);
+
+ // window start(end) key interpolation
+ doWindowBorderInterpolation(iaInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pExprSup);
+
+ updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, true);
+ doApplyFunctions(pTaskInfo, pExprSup->pCtx, &nextWin, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
+ tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
+ doCloseWindow(pResultRowInfo, iaInfo, pResult);
+
+ // output previous interval results after this interval (&nextWin) is closed
+ outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &nextWin);
+ }
+
+ if (iaInfo->timeWindowInterpo) {
+ saveDataBlockLastRow(iaInfo->pPrevValues, pBlock, iaInfo->pInterpCols);
+ }
}
static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
@@ -3776,11 +4766,12 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
SMergeIntervalAggOperatorInfo* miaInfo = pOperator->info;
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
+ SExprSupp* pExpSupp = &pOperator->exprSupp;
+
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
}
- SExprSupp* pSup = &pOperator->exprSupp;
SSDataBlock* pRes = iaInfo->binfo.pRes;
blockDataCleanup(pRes);
blockDataEnsureCapacity(pRes, pOperator->resultInfo.capacity);
@@ -3795,9 +4786,11 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
} else {
pBlock = miaInfo->prefetchedBlock;
miaInfo->groupId = pBlock->info.groupId;
+ miaInfo->prefetchedBlock = NULL;
}
if (pBlock == NULL) {
+ tdListInitIter(miaInfo->groupIntervals, &miaInfo->groupIntervalsIter, TD_LIST_FORWARD);
miaInfo->inputBlocksFinished = true;
break;
}
@@ -3811,7 +4804,7 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
}
getTableScanInfo(pOperator, &iaInfo->order, &scanFlag);
- setInputDataBlock(pOperator, pSup->pCtx, pBlock, iaInfo->order, scanFlag, true);
+ setInputDataBlock(pOperator, pExpSupp->pCtx, pBlock, iaInfo->order, scanFlag, true);
doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
if (pRes->info.rows >= pOperator->resultInfo.threshold) {
@@ -3822,6 +4815,16 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
pRes->info.groupId = miaInfo->groupId;
}
+ if (miaInfo->inputBlocksFinished) {
+ SListNode* listNode = tdListNext(&miaInfo->groupIntervalsIter);
+
+ if (listNode != NULL) {
+ SGroupTimeWindow* grpWin = (SGroupTimeWindow*)(listNode->data);
+ finalizeWindowResult(pOperator, grpWin->groupId, &grpWin->window, pRes);
+ pRes->info.groupId = grpWin->groupId;
+ }
+ }
+
if (pRes->info.rows == 0) {
doSetOperatorCompleted(pOperator);
}
@@ -3840,30 +4843,33 @@ SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprI
goto _error;
}
+ miaInfo->groupIntervals = tdListNew(sizeof(SGroupTimeWindow));
+
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
- SExprSupp* pSup = &pOperator->exprSupp;
- iaInfo->win = pTaskInfo->window;
- iaInfo->order = TSDB_ORDER_ASC;
- iaInfo->interval = *pInterval;
+ iaInfo->win = pTaskInfo->window;
+ iaInfo->order = TSDB_ORDER_ASC;
+ iaInfo->interval = *pInterval;
iaInfo->execModel = pTaskInfo->execModel;
+
iaInfo->primaryTsIndex = primaryTsSlotId;
+ SExprSupp* pExprSupp = &pOperator->exprSupp;
+
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
initResultSizeInfo(pOperator, 4096);
- int32_t code = initAggInfo(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str);
+ int32_t code = initAggInfo(pExprSupp, &iaInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str);
initBasicInfo(&iaInfo->binfo, pResBlock);
initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
- iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, numOfCols, iaInfo);
+ iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, numOfCols, iaInfo);
if (iaInfo->timeWindowInterpo) {
iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SResultRowPosition));
- }
-
- if (code != TSDB_CODE_SUCCESS) {
- goto _error;
+ if (iaInfo->binfo.resultRowInfo.openWindow == NULL) {
+ goto _error;
+ }
}
initResultRowInfo(&iaInfo->binfo.resultRowInfo);
diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c
index f21cad2dd62156d3acb87fdc811c747bd6b8ddad..8779fe54152aeb6ae26b08dccbfcf7db03b88bf2 100644
--- a/source/libs/executor/src/tsort.c
+++ b/source/libs/executor/src/tsort.c
@@ -86,6 +86,7 @@ SSortHandle* tsortCreateSortHandle(SArray* pSortInfo, int32_t type, int32_t page
pSortHandle->pOrderedSource = taosArrayInit(4, POINTER_BYTES);
pSortHandle->cmpParam.orderInfo = pSortInfo;
+ pSortHandle->cmpParam.cmpGroupId = false;
tsortSetComparFp(pSortHandle, msortComparFn);
@@ -146,7 +147,7 @@ static int32_t doAddNewExternalMemSource(SDiskbasedBuf *pBuf, SArray* pAllSource
int32_t rowSize = blockDataGetSerialRowSize(pSource->src.pBlock);
// The value of numOfRows must be greater than 0, which is guaranteed by the previous memory allocation
- int32_t numOfRows = (getBufPageSize(pBuf) - blockDataGetSerialMetaSize(pBlock->info.numOfCols))/rowSize;
+ int32_t numOfRows = (getBufPageSize(pBuf) - blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)))/rowSize;
ASSERT(numOfRows > 0);
return blockDataEnsureCapacity(pSource->src.pBlock, numOfRows);
}
@@ -177,7 +178,7 @@ static int32_t doAddToBuf(SSDataBlock* pDataBlock, SSortHandle* pHandle) {
return terrno;
}
- int32_t size = blockDataGetSize(p) + sizeof(int32_t) + p->info.numOfCols * sizeof(int32_t);
+ int32_t size = blockDataGetSize(p) + sizeof(int32_t) + taosArrayGetSize(p->pDataBlock) * sizeof(int32_t);
assert(size <= getBufPageSize(pHandle->pBuf));
blockDataToBuf(pPage, p);
@@ -251,7 +252,7 @@ static int32_t sortComparInit(SMsortComparParam* cmpParam, SArray* pSources, int
}
static void appendOneRowToDataBlock(SSDataBlock *pBlock, const SSDataBlock* pSource, int32_t* rowIndex) {
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
SColumnInfoData* pSrcColInfo = taosArrayGet(pSource->pDataBlock, i);
@@ -374,9 +375,10 @@ int32_t msortComparFn(const void *pLeft, const void *pRight, void *param) {
SSDataBlock* pLeftBlock = pLeftSource->src.pBlock;
SSDataBlock* pRightBlock = pRightSource->src.pBlock;
- // first sort by block groupId
- if (pLeftBlock->info.groupId != pRightBlock->info.groupId) {
- return pLeftBlock->info.groupId < pRightBlock->info.groupId ? -1 : 1;
+ if (pParam->cmpGroupId) {
+ if (pLeftBlock->info.groupId != pRightBlock->info.groupId) {
+ return pLeftBlock->info.groupId < pRightBlock->info.groupId ? -1 : 1;
+ }
}
for(int32_t i = 0; i < pInfo->size; ++i) {
@@ -498,7 +500,7 @@ static int32_t doInternalMergeSort(SSortHandle* pHandle) {
return terrno;
}
- int32_t size = blockDataGetSize(pDataBlock) + sizeof(int32_t) + pDataBlock->info.numOfCols * sizeof(int32_t);
+ int32_t size = blockDataGetSize(pDataBlock) + sizeof(int32_t) + taosArrayGetSize(pDataBlock->pDataBlock) * sizeof(int32_t);
assert(size <= getBufPageSize(pHandle->pBuf));
blockDataToBuf(pPage, pDataBlock);
@@ -543,6 +545,7 @@ static int32_t doInternalMergeSort(SSortHandle* pHandle) {
return 0;
}
+// TODO consider the page meta size
int32_t getProperSortPageSize(size_t rowSize) {
uint32_t defaultPageSize = 4096;
@@ -591,7 +594,10 @@ static int32_t createInitialSources(SSortHandle* pHandle) {
if (size > sortBufSize) {
// Perform the in-memory sort and then flush data in the buffer into disk.
int64_t p = taosGetTimestampUs();
- blockDataSort(pHandle->pDataBlock, pHandle->pSortInfo);
+ code = blockDataSort(pHandle->pDataBlock, pHandle->pSortInfo);
+ if (code != 0) {
+ return code;
+ }
int64_t el = taosGetTimestampUs() - p;
pHandle->sortElapsed += el;
@@ -606,7 +612,10 @@ static int32_t createInitialSources(SSortHandle* pHandle) {
// Perform the in-memory sort and then flush data in the buffer into disk.
int64_t p = taosGetTimestampUs();
- blockDataSort(pHandle->pDataBlock, pHandle->pSortInfo);
+ int32_t code = blockDataSort(pHandle->pDataBlock, pHandle->pSortInfo);
+ if (code != 0) {
+ return code;
+ }
int64_t el = taosGetTimestampUs() - p;
pHandle->sortElapsed += el;
@@ -685,6 +694,11 @@ int32_t tsortSetComparFp(SSortHandle* pHandle, _sort_merge_compar_fn_t fp) {
return TSDB_CODE_SUCCESS;
}
+int32_t tsortSetCompareGroupId(SSortHandle* pHandle, bool compareGroupId) {
+ pHandle->cmpParam.cmpGroupId = compareGroupId;
+ return TSDB_CODE_SUCCESS;
+}
+
STupleHandle* tsortNextTuple(SSortHandle* pHandle) {
if (pHandle->cmpParam.numOfSources == pHandle->numOfCompletedSources) {
return NULL;
@@ -745,6 +759,10 @@ void* tsortGetValue(STupleHandle* pVHandle, int32_t colIndex) {
}
}
+uint64_t tsortGetGroupId(STupleHandle* pVHandle) {
+ return pVHandle->pBlock->info.groupId;
+}
+
SSortExecInfo tsortGetSortExecInfo(SSortHandle* pHandle) {
SSortExecInfo info = {0};
diff --git a/source/libs/executor/test/CMakeLists.txt b/source/libs/executor/test/CMakeLists.txt
index 129509d6c692099711f5aa7c699dee673c47467d..acab27ec0876b881dc72aca67927ea3359ef9d57 100644
--- a/source/libs/executor/test/CMakeLists.txt
+++ b/source/libs/executor/test/CMakeLists.txt
@@ -1,18 +1,20 @@
MESSAGE(STATUS "build parser unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(executorTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- executorTest
- PRIVATE os util common transport gtest taos_static qcom executor function planner scalar nodes vnode
-)
+ ADD_EXECUTABLE(executorTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ executorTest
+ PRIVATE os util common transport gtest taos_static qcom executor function planner scalar nodes vnode
+ )
-TARGET_INCLUDE_DIRECTORIES(
- executorTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/executor/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/executor/inc"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ executorTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/executor/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/executor/inc"
+ )
+ENDIF ()
\ No newline at end of file
diff --git a/source/libs/executor/test/executorTests.cpp b/source/libs/executor/test/executorTests.cpp
index dba2fb897a1737c93777c8b0a468aa3d019977a9..bba4b254c5d56f2c72988897273d363a3fec3c0c 100644
--- a/source/libs/executor/test/executorTests.cpp
+++ b/source/libs/executor/test/executorTests.cpp
@@ -62,18 +62,11 @@ SSDataBlock* getDummyBlock(SOperatorInfo* pOperator) {
}
if (pInfo->pBlock == NULL) {
- pInfo->pBlock = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
+ pInfo->pBlock = createDataBlock();
- pInfo->pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
-
- SColumnInfoData colInfo = {0};
- colInfo.info.type = TSDB_DATA_TYPE_INT;
- colInfo.info.bytes = sizeof(int32_t);
- colInfo.info.colId = 1;
- colInfo.pData = static_cast(taosMemoryCalloc(pInfo->numOfRowsPerPage, sizeof(int32_t)));
- colInfo.nullbitmap = static_cast(taosMemoryCalloc(1, (pInfo->numOfRowsPerPage + 7) / 8));
-
- taosArrayPush(pInfo->pBlock->pDataBlock, &colInfo);
+ SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1);
+ blockDataAppendColInfo(pInfo->pBlock, &colInfo);
+ blockDataEnsureCapacity(pInfo->pBlock, pInfo->numOfRowsPerPage);
// SColumnInfoData colInfo1 = {0};
// colInfo1.info.type = TSDB_DATA_TYPE_BINARY;
@@ -115,7 +108,6 @@ SSDataBlock* getDummyBlock(SOperatorInfo* pOperator) {
}
pBlock->info.rows = pInfo->numOfRowsPerPage;
- pBlock->info.numOfCols = 1;
pInfo->current += 1;
return pBlock;
@@ -128,28 +120,15 @@ SSDataBlock* get2ColsDummyBlock(SOperatorInfo* pOperator) {
}
if (pInfo->pBlock == NULL) {
- pInfo->pBlock = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
-
- pInfo->pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
-
- SColumnInfoData colInfo = {0};
- colInfo.info.type = TSDB_DATA_TYPE_TIMESTAMP;
- colInfo.info.bytes = sizeof(int64_t);
- colInfo.info.colId = 1;
- colInfo.pData = static_cast(taosMemoryCalloc(pInfo->numOfRowsPerPage, sizeof(int64_t)));
- // colInfo.nullbitmap = static_cast(taosMemoryCalloc(1, (pInfo->numOfRowsPerPage + 7) / 8));
-
- taosArrayPush(pInfo->pBlock->pDataBlock, &colInfo);
+ pInfo->pBlock = createDataBlock();
- SColumnInfoData colInfo1 = {0};
- colInfo1.info.type = TSDB_DATA_TYPE_INT;
- colInfo1.info.bytes = 4;
- colInfo1.info.colId = 2;
+ SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_TIMESTAMP, sizeof(int64_t), 1);
+ blockDataAppendColInfo(pInfo->pBlock, &colInfo);
- colInfo1.pData = static_cast(taosMemoryCalloc(pInfo->numOfRowsPerPage, sizeof(int32_t)));
- colInfo1.nullbitmap = static_cast(taosMemoryCalloc(1, (pInfo->numOfRowsPerPage + 7) / 8));
+ SColumnInfoData colInfo1 = createColumnInfoData(TSDB_DATA_TYPE_INT, 4, 2);
+ blockDataAppendColInfo(pInfo->pBlock, &colInfo1);
- taosArrayPush(pInfo->pBlock->pDataBlock, &colInfo1);
+ blockDataEnsureCapacity(pInfo->pBlock, pInfo->numOfRowsPerPage);
} else {
blockDataCleanup(pInfo->pBlock);
}
@@ -185,7 +164,6 @@ SSDataBlock* get2ColsDummyBlock(SOperatorInfo* pOperator) {
}
pBlock->info.rows = pInfo->numOfRowsPerPage;
- pBlock->info.numOfCols = 1;
pInfo->current += 1;
@@ -1051,7 +1029,7 @@ TEST(testCase, external_sort_Test) {
int64_t e = taosGetTimestampUs();
if (t++ == 1) {
- printf("---------------elapsed:%ld\n", e - s);
+ printf("---------------elapsed:%" PRId64 "\n", e - s);
}
if (pRes == NULL) {
@@ -1068,7 +1046,7 @@ TEST(testCase, external_sort_Test) {
}
int64_t s2 = taosGetTimestampUs();
- printf("total:%ld\n", s2 - s1);
+ printf("total:%" PRId64 "\n", s2 - s1);
pOperator->closeFn(pOperator->info, 2);
taosMemoryFreeClear(exp);
@@ -1123,7 +1101,7 @@ TEST(testCase, sorted_merge_Test) {
int64_t e = taosGetTimestampUs();
if (t++ == 1) {
- printf("---------------elapsed:%ld\n", e - s);
+ printf("---------------elapsed:%" PRId64 "\n", e - s);
}
if (pRes == NULL) {
@@ -1134,13 +1112,13 @@ TEST(testCase, sorted_merge_Test) {
// SColumnInfoData* pCol2 = static_cast(taosArrayGet(pRes->pDataBlock, 1));
for (int32_t i = 0; i < pRes->info.rows; ++i) {
// char* p = colDataGetData(pCol2, i);
- printf("%d: %ld\n", total++, ((int64_t*)pCol1->pData)[i]);
+ printf("%d: %" PRId64 "\n", total++, ((int64_t*)pCol1->pData)[i]);
// printf("%d: %d, %s\n", total++, ((int32_t*)pCol1->pData)[i], (char*)varDataVal(p));
}
}
int64_t s2 = taosGetTimestampUs();
- printf("total:%ld\n", s2 - s1);
+ printf("total:%" PRId64 "\n", s2 - s1);
pOperator->closeFn(pOperator->info, 2);
taosMemoryFreeClear(exp);
@@ -1201,7 +1179,7 @@ TEST(testCase, time_interval_Operator_Test) {
int64_t e = taosGetTimestampUs();
if (t++ == 1) {
- printf("---------------elapsed:%ld\n", e - s);
+ printf("---------------elapsed:%" PRId64 "\n", e - s);
}
if (pRes == NULL) {
@@ -1212,13 +1190,13 @@ TEST(testCase, time_interval_Operator_Test) {
// SColumnInfoData* pCol2 = static_cast(taosArrayGet(pRes->pDataBlock, 1));
for (int32_t i = 0; i < pRes->info.rows; ++i) {
// char* p = colDataGetData(pCol2, i);
- printf("%d: %ld\n", total++, ((int64_t*)pCol1->pData)[i]);
+ printf("%d: %" PRId64 "\n", total++, ((int64_t*)pCol1->pData)[i]);
// printf("%d: %d, %s\n", total++, ((int32_t*)pCol1->pData)[i], (char*)varDataVal(p));
}
}
int64_t s2 = taosGetTimestampUs();
- printf("total:%ld\n", s2 - s1);
+ printf("total:%" PRId64 "\n", s2 - s1);
pOperator->closeFn(pOperator->info, 2);
taosMemoryFreeClear(exp);
diff --git a/source/libs/executor/test/sortTests.cpp b/source/libs/executor/test/sortTests.cpp
index 66ed078bbe305d65906b8ab00ffbb47004cd311f..6e244152f20e0d4b914b21fcb871a5bbec871fce 100644
--- a/source/libs/executor/test/sortTests.cpp
+++ b/source/libs/executor/test/sortTests.cpp
@@ -62,25 +62,21 @@ SSDataBlock* getSingleColDummyBlock(void* param) {
return NULL;
}
- SSDataBlock* pBlock = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
- pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
+ SSDataBlock* pBlock = createDataBlock();
SColumnInfoData colInfo = {0};
colInfo.info.type = pInfo->type;
if (pInfo->type == TSDB_DATA_TYPE_NCHAR){
colInfo.info.bytes = TSDB_NCHAR_SIZE * VARCOUNT + VARSTR_HEADER_SIZE;
- colInfo.varmeta.offset = static_cast(taosMemoryCalloc(pInfo->pageRows, sizeof(int32_t)));
} else if(pInfo->type == TSDB_DATA_TYPE_BINARY) {
colInfo.info.bytes = VARCOUNT + VARSTR_HEADER_SIZE;
- colInfo.varmeta.offset = static_cast(taosMemoryCalloc(pInfo->pageRows, sizeof(int32_t)));
} else{
colInfo.info.bytes = tDataTypes[pInfo->type].bytes;
- colInfo.pData = static_cast(taosMemoryCalloc(pInfo->pageRows, colInfo.info.bytes));
- colInfo.nullbitmap = static_cast(taosMemoryCalloc(1, (pInfo->pageRows + 7) / 8));
}
colInfo.info.colId = 1;
- taosArrayPush(pBlock->pDataBlock, &colInfo);
+ blockDataAppendColInfo(pBlock, &colInfo);
+ blockDataEnsureCapacity(pBlock, pInfo->pageRows);
for (int32_t i = 0; i < pInfo->pageRows; ++i) {
SColumnInfoData* pColInfo = static_cast(TARRAY_GET_ELEM(pBlock->pDataBlock, 0));
@@ -122,13 +118,12 @@ SSDataBlock* getSingleColDummyBlock(void* param) {
}
colDataAppend(pColInfo, i, result, false);
- printf("int: %ld\n", v);
+ printf("int: %" PRId64 "\n", v);
taosMemoryFree(result);
}
}
pBlock->info.rows = pInfo->pageRows;
- pBlock->info.numOfCols = 1;
return pBlock;
}
@@ -338,7 +333,7 @@ TEST(testCase, external_mem_sort_Test) {
}else{
memcpy((char*)(&result) + sizeof(int64_t) - tDataTypes[pInfo[i].type].bytes, v, tDataTypes[pInfo[i].type].bytes);
}
- printf("%d: %ld\n", row++, result);
+ printf("%d: %" PRId64 "\n", row++, result);
}
}
taosArrayDestroy(orderInfo);
@@ -354,15 +349,10 @@ TEST(testCase, ordered_merge_sort_Test) {
SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
taosArrayPush(orderInfo, &oi);
- SSDataBlock* pBlock = static_cast(taosMemoryCalloc(1, sizeof(SSDataBlock)));
- pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
- pBlock->info.numOfCols = 1;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
- SColumnInfoData colInfo = {0};
- colInfo.info.type = TSDB_DATA_TYPE_INT;
- colInfo.info.bytes = sizeof(int32_t);
- colInfo.info.colId = 1;
- taosArrayPush(pBlock->pDataBlock, &colInfo);
+ SSDataBlock* pBlock = createDataBlock();
+ for (int32_t i = 0; i < 1; ++i) {
+ SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1);
+ blockDataAppendColInfo(pBlock, &colInfo);
}
SSortHandle* phandle = tsortCreateSortHandle(orderInfo, SORT_MULTISOURCE_MERGE, 1024, 5, pBlock,"test_abc");
diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h
index e691d562c6b4426015a7a7d10906d6c4b307cb5f..e8e37e5c6b4f643142f650015f606e0746d0a4ee 100644
--- a/source/libs/function/inc/builtinsimpl.h
+++ b/source/libs/function/inc/builtinsimpl.h
@@ -101,6 +101,13 @@ bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
bool derivativeFuncSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResInfo);
int32_t derivativeFunction(SqlFunctionCtx *pCtx);
+bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
+bool irateFuncSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResInfo);
+int32_t irateFunction(SqlFunctionCtx *pCtx);
+int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+
+int32_t lastrowFunction(SqlFunctionCtx* pCtx);
+
bool getFirstLastFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
int32_t firstFunction(SqlFunctionCtx *pCtx);
int32_t firstFunctionMerge(SqlFunctionCtx *pCtx);
@@ -112,6 +119,9 @@ int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx);
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx);
int32_t getFirstLastInfoSize(int32_t resBytes);
+int32_t lastRowFunction(SqlFunctionCtx *pCtx);
+int32_t lastRowFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+
bool getTopBotFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv);
bool getTopBotMergeFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv);
bool topBotFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
@@ -147,6 +157,7 @@ int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx);
bool getHistogramFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
bool histogramFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
int32_t histogramFunction(SqlFunctionCtx* pCtx);
+int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx);
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx);
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
@@ -186,6 +197,11 @@ bool getUniqueFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
bool uniqueFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
int32_t uniqueFunction(SqlFunctionCtx *pCtx);
+bool getModeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
+bool modeFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
+int32_t modeFunction(SqlFunctionCtx *pCtx);
+int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
bool twaFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
int32_t twaFunction(SqlFunctionCtx *pCtx);
@@ -197,6 +213,10 @@ bool blockDistSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
int32_t blockDistFunction(SqlFunctionCtx *pCtx);
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
+int32_t groupKeyFunction(SqlFunctionCtx* pCtx);
+int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/libs/function/inc/fnLog.h b/source/libs/function/inc/fnLog.h
index d85dd024331d0b2ec7374079cad9af344368a3c4..9658b6b78279f676c16dfba51e8e49473fc9cd5f 100644
--- a/source/libs/function/inc/fnLog.h
+++ b/source/libs/function/inc/fnLog.h
@@ -10,12 +10,14 @@
extern "C" {
#endif
-#define fnFatal(...) { if (fnDebugFlag & DEBUG_FATAL) { taosPrintLog("FN FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
-#define fnError(...) { if (fnDebugFlag & DEBUG_ERROR) { taosPrintLog("FN ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
-#define fnWarn(...) { if (fnDebugFlag & DEBUG_WARN) { taosPrintLog("FN WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
-#define fnInfo(...) { if (fnDebugFlag & DEBUG_INFO) { taosPrintLog("FN ", DEBUG_INFO, 255, __VA_ARGS__); }}
-#define fnDebug(...) { if (fnDebugFlag & DEBUG_DEBUG) { taosPrintLog("FN ", DEBUG_DEBUG, dDebugFlag, __VA_ARGS__); }}
-#define fnTrace(...) { if (fnDebugFlag & DEBUG_TRACE) { taosPrintLog("FN ", DEBUG_TRACE, dDebugFlag, __VA_ARGS__); }}
+// clang-format off
+#define fnFatal(...) { if (udfDebugFlag & DEBUG_FATAL) { taosPrintLog("UDF FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
+#define fnError(...) { if (udfDebugFlag & DEBUG_ERROR) { taosPrintLog("UDF ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
+#define fnWarn(...) { if (udfDebugFlag & DEBUG_WARN) { taosPrintLog("UDF WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
+#define fnInfo(...) { if (udfDebugFlag & DEBUG_INFO) { taosPrintLog("UDF ", DEBUG_INFO, 255, __VA_ARGS__); }}
+#define fnDebug(...) { if (udfDebugFlag & DEBUG_DEBUG) { taosPrintLog("UDF ", DEBUG_DEBUG, udfDebugFlag, __VA_ARGS__); }}
+#define fnTrace(...) { if (udfDebugFlag & DEBUG_TRACE) { taosPrintLog("UDF ", DEBUG_TRACE, udfDebugFlag, __VA_ARGS__); }}
+// clang-format on
#ifdef __cplusplus
}
diff --git a/source/libs/function/inc/functionMgtInt.h b/source/libs/function/inc/functionMgtInt.h
index 44e1e6f7b10285594c6a497365e42862e25e3d97..da5dd0433d4a307d27d98b4caacf71d85a14092d 100644
--- a/source/libs/function/inc/functionMgtInt.h
+++ b/source/libs/function/inc/functionMgtInt.h
@@ -32,7 +32,7 @@ extern "C" {
#define FUNC_MGT_STRING_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(3)
#define FUNC_MGT_DATETIME_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(4)
#define FUNC_MGT_TIMELINE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(5)
-#define FUNC_MGT_TIMEORDER_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(6)
+#define FUNC_MGT_IMPLICIT_TS_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(6)
#define FUNC_MGT_PSEUDO_COLUMN_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(7)
#define FUNC_MGT_WINDOW_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(8)
#define FUNC_MGT_SPECIAL_DATA_REQUIRED FUNC_MGT_FUNC_CLASSIFICATION_MASK(9)
@@ -46,6 +46,8 @@ extern "C" {
#define FUNC_MGT_FORBID_STREAM_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(17)
#define FUNC_MGT_FORBID_WINDOW_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(18)
#define FUNC_MGT_FORBID_GROUP_BY_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(19)
+#define FUNC_MGT_SYSTEM_INFO_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(20)
+#define FUNC_MGT_CLIENT_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(21)
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
diff --git a/source/libs/function/inc/taggfunction.h b/source/libs/function/inc/taggfunction.h
index c3d61d426d889cecda0723b48c6c26eae16316ff..669c2635b5986eb3e47fee30b8a62b3a89fbc1be 100644
--- a/source/libs/function/inc/taggfunction.h
+++ b/source/libs/function/inc/taggfunction.h
@@ -28,19 +28,6 @@ extern "C" {
#include "function.h"
#include "tudf.h"
-
-extern SAggFunctionInfo aggFunc[35];
-
-#define FUNCSTATE_SO 0x0u
-#define FUNCSTATE_MO 0x1u // dynamic number of output, not multinumber of output e.g., TOP/BOTTOM
-#define FUNCSTATE_STREAM 0x2u // function avail for stream
-#define FUNCSTATE_STABLE 0x4u // function avail for super table
-#define FUNCSTATE_NEED_TS 0x8u // timestamp is required during query processing
-#define FUNCSTATE_SELECTIVITY 0x10u // selectivity functions, can exists along with tag columns
-
-#define BASIC_FUNC_SO FUNCSTATE_SO | FUNCSTATE_STREAM | FUNCSTATE_STABLE
-#define BASIC_FUNC_MO FUNCSTATE_MO | FUNCSTATE_STREAM | FUNCSTATE_STABLE
-
#define AVG_FUNCTION_INTER_BUFFER_SIZE 50
#define DATA_SET_FLAG ',' // to denote the output area has data, not null value
diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c
index cfad00f45898a60dc196edae522c67246d5afb69..5feb1427572af248428e454ac3f168487344f24e 100644
--- a/source/libs/function/src/builtins.c
+++ b/source/libs/function/src/builtins.c
@@ -15,6 +15,7 @@
#include "builtins.h"
#include "builtinsimpl.h"
+#include "cJSON.h"
#include "querynodes.h"
#include "scalar.h"
#include "taoserror.h"
@@ -39,6 +40,193 @@ static int32_t invaildFuncParaValueErrMsg(char* pErrBuf, int32_t len, const char
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_VALUE, "Invalid parameter value : %s", pFuncName);
}
+#define TIME_UNIT_INVALID 1
+#define TIME_UNIT_TOO_SMALL 2
+
+static int32_t validateTimeUnitParam(uint8_t dbPrec, const SValueNode* pVal) {
+ if (!pVal->isDuration) {
+ return TIME_UNIT_INVALID;
+ }
+
+ if (TSDB_TIME_PRECISION_MILLI == dbPrec &&
+ (0 == strcasecmp(pVal->literal, "1u") || 0 == strcasecmp(pVal->literal, "1b"))) {
+ return TIME_UNIT_TOO_SMALL;
+ }
+
+ if (TSDB_TIME_PRECISION_MICRO == dbPrec && 0 == strcasecmp(pVal->literal, "1b")) {
+ return TIME_UNIT_TOO_SMALL;
+ }
+
+ if (pVal->literal[0] != '1' ||
+ (pVal->literal[1] != 'u' && pVal->literal[1] != 'a' && pVal->literal[1] != 's' && pVal->literal[1] != 'm' &&
+ pVal->literal[1] != 'h' && pVal->literal[1] != 'd' && pVal->literal[1] != 'w' && pVal->literal[1] != 'b')) {
+ return TIME_UNIT_INVALID;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+/* Following are valid ISO-8601 timezone format:
+ * 1 z/Z
+ * 2 ±hh:mm
+ * 3 ±hhmm
+ * 4 ±hh
+ *
+ */
+
+static bool validateHourRange(int8_t hour) {
+ if (hour < 0 || hour > 12) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool validateMinuteRange(int8_t hour, int8_t minute, char sign) {
+ if (minute == 0 || (minute == 30 && (hour == 3 || hour == 5) && sign == '+')) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool validateTimestampDigits(const SValueNode* pVal) {
+ if (!IS_INTEGER_TYPE(pVal->node.resType.type)) {
+ return false;
+ }
+
+ int64_t tsVal = pVal->datum.i;
+ char fraction[20] = {0};
+ NUM_TO_STRING(pVal->node.resType.type, &tsVal, sizeof(fraction), fraction);
+ int32_t tsDigits = (int32_t)strlen(fraction);
+
+ if (tsDigits > TSDB_TIME_PRECISION_SEC_DIGITS) {
+ if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS || tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS ||
+ tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool validateTimezoneFormat(const SValueNode* pVal) {
+ if (TSDB_DATA_TYPE_BINARY != pVal->node.resType.type) {
+ return false;
+ }
+
+ char* tz = varDataVal(pVal->datum.p);
+ int32_t len = varDataLen(pVal->datum.p);
+
+ char buf[3] = {0};
+ int8_t hour = -1, minute = -1;
+ if (len == 0) {
+ return false;
+ } else if (len == 1 && (tz[0] == 'z' || tz[0] == 'Z')) {
+ return true;
+ } else if ((tz[0] == '+' || tz[0] == '-')) {
+ switch (len) {
+ case 3:
+ case 5: {
+ for (int32_t i = 1; i < len; ++i) {
+ if (!isdigit(tz[i])) {
+ return false;
+ }
+
+ if (i == 2) {
+ memcpy(buf, &tz[i - 1], 2);
+ hour = taosStr2Int8(buf, NULL, 10);
+ if (!validateHourRange(hour)) {
+ return false;
+ }
+ } else if (i == 4) {
+ memcpy(buf, &tz[i - 1], 2);
+ minute = taosStr2Int8(buf, NULL, 10);
+ if (!validateMinuteRange(hour, minute, tz[0])) {
+ return false;
+ }
+ }
+ }
+ break;
+ }
+ case 6: {
+ for (int32_t i = 1; i < len; ++i) {
+ if (i == 3) {
+ if (tz[i] != ':') {
+ return false;
+ }
+ continue;
+ }
+
+ if (!isdigit(tz[i])) {
+ return false;
+ }
+
+ if (i == 2) {
+ memcpy(buf, &tz[i - 1], 2);
+ hour = taosStr2Int8(buf, NULL, 10);
+ if (!validateHourRange(hour)) {
+ return false;
+ }
+ } else if (i == 5) {
+ memcpy(buf, &tz[i - 1], 2);
+ minute = taosStr2Int8(buf, NULL, 10);
+ if (!validateMinuteRange(hour, minute, tz[0])) {
+ return false;
+ }
+ }
+ }
+ break;
+ }
+ default: {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void static addTimezoneParam(SNodeList* pList) {
+ char buf[6] = {0};
+ time_t t = taosTime(NULL);
+ struct tm* tmInfo = taosLocalTime(&t, NULL);
+ strftime(buf, sizeof(buf), "%z", tmInfo);
+ int32_t len = (int32_t)strlen(buf);
+
+ SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ pVal->literal = strndup(buf, len);
+ pVal->isDuration = false;
+ pVal->translate = true;
+ pVal->node.resType.type = TSDB_DATA_TYPE_BINARY;
+ pVal->node.resType.bytes = len + VARSTR_HEADER_SIZE;
+ pVal->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
+ pVal->datum.p = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE + 1);
+ varDataSetLen(pVal->datum.p, len);
+ strncpy(varDataVal(pVal->datum.p), pVal->literal, len);
+
+ nodesListAppend(pList, (SNode*)pVal);
+}
+
+void static addDbPrecisonParam(SNodeList** pList, uint8_t precision) {
+ SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ pVal->literal = NULL;
+ pVal->isDuration = false;
+ pVal->translate = true;
+ pVal->notReserved = true;
+ pVal->node.resType.type = TSDB_DATA_TYPE_TINYINT;
+ pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TINYINT].bytes;
+ pVal->node.resType.precision = precision;
+ pVal->datum.i = (int64_t)precision;
+ pVal->typeData = (int64_t)precision;
+
+ nodesListMakeAppend(pList, (SNode*)pVal);
+}
+
// There is only one parameter of numeric type, and the return type is parameter type
static int32_t translateInOutNum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
@@ -79,7 +267,8 @@ static int32_t translateIn2NumOutDou(SFunctionNode* pFunc, char* pErrBuf, int32_
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
- if (!IS_NUMERIC_TYPE(para1Type) || !IS_NUMERIC_TYPE(para2Type)) {
+ if ((!IS_NUMERIC_TYPE(para1Type) && !IS_NULL_TYPE(para1Type)) ||
+ (!IS_NUMERIC_TYPE(para2Type) && !IS_NULL_TYPE(para2Type))) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
@@ -109,13 +298,13 @@ static int32_t translateLogarithm(SFunctionNode* pFunc, char* pErrBuf, int32_t l
}
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
- if (!IS_NUMERIC_TYPE(para1Type)) {
+ if (!IS_NUMERIC_TYPE(para1Type) && !IS_NULL_TYPE(para1Type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
if (2 == numOfParams) {
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
- if (!IS_NUMERIC_TYPE(para2Type)) {
+ if (!IS_NUMERIC_TYPE(para2Type) && !IS_NULL_TYPE(para2Type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
}
@@ -219,8 +408,20 @@ static int32_t translateWduration(SFunctionNode* pFunc, char* pErrBuf, int32_t l
return TSDB_CODE_SUCCESS;
}
+static int32_t translateNowToday(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ // pseudo column do not need to check parameters
+
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
+
+ pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP};
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t translateTimePseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
// pseudo column do not need to check parameters
+
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP};
return TSDB_CODE_SUCCESS;
}
@@ -403,7 +604,7 @@ static int32_t translateTopBot(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
}
SValueNode* pValue = (SValueNode*)pParamNode1;
- if (pValue->node.resType.type != TSDB_DATA_TYPE_BIGINT) {
+ if (!IS_INTEGER_TYPE(pValue->node.resType.type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
@@ -476,9 +677,10 @@ static int32_t translateElapsed(SFunctionNode* pFunc, char* pErrBuf, int32_t len
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
}
- uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
- if (TSDB_DATA_TYPE_TIMESTAMP != paraType) {
- return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ SNode* pPara1 = nodesListGetNode(pFunc->pParameterList, 0);
+ if (QUERY_NODE_COLUMN != nodeType(pPara1) || PRIMARYKEY_TIMESTAMP_COL_ID != ((SColumnNode*)pPara1)->colId) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "The first parameter of the ELAPSED function can only be the timestamp primary key");
}
// param1
@@ -492,14 +694,20 @@ static int32_t translateElapsed(SFunctionNode* pFunc, char* pErrBuf, int32_t len
pValue->notReserved = true;
- paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
- if (!IS_INTEGER_TYPE(paraType)) {
+ if (!IS_INTEGER_TYPE(pValue->node.resType.type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- if (pValue->datum.i == 0) {
+ uint8_t dbPrec = pFunc->node.resType.precision;
+
+ int32_t ret = validateTimeUnitParam(dbPrec, (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1));
+ if (ret == TIME_UNIT_TOO_SMALL) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
"ELAPSED function time unit parameter should be greater than db precision");
+ } else if (ret == TIME_UNIT_INVALID) {
+ return buildFuncErrMsg(
+ pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "ELAPSED function time unit parameter should be one of the following: [1b, 1u, 1a, 1s, 1m, 1h, 1d, 1w]");
}
}
@@ -594,6 +802,165 @@ static int32_t translateLeastSQR(SFunctionNode* pFunc, char* pErrBuf, int32_t le
return TSDB_CODE_SUCCESS;
}
+typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
+
+static int8_t validateHistogramBinType(char* binTypeStr) {
+ int8_t binType;
+ if (strcasecmp(binTypeStr, "user_input") == 0) {
+ binType = USER_INPUT_BIN;
+ } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
+ binType = LINEAR_BIN;
+ } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
+ binType = LOG_BIN;
+ } else {
+ binType = UNKNOWN_BIN;
+ }
+
+ return binType;
+}
+
+static bool validateHistogramBinDesc(char* binDescStr, int8_t binType, char* errMsg, int32_t msgLen) {
+ const char* msg1 = "HISTOGRAM function requires four parameters";
+ const char* msg3 = "HISTOGRAM function invalid format for binDesc parameter";
+ const char* msg4 = "HISTOGRAM function binDesc parameter \"count\" should be in range [1, 1000]";
+ const char* msg5 = "HISTOGRAM function bin/parameter should be in range [-DBL_MAX, DBL_MAX]";
+ const char* msg6 = "HISTOGRAM function binDesc parameter \"width\" cannot be 0";
+ const char* msg7 = "HISTOGRAM function binDesc parameter \"start\" cannot be 0 with \"log_bin\" type";
+ const char* msg8 = "HISTOGRAM function binDesc parameter \"factor\" cannot be negative or equal to 0/1";
+
+ cJSON* binDesc = cJSON_Parse(binDescStr);
+ int32_t numOfBins;
+ double* intervals;
+ if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
+ int32_t numOfParams = cJSON_GetArraySize(binDesc);
+ int32_t startIndex;
+ if (numOfParams != 4) {
+ snprintf(errMsg, msgLen, "%s", msg1);
+ return false;
+ }
+
+ cJSON* start = cJSON_GetObjectItem(binDesc, "start");
+ cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
+ cJSON* width = cJSON_GetObjectItem(binDesc, "width");
+ cJSON* count = cJSON_GetObjectItem(binDesc, "count");
+ cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
+
+ if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ return false;
+ }
+
+ if (count->valueint <= 0 || count->valueint > 1000) { // limit count to 1000
+ snprintf(errMsg, msgLen, "%s", msg4);
+ return false;
+ }
+
+ if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
+ (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
+ snprintf(errMsg, msgLen, "%s", msg5);
+ return false;
+ }
+
+ int32_t counter = (int32_t)count->valueint;
+ if (infinity->valueint == false) {
+ startIndex = 0;
+ numOfBins = counter + 1;
+ } else {
+ startIndex = 1;
+ numOfBins = counter + 3;
+ }
+
+ intervals = taosMemoryCalloc(numOfBins, sizeof(double));
+ if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
+ // linear bin process
+ if (width->valuedouble == 0) {
+ snprintf(errMsg, msgLen, "%s", msg6);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ for (int i = 0; i < counter + 1; ++i) {
+ intervals[startIndex] = start->valuedouble + i * width->valuedouble;
+ if (isinf(intervals[startIndex])) {
+ snprintf(errMsg, msgLen, "%s", msg5);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ startIndex++;
+ }
+ } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
+ // log bin process
+ if (start->valuedouble == 0) {
+ snprintf(errMsg, msgLen, "%s", msg7);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
+ snprintf(errMsg, msgLen, "%s", msg8);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ for (int i = 0; i < counter + 1; ++i) {
+ intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
+ if (isinf(intervals[startIndex])) {
+ snprintf(errMsg, msgLen, "%s", msg5);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ startIndex++;
+ }
+ } else {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ taosMemoryFree(intervals);
+ return false;
+ }
+
+ if (infinity->valueint == true) {
+ intervals[0] = -INFINITY;
+ intervals[numOfBins - 1] = INFINITY;
+ // in case of desc bin orders, -inf/inf should be swapped
+ ASSERT(numOfBins >= 4);
+ if (intervals[1] > intervals[numOfBins - 2]) {
+ TSWAP(intervals[0], intervals[numOfBins - 1]);
+ }
+ }
+ } else if (cJSON_IsArray(binDesc)) { /* user input bins */
+ if (binType != USER_INPUT_BIN) {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ return false;
+ }
+ numOfBins = cJSON_GetArraySize(binDesc);
+ intervals = taosMemoryCalloc(numOfBins, sizeof(double));
+ cJSON* bin = binDesc->child;
+ if (bin == NULL) {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ int i = 0;
+ while (bin) {
+ intervals[i] = bin->valuedouble;
+ if (!cJSON_IsNumber(bin)) {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ if (i != 0 && intervals[i] <= intervals[i - 1]) {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ taosMemoryFree(intervals);
+ return false;
+ }
+ bin = bin->next;
+ i++;
+ }
+ } else {
+ snprintf(errMsg, msgLen, "%s", msg3);
+ return false;
+ }
+
+ taosMemoryFree(intervals);
+ return true;
+}
+
static int32_t translateHistogram(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
if (4 != numOfParams) {
@@ -606,6 +973,14 @@ static int32_t translateHistogram(SFunctionNode* pFunc, char* pErrBuf, int32_t l
}
// param1 ~ param3
+ if (((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type != TSDB_DATA_TYPE_BINARY ||
+ ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type != TSDB_DATA_TYPE_BINARY ||
+ ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type != TSDB_DATA_TYPE_BIGINT) {
+ return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ int8_t binType;
+ char* binDesc;
for (int32_t i = 1; i < numOfParams; ++i) {
SNode* pParamNode = nodesListGetNode(pFunc->pParameterList, i);
if (QUERY_NODE_VALUE != nodeType(pParamNode)) {
@@ -615,12 +990,28 @@ static int32_t translateHistogram(SFunctionNode* pFunc, char* pErrBuf, int32_t l
SValueNode* pValue = (SValueNode*)pParamNode;
pValue->notReserved = true;
- }
- if (((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type != TSDB_DATA_TYPE_BINARY ||
- ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type != TSDB_DATA_TYPE_BINARY ||
- ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type != TSDB_DATA_TYPE_BIGINT) {
- return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ if (i == 1) {
+ binType = validateHistogramBinType(varDataVal(pValue->datum.p));
+ if (binType == UNKNOWN_BIN) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "HISTOGRAM function binType parameter should be "
+ "\"user_input\", \"log_bin\" or \"linear_bin\"");
+ }
+ }
+
+ if (i == 2) {
+ char errMsg[128] = {0};
+ binDesc = varDataVal(pValue->datum.p);
+ if (!validateHistogramBinDesc(binDesc, binType, errMsg, (int32_t)sizeof(errMsg))) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, errMsg);
+ }
+ }
+
+ if (i == 3 && pValue->datum.i != 1 && pValue->datum.i != 0) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "HISTOGRAM function normalized parameter should be 0/1");
+ }
}
pFunc->node.resType = (SDataType){.bytes = 512, .type = TSDB_DATA_TYPE_BINARY};
@@ -640,6 +1031,14 @@ static int32_t translateHistogramImpl(SFunctionNode* pFunc, char* pErrBuf, int32
}
// param1 ~ param3
+ if (((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type != TSDB_DATA_TYPE_BINARY ||
+ ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type != TSDB_DATA_TYPE_BINARY ||
+ ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type != TSDB_DATA_TYPE_BIGINT) {
+ return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ int8_t binType;
+ char* binDesc;
for (int32_t i = 1; i < numOfParams; ++i) {
SNode* pParamNode = nodesListGetNode(pFunc->pParameterList, i);
if (QUERY_NODE_VALUE != nodeType(pParamNode)) {
@@ -649,12 +1048,28 @@ static int32_t translateHistogramImpl(SFunctionNode* pFunc, char* pErrBuf, int32
SValueNode* pValue = (SValueNode*)pParamNode;
pValue->notReserved = true;
- }
- if (((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type != TSDB_DATA_TYPE_BINARY ||
- ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type != TSDB_DATA_TYPE_BINARY ||
- ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type != TSDB_DATA_TYPE_BIGINT) {
- return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ if (i == 1) {
+ binType = validateHistogramBinType(varDataVal(pValue->datum.p));
+ if (binType == UNKNOWN_BIN) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "HISTOGRAM function binType parameter should be "
+ "\"user_input\", \"log_bin\" or \"linear_bin\"");
+ }
+ }
+
+ if (i == 2) {
+ char errMsg[128] = {0};
+ binDesc = varDataVal(pValue->datum.p);
+ if (!validateHistogramBinDesc(binDesc, binType, errMsg, (int32_t)sizeof(errMsg))) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, errMsg);
+ }
+ }
+
+ if (i == 3 && pValue->datum.i != 1 && pValue->datum.i != 0) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "HISTOGRAM function normalized parameter should be 0/1");
+ }
}
pFunc->node.resType =
@@ -805,6 +1220,20 @@ static int32_t translateStateDuration(SFunctionNode* pFunc, char* pErrBuf, int32
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
+ if (numOfParams == 4) {
+ uint8_t dbPrec = pFunc->node.resType.precision;
+
+ int32_t ret = validateTimeUnitParam(dbPrec, (SValueNode*)nodesListGetNode(pFunc->pParameterList, 3));
+ if (ret == TIME_UNIT_TOO_SMALL) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "STATEDURATION function time unit parameter should be greater than db precision");
+ } else if (ret == TIME_UNIT_INVALID) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "STATEDURATION function time unit parameter should be one of the following: [1b, 1u, 1a, "
+ "1s, 1m, 1h, 1d, 1w]");
+ }
+ }
+
// set result type
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
return TSDB_CODE_SUCCESS;
@@ -970,45 +1399,52 @@ static int32_t translateDerivative(SFunctionNode* pFunc, char* pErrBuf, int32_t
SValueNode* pValue2 = (SValueNode*)pParamNode2;
pValue2->notReserved = true;
- if (pValue2->datum.i != 0 && pValue2->datum.i != 1) {
- return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
+ if (pValue2->datum.i != 0 && pValue2->datum.i != 1) {
+ return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateIrate(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ if (1 != LIST_LENGTH(pFunc->pParameterList)) {
+ return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ uint8_t colType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
+
+ if (!IS_NUMERIC_TYPE(colType)) {
+ return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
+
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE};
return TSDB_CODE_SUCCESS;
}
static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
- // first(col_list) will be rewritten as first(col)
- if (1 != LIST_LENGTH(pFunc->pParameterList)) {
- return TSDB_CODE_SUCCESS;
- }
-
- SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
- if (QUERY_NODE_COLUMN != nodeType(pPara)) {
- return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
- "The parameters of first/last can only be columns");
+ int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
+ for (int32_t i = 0; i < numOfParams; ++i) {
+ SNode* pParamNode = nodesListGetNode(pFunc->pParameterList, i);
+ if (QUERY_NODE_VALUE == nodeType(pParamNode)) {
+ return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
+ }
}
- pFunc->node.resType = ((SExprNode*)pPara)->resType;
+ pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
return TSDB_CODE_SUCCESS;
}
static int32_t translateFirstLastImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len, bool isPartial) {
// first(col_list) will be rewritten as first(col)
- if (2 != LIST_LENGTH(pFunc->pParameterList)) { // input has two params c0,ts, is this a bug?
- return TSDB_CODE_SUCCESS;
- }
-
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
uint8_t paraType = ((SExprNode*)pPara)->resType.type;
int32_t paraBytes = ((SExprNode*)pPara)->resType.bytes;
if (isPartial) {
- if (QUERY_NODE_COLUMN != nodeType(pPara)) {
- return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
- "The parameters of first/last can only be columns");
- }
-
pFunc->node.resType =
(SDataType){.bytes = getFirstLastInfoSize(paraBytes) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
} else {
@@ -1029,20 +1465,29 @@ static int32_t translateFirstLastMerge(SFunctionNode* pFunc, char* pErrBuf, int3
return translateFirstLastImpl(pFunc, pErrBuf, len, false);
}
-static int32_t translateUnique(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+static int32_t translateUniqueMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len, bool isUnique) {
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
}
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
if (!nodesExprHasColumn(pPara)) {
- return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of UNIQUE must contain columns");
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of %s must contain columns",
+ isUnique ? "UNIQUE" : "MODE");
}
pFunc->node.resType = ((SExprNode*)pPara)->resType;
return TSDB_CODE_SUCCESS;
}
+static int32_t translateUnique(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ return translateUniqueMode(pFunc, pErrBuf, len, true);
+}
+
+static int32_t translateMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ return translateUniqueMode(pFunc, pErrBuf, len, false);
+}
+
static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
if (numOfParams == 0 || numOfParams > 2) {
@@ -1174,26 +1619,27 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
}
SExprNode* pPara0 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
- SExprNode* p1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 1);
+ SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 1);
- uint8_t para1Type = p1->resType.type;
- if (!IS_VAR_DATA_TYPE(pPara0->resType.type) || !IS_INTEGER_TYPE(para1Type)) {
+ uint8_t para0Type = pPara0->resType.type;
+ uint8_t para1Type = pPara1->resType.type;
+ if (!IS_VAR_DATA_TYPE(para0Type) || !IS_INTEGER_TYPE(para1Type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- if (((SValueNode*)p1)->datum.i < 1) {
+ if (((SValueNode*)pPara1)->datum.i == 0) {
return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
}
if (3 == numOfParams) {
- SExprNode* p2 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 2);
- uint8_t para2Type = p2->resType.type;
+ SExprNode* pPara2 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 2);
+ uint8_t para2Type = pPara2->resType.type;
if (!IS_INTEGER_TYPE(para2Type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- int64_t v = ((SValueNode*)p1)->datum.i;
- if (v < 0 || v > INT16_MAX) {
+ int64_t v = ((SValueNode*)pPara2)->datum.i;
+ if (v < 0) {
return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
}
}
@@ -1204,18 +1650,9 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
// The number of parameters has been limited by the syntax definition
- uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
+
// The function return type has been set during syntax parsing
uint8_t para2Type = pFunc->node.resType.type;
- if (para2Type != TSDB_DATA_TYPE_BIGINT && para2Type != TSDB_DATA_TYPE_UBIGINT &&
- para2Type != TSDB_DATA_TYPE_VARCHAR && para2Type != TSDB_DATA_TYPE_NCHAR &&
- para2Type != TSDB_DATA_TYPE_TIMESTAMP) {
- return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
- }
- if ((para2Type == TSDB_DATA_TYPE_TIMESTAMP && IS_VAR_DATA_TYPE(para1Type)) ||
- (para2Type == TSDB_DATA_TYPE_BINARY && para1Type == TSDB_DATA_TYPE_NCHAR)) {
- return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
- }
int32_t para2Bytes = pFunc->node.resType.bytes;
if (IS_VAR_DATA_TYPE(para2Type)) {
@@ -1225,131 +1662,12 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
"CAST function converted length should be in range [0, 1000]");
}
- return TSDB_CODE_SUCCESS;
-}
-
-/* Following are valid ISO-8601 timezone format:
- * 1 z/Z
- * 2 ±hh:mm
- * 3 ±hhmm
- * 4 ±hh
- *
- */
-
-static bool validateHourRange(int8_t hour) {
- if (hour < 0 || hour > 12) {
- return false;
- }
-
- return true;
-}
-
-static bool validateMinuteRange(int8_t hour, int8_t minute, char sign) {
- if (minute == 0 || (minute == 30 && (hour == 3 || hour == 5) && sign == '+')) {
- return true;
- }
-
- return false;
-}
-
-static bool validateTimezoneFormat(const SValueNode* pVal) {
- if (TSDB_DATA_TYPE_BINARY != pVal->node.resType.type) {
- return false;
- }
-
- char* tz = varDataVal(pVal->datum.p);
- int32_t len = varDataLen(pVal->datum.p);
-
- char buf[3] = {0};
- int8_t hour = -1, minute = -1;
- if (len == 0) {
- return false;
- } else if (len == 1 && (tz[0] == 'z' || tz[0] == 'Z')) {
- return true;
- } else if ((tz[0] == '+' || tz[0] == '-')) {
- switch (len) {
- case 3:
- case 5: {
- for (int32_t i = 1; i < len; ++i) {
- if (!isdigit(tz[i])) {
- return false;
- }
-
- if (i == 2) {
- memcpy(buf, &tz[i - 1], 2);
- hour = taosStr2Int8(buf, NULL, 10);
- if (!validateHourRange(hour)) {
- return false;
- }
- } else if (i == 4) {
- memcpy(buf, &tz[i - 1], 2);
- minute = taosStr2Int8(buf, NULL, 10);
- if (!validateMinuteRange(hour, minute, tz[0])) {
- return false;
- }
- }
- }
- break;
- }
- case 6: {
- for (int32_t i = 1; i < len; ++i) {
- if (i == 3) {
- if (tz[i] != ':') {
- return false;
- }
- continue;
- }
-
- if (!isdigit(tz[i])) {
- return false;
- }
-
- if (i == 2) {
- memcpy(buf, &tz[i - 1], 2);
- hour = taosStr2Int8(buf, NULL, 10);
- if (!validateHourRange(hour)) {
- return false;
- }
- } else if (i == 5) {
- memcpy(buf, &tz[i - 1], 2);
- minute = taosStr2Int8(buf, NULL, 10);
- if (!validateMinuteRange(hour, minute, tz[0])) {
- return false;
- }
- }
- }
- break;
- }
- default: {
- return false;
- }
- }
- } else {
- return false;
- }
-
- return true;
-}
-
-void static addTimezoneParam(SNodeList* pList) {
- char buf[6] = {0};
- time_t t = taosTime(NULL);
- struct tm* tmInfo = taosLocalTime(&t, NULL);
- strftime(buf, sizeof(buf), "%z", tmInfo);
- int32_t len = (int32_t)strlen(buf);
- SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
- pVal->literal = strndup(buf, len);
- pVal->isDuration = false;
- pVal->translate = true;
- pVal->node.resType.type = TSDB_DATA_TYPE_BINARY;
- pVal->node.resType.bytes = len + VARSTR_HEADER_SIZE;
- pVal->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
- pVal->datum.p = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE + 1);
- varDataSetLen(pVal->datum.p, len);
- strncpy(varDataVal(pVal->datum.p), pVal->literal, len);
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
- nodesListAppend(pList, (SNode*)pVal);
+ return TSDB_CODE_SUCCESS;
}
static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
@@ -1364,6 +1682,15 @@ static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t l
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
+ if (QUERY_NODE_VALUE == nodeType(nodesListGetNode(pFunc->pParameterList, 0))) {
+ SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0);
+
+ if (!validateTimestampDigits(pValue)) {
+ pFunc->node.resType = (SDataType){.bytes = 0, .type = TSDB_DATA_TYPE_BINARY};
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+
// param1
if (numOfParams == 2) {
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
@@ -1389,6 +1716,10 @@ static int32_t translateToUnixtimestamp(SFunctionNode* pFunc, char* pErrBuf, int
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
+
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
return TSDB_CODE_SUCCESS;
}
@@ -1405,6 +1736,21 @@ static int32_t translateTimeTruncate(SFunctionNode* pFunc, char* pErrBuf, int32_
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+
+ int32_t ret = validateTimeUnitParam(dbPrec, (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1));
+ if (ret == TIME_UNIT_TOO_SMALL) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "TIMETRUNCATE function time unit parameter should be greater than db precision");
+ } else if (ret == TIME_UNIT_INVALID) {
+ return buildFuncErrMsg(
+ pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "TIMETRUNCATE function time unit parameter should be one of the following: [1b, 1u, 1a, 1s, 1m, 1h, 1d, 1w]");
+ }
+
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
+
pFunc->node.resType =
(SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, .type = TSDB_DATA_TYPE_TIMESTAMP};
return TSDB_CODE_SUCCESS;
@@ -1429,6 +1775,23 @@ static int32_t translateTimeDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t le
}
}
+ // add database precision as param
+ uint8_t dbPrec = pFunc->node.resType.precision;
+
+ if (3 == numOfParams) {
+ int32_t ret = validateTimeUnitParam(dbPrec, (SValueNode*)nodesListGetNode(pFunc->pParameterList, 2));
+ if (ret == TIME_UNIT_TOO_SMALL) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "TIMEDIFF function time unit parameter should be greater than db precision");
+ } else if (ret == TIME_UNIT_INVALID) {
+ return buildFuncErrMsg(
+ pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "TIMEDIFF function time unit parameter should be one of the following: [1b, 1u, 1a, 1s, 1m, 1h, 1d, 1w]");
+ }
+ }
+
+ addDbPrecisonParam(&pFunc->pParameterList, dbPrec);
+
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
return TSDB_CODE_SUCCESS;
}
@@ -1443,7 +1806,7 @@ static int32_t translateToJson(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BINARY].bytes, .type = TSDB_DATA_TYPE_BINARY};
+ pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_JSON].bytes, .type = TSDB_DATA_TYPE_JSON};
return TSDB_CODE_SUCCESS;
}
@@ -1462,11 +1825,56 @@ static int32_t translateBlockDistInfoFunc(SFunctionNode* pFunc, char* pErrBuf, i
return TSDB_CODE_SUCCESS;
}
+static int32_t translateGroupKeyFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
+ return TSDB_CODE_SUCCESS;
+}
+
static bool getBlockDistFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
pEnv->calcMemSize = sizeof(STableBlockDistInfo);
return true;
}
+static int32_t translateGroupKey(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ if (1 != LIST_LENGTH(pFunc->pParameterList)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
+ pFunc->node.resType = ((SExprNode*)pPara)->resType;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateDatabaseFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = TSDB_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateClientVersionFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = TSDB_VERSION_LEN, .type = TSDB_DATA_TYPE_VARCHAR};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateServerVersionFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = TSDB_VERSION_LEN, .type = TSDB_DATA_TYPE_VARCHAR};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateServerStatusFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes, .type = TSDB_DATA_TYPE_INT};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateCurrentUserFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = TSDB_USER_LEN, .type = TSDB_DATA_TYPE_VARCHAR};
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t translateUserFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ pFunc->node.resType = (SDataType){.bytes = TSDB_USER_LEN, .type = TSDB_DATA_TYPE_VARCHAR};
+ return TSDB_CODE_SUCCESS;
+}
+
// clang-format off
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
@@ -1568,7 +1976,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "leastsquares",
.type = FUNCTION_TYPE_LEASTSQUARES,
- .classification = FUNC_MGT_AGG_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
.translateFunc = translateLeastSQR,
.getEnvFunc = getLeastSQRFuncEnv,
.initFunc = leastSQRFunctionSetup,
@@ -1779,7 +2187,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "interp",
.type = FUNCTION_TYPE_INTERP,
- .classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC,
+ .classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLast,
.getEnvFunc = getSelectivityFuncEnv,
.initFunc = functionSetup,
@@ -1789,27 +2197,37 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "derivative",
.type = FUNCTION_TYPE_DERIVATIVE,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateDerivative,
.getEnvFunc = getDerivativeFuncEnv,
.initFunc = derivativeFuncSetup,
.processFunc = derivativeFunction,
.finalizeFunc = functionFinalize
},
+ {
+ .name = "irate",
+ .type = FUNCTION_TYPE_IRATE,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
+ .translateFunc = translateIrate,
+ .getEnvFunc = getIrateFuncEnv,
+ .initFunc = irateFuncSetup,
+ .processFunc = irateFunction,
+ .finalizeFunc = irateFinalize
+ },
{
.name = "last_row",
.type = FUNCTION_TYPE_LAST_ROW,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC,
- .translateFunc = translateLastRow,
- .getEnvFunc = getMinmaxFuncEnv,
- .initFunc = minmaxFunctionSetup,
- .processFunc = maxFunction,
- .finalizeFunc = functionFinalize
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
+ .translateFunc = translateFirstLast,
+ .getEnvFunc = getFirstLastFuncEnv,
+ .initFunc = functionSetup,
+ .processFunc = lastrowFunction,
+ .finalizeFunc = firstLastFinalize
},
{
.name = "first",
.type = FUNCTION_TYPE_FIRST,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLast,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1822,7 +2240,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "_first_partial",
.type = FUNCTION_TYPE_FIRST_PARTIAL,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLastPartial,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1833,7 +2251,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "_first_merge",
.type = FUNCTION_TYPE_FIRST_MERGE,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLastMerge,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1844,7 +2262,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "last",
.type = FUNCTION_TYPE_LAST,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLast,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1857,7 +2275,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "_last_partial",
.type = FUNCTION_TYPE_LAST_PARTIAL,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLastPartial,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1868,7 +2286,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "_last_merge",
.type = FUNCTION_TYPE_LAST_MERGE,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateFirstLastMerge,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
@@ -1879,7 +2297,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "twa",
.type = FUNCTION_TYPE_TWA,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateInNumOutDou,
.dataRequiredFunc = statisDataRequired,
.getEnvFunc = getTwaFuncEnv,
@@ -1890,7 +2308,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "histogram",
.type = FUNCTION_TYPE_HISTOGRAM,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_FORBID_FILL_FUNC,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_FORBID_FILL_FUNC,
.translateFunc = translateHistogram,
.getEnvFunc = getHistogramFuncEnv,
.initFunc = histogramFunctionSetup,
@@ -1908,7 +2326,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.translateFunc = translateHistogramPartial,
.getEnvFunc = getHistogramFuncEnv,
.initFunc = histogramFunctionSetup,
- .processFunc = histogramFunction,
+ .processFunc = histogramFunctionPartial,
.finalizeFunc = histogramPartialFinalize,
.invertFunc = NULL,
.combineFunc = histogramCombine,
@@ -1966,7 +2384,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "diff",
.type = FUNCTION_TYPE_DIFF,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC,
.translateFunc = translateDiff,
.getEnvFunc = getDiffFuncEnv,
.initFunc = diffFunctionSetup,
@@ -1976,7 +2394,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "statecount",
.type = FUNCTION_TYPE_STATE_COUNT,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC,
.translateFunc = translateStateCount,
.getEnvFunc = getStateFuncEnv,
.initFunc = functionSetup,
@@ -1986,7 +2404,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "stateduration",
.type = FUNCTION_TYPE_STATE_DURATION,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC,
.translateFunc = translateStateDuration,
.getEnvFunc = getStateFuncEnv,
.initFunc = functionSetup,
@@ -1996,7 +2414,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "csum",
.type = FUNCTION_TYPE_CSUM,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC,
.translateFunc = translateCsum,
.getEnvFunc = getCsumFuncEnv,
.initFunc = functionSetup,
@@ -2006,7 +2424,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "mavg",
.type = FUNCTION_TYPE_MAVG,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
+ .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC,
.translateFunc = translateMavg,
.getEnvFunc = getMavgFuncEnv,
.initFunc = mavgFunctionSetup,
@@ -2026,7 +2444,8 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "tail",
.type = FUNCTION_TYPE_TAIL,
- .classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
+ .classification = FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC |
+ FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateTail,
.getEnvFunc = getTailFuncEnv,
.initFunc = tailFunctionSetup,
@@ -2036,14 +2455,24 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.name = "unique",
.type = FUNCTION_TYPE_UNIQUE,
- .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC |
- FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
+ .classification = FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC |
+ FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC,
.translateFunc = translateUnique,
.getEnvFunc = getUniqueFuncEnv,
.initFunc = uniqueFunctionSetup,
.processFunc = uniqueFunction,
.finalizeFunc = NULL
},
+ {
+ .name = "mode",
+ .type = FUNCTION_TYPE_MODE,
+ .classification = FUNC_MGT_AGG_FUNC,
+ .translateFunc = translateMode,
+ .getEnvFunc = getModeFuncEnv,
+ .initFunc = modeFunctionSetup,
+ .processFunc = modeFunction,
+ .finalizeFunc = modeFinalize,
+ },
{
.name = "abs",
.type = FUNCTION_TYPE_ABS,
@@ -2318,7 +2747,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.name = "now",
.type = FUNCTION_TYPE_NOW,
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_DATETIME_FUNC,
- .translateFunc = translateTimePseudoColumn,
+ .translateFunc = translateNowToday,
.getEnvFunc = NULL,
.initFunc = NULL,
.sprocessFunc = nowFunction,
@@ -2328,7 +2757,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.name = "today",
.type = FUNCTION_TYPE_TODAY,
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_DATETIME_FUNC,
- .translateFunc = translateTimePseudoColumn,
+ .translateFunc = translateNowToday,
.getEnvFunc = NULL,
.initFunc = NULL,
.sprocessFunc = todayFunction,
@@ -2355,28 +2784,38 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.finalizeFunc = NULL
},
{
- .name = "_qstartts",
- .type = FUNCTION_TYPE_QSTARTTS,
- .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
+ .name = "_qstart",
+ .type = FUNCTION_TYPE_QSTART,
+ .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_CLIENT_PC_FUNC,
.translateFunc = translateTimePseudoColumn,
- .getEnvFunc = getTimePseudoFuncEnv,
+ .getEnvFunc = NULL,
.initFunc = NULL,
- .sprocessFunc = qStartTsFunction,
+ .sprocessFunc = NULL,
.finalizeFunc = NULL
},
{
- .name = "_qendts",
- .type = FUNCTION_TYPE_QENDTS,
- .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
+ .name = "_qend",
+ .type = FUNCTION_TYPE_QEND,
+ .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_CLIENT_PC_FUNC,
.translateFunc = translateTimePseudoColumn,
- .getEnvFunc = getTimePseudoFuncEnv,
+ .getEnvFunc = NULL,
.initFunc = NULL,
- .sprocessFunc = qEndTsFunction,
+ .sprocessFunc = NULL,
.finalizeFunc = NULL
},
{
- .name = "_wstartts",
- .type = FUNCTION_TYPE_WSTARTTS,
+ .name = "_qduration",
+ .type = FUNCTION_TYPE_QDURATION,
+ .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_CLIENT_PC_FUNC,
+ .translateFunc = translateWduration,
+ .getEnvFunc = NULL,
+ .initFunc = NULL,
+ .sprocessFunc = NULL,
+ .finalizeFunc = NULL
+ },
+ {
+ .name = "_wstart",
+ .type = FUNCTION_TYPE_WSTART,
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
.translateFunc = translateTimePseudoColumn,
.getEnvFunc = getTimePseudoFuncEnv,
@@ -2385,8 +2824,8 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.finalizeFunc = NULL
},
{
- .name = "_wendts",
- .type = FUNCTION_TYPE_WENDTS,
+ .name = "_wend",
+ .type = FUNCTION_TYPE_WEND,
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
.translateFunc = translateTimePseudoColumn,
.getEnvFunc = getTimePseudoFuncEnv,
@@ -2441,7 +2880,55 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.type = FUNCTION_TYPE_BLOCK_DIST_INFO,
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_SCAN_PC_FUNC,
.translateFunc = translateBlockDistInfoFunc,
- }
+ },
+ {
+ .name = "_group_key",
+ .type = FUNCTION_TYPE_GROUP_KEY,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC,
+ .translateFunc = translateGroupKey,
+ .getEnvFunc = getGroupKeyFuncEnv,
+ .initFunc = functionSetup,
+ .processFunc = groupKeyFunction,
+ .finalizeFunc = groupKeyFinalize,
+ .pPartialFunc = "_group_key",
+ .pMergeFunc = "_group_key"
+ },
+ {
+ .name = "database",
+ .type = FUNCTION_TYPE_DATABASE,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateDatabaseFunc,
+ },
+ {
+ .name = "client_version",
+ .type = FUNCTION_TYPE_CLIENT_VERSION,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateClientVersionFunc,
+ },
+ {
+ .name = "server_version",
+ .type = FUNCTION_TYPE_SERVER_VERSION,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateServerVersionFunc,
+ },
+ {
+ .name = "server_status",
+ .type = FUNCTION_TYPE_SERVER_STATUS,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateServerStatusFunc,
+ },
+ {
+ .name = "current_user",
+ .type = FUNCTION_TYPE_CURRENT_USER,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateCurrentUserFunc,
+ },
+ {
+ .name = "user",
+ .type = FUNCTION_TYPE_USER,
+ .classification = FUNC_MGT_SYSTEM_INFO_FUNC | FUNC_MGT_SCALAR_FUNC,
+ .translateFunc = translateUserFunc,
+ },
};
// clang-format on
diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c
index 076ae6146021b33179eb2271086c4b5a613176fd..97cb1f0ee112966412e777909387a3f6ad66aa67 100644
--- a/source/libs/function/src/builtinsimpl.c
+++ b/source/libs/function/src/builtinsimpl.c
@@ -16,6 +16,7 @@
#include "builtinsimpl.h"
#include "cJSON.h"
#include "function.h"
+#include "query.h"
#include "querynodes.h"
#include "taggfunction.h"
#include "tcompare.h"
@@ -32,6 +33,7 @@
#define TAIL_MAX_OFFSET 100
#define UNIQUE_MAX_RESULT_SIZE (1024 * 1024 * 10)
+#define MODE_MAX_RESULT_SIZE UNIQUE_MAX_RESULT_SIZE
#define HLL_BUCKET_BITS 14 // The bits of the bucket
#define HLL_DATA_BITS (64 - HLL_BUCKET_BITS)
@@ -59,6 +61,12 @@ typedef struct STuplePos {
int32_t offset;
} STuplePos;
+typedef struct SMinmaxResInfo {
+ bool assign; // assign the first value or not
+ int64_t v;
+ STuplePos tuplePos;
+} SMinmaxResInfo;
+
typedef struct STopBotResItem {
SVariant v;
uint64_t uid; // it is a table uid, used to extract tag data during building of the final result for the tag data
@@ -73,7 +81,11 @@ typedef struct STopBotRes {
typedef struct SFirstLastRes {
bool hasResult;
+ // used for last_row function only, isNullRes in SResultRowEntry can not be passed to downstream.So,
+ // this attribute is required
+ bool isNull;
int32_t bytes;
+ int64_t ts;
char buf[];
} SFirstLastRes;
@@ -81,12 +93,14 @@ typedef struct SStddevRes {
double result;
int64_t count;
union {
- double quadraticDSum;
- int64_t quadraticISum;
+ double quadraticDSum;
+ int64_t quadraticISum;
+ uint64_t quadraticUSum;
};
union {
- double dsum;
- int64_t isum;
+ double dsum;
+ int64_t isum;
+ uint64_t usum;
};
int16_t type;
} SStddevRes;
@@ -148,6 +162,12 @@ typedef struct SElapsedInfo {
int64_t timeUnit;
} SElapsedInfo;
+typedef struct STwaInfo {
+ double dOutput;
+ SPoint1 p;
+ STimeWindow win;
+} STwaInfo;
+
typedef struct SHistoFuncBin {
double lower;
double upper;
@@ -195,13 +215,13 @@ typedef struct SMavgInfo {
} SMavgInfo;
typedef struct SSampleInfo {
- int32_t samples;
- int32_t totalPoints;
- int32_t numSampled;
- uint8_t colType;
- int16_t colBytes;
- char* data;
- int64_t* timestamp;
+ int32_t samples;
+ int32_t totalPoints;
+ int32_t numSampled;
+ uint8_t colType;
+ int16_t colBytes;
+ char* data;
+ STuplePos* tuplePos;
} SSampleInfo;
typedef struct STailItem {
@@ -234,6 +254,41 @@ typedef struct SUniqueInfo {
char pItems[];
} SUniqueInfo;
+typedef struct SModeItem {
+ int64_t count;
+ char data[];
+} SModeItem;
+
+typedef struct SModeInfo {
+ int32_t numOfPoints;
+ uint8_t colType;
+ int16_t colBytes;
+ SHashObj* pHash;
+ char pItems[];
+} SModeInfo;
+
+typedef struct SDerivInfo {
+ double prevValue; // previous value
+ TSKEY prevTs; // previous timestamp
+ bool ignoreNegative; // ignore the negative value
+ int64_t tsWindow; // time window for derivative
+ bool valueSet; // the value has been set already
+} SDerivInfo;
+
+typedef struct SRateInfo {
+ double firstValue;
+ TSKEY firstKey;
+ double lastValue;
+ TSKEY lastKey;
+ int8_t hasResult; // flag to denote has value
+} SRateInfo;
+
+typedef struct SGroupKeyInfo {
+ bool hasResult;
+ bool isNull;
+ char data[];
+} SGroupKeyInfo;
+
#define SET_VAL(_info, numOfElem, res) \
do { \
if ((numOfElem) <= 0) { \
@@ -286,6 +341,104 @@ typedef struct SUniqueInfo {
} \
} while (0)
+#define LIST_ADD_N(_res, _col, _start, _rows, _t, numOfElem) \
+ do { \
+ _t* d = (_t*)(_col->pData); \
+ for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
+ if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
+ continue; \
+ }; \
+ (_res) += (d)[i]; \
+ (numOfElem)++; \
+ } \
+ } while (0)
+
+#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem) \
+ do { \
+ _t* d = (_t*)(_col->pData); \
+ for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
+ if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
+ continue; \
+ }; \
+ (_res) -= (d)[i]; \
+ (numOfElem)++; \
+ } \
+ } while (0)
+
+#define LIST_AVG_N(sumT, T) \
+ do { \
+ T* plist = (T*)pCol->pData; \
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
+ continue; \
+ } \
+ \
+ numOfElem += 1; \
+ pAvgRes->count -= 1; \
+ sumT -= plist[i]; \
+ } \
+ } while (0)
+
+#define LIST_STDDEV_SUB_N(sumT, T) \
+ do { \
+ T* plist = (T*)pCol->pData; \
+ for (int32_t i = start; i < numOfRows + start; ++i) { \
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
+ continue; \
+ } \
+ numOfElem += 1; \
+ pStddevRes->count -= 1; \
+ sumT -= plist[i]; \
+ pStddevRes->quadraticISum -= plist[i] * plist[i]; \
+ } \
+ } while (0)
+
+#define LEASTSQR_CAL(p, x, y, index, step) \
+ do { \
+ (p)[0][0] += (double)(x) * (x); \
+ (p)[0][1] += (double)(x); \
+ (p)[0][2] += (double)(x) * (y)[index]; \
+ (p)[1][2] += (y)[index]; \
+ (x) += step; \
+ } while (0)
+
+
+#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
+
+#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
+
+#define STATE_COMP_IMPL(_op, _lval, _rval) \
+ do { \
+ switch (_op) { \
+ case STATE_OPER_LT: \
+ return ((_lval) < (_rval)); \
+ break; \
+ case STATE_OPER_GT: \
+ return ((_lval) > (_rval)); \
+ break; \
+ case STATE_OPER_LE: \
+ return ((_lval) <= (_rval)); \
+ break; \
+ case STATE_OPER_GE: \
+ return ((_lval) >= (_rval)); \
+ break; \
+ case STATE_OPER_NE: \
+ return ((_lval) != (_rval)); \
+ break; \
+ case STATE_OPER_EQ: \
+ return ((_lval) == (_rval)); \
+ break; \
+ default: \
+ break; \
+ } \
+ } while (0)
+
+#define INIT_INTP_POINT(_p, _k, _v) \
+ do { \
+ (_p).key = (_k); \
+ (_p).val = (_v); \
+ } while (0)
+
bool dummyGetEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* UNUSED_PARAM(pEnv)) { return true; }
bool dummyInit(SqlFunctionCtx* UNUSED_PARAM(pCtx), SResultRowEntryInfo* UNUSED_PARAM(pResultInfo)) { return true; }
@@ -447,30 +600,6 @@ int32_t combineFunction(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
return TSDB_CODE_SUCCESS;
}
-#define LIST_ADD_N(_res, _col, _start, _rows, _t, numOfElem) \
- do { \
- _t* d = (_t*)(_col->pData); \
- for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
- if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
- continue; \
- }; \
- (_res) += (d)[i]; \
- (numOfElem)++; \
- } \
- } while (0)
-
-#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem) \
- do { \
- _t* d = (_t*)(_col->pData); \
- for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
- if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
- continue; \
- }; \
- (_res) -= (d)[i]; \
- (numOfElem)++; \
- } \
- } while (0)
-
int32_t sumFunction(SqlFunctionCtx* pCtx) {
int32_t numOfElem = 0;
@@ -533,7 +662,7 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) {
// check for overflow
if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
- GET_RES_INFO(pCtx)->isNullRes = 1;
+ numOfElem = 0;
}
_sum_over:
@@ -669,8 +798,10 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
ASSERT(numOfElem >= 0);
pAvgRes->count += numOfElem;
- if (IS_INTEGER_TYPE(type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(type)) {
pAvgRes->sum.isum += pAgg->sum;
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ pAvgRes->sum.usum += pAgg->sum;
} else if (IS_FLOAT_TYPE(type)) {
pAvgRes->sum.dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
}
@@ -734,6 +865,64 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
break;
}
+ case TSDB_DATA_TYPE_UTINYINT: {
+ uint8_t* plist = (uint8_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pAvgRes->count += 1;
+ pAvgRes->sum.usum += plist[i];
+ }
+
+ break;
+ }
+
+ case TSDB_DATA_TYPE_USMALLINT: {
+ uint16_t* plist = (uint16_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pAvgRes->count += 1;
+ pAvgRes->sum.usum += plist[i];
+ }
+ break;
+ }
+
+ case TSDB_DATA_TYPE_UINT: {
+ uint32_t* plist = (uint32_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pAvgRes->count += 1;
+ pAvgRes->sum.usum += plist[i];
+ }
+
+ break;
+ }
+
+ case TSDB_DATA_TYPE_UBIGINT: {
+ uint64_t* plist = (uint64_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pAvgRes->count += 1;
+ pAvgRes->sum.usum += plist[i];
+ }
+ break;
+ }
+
case TSDB_DATA_TYPE_FLOAT: {
float* plist = (float*)pCol->pData;
for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
@@ -775,8 +964,10 @@ _avg_over:
static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) {
pOutput->type = pInput->type;
- if (IS_INTEGER_TYPE(pOutput->type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
pOutput->sum.isum += pInput->sum.isum;
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
+ pOutput->sum.usum += pInput->sum.usum;
} else {
pOutput->sum.dsum += pInput->sum.dsum;
}
@@ -793,31 +984,19 @@ int32_t avgFunctionMerge(SqlFunctionCtx* pCtx) {
SAvgRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SAvgRes* pInputInfo = (SAvgRes*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- avgTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SAvgRes* pInputInfo = (SAvgRes*)varDataVal(data);
+ avgTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
return TSDB_CODE_SUCCESS;
}
-#define LIST_AVG_N(sumT, T) \
- do { \
- T* plist = (T*)pCol->pData; \
- for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
- if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
- continue; \
- } \
- \
- numOfElem += 1; \
- pAvgRes->count -= 1; \
- sumT -= plist[i]; \
- } \
- } while (0)
-
int32_t avgInvertFunction(SqlFunctionCtx* pCtx) {
int32_t numOfElem = 0;
@@ -850,6 +1029,22 @@ int32_t avgInvertFunction(SqlFunctionCtx* pCtx) {
LIST_AVG_N(pAvgRes->sum.isum, int64_t);
break;
}
+ case TSDB_DATA_TYPE_UTINYINT: {
+ LIST_AVG_N(pAvgRes->sum.usum, uint8_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_USMALLINT: {
+ LIST_AVG_N(pAvgRes->sum.usum, uint16_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_UINT: {
+ LIST_AVG_N(pAvgRes->sum.usum, uint32_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_UBIGINT: {
+ LIST_AVG_N(pAvgRes->sum.usum, uint64_t);
+ break;
+ }
case TSDB_DATA_TYPE_FLOAT: {
LIST_AVG_N(pAvgRes->sum.dsum, float);
break;
@@ -875,8 +1070,10 @@ int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
SAvgRes* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
- if (IS_INTEGER_TYPE(type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(type)) {
pDBuf->sum.isum += pSBuf->sum.isum;
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ pDBuf->sum.usum += pSBuf->sum.usum;
} else {
pDBuf->sum.dsum += pSBuf->sum.dsum;
}
@@ -891,15 +1088,17 @@ int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
int32_t type = pAvgRes->type;
- if (IS_INTEGER_TYPE(type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(type)) {
pAvgRes->result = pAvgRes->sum.isum / ((double)pAvgRes->count);
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ pAvgRes->result = pAvgRes->sum.usum / ((double)pAvgRes->count);
} else {
pAvgRes->result = pAvgRes->sum.dsum / ((double)pAvgRes->count);
}
// check for overflow
if (isinf(pAvgRes->result) || isnan(pAvgRes->result)) {
- GET_RES_INFO(pCtx)->isNullRes = 1;
+ GET_RES_INFO(pCtx)->numOfRes = 0;
}
return functionFinalize(pCtx, pBlock);
@@ -927,12 +1126,6 @@ EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWin
return FUNC_DATA_REQUIRED_STATIS_LOAD;
}
-typedef struct SMinmaxResInfo {
- bool assign; // assign the first value or not
- int64_t v;
- STuplePos tuplePos;
-} SMinmaxResInfo;
-
bool minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
if (!functionSetup(pCtx, pResultInfo)) {
return false; // not initialized since it has been initialized
@@ -952,6 +1145,18 @@ bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
static void saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos);
static void copyTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos);
+static int32_t findRowIndex(int32_t start, int32_t num, SColumnInfoData* pCol, const char* tval) {
+ // the data is loaded, not only the block SMA value
+ for (int32_t i = start; i < num + start; ++i) {
+ char* p = colDataGetData(pCol, i);
+ if (memcpy((void*)tval, p, pCol->info.bytes) == 0) {
+ return i;
+ }
+ }
+
+ ASSERT(0);
+}
+
int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
int32_t numOfElems = 0;
@@ -983,15 +1188,14 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
if (isMinFunc) {
tval = &pInput->pColumnDataAgg[0]->min;
- index = pInput->pColumnDataAgg[0]->minIndex;
} else {
tval = &pInput->pColumnDataAgg[0]->max;
- index = pInput->pColumnDataAgg[0]->maxIndex;
}
if (!pBuf->assign) {
pBuf->v = *(int64_t*)tval;
if (pCtx->subsidiaries.num > 0) {
+ index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval);
saveTupleData(pCtx, index, pCtx->pSrcBlock, &pBuf->tuplePos);
}
} else {
@@ -1003,6 +1207,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
if ((prev < val) ^ isMinFunc) {
pBuf->v = val;
if (pCtx->subsidiaries.num > 0) {
+ index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval);
saveTupleData(pCtx, index, pCtx->pSrcBlock, &pBuf->tuplePos);
}
}
@@ -1015,6 +1220,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
if ((prev < val) ^ isMinFunc) {
pBuf->v = val;
if (pCtx->subsidiaries.num > 0) {
+ index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval);
saveTupleData(pCtx, index, pCtx->pSrcBlock, &pBuf->tuplePos);
}
}
@@ -1026,6 +1232,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
if ((prev < val) ^ isMinFunc) {
pBuf->v = val;
if (pCtx->subsidiaries.num > 0) {
+ index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval);
saveTupleData(pCtx, index, pCtx->pSrcBlock, &pBuf->tuplePos);
}
}
@@ -1039,6 +1246,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
}
if (pCtx->subsidiaries.num > 0) {
+ index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval);
saveTupleData(pCtx, index, pCtx->pSrcBlock, &pBuf->tuplePos);
}
}
@@ -1425,35 +1633,40 @@ void setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t
}
void setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
+ if (pCtx->subsidiaries.num <= 0) {
+ return;
+ }
+
int32_t pageId = pTuplePos->pageId;
int32_t offset = pTuplePos->offset;
+
if (pTuplePos->pageId != -1) {
+ int32_t numOfCols = pCtx->subsidiaries.num;
SFilePage* pPage = getBufPage(pCtx->pBuf, pageId);
bool* nullList = (bool*)((char*)pPage + offset);
- char* pStart = (char*)(nullList + pCtx->pSrcBlock->info.numOfCols * sizeof(bool));
+ char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
// todo set the offset value to optimize the performance.
for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
- int32_t srcSlotId = pFuncParam->pCol->slotId;
int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
int32_t ps = 0;
- for (int32_t k = 0; k < srcSlotId; ++k) {
- SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, k);
- ps += pSrcCol->info.bytes;
- }
SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
- if (nullList[srcSlotId]) {
+ ASSERT(pc->pExpr->base.resSchema.bytes == pDstCol->info.bytes);
+ if (nullList[j]) {
colDataAppendNULL(pDstCol, rowIndex);
} else {
- colDataAppend(pDstCol, rowIndex, (pStart + ps), false);
+ colDataAppend(pDstCol, rowIndex, pStart, false);
}
+ pStart += pDstCol->info.bytes;
}
+
+ releaseBufPage(pCtx->pBuf, pPage);
}
}
@@ -1602,6 +1815,68 @@ int32_t stddevFunction(SqlFunctionCtx* pCtx) {
break;
}
+ case TSDB_DATA_TYPE_UTINYINT: {
+ uint8_t* plist = (uint8_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + start; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pStddevRes->count += 1;
+ pStddevRes->usum += plist[i];
+ pStddevRes->quadraticISum += plist[i] * plist[i];
+ }
+
+ break;
+ }
+
+ case TSDB_DATA_TYPE_USMALLINT: {
+ uint16_t* plist = (uint16_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pStddevRes->count += 1;
+ pStddevRes->usum += plist[i];
+ pStddevRes->quadraticISum += plist[i] * plist[i];
+ }
+ break;
+ }
+
+ case TSDB_DATA_TYPE_UINT: {
+ uint32_t* plist = (uint32_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pStddevRes->count += 1;
+ pStddevRes->usum += plist[i];
+ pStddevRes->quadraticISum += plist[i] * plist[i];
+ }
+
+ break;
+ }
+
+ case TSDB_DATA_TYPE_UBIGINT: {
+ uint64_t* plist = (uint64_t*)pCol->pData;
+ for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
+ if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElem += 1;
+ pStddevRes->count += 1;
+ pStddevRes->usum += plist[i];
+ pStddevRes->quadraticISum += plist[i] * plist[i];
+ }
+ break;
+ }
+
case TSDB_DATA_TYPE_FLOAT: {
float* plist = (float*)pCol->pData;
for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
@@ -1644,17 +1919,18 @@ _stddev_over:
static void stddevTransferInfo(SStddevRes* pInput, SStddevRes* pOutput) {
pOutput->type = pInput->type;
- if (IS_INTEGER_TYPE(pOutput->type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
pOutput->quadraticISum += pInput->quadraticISum;
pOutput->isum += pInput->isum;
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
+ pOutput->quadraticUSum += pInput->quadraticUSum;
+ pOutput->usum += pInput->usum;
} else {
pOutput->quadraticDSum += pInput->quadraticDSum;
pOutput->dsum += pInput->dsum;
}
pOutput->count += pInput->count;
-
- return;
}
int32_t stddevFunctionMerge(SqlFunctionCtx* pCtx) {
@@ -1664,31 +1940,16 @@ int32_t stddevFunctionMerge(SqlFunctionCtx* pCtx) {
SStddevRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SStddevRes* pInputInfo = (SStddevRes*)varDataVal(data);
-
- stddevTransferInfo(pInputInfo, pInfo);
+ for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SStddevRes* pInputInfo = (SStddevRes*)varDataVal(data);
+ stddevTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
-
return TSDB_CODE_SUCCESS;
}
-#define LIST_STDDEV_SUB_N(sumT, T) \
- do { \
- T* plist = (T*)pCol->pData; \
- for (int32_t i = start; i < numOfRows + start; ++i) { \
- if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
- continue; \
- } \
- numOfElem += 1; \
- pStddevRes->count -= 1; \
- sumT -= plist[i]; \
- pStddevRes->quadraticISum -= plist[i] * plist[i]; \
- } \
- } while (0)
-
int32_t stddevInvertFunction(SqlFunctionCtx* pCtx) {
int32_t numOfElem = 0;
@@ -1721,6 +1982,22 @@ int32_t stddevInvertFunction(SqlFunctionCtx* pCtx) {
LIST_STDDEV_SUB_N(pStddevRes->isum, int64_t);
break;
}
+ case TSDB_DATA_TYPE_UTINYINT: {
+ LIST_STDDEV_SUB_N(pStddevRes->isum, uint8_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_USMALLINT: {
+ LIST_STDDEV_SUB_N(pStddevRes->isum, uint16_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_UINT: {
+ LIST_STDDEV_SUB_N(pStddevRes->isum, uint32_t);
+ break;
+ }
+ case TSDB_DATA_TYPE_UBIGINT: {
+ LIST_STDDEV_SUB_N(pStddevRes->isum, uint64_t);
+ break;
+ }
case TSDB_DATA_TYPE_FLOAT: {
LIST_STDDEV_SUB_N(pStddevRes->dsum, float);
break;
@@ -1744,14 +2021,22 @@ int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
int32_t type = pStddevRes->type;
double avg;
- if (IS_INTEGER_TYPE(type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(type)) {
avg = pStddevRes->isum / ((double)pStddevRes->count);
pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ avg = pStddevRes->usum / ((double)pStddevRes->count);
+ pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
} else {
avg = pStddevRes->dsum / ((double)pStddevRes->count);
pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
}
+ // check for overflow
+ if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
+ GET_RES_INFO(pCtx)->numOfRes = 0;
+ }
+
return functionFinalize(pCtx, pBlock);
}
@@ -1781,9 +2066,12 @@ int32_t stddevCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
SStddevRes* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
- if (IS_INTEGER_TYPE(type)) {
+ if (IS_SIGNED_NUMERIC_TYPE(type)) {
pDBuf->isum += pSBuf->isum;
pDBuf->quadraticISum += pSBuf->quadraticISum;
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ pDBuf->usum += pSBuf->usum;
+ pDBuf->quadraticUSum += pSBuf->quadraticUSum;
} else {
pDBuf->dsum += pSBuf->dsum;
pDBuf->quadraticDSum += pSBuf->quadraticDSum;
@@ -1810,15 +2098,6 @@ bool leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInf
return true;
}
-#define LEASTSQR_CAL(p, x, y, index, step) \
- do { \
- (p)[0][0] += (double)(x) * (x); \
- (p)[0][1] += (double)(x); \
- (p)[0][2] += (double)(x) * (y)[index]; \
- (p)[1][2] += (y)[index]; \
- (x) += step; \
- } while (0)
-
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
int32_t numOfElem = 0;
@@ -1844,9 +2123,8 @@ int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
}
numOfElem++;
LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
-
- break;
}
+ break;
}
case TSDB_DATA_TYPE_SMALLINT: {
int16_t* plist = (int16_t*)pCol->pData;
@@ -1871,7 +2149,6 @@ int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
numOfElem++;
LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
}
-
break;
}
@@ -2280,11 +2557,13 @@ int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- apercentileTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
+ apercentileTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(pResInfo, 1, 1);
return TSDB_CODE_SUCCESS;
@@ -2361,11 +2640,13 @@ int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx)
return TSDB_CODE_SUCCESS;
}
-int32_t getFirstLastInfoSize(int32_t resBytes) { return sizeof(SFirstLastRes) + resBytes + sizeof(int64_t); }
+int32_t getFirstLastInfoSize(int32_t resBytes) {
+ return sizeof(SFirstLastRes) + resBytes + sizeof(int64_t) + sizeof(STuplePos);
+}
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
- pEnv->calcMemSize = sizeof(SFirstLastRes) + pNode->node.resType.bytes + sizeof(int64_t);
+ pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes);
return true;
}
@@ -2375,6 +2656,12 @@ bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
return true;
}
+bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
+ SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
+ pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
+ return true;
+}
+
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
if (pTsColInfo == NULL) {
return 0;
@@ -2437,9 +2724,17 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) {
}
memcpy(pInfo->buf, data, bytes);
*(TSKEY*)(pInfo->buf + bytes) = cts;
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
pInfo->hasResult = true;
- // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
-
+ // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
pResInfo->numOfRes = 1;
break;
}
@@ -2471,8 +2766,16 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) {
}
memcpy(pInfo->buf, data, bytes);
*(TSKEY*)(pInfo->buf + bytes) = cts;
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
pInfo->hasResult = true;
- // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
pResInfo->numOfRes = 1;
break;
}
@@ -2526,8 +2829,17 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
}
memcpy(pInfo->buf, data, bytes);
*(TSKEY*)(pInfo->buf + bytes) = cts;
- // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
pInfo->hasResult = true;
+ // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
pResInfo->numOfRes = 1;
}
break;
@@ -2549,9 +2861,17 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
}
memcpy(pInfo->buf, data, bytes);
*(TSKEY*)(pInfo->buf + bytes) = cts;
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
pInfo->hasResult = true;
pResInfo->numOfRes = 1;
- // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
}
break;
}
@@ -2561,7 +2881,10 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
return TSDB_CODE_SUCCESS;
}
-static void firstLastTransferInfo(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
+static void firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
+ SInputColumnInfoData* pColInfo = &pCtx->input;
+ int32_t start = pColInfo->startRowIndex;
+
pOutput->bytes = pInput->bytes;
TSKEY* tsIn = (TSKEY*)(pInput->buf + pInput->bytes);
TSKEY* tsOut = (TSKEY*)(pOutput->buf + pInput->bytes);
@@ -2578,7 +2901,17 @@ static void firstLastTransferInfo(SFirstLastRes* pInput, SFirstLastRes* pOutput,
}
*tsOut = *tsIn;
memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
+ // handle selectivity
+ STuplePos* pTuplePos = (STuplePos*)(pOutput->buf + pOutput->bytes + sizeof(TSKEY));
+ if (pCtx->subsidiaries.num > 0) {
+ if (!pOutput->hasResult) {
+ saveTupleData(pCtx, start, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, start, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
pOutput->hasResult = true;
+
return;
}
@@ -2589,13 +2922,17 @@ static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuer
SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
-
- firstLastTransferInfo(pInputInfo, pInfo, isFirstQuery);
+ int32_t start = pInput->startRowIndex;
+ int32_t numOfElems = 0;
- int32_t numOfElems = pInputInfo->hasResult ? 1 : 0;
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
+ firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery);
+ if (!numOfElems) {
+ numOfElems = pInputInfo->hasResult ? 1 : 0;
+ }
+ }
SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
@@ -2614,7 +2951,11 @@ int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
- colDataAppend(pCol, pBlock->info.rows, pRes->buf, pResInfo->isNullRes);
+ colDataAppend(pCol, pBlock->info.rows, pRes->buf, pRes->isNull||pResInfo->isNullRes);
+
+ // handle selectivity
+ STuplePos* pTuplePos = (STuplePos*)(pRes->buf + pRes->bytes + sizeof(TSKEY));
+ setSelectivityValue(pCtx, pBlock, pTuplePos, pBlock->info.rows);
return pResInfo->numOfRes;
}
@@ -2623,8 +2964,8 @@ int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t resultBytes = getFirstLastInfoSize(pRes->bytes);
- char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
+ int32_t resultBytes = getFirstLastInfoSize(pRes->bytes);
+ char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
memcpy(varDataVal(res), pRes, resultBytes);
varDataSetLen(res, resultBytes);
@@ -2633,6 +2974,9 @@ int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
colDataAppend(pCol, pBlock->info.rows, res, false);
+ // handle selectivity
+ STuplePos* pTuplePos = (STuplePos*)(pRes->buf + pRes->bytes + sizeof(TSKEY));
+ setSelectivityValue(pCtx, pBlock, pTuplePos, pBlock->info.rows);
taosMemoryFree(res);
return 1;
@@ -2655,6 +2999,111 @@ int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
return TSDB_CODE_SUCCESS;
}
+int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
+ int32_t numOfElems = 0;
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ SInputColumnInfoData* pInput = &pCtx->input;
+ SColumnInfoData* pInputCol = pInput->pData[0];
+
+ int32_t type = pInputCol->info.type;
+ int32_t bytes = pInputCol->info.bytes;
+ pInfo->bytes = bytes;
+
+ SColumnDataAgg* pColAgg = (pInput->colDataAggIsSet) ? pInput->pColumnDataAgg[0] : NULL;
+
+ TSKEY startKey = getRowPTs(pInput->pPTS, 0);
+ TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
+
+ int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
+
+ if (blockDataOrder == TSDB_ORDER_ASC) {
+ for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
+ char* data = colDataGetData(pInputCol, i);
+ TSKEY cts = getRowPTs(pInput->pPTS, i);
+ if (pResInfo->numOfRes == 0 || *(TSKEY*)(pInfo->buf) < cts) {
+ if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
+ pInfo->isNull = true;
+ } else {
+ pInfo->isNull = false;
+ if (IS_VAR_DATA_TYPE(type)) {
+ bytes = varDataTLen(data);
+ pInfo->bytes = bytes;
+ }
+ memcpy(pInfo->buf + sizeof(TSKEY), data, bytes);
+ }
+ *(TSKEY*)(pInfo->buf) = cts;
+ numOfElems++;
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
+ pInfo->hasResult = true;
+ // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
+ pResInfo->numOfRes = 1;
+ }
+ break;
+ }
+ } else { // descending order
+ for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
+ char* data = colDataGetData(pInputCol, i);
+ TSKEY cts = getRowPTs(pInput->pPTS, i);
+ if (pResInfo->numOfRes == 0 || *(TSKEY*)(pInfo->buf) < cts) {
+ if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
+ pInfo->isNull = true;
+ } else {
+ pInfo->isNull = false;
+ if (IS_VAR_DATA_TYPE(type)) {
+ bytes = varDataTLen(data);
+ pInfo->bytes = bytes;
+ }
+ memcpy(pInfo->buf + sizeof(TSKEY), data, bytes);
+ }
+ *(TSKEY*)(pInfo->buf) = cts;
+ numOfElems++;
+ // handle selectivity
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
+ pInfo->hasResult = true;
+ pResInfo->numOfRes = 1;
+ // DO_UPDATE_TAG_COLUMNS(pCtx, ts);
+ }
+ break;
+ }
+ }
+
+ SET_VAL(pResInfo, numOfElems, 1);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t lastRowFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+ int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
+ SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+
+ SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
+ colDataAppend(pCol, pBlock->info.rows, pRes->buf + sizeof(TSKEY), pRes->isNull);
+ // handle selectivity
+ STuplePos* pTuplePos = (STuplePos*)(pRes->buf + pRes->bytes + sizeof(TSKEY));
+ setSelectivityValue(pCtx, pBlock, pTuplePos, pBlock->info.rows);
+
+ return pResInfo->numOfRes;
+}
+
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
pEnv->calcMemSize = sizeof(SDiffInfo);
return true;
@@ -2668,7 +3117,11 @@ bool diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
pDiffInfo->hasPrev = false;
pDiffInfo->prev.i64 = 0;
- pDiffInfo->ignoreNegative = pCtx->param[1].param.i; // TODO set correct param
+ if (pCtx->numOfParams > 1) {
+ pDiffInfo->ignoreNegative = pCtx->param[1].param.i; // TODO set correct param
+ } else {
+ pDiffInfo->ignoreNegative = false;
+ }
pDiffInfo->includeNull = false;
pDiffInfo->firstOutput = false;
return true;
@@ -2783,10 +3236,8 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
SInputColumnInfoData* pInput = &pCtx->input;
SColumnInfoData* pInputCol = pInput->pData[0];
- SColumnInfoData* pTsOutput = pCtx->pTsOutput;
int32_t numOfElems = 0;
- TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
int32_t startOffset = pCtx->offset;
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
@@ -2798,9 +3249,6 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
if (pDiffInfo->includeNull) {
colDataSetNull_f(pOutput->nullbitmap, pos);
- if (tsList != NULL) {
- colDataAppendInt64(pTsOutput, pos, &tsList[i]);
- }
numOfElems += 1;
}
@@ -2811,9 +3259,6 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
if (pDiffInfo->hasPrev) {
doHandleDiff(pDiffInfo, pInputCol->info.type, pv, pOutput, pos, pCtx->order);
- if (pTsOutput != NULL) {
- colDataAppendInt64(pTsOutput, pos, &tsList[i]);
- }
numOfElems++;
} else {
@@ -2829,9 +3274,6 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
if (pDiffInfo->includeNull) {
colDataSetNull_f(pOutput->nullbitmap, pos);
- if (tsList != NULL) {
- colDataAppendInt64(pTsOutput, pos, &tsList[i]);
- }
numOfElems += 1;
}
@@ -2843,9 +3285,6 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
// there is a row of previous data block to be handled in the first place.
if (pDiffInfo->hasPrev) {
doHandleDiff(pDiffInfo, pInputCol->info.type, pv, pOutput, pos, pCtx->order);
- if (pTsOutput != NULL) {
- colDataAppendInt64(pTsOutput, pos, &pDiffInfo->prevTs);
- }
numOfElems++;
} else {
@@ -2853,9 +3292,6 @@ int32_t diffFunction(SqlFunctionCtx* pCtx) {
}
pDiffInfo->hasPrev = true;
- if (pTsOutput != NULL) {
- pDiffInfo->prevTs = tsList[i];
- }
}
}
@@ -2989,8 +3425,13 @@ void doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSData
pItem->uid = uid;
// save the data of this tuple
- saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
-
+ if (pCtx->subsidiaries.num > 0) {
+ saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
+ }
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
+ pItem->tuplePos.offset);
+#endif
// allocate the buffer and keep the data of this row into the new allocated buffer
pEntryInfo->numOfRes++;
taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type, topBotResComparFn,
@@ -3008,17 +3449,33 @@ void doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSData
pItem->uid = uid;
// save the data of this tuple by over writing the old data
- copyTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
+ if (pCtx->subsidiaries.num > 0) {
+ copyTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
+ }
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
+#endif
taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
topBotResComparFn, NULL, !isTopQuery);
}
}
}
+/*
+ * +------------------------------------+--------------+--------------+
+ * | null bitmap | | |
+ * |(n columns, one bit for each column)| src column #1| src column #2|
+ * +------------------------------------+--------------+--------------+
+ */
void saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
SFilePage* pPage = NULL;
- int32_t completeRowSize = pSrcBlock->info.rowSize + pSrcBlock->info.numOfCols * sizeof(bool);
+ // todo refactor: move away
+ int32_t completeRowSize = pCtx->subsidiaries.num * sizeof(bool);
+ for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
+ SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
+ completeRowSize += pc->pExpr->base.resSchema.bytes;
+ }
if (pCtx->curBufPage == -1) {
pPage = getNewBufPage(pCtx->pBuf, 0, &pCtx->curBufPage);
@@ -3026,29 +3483,35 @@ void saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pS
} else {
pPage = getBufPage(pCtx->pBuf, pCtx->curBufPage);
if (pPage->num + completeRowSize > getBufPageSize(pCtx->pBuf)) {
+ // current page is all used, let's prepare a new buffer page
+ releaseBufPage(pCtx->pBuf, pPage);
pPage = getNewBufPage(pCtx->pBuf, 0, &pCtx->curBufPage);
pPage->num = sizeof(SFilePage);
}
}
pPos->pageId = pCtx->curBufPage;
+ pPos->offset = pPage->num;
// keep the current row data, extract method
int32_t offset = 0;
bool* nullList = (bool*)((char*)pPage + pPage->num);
- char* pStart = (char*)(nullList + sizeof(bool) * pSrcBlock->info.numOfCols);
- for (int32_t i = 0; i < pSrcBlock->info.numOfCols; ++i) {
- SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, i);
- bool isNull = colDataIsNull_s(pCol, rowIndex);
- if (isNull) {
- nullList[i] = true;
+ char* pStart = (char*)(nullList + sizeof(bool) * pCtx->subsidiaries.num);
+ for (int32_t i = 0; i < pCtx->subsidiaries.num; ++i) {
+ SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[i];
+
+ SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
+ int32_t srcSlotId = pFuncParam->pCol->slotId;
+
+ SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
+ if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
offset += pCol->info.bytes;
continue;
}
char* p = colDataGetData(pCol, rowIndex);
if (IS_VAR_DATA_TYPE(pCol->info.type)) {
- memcpy(pStart + offset, p, varDataTLen(p));
+ memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
} else {
memcpy(pStart + offset, p, pCol->info.bytes);
}
@@ -3056,22 +3519,30 @@ void saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pS
offset += pCol->info.bytes;
}
- pPos->offset = pPage->num;
pPage->num += completeRowSize;
setBufPageDirty(pPage, true);
releaseBufPage(pCtx->pBuf, pPage);
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_saveTuple pos:%p,pageId:%d, offset:%d\n", pPos, pPos->pageId, pPos->offset);
+#endif
}
void copyTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
SFilePage* pPage = getBufPage(pCtx->pBuf, pPos->pageId);
+ int32_t numOfCols = pCtx->subsidiaries.num;
+
bool* nullList = (bool*)((char*)pPage + pPos->offset);
- char* pStart = (char*)(nullList + pSrcBlock->info.numOfCols * sizeof(bool));
+ char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
int32_t offset = 0;
- for (int32_t i = 0; i < pSrcBlock->info.numOfCols; ++i) {
- SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, i);
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[i];
+ SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
+ int32_t srcSlotId = pFuncParam->pCol->slotId;
+
+ SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
offset += pCol->info.bytes;
continue;
@@ -3079,7 +3550,7 @@ void copyTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pS
char* p = colDataGetData(pCol, rowIndex);
if (IS_VAR_DATA_TYPE(pCol->info.type)) {
- memcpy(pStart + offset, p, varDataTLen(p));
+ memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
} else {
memcpy(pStart + offset, p, pCol->info.bytes);
}
@@ -3089,11 +3560,14 @@ void copyTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pS
setBufPageDirty(pPage, true);
releaseBufPage(pCtx->pBuf, pPage);
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_copyTuple pos:%p, pageId:%d, offset:%d", pPos, pPos->pageId, pPos->offset);
+#endif
}
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
- STopBotRes* pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
+ STopBotRes* pRes = getTopBotOutputInfo(pCtx);
int16_t type = pCtx->input.pData[0]->info.type;
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
@@ -3110,7 +3584,10 @@ int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
} else {
colDataAppend(pCol, currentRow, (const char*)&pItem->v.i, false);
}
-
+#ifdef BUF_PAGE_DEBUG
+ qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
+ pItem->tuplePos.offset);
+#endif
setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
currentRow += 1;
}
@@ -3284,11 +3761,13 @@ int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- spreadTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
+ spreadTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
@@ -3346,10 +3825,10 @@ bool elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo
SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
pInfo->result = 0;
- pInfo->min = MAX_TS_KEY;
+ pInfo->min = TSKEY_MAX;
pInfo->max = 0;
- if (pCtx->numOfParams > 2) {
+ if (pCtx->numOfParams > 1) {
pInfo->timeUnit = pCtx->param[1].param.i;
} else {
pInfo->timeUnit = 1;
@@ -3373,7 +3852,7 @@ int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
}
if (pInput->colDataAggIsSet) {
- if (pInfo->min == MAX_TS_KEY) {
+ if (pInfo->min == TSKEY_MAX) {
pInfo->min = GET_INT64_VAL(&pAgg->min);
pInfo->max = GET_INT64_VAL(&pAgg->max);
} else {
@@ -3454,11 +3933,13 @@ int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- elapsedTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
+ elapsedTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
return TSDB_CODE_SUCCESS;
@@ -3679,7 +4160,7 @@ bool histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultIn
return true;
}
-int32_t histogramFunction(SqlFunctionCtx* pCtx) {
+static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
SInputColumnInfoData* pInput = &pCtx->input;
@@ -3711,10 +4192,22 @@ int32_t histogramFunction(SqlFunctionCtx* pCtx) {
}
}
- SET_VAL(GET_RES_INFO(pCtx), numOfElems, pInfo->numOfBins);
+ if (!isPartial) {
+ SET_VAL(GET_RES_INFO(pCtx), numOfElems, pInfo->numOfBins);
+ } else {
+ SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
+ }
return TSDB_CODE_SUCCESS;
}
+int32_t histogramFunction(SqlFunctionCtx* pCtx) {
+ return histogramFunctionImpl(pCtx, false);
+}
+
+int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) {
+ return histogramFunctionImpl(pCtx, true);
+}
+
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
pOutput->normalized = pInput->normalized;
pOutput->numOfBins = pInput->numOfBins;
@@ -3733,11 +4226,13 @@ int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- histogramTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
+ histogramTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
return TSDB_CODE_SUCCESS;
@@ -3780,6 +4275,7 @@ int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
}
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
int32_t resultBytes = getHistogramInfoSize();
char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
@@ -3793,7 +4289,7 @@ int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
colDataAppend(pCol, pBlock->info.rows, res, false);
taosMemoryFree(res);
- return 1;
+ return pResInfo->numOfRes;
}
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
@@ -3951,11 +4447,13 @@ int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
- int32_t start = pInput->startRowIndex;
- char* data = colDataGetData(pCol, start);
- SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
+ int32_t start = pInput->startRowIndex;
- hllTransferInfo(pInputInfo, pInfo);
+ for(int32_t i = start; i < start + pInput->numOfRows; ++i) {
+ char* data = colDataGetData(pCol, i);
+ SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
+ hllTransferInfo(pInputInfo, pInfo);
+ }
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
return TSDB_CODE_SUCCESS;
@@ -4029,36 +4527,6 @@ static int8_t getStateOpType(char* opStr) {
return opType;
}
-#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
-
-#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
-
-#define STATE_COMP_IMPL(_op, _lval, _rval) \
- do { \
- switch (_op) { \
- case STATE_OPER_LT: \
- return ((_lval) < (_rval)); \
- break; \
- case STATE_OPER_GT: \
- return ((_lval) > (_rval)); \
- break; \
- case STATE_OPER_LE: \
- return ((_lval) <= (_rval)); \
- break; \
- case STATE_OPER_GE: \
- return ((_lval) >= (_rval)); \
- break; \
- case STATE_OPER_NE: \
- return ((_lval) != (_rval)); \
- break; \
- case STATE_OPER_EQ: \
- return ((_lval) == (_rval)); \
- break; \
- default: \
- break; \
- } \
- } while (0)
-
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
char* data = colDataGetData(pCol, index);
switch (pCol->info.type) {
@@ -4168,7 +4636,7 @@ int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
// TODO: process timeUnit for different db precisions
- int32_t timeUnit = 1000;
+ int32_t timeUnit = 1;
if (pCtx->numOfParams == 5) { // TODO: param number incorrect
timeUnit = pCtx->param[3].param.i;
}
@@ -4290,7 +4758,6 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx) {
SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
SInputColumnInfoData* pInput = &pCtx->input;
- TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
SColumnInfoData* pInputCol = pInput->pData[0];
SColumnInfoData* pTsOutput = pCtx->pTsOutput;
@@ -4330,10 +4797,6 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx) {
colDataAppend(pOutput, pos, (char*)&result, false);
}
- // TODO: remove this after pTsOutput is handled
- if (pTsOutput != NULL) {
- colDataAppendInt64(pTsOutput, pos, &tsList[i]);
- }
numOfElems++;
}
@@ -4350,7 +4813,7 @@ bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
int32_t numOfSamples = pVal->datum.i;
- pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(int64_t));
+ pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
return true;
}
@@ -4371,25 +4834,30 @@ bool sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo)
return false;
}
pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
- pInfo->timestamp = (int64_t*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
+ pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
return true;
}
-static void sampleAssignResult(SSampleInfo* pInfo, char* data, TSKEY ts, int32_t index) {
+static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
- *(pInfo->timestamp + index) = ts;
}
-static void doReservoirSample(SSampleInfo* pInfo, char* data, TSKEY ts, int32_t index) {
+static void doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
pInfo->totalPoints++;
if (pInfo->numSampled < pInfo->samples) {
- sampleAssignResult(pInfo, data, ts, pInfo->numSampled);
+ sampleAssignResult(pInfo, data, pInfo->numSampled);
+ if (pCtx->subsidiaries.num > 0) {
+ saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
+ }
pInfo->numSampled++;
} else {
int32_t j = taosRand() % (pInfo->totalPoints);
if (j < pInfo->samples) {
- sampleAssignResult(pInfo, data, ts, j);
+ sampleAssignResult(pInfo, data, j);
+ if (pCtx->subsidiaries.num > 0) {
+ copyTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
+ }
}
}
}
@@ -4400,11 +4868,6 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) {
SInputColumnInfoData* pInput = &pCtx->input;
- TSKEY* tsList = NULL;
- if (pInput->pPTS != NULL) {
- tsList = (int64_t*)pInput->pPTS->pData;
- }
-
SColumnInfoData* pInputCol = pInput->pData[0];
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
if (colDataIsNull_s(pInputCol, i)) {
@@ -4412,7 +4875,7 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) {
}
char* data = colDataGetData(pInputCol, i);
- doReservoirSample(pInfo, data, /*tsList[i]*/ 0, i);
+ doReservoirSample(pCtx, pInfo, data, i);
}
SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
@@ -4431,6 +4894,7 @@ int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
int32_t currentRow = pBlock->info.rows;
for (int32_t i = 0; i < pInfo->numSampled; ++i) {
colDataAppend(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
+ setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
}
return pInfo->numSampled;
@@ -4651,27 +5115,99 @@ int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
return pInfo->numOfPoints;
}
-int32_t uniqueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
+ pEnv->calcMemSize = sizeof(SModeInfo) + MODE_MAX_RESULT_SIZE;
+ return true;
+}
+
+bool modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
+ if (!functionSetup(pCtx, pResInfo)) {
+ return false;
+ }
+
+ SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+ pInfo->numOfPoints = 0;
+ pInfo->colType = pCtx->resDataInfo.type;
+ pInfo->colBytes = pCtx->resDataInfo.bytes;
+ if (pInfo->pHash != NULL) {
+ taosHashClear(pInfo->pHash);
+ } else {
+ pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
+ }
+ return true;
+}
+
+static void doModeAdd(SModeInfo* pInfo, char* data, bool isNull) {
+ // ignore null elements
+ if (isNull) {
+ return;
+ }
+
+ int32_t hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
+ SModeItem** pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
+ if (pHashItem == NULL) {
+ int32_t size = sizeof(SModeItem) + pInfo->colBytes;
+ SModeItem* pItem = (SModeItem*)(pInfo->pItems + pInfo->numOfPoints * size);
+ memcpy(pItem->data, data, pInfo->colBytes);
+ pItem->count += 1;
+
+ taosHashPut(pInfo->pHash, data, hashKeyBytes, &pItem, sizeof(SModeItem*));
+ pInfo->numOfPoints++;
+ } else {
+ (*pHashItem)->count += 1;
+ }
+}
+
+int32_t modeFunction(SqlFunctionCtx* pCtx) {
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
- SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+ SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ SInputColumnInfoData* pInput = &pCtx->input;
+
+ SColumnInfoData* pInputCol = pInput->pData[0];
+ SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
+
+ int32_t startOffset = pCtx->offset;
+ for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
+ char* data = colDataGetData(pInputCol, i);
+ doModeAdd(pInfo, data, colDataIsNull_s(pInputCol, i));
+
+ if (sizeof(SModeInfo) + pInfo->numOfPoints * (sizeof(SModeItem) + pInfo->colBytes) >= MODE_MAX_RESULT_SIZE) {
+ taosHashCleanup(pInfo->pHash);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+
+ SET_VAL(pResInfo, 1, 1);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
+ int32_t currentRow = pBlock->info.rows;
- for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
- SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
- colDataAppend(pCol, i, pItem->data, false);
- // TODO: handle ts output
+ int32_t resIndex;
+ int32_t maxCount = 0;
+ for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
+ SModeItem* pItem = (SModeItem*)(pInfo->pItems + i * (sizeof(SModeItem) + pInfo->colBytes));
+ if (pItem->count > maxCount) {
+ maxCount = pItem->count;
+ resIndex = i;
+ } else if (pItem->count == maxCount) {
+ resIndex = -1;
+ }
}
+ SModeItem* pResItem = (SModeItem*)(pInfo->pItems + resIndex * (sizeof(SModeItem) + pInfo->colBytes));
+ colDataAppend(pCol, currentRow, pResItem->data, (resIndex == -1) ? true : false);
+
return pResInfo->numOfRes;
}
-typedef struct STwaInfo {
- double dOutput;
- SPoint1 p;
- STimeWindow win;
-} STwaInfo;
-
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
pEnv->calcMemSize = sizeof(STwaInfo);
return true;
@@ -4698,12 +5234,6 @@ static double twa_get_area(SPoint1 s, SPoint1 e) {
return val;
}
-#define INIT_INTP_POINT(_p, _k, _v) \
- do { \
- (_p).key = (_k); \
- (_p).val = (_v); \
- } while (0)
-
int32_t twaFunction(SqlFunctionCtx* pCtx) {
SInputColumnInfoData* pInput = &pCtx->input;
SColumnInfoData* pInputCol = pInput->pData[0];
@@ -4923,7 +5453,7 @@ int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
return functionFinalize(pCtx, pBlock);
}
-bool blockDistSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) {
+bool blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
if (!functionSetup(pCtx, pResultInfo)) {
return false;
}
@@ -4955,7 +5485,7 @@ int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
pDistInfo->defMinRows = p1.defMinRows;
pDistInfo->defMaxRows = p1.defMaxRows;
- pDistInfo->rowSize = p1.rowSize;
+ pDistInfo->rowSize = p1.rowSize;
pDistInfo->numOfSmallBlocks = p1.numOfSmallBlocks;
if (pDistInfo->minRows > p1.minRows) {
@@ -5038,19 +5568,29 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
+ if (pData->totalRows == 0) {
+ pData->minRows = 0;
+ }
+
int32_t row = 0;
char st[256] = {0};
double totalRawSize = pData->totalRows * pData->rowSize;
- int32_t len =
- sprintf(st + VARSTR_HEADER_SIZE, "Total_Blocks=[%d] Total_Size=[%.2f Kb] Average_size=[%.2f Kb] Compression_Ratio=[%.2f %c]",
- pData->numOfBlocks, pData->totalSize / 1024.0, ((double)pData->totalSize) / pData->numOfBlocks,
- pData->totalSize * 100 / totalRawSize, '%');
+ int32_t len = sprintf(st + VARSTR_HEADER_SIZE,
+ "Total_Blocks=[%d] Total_Size=[%.2f Kb] Average_size=[%.2f Kb] Compression_Ratio=[%.2f %c]",
+ pData->numOfBlocks, pData->totalSize / 1024.0, ((double)pData->totalSize) / pData->numOfBlocks,
+ pData->totalSize * 100 / totalRawSize, '%');
varDataSetLen(st, len);
colDataAppend(pColInfo, row++, st, false);
- len = sprintf(st + VARSTR_HEADER_SIZE, "Total_Rows=[%"PRId64"] Inmem_Rows=[%d] MinRows=[%d] MaxRows=[%d] Average_Rows=[%"PRId64"]",
- pData->totalRows, pData->numOfInmemRows, pData->minRows, pData->maxRows, pData->totalRows / pData->numOfBlocks);
+ int64_t avgRows = 0;
+ if (pData->numOfBlocks > 0) {
+ avgRows = pData->totalRows / pData->numOfBlocks;
+ }
+
+ len = sprintf(st + VARSTR_HEADER_SIZE,
+ "Total_Rows=[%" PRId64 "] Inmem_Rows=[%d] MinRows=[%d] MaxRows=[%d] Average_Rows=[%" PRId64 "]",
+ pData->totalRows, pData->numOfInmemRows, pData->minRows, pData->maxRows, avgRows);
varDataSetLen(st, len);
colDataAppend(pColInfo, row++, st, false);
@@ -5078,30 +5618,18 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
}
}
- int32_t delta = maxVal - minVal;
- int32_t step = delta / 50;
- if (step == 0) {
- step = 1;
- }
+ // maximum number of step is 80
+ double factor = pData->numOfBlocks / 80.0;
int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
- int32_t bucketRange = (pData->maxRows - pData->minRows) / numOfBuckets;
-
- bool singleModel = false;
- if (bucketRange == 0) {
- singleModel = true;
- step = 20;
- bucketRange = (pData->defMaxRows - pData->defMinRows) / numOfBuckets;
- }
+ int32_t bucketRange = (pData->defMaxRows - pData->defMinRows) / numOfBuckets;
for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
- len = sprintf(st + VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
+ len = sprintf(st + VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * i);
int32_t num = 0;
- if (singleModel && pData->blockRowsHisto[i] > 0) {
- num = 20;
- } else {
- num = (pData->blockRowsHisto[i] + step - 1) / step;
+ if (pData->blockRowsHisto[i] > 0) {
+ num = (pData->blockRowsHisto[i]) / factor;
}
for (int32_t j = 0; j < num; ++j) {
@@ -5109,9 +5637,10 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
len += x;
}
- double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
- len += sprintf(st + VARSTR_HEADER_SIZE + len, " %d (%.2f%c)", pData->blockRowsHisto[i], v, '%');
- printf("%s\n", st);
+ if (num > 0) {
+ double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
+ len += sprintf(st + VARSTR_HEADER_SIZE + len, " %d (%.2f%c)", pData->blockRowsHisto[i], v, '%');
+ }
varDataSetLen(st, len);
colDataAppend(pColInfo, row++, st, false);
@@ -5120,14 +5649,6 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
return TSDB_CODE_SUCCESS;
}
-typedef struct SDerivInfo {
- double prevValue; // previous value
- TSKEY prevTs; // previous timestamp
- bool ignoreNegative; // ignore the negative value
- int64_t tsWindow; // time window for derivative
- bool valueSet; // the value has been set already
-} SDerivInfo;
-
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
pEnv->calcMemSize = sizeof(SDerivInfo);
return true;
@@ -5222,6 +5743,168 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
return numOfElems;
}
+bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
+ pEnv->calcMemSize = sizeof(SRateInfo);
+ return true;
+}
+
+bool irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
+ if (!functionSetup(pCtx, pResInfo)) {
+ return false; // not initialized since it has been initialized
+ }
+
+ SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ pInfo->firstKey = INT64_MIN;
+ pInfo->lastKey = INT64_MIN;
+ pInfo->firstValue = (double)INT64_MIN;
+ pInfo->lastValue = (double)INT64_MIN;
+
+ pInfo->hasResult = 0;
+ return true;
+}
+
+int32_t irateFunction(SqlFunctionCtx* pCtx) {
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo* pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ SInputColumnInfoData* pInput = &pCtx->input;
+ SColumnInfoData* pInputCol = pInput->pData[0];
+
+ SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
+
+ TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
+
+ int32_t numOfElems = 0;
+ int32_t type = pInputCol->info.type;
+
+ for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ numOfElems++;
+
+ char* data = colDataGetData(pInputCol, i);
+ double v = 0;
+ GET_TYPED_DATA(v, double, type, data);
+
+ if (INT64_MIN == pRateInfo->lastKey) {
+ pRateInfo->lastValue = v;
+ pRateInfo->lastKey = tsList[i];
+ continue;
+ }
+
+ if (tsList[i] > pRateInfo->lastKey) {
+ if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
+ pRateInfo->firstValue = pRateInfo->lastValue;
+ pRateInfo->firstKey = pRateInfo->lastKey;
+ }
+
+ pRateInfo->lastValue = v;
+ pRateInfo->lastKey = tsList[i];
+
+ continue;
+ }
+
+ if ((INT64_MIN == pRateInfo->firstKey) || tsList[i] > pRateInfo->firstKey) {
+ pRateInfo->firstValue = v;
+ pRateInfo->firstKey = tsList[i];
+ }
+ }
+
+ SET_VAL(pResInfo, numOfElems, 1);
+ return TSDB_CODE_SUCCESS;
+}
+
+static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
+ if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
+ (pRateInfo->firstKey >= pRateInfo->lastKey)) {
+ return 0.0;
+ }
+
+ double diff = 0;
+ // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
+ // value between two values.
+ diff = pRateInfo->lastValue;
+ if (diff >= pRateInfo->firstValue) {
+ diff -= pRateInfo->firstValue;
+ }
+
+ int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
+ if (duration == 0) {
+ return 0;
+ }
+
+ return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
+}
+
+int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+ int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
+ SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
+
+ SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+ double result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
+ colDataAppend(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
+
+ return pResInfo->numOfRes;
+}
+
+int32_t groupKeyFunction(SqlFunctionCtx* pCtx) {
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ SInputColumnInfoData* pInput = &pCtx->input;
+ SColumnInfoData* pInputCol = pInput->pData[0];
+
+ int32_t startIndex = pInput->startRowIndex;
+
+ // escape rest of data blocks to avoid first entry to be overwritten.
+ if (pInfo->hasResult) {
+ goto _group_key_over;
+ }
+
+ if (colDataIsNull_s(pInputCol, startIndex)) {
+ pInfo->isNull = true;
+ pInfo->hasResult = true;
+ goto _group_key_over;
+ }
+
+ char* data = colDataGetData(pInputCol, startIndex);
+ if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
+ memcpy(pInfo->data, data,
+ (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
+ } else {
+ memcpy(pInfo->data, data, pInputCol->info.bytes);
+ }
+ pInfo->hasResult = true;
+
+_group_key_over:
+
+ SET_VAL(pResInfo, 1, 1);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
+ int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
+ SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+
+ SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ if (pInfo->hasResult) {
+ colDataAppend(pCol, pBlock->info.rows, pInfo->data, pInfo->isNull ? true : false);
+ } else {
+ pResInfo->numOfRes = 0;
+ }
+
+ return pResInfo->numOfRes;
+}
+
int32_t interpFunction(SqlFunctionCtx* pCtx) {
#if 0
int32_t fillType = (int32_t) pCtx->param[2].i64;
@@ -5314,3 +5997,55 @@ int32_t interpFunction(SqlFunctionCtx* pCtx) {
return TSDB_CODE_SUCCESS;
}
+
+int32_t lastrowFunction(SqlFunctionCtx* pCtx) {
+ int32_t numOfElems = 0;
+
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+
+ SInputColumnInfoData* pInput = &pCtx->input;
+ SColumnInfoData* pInputCol = pInput->pData[0];
+
+ int32_t type = pInputCol->info.type;
+ int32_t bytes = pInputCol->info.bytes;
+
+ pInfo->bytes = bytes;
+
+ // last_row function does not ignore the null value
+ for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
+ numOfElems++;
+
+ char* data = colDataGetData(pInputCol, i);
+ TSKEY cts = getRowPTs(pInput->pPTS, i);
+ if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
+
+ if (colDataIsNull_s(pInputCol, i)) {
+ pInfo->isNull = true;
+ } else {
+ if (IS_VAR_DATA_TYPE(type)) {
+ bytes = varDataTLen(data);
+ pInfo->bytes = bytes;
+ }
+
+ memcpy(pInfo->buf, data, bytes);
+ }
+
+ pInfo->ts = cts;
+ pInfo->hasResult = true;
+ pResInfo->numOfRes = 1;
+
+ if (pCtx->subsidiaries.num > 0) {
+ STuplePos* pTuplePos = (STuplePos*)(pInfo->buf + bytes + sizeof(TSKEY));
+ if (!pInfo->hasResult) {
+ saveTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ } else {
+ copyTupleData(pCtx, i, pCtx->pSrcBlock, pTuplePos);
+ }
+ }
+ }
+ }
+
+ SET_VAL(pResInfo, numOfElems, 1);
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c
index 710b01ce59eb04573ed3ec9befe3046f1876df4e..f73a61fa60c971b78f32c5468b6eee8c3a7cf1d9 100644
--- a/source/libs/function/src/functionMgt.c
+++ b/source/libs/function/src/functionMgt.c
@@ -139,7 +139,7 @@ bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MG
bool fmIsScalarFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCALAR_FUNC); }
-bool fmIsVectorFunc(int32_t funcId) { return !fmIsScalarFunc(funcId); }
+bool fmIsVectorFunc(int32_t funcId) { return !fmIsScalarFunc(funcId) && !fmIsPseudoColumnFunc(funcId); }
bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SELECT_FUNC); }
@@ -179,6 +179,12 @@ bool fmIsForbidWindowFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId
bool fmIsForbidGroupByFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORBID_GROUP_BY_FUNC); }
+bool fmIsSystemInfoFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SYSTEM_INFO_FUNC); }
+
+bool fmIsImplicitTsFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_IMPLICIT_TS_FUNC); }
+
+bool fmIsClientPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_CLIENT_PC_FUNC); }
+
bool fmIsInterpFunc(int32_t funcId) {
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
return false;
@@ -186,6 +192,13 @@ bool fmIsInterpFunc(int32_t funcId) {
return FUNCTION_TYPE_INTERP == funcMgtBuiltins[funcId].type;
}
+bool fmIsLastRowFunc(int32_t funcId) {
+ if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
+ return false;
+ }
+ return FUNCTION_TYPE_LAST_ROW == funcMgtBuiltins[funcId].type;
+}
+
void fmFuncMgtDestroy() {
void* m = gFunMgtService.pFuncNameHashTable;
if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) {
@@ -216,8 +229,8 @@ bool fmIsInvertible(int32_t funcId) {
case FUNCTION_TYPE_SUM:
case FUNCTION_TYPE_STDDEV:
case FUNCTION_TYPE_AVG:
- case FUNCTION_TYPE_WSTARTTS:
- case FUNCTION_TYPE_WENDTS:
+ case FUNCTION_TYPE_WSTART:
+ case FUNCTION_TYPE_WEND:
case FUNCTION_TYPE_WDURATION:
res = true;
break;
@@ -249,7 +262,7 @@ bool fmIsSameInOutType(int32_t funcId) {
}
static int32_t getFuncInfo(SFunctionNode* pFunc) {
- char msg[64] = {0};
+ char msg[128] = {0};
return fmGetFuncInfo(pFunc, msg, sizeof(msg));
}
diff --git a/source/libs/function/src/taggfunction.c b/source/libs/function/src/taggfunction.c
index 47ae07f82377985f94a91906ecccde2818f1b8b2..c8998b9d948c7df356c177329aced975656b9401 100644
--- a/source/libs/function/src/taggfunction.c
+++ b/source/libs/function/src/taggfunction.c
@@ -1887,10 +1887,10 @@ static void top_bottom_func_finalizer(SqlFunctionCtx *pCtx) {
// user specify the order of output by sort the result according to timestamp
if (pCtx->param[1].param.i == PRIMARYKEY_TIMESTAMP_COL_ID) {
__compar_fn_t comparator = (pCtx->param[2].param.i == TSDB_ORDER_ASC) ? resAscComparFn : resDescComparFn;
- qsort(tvp, (size_t)pResInfo->numOfRes, POINTER_BYTES, comparator);
+ taosSort(tvp, (size_t)pResInfo->numOfRes, POINTER_BYTES, comparator);
} else /*if (pCtx->param[1].param.i > PRIMARYKEY_TIMESTAMP_COL_ID)*/ {
__compar_fn_t comparator = (pCtx->param[2].param.i == TSDB_ORDER_ASC) ? resDataAscComparFn : resDataDescComparFn;
- qsort(tvp, (size_t)pResInfo->numOfRes, POINTER_BYTES, comparator);
+ taosSort(tvp, (size_t)pResInfo->numOfRes, POINTER_BYTES, comparator);
}
GET_TRUE_DATA_TYPE();
diff --git a/source/libs/function/src/tpercentile.c b/source/libs/function/src/tpercentile.c
index b40dd8b78da4860c18df56b3c0da7f668a2ce5d1..057d2bc7dc0c87b72e07780f440ced86870c9432 100644
--- a/source/libs/function/src/tpercentile.c
+++ b/source/libs/function/src/tpercentile.c
@@ -44,7 +44,7 @@ static SFilePage *loadDataFromFilePage(tMemBucket *pMemBucket, int32_t slotIdx)
offset += (int32_t)(pg->num * pMemBucket->bytes);
}
- qsort(buffer->data, pMemBucket->pSlots[slotIdx].info.size, pMemBucket->bytes, pMemBucket->comparFn);
+ taosSort(buffer->data, pMemBucket->pSlots[slotIdx].info.size, pMemBucket->bytes, pMemBucket->comparFn);
return buffer;
}
diff --git a/source/libs/function/src/tudf.c b/source/libs/function/src/tudf.c
index f6ae027e48cc01a3d098d25156de168365abd04a..c16c3e39371dd23683fc15402bbb9f9887209c25 100644
--- a/source/libs/function/src/tudf.c
+++ b/source/libs/function/src/tudf.c
@@ -75,6 +75,10 @@ static int32_t udfSpawnUdfd(SUdfdData* pData) {
#ifdef WINDOWS
GetModuleFileName(NULL, path, PATH_MAX);
taosDirName(path);
+ #elif defined(_TD_DARWIN_64)
+ uint32_t pathSize = sizeof(path);
+ _NSGetExecutablePath(path, &pathSize);
+ taosDirName(path);
#endif
} else {
strncpy(path, tsProcPath, strlen(tsProcPath));
@@ -199,7 +203,7 @@ int32_t udfStartUdfd(int32_t startDnodeId) {
uv_async_send(&pData->stopAsync);
uv_thread_join(&pData->thread);
pData->needCleanUp = false;
- fnInfo("dnode udfd cleaned up after spawn err");
+ fnInfo("udfd is cleaned up after spawn err");
} else {
pData->needCleanUp = true;
}
@@ -208,7 +212,7 @@ int32_t udfStartUdfd(int32_t startDnodeId) {
int32_t udfStopUdfd() {
SUdfdData *pData = &udfdGlobal;
- fnInfo("dnode to stop udfd. need cleanup: %d, spawn err: %d",
+ fnInfo("udfd start to stop, need cleanup:%d, spawn err:%d",
pData->needCleanUp, pData->spawnErr);
if (!pData->needCleanUp || atomic_load_32(&pData->stopCalled)) {
return 0;
@@ -221,7 +225,7 @@ int32_t udfStopUdfd() {
#ifdef WINDOWS
if (pData->jobHandle != NULL) CloseHandle(pData->jobHandle);
#endif
- fnInfo("dnode udfd cleaned up");
+ fnInfo("udfd is cleaned up");
return 0;
}
@@ -463,15 +467,15 @@ int32_t getUdfdPipeName(char* pipeName, int32_t size) {
size_t dnodeIdSize = sizeof(dnodeId);
int32_t err = uv_os_getenv(UDF_DNODE_ID_ENV_NAME, dnodeId, &dnodeIdSize);
if (err != 0) {
- fnError("get dnode id from env. error: %s.", uv_err_name(err));
+ fnError("failed to get dnodeId from env since %s", uv_err_name(err));
dnodeId[0] = '1';
}
#ifdef _WIN32
- snprintf(pipeName, size, "%s%s", UDF_LISTEN_PIPE_NAME_PREFIX, dnodeId);
+ snprintf(pipeName, size, "%s.%x.%s", UDF_LISTEN_PIPE_NAME_PREFIX,MurmurHash3_32(tsDataDir, strlen(tsDataDir)), dnodeId);
#else
snprintf(pipeName, size, "%s/%s%s", tsDataDir, UDF_LISTEN_PIPE_NAME_PREFIX, dnodeId);
#endif
- fnInfo("get dnode id from env. dnode id: %s. pipe path: %s", dnodeId, pipeName);
+ fnInfo("get dnodeId:%s from env, pipe path:%s", dnodeId, pipeName);
return 0;
}
@@ -763,8 +767,8 @@ void freeUdfInterBuf(SUdfInterBuf *buf) {
int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlock) {
udfBlock->numOfRows = block->info.rows;
- udfBlock->numOfCols = block->info.numOfCols;
- udfBlock->udfCols = taosMemoryCalloc(udfBlock->numOfCols, sizeof(SUdfColumn*));
+ udfBlock->numOfCols = taosArrayGetSize(block->pDataBlock);
+ udfBlock->udfCols = taosMemoryCalloc(taosArrayGetSize(block->pDataBlock), sizeof(SUdfColumn*));
for (int32_t i = 0; i < udfBlock->numOfCols; ++i) {
udfBlock->udfCols[i] = taosMemoryCalloc(1, sizeof(SUdfColumn));
SColumnInfoData *col= (SColumnInfoData*)taosArrayGet(block->pDataBlock, i);
@@ -799,7 +803,6 @@ int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlo
}
int32_t convertUdfColumnToDataBlock(SUdfColumn *udfCol, SSDataBlock *block) {
- block->info.numOfCols = 1;
block->info.rows = udfCol->colData.numOfRows;
block->info.hasVarCol = IS_VAR_DATA_TYPE(udfCol->colMeta.type);
@@ -830,25 +833,19 @@ int32_t convertUdfColumnToDataBlock(SUdfColumn *udfCol, SSDataBlock *block) {
int32_t convertScalarParamToDataBlock(SScalarParam *input, int32_t numOfCols, SSDataBlock *output) {
output->info.rows = input->numOfRows;
- output->info.numOfCols = numOfCols;
- bool hasVarCol = false;
- for (int32_t i = 0; i < numOfCols; ++i) {
- if (IS_VAR_DATA_TYPE((input+i)->columnData->info.type)) {
- hasVarCol = true;
- break;
- }
- }
- output->info.hasVarCol = hasVarCol;
-
output->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
for (int32_t i = 0; i < numOfCols; ++i) {
taosArrayPush(output->pDataBlock, (input + i)->columnData);
+
+ if (IS_VAR_DATA_TYPE((input+i)->columnData->info.type)) {
+ output->info.hasVarCol = true;
+ }
}
return 0;
}
int32_t convertDataBlockToScalarParm(SSDataBlock *input, SScalarParam *output) {
- if (input->info.numOfCols != 1) {
+ if (taosArrayGetSize(input->pDataBlock) != 1) {
fnError("scalar function only support one column");
return -1;
}
@@ -1089,24 +1086,14 @@ int32_t udfAggProcess(struct SqlFunctionCtx *pCtx) {
int32_t start = pInput->startRowIndex;
int32_t numOfRows = pInput->numOfRows;
-
- SSDataBlock tempBlock = {0};
- tempBlock.info.numOfCols = numOfCols;
- tempBlock.info.rows = pInput->totalRows;
- tempBlock.info.uid = pInput->uid;
- bool hasVarCol = false;
- tempBlock.pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
-
+ SSDataBlock* pTempBlock = createDataBlock();
+ pTempBlock->info.rows = pInput->totalRows;
+ pTempBlock->info.uid = pInput->uid;
for (int32_t i = 0; i < numOfCols; ++i) {
- SColumnInfoData *col = pInput->pData[i];
- if (IS_VAR_DATA_TYPE(col->info.type)) {
- hasVarCol = true;
- }
- taosArrayPush(tempBlock.pDataBlock, col);
+ blockDataAppendColInfo(pTempBlock, pInput->pData[i]);
}
- tempBlock.info.hasVarCol = hasVarCol;
- SSDataBlock *inputBlock = blockDataExtractBlock(&tempBlock, start, numOfRows);
+ SSDataBlock *inputBlock = blockDataExtractBlock(pTempBlock, start, numOfRows);
SUdfInterBuf state = {.buf = udfRes->interResBuf,
.bufLen = session->bufSize,
@@ -1131,7 +1118,9 @@ int32_t udfAggProcess(struct SqlFunctionCtx *pCtx) {
}
blockDataDestroy(inputBlock);
- taosArrayDestroy(tempBlock.pDataBlock);
+
+ taosArrayDestroy(pTempBlock->pDataBlock);
+ taosMemoryFree(pTempBlock);
releaseUdfFuncHandle(pCtx->udfName);
freeUdfInterBuf(&newState);
@@ -1580,6 +1569,10 @@ void constructUdfService(void *argsThread) {
//TODO return value of uv_run
uv_run(&udfc->uvLoop, UV_RUN_DEFAULT);
uv_loop_close(&udfc->uvLoop);
+
+ uv_walk(&udfc->uvLoop, udfUdfdCloseWalkCb, NULL);
+ uv_run(&udfc->uvLoop, UV_RUN_DEFAULT);
+ uv_loop_close(&udfc->uvLoop);
}
int32_t udfcOpen() {
@@ -1616,7 +1609,7 @@ int32_t udfcClose() {
taosArrayDestroy(udfc->udfStubs);
uv_mutex_destroy(&udfc->udfStubsMutex);
udfc->udfcState = UDFC_STATE_INITAL;
- fnInfo("udfc cleaned up");
+ fnInfo("udfc is cleaned up");
return 0;
}
diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c
index 7fffa84e0b4ef85b846259a5173d9d2a263b143c..fd9b588d46d182742cfd7b8568257d375ee42942 100644
--- a/source/libs/function/src/udfd.c
+++ b/source/libs/function/src/udfd.c
@@ -12,6 +12,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
+
+// clang-format off
#include "uv.h"
#include "os.h"
#include "fnLog.h"
@@ -25,6 +27,7 @@
#include "tglobal.h"
#include "tmsg.h"
#include "trpc.h"
+// clang-foramt on
typedef struct SUdfdContext {
uv_loop_t * loop;
@@ -103,12 +106,12 @@ typedef struct SUdfdRpcSendRecvInfo {
uv_sem_t resultSem;
} SUdfdRpcSendRecvInfo;
-static void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet);
+static void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet);
static int32_t udfdFillUdfInfoFromMNode(void *clientRpc, char *udfName, SUdf *udf);
static int32_t udfdConnectToMnode();
static int32_t udfdLoadUdf(char *udfName, SUdf *udf);
-static bool udfdRpcRfp(int32_t code);
-static int initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet);
+static bool udfdRpcRfp(int32_t code, tmsg_t msgType);
+static int initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet);
static int32_t udfdOpenClientRpc();
static int32_t udfdCloseClientRpc();
@@ -126,19 +129,19 @@ static void udfdUvHandleError(SUdfdUvConn *conn) { uv_close((uv_handle_t *)conn-
static void udfdPipeRead(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf);
static void udfdOnNewConnection(uv_stream_t *server, int status);
-static void udfdIntrSignalHandler(uv_signal_t *handle, int signum);
+static void udfdIntrSignalHandler(uv_signal_t *handle, int signum);
static int32_t removeListeningPipe();
-static void udfdPrintVersion();
+static void udfdPrintVersion();
static int32_t udfdParseArgs(int32_t argc, char *argv[]);
static int32_t udfdInitLog();
-static void udfdCtrlAllocBufCb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
-static void udfdCtrlReadCb(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf);
+static void udfdCtrlAllocBufCb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
+static void udfdCtrlReadCb(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf);
static int32_t udfdUvInit();
-static void udfdCloseWalkCb(uv_handle_t *handle, void *arg);
+static void udfdCloseWalkCb(uv_handle_t *handle, void *arg);
static int32_t udfdRun();
-static void udfdConnectMnodeThreadFunc(void* args);
+static void udfdConnectMnodeThreadFunc(void *args);
void udfdProcessRequest(uv_work_t *req) {
SUvUdfWork *uvUdf = (SUvUdfWork *)(req->data);
@@ -293,8 +296,8 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
switch (call->callType) {
case TSDB_UDF_CALL_SCALA_PROC: {
- tDeleteSSDataBlock(&call->block);
- tDeleteSSDataBlock(&subRsp->resultData);
+ blockDataFreeRes(&call->block);
+ blockDataFreeRes(&subRsp->resultData);
break;
}
case TSDB_UDF_CALL_AGG_INIT: {
@@ -302,7 +305,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
break;
}
case TSDB_UDF_CALL_AGG_PROC: {
- tDeleteSSDataBlock(&call->block);
+ blockDataFreeRes(&call->block);
freeUdfInterBuf(&subRsp->resultBuf);
break;
}
@@ -401,11 +404,11 @@ void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
udf->bufSize = pFuncInfo->bufSize;
char path[PATH_MAX] = {0};
- #ifdef WINDOWS
+#ifdef WINDOWS
snprintf(path, sizeof(path), "%s%s.dll", TD_TMP_DIR_PATH, pFuncInfo->name);
- #else
+#else
snprintf(path, sizeof(path), "%s/lib%s.so", TD_TMP_DIR_PATH, pFuncInfo->name);
- #endif
+#endif
TdFilePtr file =
taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ | TD_FILE_TRUNC | TD_FILE_AUTO_DEL);
if (file == NULL) {
@@ -543,8 +546,12 @@ int32_t udfdLoadUdf(char *udfName, SUdf *udf) {
}
return 0;
}
-static bool udfdRpcRfp(int32_t code) {
- if (code == TSDB_CODE_RPC_REDIRECT) {
+static bool udfdRpcRfp(int32_t code, tmsg_t msgType) {
+ if (code == TSDB_CODE_RPC_REDIRECT || code == TSDB_CODE_RPC_NETWORK_UNAVAIL || code == TSDB_CODE_NODE_NOT_DEPLOYED ||
+ code == TSDB_CODE_SYN_NOT_LEADER || code == TSDB_CODE_APP_NOT_READY || code == TSDB_CODE_RPC_BROKEN_LINK) {
+ if (msgType == TDMT_SCH_QUERY || msgType == TDMT_SCH_MERGE_QUERY || msgType == TDMT_SCH_FETCH || msgType == TDMT_SCH_MERGE_FETCH) {
+ return false;
+ }
return true;
} else {
return false;
@@ -613,7 +620,9 @@ int32_t udfdOpenClientRpc() {
}
int32_t udfdCloseClientRpc() {
+ fnInfo("udfd begin closing rpc");
rpcClose(global.clientRpc);
+ fnInfo("udfd finish closing rpc");
return 0;
}
@@ -650,8 +659,7 @@ void udfdAllocBuffer(uv_handle_t *handle, size_t suggestedSize, uv_buf_t *buf) {
buf->base = ctx->inputBuf;
buf->len = ctx->inputCap;
} else {
- fnError("udfd can not allocate enough memory")
- buf->base = NULL;
+ fnError("udfd can not allocate enough memory") buf->base = NULL;
buf->len = 0;
}
} else {
@@ -662,8 +670,7 @@ void udfdAllocBuffer(uv_handle_t *handle, size_t suggestedSize, uv_buf_t *buf) {
buf->base = ctx->inputBuf + ctx->inputLen;
buf->len = ctx->inputCap - ctx->inputLen;
} else {
- fnError("udfd can not allocate enough memory")
- buf->base = NULL;
+ fnError("udfd can not allocate enough memory") buf->base = NULL;
buf->len = 0;
}
}
@@ -879,7 +886,7 @@ static int32_t udfdRun() {
return 0;
}
-void udfdConnectMnodeThreadFunc(void* args) {
+void udfdConnectMnodeThreadFunc(void *args) {
int32_t retryMnodeTimes = 0;
int32_t code = 0;
while (retryMnodeTimes++ <= TSDB_MAX_REPLICA) {
@@ -939,7 +946,6 @@ int main(int argc, char *argv[]) {
udfdRun();
removeListeningPipe();
- uv_thread_join(&mnodeConnectThread);
udfdCloseClientRpc();
return 0;
diff --git a/source/libs/function/test/runUdf.c b/source/libs/function/test/runUdf.c
index 15109db22064ad8d761821510db930b58db0f51d..7395f1e14cfba22e497e8bc760a5883bbc4e11cd 100644
--- a/source/libs/function/test/runUdf.c
+++ b/source/libs/function/test/runUdf.c
@@ -45,27 +45,27 @@ int scalarFuncTest() {
for (int k = 0; k < 1; ++k) {
SSDataBlock block = {0};
SSDataBlock *pBlock = █
- pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
- pBlock->info.numOfCols = 1;
+ for (int32_t i = 0; i < 1; ++i) {
+ SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1);
+ blockDataAppendColInfo(pBlock, &colInfo);
+ }
+
+ blockDataEnsureCapacity(pBlock, 1024);
pBlock->info.rows = 1024;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
- SColumnInfoData colInfo = {0};
- colInfo.info.type = TSDB_DATA_TYPE_INT;
- colInfo.info.bytes = sizeof(int32_t);
- colInfo.info.colId = 1;
- colInfoDataEnsureCapacity(&colInfo, 0, pBlock->info.rows);
- for (int32_t j = 0; j < pBlock->info.rows; ++j) {
- colDataAppendInt32(&colInfo, j, &j);
- }
- taosArrayPush(pBlock->pDataBlock, &colInfo);
+
+ SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
+ for (int32_t j = 0; j < pBlock->info.rows; ++j) {
+ colDataAppendInt32(pCol, j, &j);
}
SScalarParam input = {0};
input.numOfRows = pBlock->info.rows;
input.columnData = taosArrayGet(pBlock->pDataBlock, 0);
+
SScalarParam output = {0};
doCallUdfScalarFunc(handle, &input, 1, &output);
taosArrayDestroy(pBlock->pDataBlock);
+
SColumnInfoData *col = output.columnData;
for (int32_t i = 0; i < output.numOfRows; ++i) {
if (i % 100 == 0)
@@ -89,21 +89,18 @@ int aggregateFuncTest() {
return -1;
}
- SSDataBlock block = {0};
- SSDataBlock *pBlock = █
- pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
- pBlock->info.numOfCols = 1;
+ SSDataBlock *pBlock = createDataBlock();
+ for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
+ SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1);
+ blockDataAppendColInfo(pBlock, &colInfo);
+ }
+
+ blockDataEnsureCapacity(pBlock, 1024);
pBlock->info.rows = 1024;
- for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
- SColumnInfoData colInfo = {0};
- colInfo.info.type = TSDB_DATA_TYPE_INT;
- colInfo.info.bytes = sizeof(int32_t);
- colInfo.info.colId = 1;
- colInfoDataEnsureCapacity(&colInfo, 0, pBlock->info.rows);
- for (int32_t j = 0; j < pBlock->info.rows; ++j) {
- colDataAppendInt32(&colInfo, j, &j);
- }
- taosArrayPush(pBlock->pDataBlock, &colInfo);
+
+ SColumnInfoData* pColInfo = bdGetColumnInfoData(pBlock, 0);
+ for (int32_t j = 0; j < pBlock->info.rows; ++j) {
+ colDataAppendInt32(pColInfo, j, &j);
}
SUdfInterBuf buf = {0};
@@ -121,6 +118,7 @@ int aggregateFuncTest() {
freeUdfInterBuf(&resultBuf);
doTeardownUdf(handle);
+ blockDataDestroy(pBlock);
return 0;
}
diff --git a/source/libs/function/test/udf1.c b/source/libs/function/test/udf1.c
index 9443d5cb945d6dfdbea37b8a090e5f5ebf045a01..dfbae357efd71c646bff5060d06ee984c05fae63 100644
--- a/source/libs/function/test/udf1.c
+++ b/source/libs/function/test/udf1.c
@@ -2,12 +2,8 @@
#include
#include
-#include "tudf.h"
+#include "taosudf.h"
-#undef malloc
-#define malloc malloc
-#undef free
-#define free free
DLL_EXPORT int32_t udf1_init() {
return 0;
diff --git a/source/libs/function/test/udf2.c b/source/libs/function/test/udf2.c
index 1c270f5cf45880f7d56975617932e45f318331f2..975832209eb6ec8e28967c54faf551b359ded455 100644
--- a/source/libs/function/test/udf2.c
+++ b/source/libs/function/test/udf2.c
@@ -1,13 +1,9 @@
#include
#include
#include
+#include
-#include "tudf.h"
-
-#undef malloc
-#define malloc malloc
-#undef free
-#define free free
+#include "taosudf.h"
DLL_EXPORT int32_t udf2_init() {
return 0;
diff --git a/source/libs/index/CMakeLists.txt b/source/libs/index/CMakeLists.txt
index 75eac2430f70c7a4cfc215eee5515a392d1bcd40..0c2ce37c4030dbb018eb7871f396be60aa0fc076 100644
--- a/source/libs/index/CMakeLists.txt
+++ b/source/libs/index/CMakeLists.txt
@@ -36,6 +36,6 @@ endif(${BUILD_WITH_INVERTEDINDEX})
if (${BUILD_TEST})
- add_subdirectory(test)
+ add_subdirectory(test)
endif(${BUILD_TEST})
diff --git a/source/libs/index/inc/indexFst.h b/source/libs/index/inc/indexFst.h
index 6fd12c110cc3a00b72aa009123c2299edf372224..4c5bca864a0be6b4926965fc1695a8e61d88feaa 100644
--- a/source/libs/index/inc/indexFst.h
+++ b/source/libs/index/inc/indexFst.h
@@ -21,7 +21,7 @@ extern "C" {
#endif
#include "indexFstAutomation.h"
-#include "indexFstCountingWriter.h"
+#include "indexFstFile.h"
#include "indexFstNode.h"
#include "indexFstRegistry.h"
#include "indexFstUtil.h"
@@ -53,7 +53,7 @@ typedef struct FstRange {
} FstRange;
typedef enum { OneTransNext, OneTrans, AnyTrans, EmptyFinal } State;
-typedef enum { Ordered, OutOfOrdered, DuplicateKey } OrderType;
+typedef enum { Ordered, OutOfOrdered, DuplicateKey } FstOrderType;
FstBoundWithData* fstBoundStateCreate(FstBound type, FstSlice* data);
bool fstBoundWithDataExceededBy(FstBoundWithData* bound, FstSlice* slice);
@@ -90,8 +90,8 @@ FstBuilderNode* fstUnFinishedNodesPopEmpty(FstUnFinishedNodes* nodes);
uint64_t fstUnFinishedNodesFindCommPrefixAndSetOutput(FstUnFinishedNodes* node, FstSlice bs, Output in, Output* out);
typedef struct FstBuilder {
- FstCountingWriter* wrt; // The FST raw data is written directly to `wtr`.
- FstUnFinishedNodes* unfinished; // The stack of unfinished nodes
+ IdxFstFile* wrt; // The FST raw data is written directly to `wtr`.
+ FstUnFinishedNodes* unfinished; // The stack of unfinished nodes
FstRegistry* registry; // A map of finished nodes.
FstSlice last; // The last word added
CompiledAddr lastAddr; // The address of the last compiled node
@@ -106,7 +106,7 @@ bool fstBuilderInsert(FstBuilder* b, FstSlice bs, Output in);
void fstBuilderCompileFrom(FstBuilder* b, uint64_t istate);
void* fstBuilerIntoInner(FstBuilder* b);
void fstBuilderFinish(FstBuilder* b);
-OrderType fstBuilderCheckLastKey(FstBuilder* b, FstSlice bs, bool ckDup);
+FstOrderType fstBuilderCheckLastKey(FstBuilder* b, FstSlice bs, bool ckDup);
CompiledAddr fstBuilderCompile(FstBuilder* b, FstBuilderNode* bn);
typedef struct FstTransitions {
@@ -125,9 +125,9 @@ FstState fstStateCreateFrom(FstSlice* data, CompiledAddr addr);
FstState fstStateCreate(State state);
// compile
-void fstStateCompileForOneTransNext(FstCountingWriter* w, CompiledAddr addr, uint8_t inp);
-void fstStateCompileForOneTrans(FstCountingWriter* w, CompiledAddr addr, FstTransition* trn);
-void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuilderNode* node);
+void fstStateCompileForOneTransNext(IdxFstFile* w, CompiledAddr addr, uint8_t inp);
+void fstStateCompileForOneTrans(IdxFstFile* w, CompiledAddr addr, FstTransition* trn);
+void fstStateCompileForAnyTrans(IdxFstFile* w, CompiledAddr addr, FstBuilderNode* node);
// set_comm_input
void fstStateSetCommInput(FstState* state, uint8_t inp);
@@ -213,14 +213,18 @@ typedef struct FstNode {
// If this node is final and has a terminal output value, then it is, returned.
// Otherwise, a zero output is returned
#define FST_NODE_FINAL_OUTPUT(node) node->finalOutput
+
// Returns true if and only if this node corresponds to a final or "match",
// state in the finite state transducer.
#define FST_NODE_IS_FINAL(node) node->isFinal
+
// Returns the number of transitions in this node, The maximum number of
// transitions is 256.
#define FST_NODE_LEN(node) node->nTrans
+
// Returns true if and only if this node has zero transitions.
#define FST_NODE_IS_EMPTYE(node) (node->nTrans == 0)
+
// Return the address of this node.
#define FST_NODE_ADDR(node) node->start
@@ -277,12 +281,14 @@ FStmBuilder* fstSearch(Fst* fst, FAutoCtx* ctx);
FStmStBuilder* fstSearchWithState(Fst* fst, FAutoCtx* ctx);
// into stream to expand later
+//
+
FStmSt* stmBuilderIntoStm(FStmBuilder* sb);
bool fstVerify(Fst* fst);
// refactor this function
-bool fstBuilderNodeCompileTo(FstBuilderNode* b, FstCountingWriter* wrt, CompiledAddr lastAddr, CompiledAddr startAddr);
+bool fstBuilderNodeCompileTo(FstBuilderNode* b, IdxFstFile* wrt, CompiledAddr lastAddr, CompiledAddr startAddr);
typedef struct StreamState {
FstNode* node;
@@ -325,7 +331,8 @@ FStmBuilder* stmBuilderCreate(Fst* fst, FAutoCtx* aut);
void stmBuilderDestroy(FStmBuilder* b);
// set up bound range
-// refator later: to simple code by marco
+// refator later
+// simple code by marco
void stmBuilderSetRange(FStmBuilder* b, FstSlice* val, RangeType type);
#ifdef __cplusplus
diff --git a/source/libs/index/inc/indexFstCommon.h b/source/libs/index/inc/indexFstCommon.h
index 8335e437fb148b5f83f3b0db8fc2c6f63a4caa72..e15df5dc340ff4769e87f7329f7b4ec82d0ff4df 100644
--- a/source/libs/index/inc/indexFstCommon.h
+++ b/source/libs/index/inc/indexFstCommon.h
@@ -4,6 +4,7 @@
#include "tutil.h"
extern const uint8_t COMMON_INPUTS[];
extern const char COMMON_INPUTS_INV[];
+extern const int32_t COMMON_INPUTS_LEN;
#ifdef __cplusplus
extern "C" {
diff --git a/source/libs/index/inc/indexFstCountingWriter.h b/source/libs/index/inc/indexFstCountingWriter.h
deleted file mode 100644
index f8a62467239f55e8461fef562d25ee3cacaf20c1..0000000000000000000000000000000000000000
--- a/source/libs/index/inc/indexFstCountingWriter.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#ifndef __INDEX_FST_COUNTING_WRITER_H__
-#define __INDEX_FST_COUNTING_WRITER_H__
-
-#include "indexInt.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//#define USE_MMAP 1
-
-#define DefaultMem 1024 * 1024
-
-static char tmpFile[] = "./index";
-typedef enum WriterType { TMemory, TFile } WriterType;
-
-typedef struct WriterCtx {
- int (*write)(struct WriterCtx* ctx, uint8_t* buf, int len);
- int (*read)(struct WriterCtx* ctx, uint8_t* buf, int len);
- int (*flush)(struct WriterCtx* ctx);
- int (*readFrom)(struct WriterCtx* ctx, uint8_t* buf, int len, int32_t offset);
- int (*size)(struct WriterCtx* ctx);
- WriterType type;
- union {
- struct {
- TdFilePtr pFile;
- bool readOnly;
- char buf[256];
- int size;
-#ifdef USE_MMAP
- char* ptr;
-#endif
- } file;
- struct {
- int32_t capa;
- char* buf;
- } mem;
- };
- int32_t offset;
- int32_t limit;
-} WriterCtx;
-
-static int writeCtxDoWrite(WriterCtx* ctx, uint8_t* buf, int len);
-static int writeCtxDoRead(WriterCtx* ctx, uint8_t* buf, int len);
-static int writeCtxDoReadFrom(WriterCtx* ctx, uint8_t* buf, int len, int32_t offset);
-static int writeCtxDoFlush(WriterCtx* ctx);
-
-WriterCtx* writerCtxCreate(WriterType type, const char* path, bool readOnly, int32_t capacity);
-void writerCtxDestroy(WriterCtx* w, bool remove);
-
-typedef uint32_t CheckSummer;
-
-typedef struct FstCountingWriter {
- void* wrt; // wrap any writer that counts and checksum bytes written
- uint64_t count;
- CheckSummer summer;
-} FstCountingWriter;
-
-int fstCountingWriterWrite(FstCountingWriter* write, uint8_t* buf, uint32_t len);
-
-int fstCountingWriterRead(FstCountingWriter* write, uint8_t* buf, uint32_t len);
-
-int fstCountingWriterFlush(FstCountingWriter* write);
-
-uint32_t fstCountingWriterMaskedCheckSum(FstCountingWriter* write);
-
-FstCountingWriter* fstCountingWriterCreate(void* wtr);
-void fstCountingWriterDestroy(FstCountingWriter* w);
-
-void fstCountingWriterPackUintIn(FstCountingWriter* writer, uint64_t n, uint8_t nBytes);
-uint8_t fstCountingWriterPackUint(FstCountingWriter* writer, uint64_t n);
-
-#define FST_WRITER_COUNT(writer) (writer->count)
-#define FST_WRITER_INTER_WRITER(writer) (writer->wtr)
-#define FST_WRITE_CHECK_SUMMER(writer) (writer->summer)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/libs/index/inc/indexFstDfa.h b/source/libs/index/inc/indexFstDfa.h
index f6c220bcb7a6468d7be58249b54c62dcc2402306..5a5622e2809c10cc1277cbdc1d3a322d320485f5 100644
--- a/source/libs/index/inc/indexFstDfa.h
+++ b/source/libs/index/inc/indexFstDfa.h
@@ -29,16 +29,16 @@ extern "C" {
typedef struct FstDfa FstDfa;
typedef struct {
- SArray * insts;
+ SArray *insts;
uint32_t next[256];
bool isMatch;
-} State;
+} DfaState;
/*
* dfa builder related func
**/
typedef struct FstDfaBuilder {
- FstDfa * dfa;
+ FstDfa *dfa;
SHashObj *cache;
} FstDfaBuilder;
@@ -51,7 +51,7 @@ FstDfa *dfaBuilderBuild(FstDfaBuilder *builder);
bool dfaBuilderRunState(FstDfaBuilder *builder, FstSparseSet *cur, FstSparseSet *next, uint32_t state, uint8_t bytes,
uint32_t *result);
-bool dfaBuilderCachedState(FstDfaBuilder *builder, FstSparseSet *set, uint32_t *result);
+bool dfaBuilderCacheState(FstDfaBuilder *builder, FstSparseSet *set, uint32_t *result);
/*
* dfa related func
diff --git a/source/libs/index/inc/indexFstFile.h b/source/libs/index/inc/indexFstFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..a161c4aee19c76bd9cc98fb8f4d02815831c8f84
--- /dev/null
+++ b/source/libs/index/inc/indexFstFile.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __INDEX_FST_FILE_H__
+#define __INDEX_FST_FILE_H__
+
+#include "indexInt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define USE_MMAP 1
+
+#define DefaultMem 1024 * 1024
+
+static char tmpFile[] = "./index";
+typedef enum WriterType { TMemory, TFile } WriterType;
+
+typedef struct IFileCtx {
+ int (*write)(struct IFileCtx* ctx, uint8_t* buf, int len);
+ int (*read)(struct IFileCtx* ctx, uint8_t* buf, int len);
+ int (*flush)(struct IFileCtx* ctx);
+ int (*readFrom)(struct IFileCtx* ctx, uint8_t* buf, int len, int32_t offset);
+ int (*size)(struct IFileCtx* ctx);
+ WriterType type;
+ union {
+ struct {
+ TdFilePtr pFile;
+ bool readOnly;
+ char buf[256];
+ int64_t size;
+#ifdef USE_MMAP
+ char* ptr;
+#endif
+ } file;
+ struct {
+ int32_t cap;
+ char* buf;
+ } mem;
+ };
+ int32_t offset;
+ int32_t limit;
+} IFileCtx;
+
+static int idxFileCtxDoWrite(IFileCtx* ctx, uint8_t* buf, int len);
+static int idxFileCtxDoRead(IFileCtx* ctx, uint8_t* buf, int len);
+static int idxFileCtxDoReadFrom(IFileCtx* ctx, uint8_t* buf, int len, int32_t offset);
+static int idxFileCtxDoFlush(IFileCtx* ctx);
+
+IFileCtx* idxFileCtxCreate(WriterType type, const char* path, bool readOnly, int32_t capacity);
+void idxFileCtxDestroy(IFileCtx* w, bool remove);
+
+typedef uint32_t CheckSummer;
+
+typedef struct IdxFstFile {
+ void* wrt; // wrap any writer that counts and checksum bytes written
+ uint64_t count;
+ CheckSummer summer;
+} IdxFstFile;
+
+int idxFileWrite(IdxFstFile* write, uint8_t* buf, uint32_t len);
+
+int idxFileRead(IdxFstFile* write, uint8_t* buf, uint32_t len);
+
+int idxFileFlush(IdxFstFile* write);
+
+uint32_t idxFileMaskedCheckSum(IdxFstFile* write);
+
+IdxFstFile* idxFileCreate(void* wtr);
+void idxFileDestroy(IdxFstFile* w);
+
+void idxFilePackUintIn(IdxFstFile* writer, uint64_t n, uint8_t nBytes);
+uint8_t idxFilePackUint(IdxFstFile* writer, uint64_t n);
+
+#define FST_WRITER_COUNT(writer) (writer->count)
+#define FST_WRITER_INTER_WRITER(writer) (writer->wtr)
+#define FST_WRITE_CHECK_SUMMER(writer) (writer->summer)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/libs/index/inc/indexFstNode.h b/source/libs/index/inc/indexFstNode.h
index 4bbc739c731c39200549043a1e8caf5bd85d29d7..5bdb2acb32bdc694422ec903d85489ab264f0f2a 100644
--- a/source/libs/index/inc/indexFstNode.h
+++ b/source/libs/index/inc/indexFstNode.h
@@ -20,12 +20,12 @@
extern "C" {
#endif
-#include "indexFstCountingWriter.h"
+#include "indexFstFile.h"
#include "indexFstUtil.h"
#include "indexInt.h"
-#define FST_BUILDER_NODE_IS_FINAL(bn) (bn->isFinal)
-#define FST_BUILDER_NODE_TRANS_ISEMPTY(bn) (taosArrayGetSize(bn->trans) == 0)
+#define FST_BUILDER_NODE_IS_FINAL(bn) (bn->isFinal)
+#define FST_BUILDER_NODE_TRANS_ISEMPTY(bn) (taosArrayGetSize(bn->trans) == 0)
#define FST_BUILDER_NODE_FINALOUTPUT_ISZERO(bn) (bn->finalOutput == 0)
typedef struct FstTransition {
@@ -46,7 +46,7 @@ FstBuilderNode* fstBuilderNodeClone(FstBuilderNode* src);
void fstBuilderNodeCloneFrom(FstBuilderNode* dst, FstBuilderNode* src);
-// bool fstBuilderNodeCompileTo(FstBuilderNode *b, FstCountingWriter *wrt,
+// bool fstBuilderNodeCompileTo(FstBuilderNode *b, IdxFile' *wrt,
// CompiledAddr lastAddr, CompiledAddr startAddr);
bool fstBuilderNodeEqual(FstBuilderNode* n1, FstBuilderNode* n2);
diff --git a/source/libs/index/inc/indexFstRegex.h b/source/libs/index/inc/indexFstRegex.h
index 2bf9c9b791397d634cc0704d5f556448d796c6aa..2814b5dc16bedf822a98be003230431ecb665cda 100644
--- a/source/libs/index/inc/indexFstRegex.h
+++ b/source/libs/index/inc/indexFstRegex.h
@@ -65,6 +65,7 @@ typedef struct {
} FstRegex;
FstRegex *regexCreate(const char *str);
+void regexDestroy(FstRegex *regex);
uint32_t regexAutomStart(FstRegex *regex);
bool regexAutomIsMatch(FstRegex *regex, uint32_t state);
diff --git a/source/libs/index/inc/indexFstSparse.h b/source/libs/index/inc/indexFstSparse.h
index 665fb2ba5cb9c0c426e9f3bf345351deed1d4abb..bd704fb427002424e6d4635fa3fef1366bdf9fb9 100644
--- a/source/libs/index/inc/indexFstSparse.h
+++ b/source/libs/index/inc/indexFstSparse.h
@@ -23,17 +23,18 @@ extern "C" {
#endif
typedef struct FstSparseSet {
- uint32_t *dense;
- uint32_t *sparse;
- int32_t size;
+ int32_t *dense;
+ int32_t *sparse;
+ int32_t size;
+ int32_t cap;
} FstSparseSet;
FstSparseSet *sparSetCreate(int32_t sz);
void sparSetDestroy(FstSparseSet *s);
uint32_t sparSetLen(FstSparseSet *ss);
-uint32_t sparSetAdd(FstSparseSet *ss, uint32_t ip);
-uint32_t sparSetGet(FstSparseSet *ss, uint32_t i);
-bool sparSetContains(FstSparseSet *ss, uint32_t ip);
+bool sparSetAdd(FstSparseSet *ss, int32_t ip, int32_t *val);
+bool sparSetGet(FstSparseSet *ss, int32_t i, int32_t *val);
+bool sparSetContains(FstSparseSet *ss, int32_t ip);
void sparSetClear(FstSparseSet *ss);
#ifdef __cplusplus
diff --git a/source/libs/index/inc/indexInt.h b/source/libs/index/inc/indexInt.h
index 906cbb6a20120f06ddd7bfccf8e53581ecdf792f..d50fa0e917c1d672ccad2c8b7ef3900afd56668a 100644
--- a/source/libs/index/inc/indexInt.h
+++ b/source/libs/index/inc/indexInt.h
@@ -45,6 +45,7 @@ extern "C" {
typedef enum { LT, LE, GT, GE, CONTAINS, EQ } RangeType;
typedef enum { kTypeValue, kTypeDeletion } STermValueType;
+typedef enum { kRebuild, kFinished } SIdxStatus;
typedef struct SIndexStat {
int32_t totalAdded; //
@@ -65,6 +66,7 @@ struct SIndex {
char* path;
+ int8_t status;
SIndexStat stat;
TdThreadMutex mtx;
tsem_t sem;
diff --git a/source/libs/index/inc/indexTfile.h b/source/libs/index/inc/indexTfile.h
index 6cfea5bc0bd799dd58fa221269cf34faa84cb5bf..ca5c688162d46de527f9333c9c29db4699e00082 100644
--- a/source/libs/index/inc/indexTfile.h
+++ b/source/libs/index/inc/indexTfile.h
@@ -16,7 +16,7 @@
#define __INDEX_TFILE_H__
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
+#include "indexFstFile.h"
#include "indexInt.h"
#include "indexTfile.h"
#include "indexUtil.h"
@@ -59,7 +59,7 @@ typedef struct TFileCache {
typedef struct TFileWriter {
FstBuilder* fb;
- WriterCtx* ctx;
+ IFileCtx* ctx;
TFileHeader header;
uint32_t offset;
} TFileWriter;
@@ -68,7 +68,7 @@ typedef struct TFileWriter {
typedef struct TFileReader {
T_REF_DECLARE()
Fst* fst;
- WriterCtx* ctx;
+ IFileCtx* ctx;
TFileHeader header;
bool remove;
} TFileReader;
@@ -103,7 +103,7 @@ void tfileCachePut(TFileCache* tcache, ICacheKey* key, TFileReader* read
TFileReader* tfileGetReaderByCol(IndexTFile* tf, uint64_t suid, char* colName);
TFileReader* tfileReaderOpen(char* path, uint64_t suid, int64_t version, const char* colName);
-TFileReader* tfileReaderCreate(WriterCtx* ctx);
+TFileReader* tfileReaderCreate(IFileCtx* ctx);
void tfileReaderDestroy(TFileReader* reader);
int tfileReaderSearch(TFileReader* reader, SIndexTermQuery* query, SIdxTRslt* tr);
void tfileReaderRef(TFileReader* reader);
@@ -111,7 +111,7 @@ void tfileReaderUnRef(TFileReader* reader);
TFileWriter* tfileWriterOpen(char* path, uint64_t suid, int64_t version, const char* colName, uint8_t type);
void tfileWriterClose(TFileWriter* tw);
-TFileWriter* tfileWriterCreate(WriterCtx* ctx, TFileHeader* header);
+TFileWriter* tfileWriterCreate(IFileCtx* ctx, TFileHeader* header);
void tfileWriterDestroy(TFileWriter* tw);
int tfileWriterPut(TFileWriter* tw, void* data, bool order);
int tfileWriterFinish(TFileWriter* tw);
diff --git a/source/libs/index/src/index.c b/source/libs/index/src/index.c
index 04d7e04b30848329c9edfda3d569d7aa0d225f5d..e3d367e59c2a484ea471d06199fd236ff7c1d930 100644
--- a/source/libs/index/src/index.c
+++ b/source/libs/index/src/index.c
@@ -35,12 +35,12 @@
#define INDEX_DATA_BOOL_NULL 0x02
#define INDEX_DATA_TINYINT_NULL 0x80
#define INDEX_DATA_SMALLINT_NULL 0x8000
-#define INDEX_DATA_INT_NULL 0x80000000L
-#define INDEX_DATA_BIGINT_NULL 0x8000000000000000L
+#define INDEX_DATA_INT_NULL 0x80000000LL
+#define INDEX_DATA_BIGINT_NULL 0x8000000000000000LL
#define INDEX_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
-#define INDEX_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
-#define INDEX_DATA_DOUBLE_NULL 0x7FFFFF0000000000L // an NAN
+#define INDEX_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
+#define INDEX_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
#define INDEX_DATA_NCHAR_NULL 0xFFFFFFFF
#define INDEX_DATA_BINARY_NULL 0xFF
#define INDEX_DATA_JSON_NULL 0xFFFFFFFF
@@ -63,11 +63,12 @@ static void indexDestroy(void* sIdx);
void indexInit() {
// refactor later
indexQhandle = taosInitScheduler(INDEX_QUEUE_SIZE, INDEX_NUM_OF_THREADS, "index");
- indexRefMgt = taosOpenRef(10, indexDestroy);
+ indexRefMgt = taosOpenRef(1000, indexDestroy);
}
-void indexCleanUp() {
+void indexCleanup() {
// refacto later
taosCleanUpScheduler(indexQhandle);
+ taosCloseRef(indexRefMgt);
}
typedef struct SIdxColInfo {
@@ -100,15 +101,16 @@ static void indexWait(void* idx) {
}
int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
+ int ret = TSDB_CODE_SUCCESS;
taosThreadOnce(&isInit, indexInit);
SIndex* sIdx = taosMemoryCalloc(1, sizeof(SIndex));
if (sIdx == NULL) {
- return -1;
+ return TSDB_CODE_OUT_OF_MEMORY;
}
- // sIdx->cache = (void*)idxCacheCreate(sIdx);
sIdx->tindex = idxTFileCreate(path);
if (sIdx->tindex == NULL) {
+ ret = TSDB_CODE_OUT_OF_MEMORY;
goto END;
}
@@ -122,14 +124,14 @@ int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
idxAcquireRef(sIdx->refId);
*index = sIdx;
- return 0;
+ return ret;
END:
if (sIdx != NULL) {
indexClose(sIdx);
}
*index = NULL;
- return -1;
+ return ret;
}
void indexDestroy(void* handle) {
@@ -230,7 +232,7 @@ int indexSearch(SIndex* index, SIndexMultiTermQuery* multiQuerys, SArray* result
}
int indexDelete(SIndex* index, SIndexMultiTermQuery* query) { return 1; }
-int indexRebuild(SIndex* index, SIndexOpts* opts) { return 0; }
+// int indexRebuild(SIndex* index, SIndexOpts* opts) { return 0; }
SIndexOpts* indexOptsCreate() { return NULL; }
void indexOptsDestroy(SIndexOpts* opts) { return; }
@@ -272,33 +274,28 @@ SIndexTerm* indexTermCreate(int64_t suid, SIndexOperOnColumn oper, uint8_t colTy
tm->operType = oper;
tm->colType = colType;
-#if 0
- tm->colName = (char*)taosMemoryCalloc(1, nColName + 1);
- memcpy(tm->colName, colName, nColName);
- tm->nColName = nColName;
-
- tm->colVal = (char*)taosMemoryCalloc(1, nColVal + 1);
- memcpy(tm->colVal, colVal, nColVal);
- tm->nColVal = nColVal;
-#endif
-
-#if 1
-
tm->colName = (char*)taosMemoryCalloc(1, nColName + 1);
memcpy(tm->colName, colName, nColName);
tm->nColName = nColName;
char* buf = NULL;
- int32_t len = idxConvertDataToStr((void*)colVal, IDX_TYPE_GET_TYPE(colType), (void**)&buf);
- assert(len != -1);
-
+ int32_t len = 0;
+ if (colVal != NULL && nColVal != 0) {
+ len = idxConvertDataToStr((void*)colVal, IDX_TYPE_GET_TYPE(colType), (void**)&buf);
+ } else if (colVal == NULL) {
+ buf = strndup(INDEX_DATA_NULL_STR, (int32_t)strlen(INDEX_DATA_NULL_STR));
+ len = (int32_t)strlen(INDEX_DATA_NULL_STR);
+ } else {
+ const char* emptyStr = " ";
+ buf = strndup(emptyStr, (int32_t)strlen(emptyStr));
+ len = (int32_t)strlen(emptyStr);
+ }
tm->colVal = buf;
tm->nColVal = len;
-#endif
-
return tm;
}
+
void indexTermDestroy(SIndexTerm* p) {
taosMemoryFree(p->colName);
taosMemoryFree(p->colVal);
@@ -319,6 +316,54 @@ void indexMultiTermDestroy(SIndexMultiTerm* terms) {
taosArrayDestroy(terms);
}
+/*
+ * rebuild index
+ */
+
+static void idxSchedRebuildIdx(SSchedMsg* msg) {
+ // TODO, no need rebuild index
+ SIndex* idx = msg->ahandle;
+
+ int8_t st = kFinished;
+ atomic_store_8(&idx->status, st);
+ idxReleaseRef(idx->refId);
+}
+void indexRebuild(SIndexJson* idx, void* iter) {
+ // set up rebuild status
+ int8_t st = kRebuild;
+ atomic_store_8(&idx->status, st);
+
+ // task put into BG thread
+ SSchedMsg schedMsg = {0};
+ schedMsg.fp = idxSchedRebuildIdx;
+ schedMsg.ahandle = idx;
+ idxAcquireRef(idx->refId);
+ taosScheduleTask(indexQhandle, &schedMsg);
+}
+
+/*
+ * check index json status
+ **/
+bool indexIsRebuild(SIndex* idx) {
+ // idx rebuild or not
+ return ((SIdxStatus)atomic_load_8(&idx->status)) == kRebuild ? true : false;
+}
+/*
+ * rebuild index
+ */
+void indexJsonRebuild(SIndexJson* idx, void* iter) {
+ // idx rebuild or not
+ indexRebuild(idx, iter);
+}
+
+/*
+ * check index json status
+ **/
+bool indexJsonIsRebuild(SIndexJson* idx) {
+ // load idx rebuild or not
+ return ((SIdxStatus)atomic_load_8(&idx->status)) == kRebuild ? true : false;
+}
+
static int idxTermSearch(SIndex* sIdx, SIndexTermQuery* query, SArray** result) {
SIndexTerm* term = query->term;
const char* colName = term->colName;
@@ -614,7 +659,7 @@ static int idxGenTFile(SIndex* sIdx, IndexCache* cache, SArray* batch) {
return ret;
END:
if (tw != NULL) {
- writerCtxDestroy(tw->ctx, true);
+ idxFileCtxDestroy(tw->ctx, true);
taosMemoryFree(tw);
}
return -1;
diff --git a/source/libs/index/src/indexCache.c b/source/libs/index/src/indexCache.c
index 040e8ed83029dba1d2f259509d800bfc740bd64b..05ce418037baeea854adfc57d2ad4b96fb6ac22d 100644
--- a/source/libs/index/src/indexCache.c
+++ b/source/libs/index/src/indexCache.c
@@ -22,7 +22,7 @@
#define MAX_INDEX_KEY_LEN 256 // test only, change later
#define MEM_TERM_LIMIT 10 * 10000
-#define MEM_THRESHOLD 64 * 1024
+#define MEM_THRESHOLD 512 * 1024
#define MEM_SIGNAL_QUIT MEM_THRESHOLD * 20
#define MEM_ESTIMATE_RADIO 1.5
@@ -204,7 +204,6 @@ static int32_t cacheSearchTerm_JSON(void* cache, SIndexTerm* term, SIdxTRslt* tr
if (0 == strcmp(c->colVal, pCt->colVal)) {
if (c->operaType == ADD_VALUE) {
INDEX_MERGE_ADD_DEL(tr->del, tr->add, c->uid)
- // taosArrayPush(result, &c->uid);
*s = kTypeValue;
} else if (c->operaType == DEL_VALUE) {
INDEX_MERGE_ADD_DEL(tr->add, tr->del, c->uid)
@@ -309,7 +308,6 @@ static int32_t cacheSearchCompareFunc_JSON(void* cache, SIndexTerm* term, SIdxTR
if (cond == MATCH) {
if (c->operaType == ADD_VALUE) {
INDEX_MERGE_ADD_DEL(tr->del, tr->add, c->uid)
- // taosArrayPush(result, &c->uid);
*s = kTypeValue;
} else if (c->operaType == DEL_VALUE) {
INDEX_MERGE_ADD_DEL(tr->add, tr->del, c->uid)
diff --git a/source/libs/index/src/indexComm.c b/source/libs/index/src/indexComm.c
index 99b49f97bd13b57a47a0e1160fdbfd0b4f9e1717..4f33d98f9e4f7e5b210922b0dd6da0b5448d4472 100644
--- a/source/libs/index/src/indexComm.c
+++ b/source/libs/index/src/indexComm.c
@@ -25,12 +25,12 @@
#define INDEX_DATA_BOOL_NULL 0x02
#define INDEX_DATA_TINYINT_NULL 0x80
#define INDEX_DATA_SMALLINT_NULL 0x8000
-#define INDEX_DATA_INT_NULL 0x80000000L
-#define INDEX_DATA_BIGINT_NULL 0x8000000000000000L
+#define INDEX_DATA_INT_NULL 0x80000000LL
+#define INDEX_DATA_BIGINT_NULL 0x8000000000000000LL
#define INDEX_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
-#define INDEX_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
-#define INDEX_DATA_DOUBLE_NULL 0x7FFFFF0000000000L // an NAN
+#define INDEX_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
+#define INDEX_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
#define INDEX_DATA_NCHAR_NULL 0xFFFFFFFF
#define INDEX_DATA_BINARY_NULL 0xFF
#define INDEX_DATA_JSON_NULL 0xFFFFFFFF
@@ -374,6 +374,10 @@ int32_t idxConvertData(void* src, int8_t type, void** dst) {
return tlen;
}
int32_t idxConvertDataToStr(void* src, int8_t type, void** dst) {
+ if (src == NULL) {
+ *dst = strndup(INDEX_DATA_NULL_STR, (int)strlen(INDEX_DATA_NULL_STR));
+ return (int32_t)strlen(INDEX_DATA_NULL_STR);
+ }
int tlen = tDataTypes[type].bytes;
int32_t bufSize = 64;
switch (type) {
diff --git a/source/libs/index/src/indexFilter.c b/source/libs/index/src/indexFilter.c
index 90aafb10977166da5238f7e9f31e5c46258e219e..7bed059dfdfef8c99fd728f493241f2befcf1efb 100644
--- a/source/libs/index/src/indexFilter.c
+++ b/source/libs/index/src/indexFilter.c
@@ -181,11 +181,9 @@ static int32_t sifInitJsonParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
param->colValType = l->node.resType.type;
memcpy(param->dbName, l->dbName, sizeof(l->dbName));
memcpy(param->colName, r->literal, strlen(r->literal));
- // sprintf(param->colName, "%s_%s", l->colName, r->literal);
param->colValType = r->typeData;
param->status = SFLT_COARSE_INDEX;
return 0;
- // memcpy(param->colName, l->colName, sizeof(l->colName));
}
static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
param->status = SFLT_COARSE_INDEX;
@@ -274,6 +272,10 @@ static int32_t sifInitOperParams(SIFParam **params, SOperatorNode *node, SIFCtx
SIF_ERR_JRET(sifInitParam(node->pLeft, ¶mList[0], ctx));
if (nParam > 1) {
SIF_ERR_JRET(sifInitParam(node->pRight, ¶mList[1], ctx));
+ // if (paramList[0].colValType == TSDB_DATA_TYPE_JSON &&
+ // ((SOperatorNode *)(node))->opType == OP_TYPE_JSON_CONTAINS) {
+ // return TSDB_CODE_QRY_OUT_OF_MEMORY;
+ //}
}
*params = paramList;
return TSDB_CODE_SUCCESS;
@@ -511,11 +513,12 @@ static int32_t sifGetOperFn(int32_t funcId, sif_func_t *func, SIdxFltStatus *sta
}
return 0;
}
-// typedef struct filterFuncDict {
static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) {
int32_t code = 0;
if (sifValidOp(node->opType) < 0) {
+ code = TSDB_CODE_QRY_INVALID_INPUT;
+ ctx->code = code;
output->status = SFLT_NOT_INDEX;
return code;
}
@@ -532,7 +535,7 @@ static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) {
SIFParam *params = NULL;
SIF_ERR_RET(sifInitOperParams(¶ms, node, ctx));
- if (params[0].status == SFLT_NOT_INDEX || (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) {
+ if (params[0].status == SFLT_NOT_INDEX && (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) {
output->status = SFLT_NOT_INDEX;
return code;
}
@@ -737,23 +740,23 @@ static int32_t sifGetFltHint(SNode *pNode, SIdxFltStatus *status) {
SIF_RET(code);
}
-int32_t doFilterTag(const SNode *pFilterNode, SIndexMetaArg *metaArg, SArray *result) {
- if (pFilterNode == NULL) {
- return TSDB_CODE_SUCCESS;
+int32_t doFilterTag(SNode *pFilterNode, SIndexMetaArg *metaArg, SArray *result, SIdxFltStatus *status) {
+ SIdxFltStatus st = idxGetFltStatus(pFilterNode);
+ if (st == SFLT_NOT_INDEX) {
+ *status = st;
+ return 0;
}
SFilterInfo *filter = NULL;
- // todo move to the initialization function
- // SIF_ERR_RET(filterInitFromNode((SNode *)pFilterNode, &filter, 0));
SArray * output = taosArrayInit(8, sizeof(uint64_t));
SIFParam param = {.arg = *metaArg, .result = output};
SIF_ERR_RET(sifCalculate((SNode *)pFilterNode, ¶m));
taosArrayAddAll(result, param.result);
- // taosArrayAddAll(result, param.result);
sifFreeParam(¶m);
- SIF_RET(TSDB_CODE_SUCCESS);
+ *status = st;
+ return TSDB_CODE_SUCCESS;
}
SIdxFltStatus idxGetFltStatus(SNode *pFilterNode) {
@@ -761,10 +764,9 @@ SIdxFltStatus idxGetFltStatus(SNode *pFilterNode) {
if (pFilterNode == NULL) {
return SFLT_NOT_INDEX;
}
- // SFilterInfo *filter = NULL;
- // todo move to the initialization function
- // SIF_ERR_RET(filterInitFromNode((SNode *)pFilterNode, &filter, 0));
- SIF_ERR_RET(sifGetFltHint((SNode *)pFilterNode, &st));
+ if (sifGetFltHint((SNode *)pFilterNode, &st) != TSDB_CODE_SUCCESS) {
+ st = SFLT_NOT_INDEX;
+ }
return st;
}
diff --git a/source/libs/index/src/indexFst.c b/source/libs/index/src/indexFst.c
index b368c6faf30cfa3a3833d24a7398f9610a033b1e..c4b83f8a073464c232d916ea30b2a2859ccb1e22 100644
--- a/source/libs/index/src/indexFst.c
+++ b/source/libs/index/src/indexFst.c
@@ -19,11 +19,11 @@
#include "tchecksum.h"
#include "tcoding.h"
-static void fstPackDeltaIn(FstCountingWriter* wrt, CompiledAddr nodeAddr, CompiledAddr transAddr, uint8_t nBytes) {
+static void fstPackDeltaIn(IdxFstFile* wrt, CompiledAddr nodeAddr, CompiledAddr transAddr, uint8_t nBytes) {
CompiledAddr deltaAddr = (transAddr == EMPTY_ADDRESS) ? EMPTY_ADDRESS : nodeAddr - transAddr;
- fstCountingWriterPackUintIn(wrt, deltaAddr, nBytes);
+ idxFilePackUintIn(wrt, deltaAddr, nBytes);
}
-static uint8_t fstPackDetla(FstCountingWriter* wrt, CompiledAddr nodeAddr, CompiledAddr transAddr) {
+static uint8_t fstPackDetla(IdxFstFile* wrt, CompiledAddr nodeAddr, CompiledAddr transAddr) {
uint8_t nBytes = packDeltaSize(nodeAddr, transAddr);
fstPackDeltaIn(wrt, nodeAddr, transAddr, nBytes);
return nBytes;
@@ -208,7 +208,7 @@ FstState fstStateCreate(State state) {
return fstStateDict[idx];
}
// compile
-void fstStateCompileForOneTransNext(FstCountingWriter* w, CompiledAddr addr, uint8_t inp) {
+void fstStateCompileForOneTransNext(IdxFstFile* w, CompiledAddr addr, uint8_t inp) {
FstState s = fstStateCreate(OneTransNext);
fstStateSetCommInput(&s, inp);
@@ -216,21 +216,21 @@ void fstStateCompileForOneTransNext(FstCountingWriter* w, CompiledAddr addr, uin
uint8_t v = fstStateCommInput(&s, &null);
if (null) {
// w->write_all(&[inp])
- fstCountingWriterWrite(w, &inp, 1);
+ idxFileWrite(w, &inp, 1);
}
- fstCountingWriterWrite(w, &(s.val), 1);
+ idxFileWrite(w, &(s.val), 1);
// w->write_all(&[s.val])
return;
}
-void fstStateCompileForOneTrans(FstCountingWriter* w, CompiledAddr addr, FstTransition* trn) {
+void fstStateCompileForOneTrans(IdxFstFile* w, CompiledAddr addr, FstTransition* trn) {
Output out = trn->out;
- uint8_t outPackSize = (out == 0 ? 0 : fstCountingWriterPackUint(w, out));
+ uint8_t outPackSize = (out == 0 ? 0 : idxFilePackUint(w, out));
uint8_t transPackSize = fstPackDetla(w, addr, trn->addr);
PackSizes packSizes = 0;
FST_SET_OUTPUT_PACK_SIZE(packSizes, outPackSize);
FST_SET_TRANSITION_PACK_SIZE(packSizes, transPackSize);
- fstCountingWriterWrite(w, (char*)&packSizes, sizeof(packSizes));
+ idxFileWrite(w, (char*)&packSizes, sizeof(packSizes));
FstState st = fstStateCreate(OneTrans);
@@ -239,12 +239,12 @@ void fstStateCompileForOneTrans(FstCountingWriter* w, CompiledAddr addr, FstTran
bool null = false;
uint8_t inp = fstStateCommInput(&st, &null);
if (null == true) {
- fstCountingWriterWrite(w, (char*)&trn->inp, sizeof(trn->inp));
+ idxFileWrite(w, (char*)&trn->inp, sizeof(trn->inp));
}
- fstCountingWriterWrite(w, (char*)(&(st.val)), sizeof(st.val));
+ idxFileWrite(w, (char*)(&(st.val)), sizeof(st.val));
return;
}
-void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuilderNode* node) {
+void fstStateCompileForAnyTrans(IdxFstFile* w, CompiledAddr addr, FstBuilderNode* node) {
int32_t sz = taosArrayGetSize(node->trans);
assert(sz <= 256);
@@ -275,11 +275,11 @@ void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuil
if (anyOuts) {
if (FST_BUILDER_NODE_IS_FINAL(node)) {
- fstCountingWriterPackUintIn(w, node->finalOutput, oSize);
+ idxFilePackUintIn(w, node->finalOutput, oSize);
}
for (int32_t i = sz - 1; i >= 0; i--) {
FstTransition* t = taosArrayGet(node->trans, i);
- fstCountingWriterPackUintIn(w, t->out, oSize);
+ idxFilePackUintIn(w, t->out, oSize);
}
}
for (int32_t i = sz - 1; i >= 0; i--) {
@@ -288,28 +288,20 @@ void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuil
}
for (int32_t i = sz - 1; i >= 0; i--) {
FstTransition* t = taosArrayGet(node->trans, i);
- fstCountingWriterWrite(w, (char*)&t->inp, 1);
- // fstPackDeltaIn(w, addr, t->addr, tSize);
+ idxFileWrite(w, (char*)&t->inp, 1);
}
if (sz > TRANS_INDEX_THRESHOLD) {
- // A value of 255 indicates that no transition exists for the byte
- // at that index. (Except when there are 256 transitions.) Namely,
- // any value greater than or equal to the number of transitions in
- // this node indicates an absent transition.
+ // A value of 255 indicates that no transition exists for the byte at that idx
uint8_t* index = (uint8_t*)taosMemoryMalloc(sizeof(uint8_t) * 256);
memset(index, 255, sizeof(uint8_t) * 256);
- /// for (uint8_t i = 0; i < 256; i++) {
- // index[i] = 255;
- ///}
for (int32_t i = 0; i < sz; i++) {
FstTransition* t = taosArrayGet(node->trans, i);
index[t->inp] = i;
- // fstPackDeltaIn(w, addr, t->addr, tSize);
}
- fstCountingWriterWrite(w, (char*)index, 256);
+ idxFileWrite(w, (char*)index, 256);
taosMemoryFree(index);
}
- fstCountingWriterWrite(w, (char*)&packSizes, 1);
+ idxFileWrite(w, (char*)&packSizes, 1);
bool null = false;
fstStateStateNtrans(&st, &null);
if (null == true) {
@@ -318,12 +310,12 @@ void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuil
// encoded in the state byte.
uint8_t v = 1;
if (sz == 256) {
- fstCountingWriterWrite(w, (char*)&v, 1);
+ idxFileWrite(w, (char*)&v, 1);
} else {
- fstCountingWriterWrite(w, (char*)&sz, 1);
+ idxFileWrite(w, (char*)&sz, 1);
}
}
- fstCountingWriterWrite(w, (char*)(&(st.val)), 1);
+ idxFileWrite(w, (char*)(&(st.val)), 1);
return;
}
@@ -344,7 +336,7 @@ uint8_t fstStateCommInput(FstState* s, bool* null) {
*null = true;
return v;
}
- // v = 0 indicate that common_input is None
+ // 0 indicate that common_input is None
return v == 0 ? 0 : COMMON_INPUT(v);
}
@@ -522,7 +514,6 @@ uint64_t fstStateNtrans(FstState* s, FstSlice* slice) {
int32_t len;
uint8_t* data = fstSliceData(slice, &len);
n = data[len - 2];
- // n = data[slice->end - 1]; // data[data.len() - 2]
return n == 1 ? 256 : n; // // "1" is never a normal legal value here, because if there, // is only 1 transition,
// then it is encoded in the state byte
}
@@ -546,7 +537,6 @@ uint64_t fstStateFindInput(FstState* s, FstNode* node, uint8_t b, bool* null) {
int32_t dlen = 0;
uint8_t* data = fstSliceData(slice, &dlen);
uint64_t i = data[at + b];
- // uint64_t i = slice->data[slice->start + at + b];
if (i >= node->nTrans) {
*null = true;
}
@@ -558,16 +548,15 @@ uint64_t fstStateFindInput(FstState* s, FstNode* node, uint8_t b, bool* null) {
FstSlice t = fstSliceCopy(slice, start, end - 1);
int32_t len = 0;
uint8_t* data = fstSliceData(&t, &len);
- int i = 0;
- for (; i < len; i++) {
+ for (int i = 0; i < len; i++) {
uint8_t v = data[i];
if (v == b) {
fstSliceDestroy(&t);
return node->nTrans - i - 1; // bug
}
- }
- if (i == len) {
- *null = true;
+ if (i + 1 == len) {
+ *null = true;
+ }
}
fstSliceDestroy(&t);
}
@@ -737,23 +726,20 @@ bool fstNodeCompile(FstNode* node, void* w, CompiledAddr lastAddr, CompiledAddr
return true;
} else if (sz != 1 || builderNode->isFinal) {
fstStateCompileForAnyTrans(w, addr, builderNode);
- // AnyTrans->Compile(w, addr, node);
} else {
FstTransition* tran = taosArrayGet(builderNode->trans, 0);
if (tran->addr == lastAddr && tran->out == 0) {
fstStateCompileForOneTransNext(w, addr, tran->inp);
- // OneTransNext::compile(w, lastAddr, tran->inp);
return true;
} else {
fstStateCompileForOneTrans(w, addr, tran);
- // OneTrans::Compile(w, lastAddr, *tran);
return true;
}
}
return true;
}
-bool fstBuilderNodeCompileTo(FstBuilderNode* b, FstCountingWriter* wrt, CompiledAddr lastAddr, CompiledAddr startAddr) {
+bool fstBuilderNodeCompileTo(FstBuilderNode* b, IdxFstFile* wrt, CompiledAddr lastAddr, CompiledAddr startAddr) {
return fstNodeCompile(NULL, wrt, lastAddr, startAddr, b);
}
@@ -763,7 +749,7 @@ FstBuilder* fstBuilderCreate(void* w, FstType ty) {
return b;
}
- b->wrt = fstCountingWriterCreate(w);
+ b->wrt = idxFileCreate(w);
b->unfinished = fstUnFinishedNodesCreate();
b->registry = fstRegistryCreate(10000, 2);
b->last = fstSliceCreate(NULL, 0);
@@ -773,12 +759,12 @@ FstBuilder* fstBuilderCreate(void* w, FstType ty) {
char buf64[8] = {0};
void* pBuf64 = buf64;
taosEncodeFixedU64(&pBuf64, VERSION);
- fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
+ idxFileWrite(b->wrt, buf64, sizeof(buf64));
pBuf64 = buf64;
memset(buf64, 0, sizeof(buf64));
taosEncodeFixedU64(&pBuf64, ty);
- fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
+ idxFileWrite(b->wrt, buf64, sizeof(buf64));
return b;
}
@@ -787,7 +773,7 @@ void fstBuilderDestroy(FstBuilder* b) {
return;
}
- fstCountingWriterDestroy(b->wrt);
+ idxFileDestroy(b->wrt);
fstUnFinishedNodesDestroy(b->unfinished);
fstRegistryDestroy(b->registry);
fstSliceDestroy(&b->last);
@@ -795,7 +781,7 @@ void fstBuilderDestroy(FstBuilder* b) {
}
bool fstBuilderInsert(FstBuilder* b, FstSlice bs, Output in) {
- OrderType t = fstBuilderCheckLastKey(b, bs, true);
+ FstOrderType t = fstBuilderCheckLastKey(b, bs, true);
if (t == Ordered) {
// add log info
fstBuilderInsertOutput(b, bs, in);
@@ -812,12 +798,6 @@ void fstBuilderInsertOutput(FstBuilder* b, FstSlice bs, Output in) {
fstUnFinishedNodesSetRootOutput(b->unfinished, in);
return;
}
- // if (in != 0) { //if let Some(in) = in
- // prefixLen = fstUnFinishedNodesFindCommPrefixAndSetOutput(b->unfinished, bs, in, &out);
- //} else {
- // prefixLen = fstUnFinishedNodesFindCommPrefix(b->unfinished, bs);
- // out = 0;
- //}
Output out;
uint64_t prefixLen = fstUnFinishedNodesFindCommPrefixAndSetOutput(b->unfinished, bs, in, &out);
@@ -835,7 +815,7 @@ void fstBuilderInsertOutput(FstBuilder* b, FstSlice bs, Output in) {
return;
}
-OrderType fstBuilderCheckLastKey(FstBuilder* b, FstSlice bs, bool ckDup) {
+FstOrderType fstBuilderCheckLastKey(FstBuilder* b, FstSlice bs, bool ckDup) {
FstSlice* input = &bs;
if (fstSliceIsEmpty(&b->last)) {
fstSliceDestroy(&b->last);
@@ -867,7 +847,6 @@ void fstBuilderCompileFrom(FstBuilder* b, uint64_t istate) {
fstBuilderNodeDestroy(bn);
assert(addr != NONE_ADDRESS);
- // fstBuilderNodeDestroy(n);
}
fstUnFinishedNodesTopLastFreeze(b->unfinished, addr);
return;
@@ -905,21 +884,19 @@ void* fstBuilderInsertInner(FstBuilder* b) {
void* pBuf64 = buf64;
taosEncodeFixedU64(&pBuf64, b->len);
- fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
+ idxFileWrite(b->wrt, buf64, sizeof(buf64));
pBuf64 = buf64;
taosEncodeFixedU64(&pBuf64, rootAddr);
- fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
+ idxFileWrite(b->wrt, buf64, sizeof(buf64));
char buf32[4] = {0};
void* pBuf32 = buf32;
- uint32_t sum = fstCountingWriterMaskedCheckSum(b->wrt);
+ uint32_t sum = idxFileMaskedCheckSum(b->wrt);
taosEncodeFixedU32(&pBuf32, sum);
- fstCountingWriterWrite(b->wrt, buf32, sizeof(buf32));
+ idxFileWrite(b->wrt, buf32, sizeof(buf32));
- fstCountingWriterFlush(b->wrt);
- // fstCountingWriterDestroy(b->wrt);
- // b->wrt = NULL;
+ idxFileFlush(b->wrt);
return b->wrt;
}
void fstBuilderFinish(FstBuilder* b) { fstBuilderInsertInner(b); }
@@ -1046,8 +1023,6 @@ void fstDestroy(Fst* fst) {
}
bool fstGet(Fst* fst, FstSlice* b, Output* out) {
- // dec lock range
- // taosThreadMutexLock(&fst->mtx);
FstNode* root = fstGetRoot(fst);
Output tOut = 0;
int32_t len;
@@ -1060,7 +1035,6 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
uint8_t inp = data[i];
Output res = 0;
if (false == fstNodeFindInput(root, inp, &res)) {
- // taosThreadMutexUnlock(&fst->mtx);
return false;
}
@@ -1071,7 +1045,6 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
taosArrayPush(nodes, &root);
}
if (!FST_NODE_IS_FINAL(root)) {
- // taosThreadMutexUnlock(&fst->mtx);
return false;
} else {
tOut = tOut + FST_NODE_FINAL_OUTPUT(root);
@@ -1082,8 +1055,6 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
fstNodeDestroy(*node);
}
taosArrayDestroy(nodes);
- // fst->root = NULL;
- // taosThreadMutexUnlock(&fst->mtx);
*out = tOut;
return true;
}
@@ -1233,20 +1204,17 @@ bool stmStSeekMin(FStmSt* sws, FstBoundWithData* min) {
FstNode* node = fstGetRoot(sws->fst);
Output out = 0;
- // void* autState = sws->aut->start();
- void* autState = automFuncs[aut->type].start(aut);
+ void* autState = automFuncs[aut->type].start(aut);
int32_t len;
uint8_t* data = fstSliceData(key, &len);
for (uint32_t i = 0; i < len; i++) {
uint8_t b = data[i];
uint64_t res = 0;
- bool find = fstNodeFindInput(node, b, &res);
- if (find == true) {
+ if (fstNodeFindInput(node, b, &res)) {
FstTransition trn;
fstNodeGetTransitionAt(node, res, &trn);
void* preState = autState;
- // autState = sws->aut->accept(preState, b);
autState = automFuncs[aut->type].accept(aut, preState, b);
taosArrayPush(sws->inp, &b);
@@ -1339,7 +1307,6 @@ FStmStRslt* stmStNextWith(FStmSt* sws, StreamCallback callback) {
taosArrayPush(sws->inp, &(trn.inp));
if (FST_NODE_IS_FINAL(nextNode)) {
- // void *eofState = sws->aut->acceptEof(nextState);
void* eofState = automFuncs[aut->type].acceptEof(aut, nextState);
if (eofState != NULL) {
isMatch = automFuncs[aut->type].isMatch(aut, eofState);
@@ -1381,14 +1348,14 @@ FStmStRslt* stmStNextWith(FStmSt* sws, StreamCallback callback) {
return NULL;
}
-FStmStRslt* swsResultCreate(FstSlice* data, FstOutput fOut, void* state) {
+FStmStRslt* swsResultCreate(FstSlice* data, FstOutput out, void* state) {
FStmStRslt* result = taosMemoryCalloc(1, sizeof(FStmStRslt));
if (result == NULL) {
return NULL;
}
result->data = fstSliceCopy(data, 0, FST_SLICE_LEN(data) - 1);
- result->out = fOut;
+ result->out = out;
result->state = state;
return result;
}
diff --git a/source/libs/index/src/indexFstCommon.c b/source/libs/index/src/indexFstCommon.c
index 902e68ce091c0a7316f5404515a742a911fb603e..0b201570090878b6227ebfa2b3c552049a895aaf 100644
--- a/source/libs/index/src/indexFstCommon.c
+++ b/source/libs/index/src/indexFstCommon.c
@@ -294,3 +294,4 @@ const char COMMON_INPUTS_INV[] = {
'\xee', '\xef', '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb',
'\xfc', '\xfd', '\xfe', '\xff',
};
+const int32_t COMMON_INPUTS_LEN = sizeof(COMMON_INPUTS) / sizeof(COMMON_INPUTS[0]);
diff --git a/source/libs/index/src/indexFstDfa.c b/source/libs/index/src/indexFstDfa.c
index ff6b154c547e9c9f0740b083e3f947c35123f5a2..046ed0f4f4a16bc63fb588c850784d6a1ae066e7 100644
--- a/source/libs/index/src/indexFstDfa.c
+++ b/source/libs/index/src/indexFstDfa.c
@@ -41,7 +41,7 @@ FstDfaBuilder *dfaBuilderCreate(SArray *insts) {
return NULL;
}
- SArray *states = taosArrayInit(4, sizeof(State));
+ SArray *states = taosArrayInit(4, sizeof(DfaState));
builder->dfa = dfaCreate(insts, states);
builder->cache = taosHashInit(
@@ -61,6 +61,7 @@ void dfaBuilderDestroy(FstDfaBuilder *builder) {
pIter = taosHashIterate(builder->cache, pIter);
}
taosHashCleanup(builder->cache);
+ taosMemoryFree(builder);
}
FstDfa *dfaBuilderBuild(FstDfaBuilder *builder) {
@@ -70,9 +71,9 @@ FstDfa *dfaBuilderBuild(FstDfaBuilder *builder) {
dfaAdd(builder->dfa, cur, 0);
- SArray * states = taosArrayInit(0, sizeof(uint32_t));
+ SArray *states = taosArrayInit(0, sizeof(uint32_t));
uint32_t result;
- if (dfaBuilderCachedState(builder, cur, &result)) {
+ if (dfaBuilderCacheState(builder, cur, &result)) {
taosArrayPush(states, &result);
}
SHashObj *seen = taosHashInit(12, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
@@ -100,17 +101,18 @@ FstDfa *dfaBuilderBuild(FstDfaBuilder *builder) {
bool dfaBuilderRunState(FstDfaBuilder *builder, FstSparseSet *cur, FstSparseSet *next, uint32_t state, uint8_t byte,
uint32_t *result) {
sparSetClear(cur);
- State *t = taosArrayGet(builder->dfa->states, state);
+ DfaState *t = taosArrayGet(builder->dfa->states, state);
for (int i = 0; i < taosArrayGetSize(t->insts); i++) {
- uint32_t ip = *(int32_t *)taosArrayGet(t->insts, i);
- sparSetAdd(cur, ip);
+ int32_t ip = *(int32_t *)taosArrayGet(t->insts, i);
+ bool succ = sparSetAdd(cur, ip, NULL);
+ assert(succ == true);
}
dfaRun(builder->dfa, cur, next, byte);
t = taosArrayGet(builder->dfa->states, state);
uint32_t nxtState;
- if (dfaBuilderCachedState(builder, next, &nxtState)) {
+ if (dfaBuilderCacheState(builder, next, &nxtState)) {
t->next[byte] = nxtState;
*result = nxtState;
return true;
@@ -118,12 +120,13 @@ bool dfaBuilderRunState(FstDfaBuilder *builder, FstSparseSet *cur, FstSparseSet
return false;
}
-bool dfaBuilderCachedState(FstDfaBuilder *builder, FstSparseSet *set, uint32_t *result) {
+bool dfaBuilderCacheState(FstDfaBuilder *builder, FstSparseSet *set, uint32_t *result) {
SArray *tinsts = taosArrayInit(4, sizeof(uint32_t));
bool isMatch = false;
for (int i = 0; i < sparSetLen(set); i++) {
- uint32_t ip = sparSetGet(set, i);
+ int32_t ip;
+ if (false == sparSetGet(set, i, &ip)) continue;
Inst *inst = taosArrayGet(builder->dfa->insts, ip);
if (inst->ty == JUMP || inst->ty == SPLIT) {
@@ -143,7 +146,7 @@ bool dfaBuilderCachedState(FstDfaBuilder *builder, FstSparseSet *set, uint32_t *
*result = *v;
taosArrayDestroy(tinsts);
} else {
- State st;
+ DfaState st;
st.insts = tinsts;
st.isMatch = isMatch;
taosArrayPush(builder->dfa->states, &st);
@@ -168,14 +171,14 @@ bool dfaIsMatch(FstDfa *dfa, uint32_t si) {
if (dfa->states == NULL || si < taosArrayGetSize(dfa->states)) {
return false;
}
- State *st = taosArrayGet(dfa->states, si);
+ DfaState *st = taosArrayGet(dfa->states, si);
return st != NULL ? st->isMatch : false;
}
bool dfaAccept(FstDfa *dfa, uint32_t si, uint8_t byte, uint32_t *result) {
if (dfa->states == NULL || si < taosArrayGetSize(dfa->states)) {
return false;
}
- State *st = taosArrayGet(dfa->states, si);
+ DfaState *st = taosArrayGet(dfa->states, si);
*result = st->next[byte];
return true;
}
@@ -183,7 +186,8 @@ void dfaAdd(FstDfa *dfa, FstSparseSet *set, uint32_t ip) {
if (sparSetContains(set, ip)) {
return;
}
- sparSetAdd(set, ip);
+ bool succ = sparSetAdd(set, ip, NULL);
+ // assert(succ == true);
Inst *inst = taosArrayGet(dfa->insts, ip);
if (inst->ty == MATCH || inst->ty == RANGE) {
// do nothing
@@ -200,7 +204,8 @@ bool dfaRun(FstDfa *dfa, FstSparseSet *from, FstSparseSet *to, uint8_t byte) {
bool isMatch = false;
sparSetClear(to);
for (int i = 0; i < sparSetLen(from); i++) {
- uint32_t ip = sparSetGet(from, i);
+ int32_t ip;
+ if (false == sparSetGet(from, i, &ip)) continue;
Inst *inst = taosArrayGet(dfa->insts, ip);
if (inst->ty == JUMP || inst->ty == SPLIT) {
diff --git a/source/libs/index/src/indexFstCountingWriter.c b/source/libs/index/src/indexFstFile.c
similarity index 63%
rename from source/libs/index/src/indexFstCountingWriter.c
rename to source/libs/index/src/indexFstFile.c
index 8ba51736028515f2d671ecab876ed7437c96b8b7..9106caebd6b61581041167bfd4ac4e4a6b090cf1 100644
--- a/source/libs/index/src/indexFstCountingWriter.c
+++ b/source/libs/index/src/indexFstFile.c
@@ -13,13 +13,13 @@
* along with this program. If not, see .
*/
-#include "indexFstCountingWriter.h"
+#include "indexFstFile.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "os.h"
#include "tutil.h"
-static int writeCtxDoWrite(WriterCtx* ctx, uint8_t* buf, int len) {
+static int idxFileCtxDoWrite(IFileCtx* ctx, uint8_t* buf, int len) {
if (ctx->type == TFile) {
assert(len == taosWriteFile(ctx->file.pFile, buf, len));
} else {
@@ -28,7 +28,7 @@ static int writeCtxDoWrite(WriterCtx* ctx, uint8_t* buf, int len) {
ctx->offset += len;
return len;
}
-static int writeCtxDoRead(WriterCtx* ctx, uint8_t* buf, int len) {
+static int idxFileCtxDoRead(IFileCtx* ctx, uint8_t* buf, int len) {
int nRead = 0;
if (ctx->type == TFile) {
#ifdef USE_MMAP
@@ -44,7 +44,7 @@ static int writeCtxDoRead(WriterCtx* ctx, uint8_t* buf, int len) {
return nRead;
}
-static int writeCtxDoReadFrom(WriterCtx* ctx, uint8_t* buf, int len, int32_t offset) {
+static int idxFileCtxDoReadFrom(IFileCtx* ctx, uint8_t* buf, int len, int32_t offset) {
int nRead = 0;
if (ctx->type == TFile) {
// tfLseek(ctx->file.pFile, offset, 0);
@@ -61,7 +61,7 @@ static int writeCtxDoReadFrom(WriterCtx* ctx, uint8_t* buf, int len, int32_t off
}
return nRead;
}
-static int writeCtxGetSize(WriterCtx* ctx) {
+static int idxFileCtxGetSize(IFileCtx* ctx) {
if (ctx->type == TFile) {
int64_t file_size = 0;
taosStatFile(ctx->file.buf, &file_size, NULL);
@@ -69,19 +69,17 @@ static int writeCtxGetSize(WriterCtx* ctx) {
}
return 0;
}
-static int writeCtxDoFlush(WriterCtx* ctx) {
+static int idxFileCtxDoFlush(IFileCtx* ctx) {
if (ctx->type == TFile) {
- // taosFsyncFile(ctx->file.pFile);
taosFsyncFile(ctx->file.pFile);
- // tfFlush(ctx->file.pFile);
} else {
// do nothing
}
return 1;
}
-WriterCtx* writerCtxCreate(WriterType type, const char* path, bool readOnly, int32_t capacity) {
- WriterCtx* ctx = taosMemoryCalloc(1, sizeof(WriterCtx));
+IFileCtx* idxFileCtxCreate(WriterType type, const char* path, bool readOnly, int32_t capacity) {
+ IFileCtx* ctx = taosMemoryCalloc(1, sizeof(IFileCtx));
if (ctx == NULL) {
return NULL;
}
@@ -90,39 +88,36 @@ WriterCtx* writerCtxCreate(WriterType type, const char* path, bool readOnly, int
if (ctx->type == TFile) {
// ugly code, refactor later
ctx->file.readOnly = readOnly;
+ memcpy(ctx->file.buf, path, strlen(path));
if (readOnly == false) {
- // ctx->file.pFile = open(path, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO);
ctx->file.pFile = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
taosFtruncateFile(ctx->file.pFile, 0);
- int64_t file_size;
- taosStatFile(path, &file_size, NULL);
- ctx->file.size = (int)file_size;
+ taosStatFile(path, &ctx->file.size, NULL);
+ // ctx->file.size = (int)size;
} else {
- // ctx->file.pFile = open(path, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
ctx->file.pFile = taosOpenFile(path, TD_FILE_READ);
- int64_t file_size = 0;
- taosFStatFile(ctx->file.pFile, &file_size, NULL);
- ctx->file.size = (int)file_size;
+ int64_t size = 0;
+ taosFStatFile(ctx->file.pFile, &ctx->file.size, NULL);
+ ctx->file.size = (int)size;
#ifdef USE_MMAP
ctx->file.ptr = (char*)tfMmapReadOnly(ctx->file.pFile, ctx->file.size);
#endif
}
- memcpy(ctx->file.buf, path, strlen(path));
if (ctx->file.pFile == NULL) {
indexError("failed to open file, error %d", errno);
goto END;
}
} else if (ctx->type == TMemory) {
ctx->mem.buf = taosMemoryCalloc(1, sizeof(char) * capacity);
- ctx->mem.capa = capacity;
+ ctx->mem.cap = capacity;
}
- ctx->write = writeCtxDoWrite;
- ctx->read = writeCtxDoRead;
- ctx->flush = writeCtxDoFlush;
- ctx->readFrom = writeCtxDoReadFrom;
- ctx->size = writeCtxGetSize;
+ ctx->write = idxFileCtxDoWrite;
+ ctx->read = idxFileCtxDoRead;
+ ctx->flush = idxFileCtxDoFlush;
+ ctx->readFrom = idxFileCtxDoReadFrom;
+ ctx->size = idxFileCtxGetSize;
ctx->offset = 0;
ctx->limit = capacity;
@@ -135,7 +130,7 @@ END:
taosMemoryFree(ctx);
return NULL;
}
-void writerCtxDestroy(WriterCtx* ctx, bool remove) {
+void idxFileCtxDestroy(IFileCtx* ctx, bool remove) {
if (ctx->type == TMemory) {
taosMemoryFree(ctx->mem.buf);
} else {
@@ -149,9 +144,6 @@ void writerCtxDestroy(WriterCtx* ctx, bool remove) {
if (ctx->file.readOnly == false) {
int64_t file_size = 0;
taosStatFile(ctx->file.buf, &file_size, NULL);
- // struct stat fstat;
- // stat(ctx->file.buf, &fstat);
- // indexError("write file size: %d", (int)(fstat.st_size));
}
if (remove) {
unlink(ctx->file.buf);
@@ -160,30 +152,29 @@ void writerCtxDestroy(WriterCtx* ctx, bool remove) {
taosMemoryFree(ctx);
}
-FstCountingWriter* fstCountingWriterCreate(void* wrt) {
- FstCountingWriter* cw = taosMemoryCalloc(1, sizeof(FstCountingWriter));
+IdxFstFile* idxFileCreate(void* wrt) {
+ IdxFstFile* cw = taosMemoryCalloc(1, sizeof(IdxFstFile));
if (cw == NULL) {
return NULL;
}
cw->wrt = wrt;
- //(void *)(writerCtxCreate(TFile, readOnly));
return cw;
}
-void fstCountingWriterDestroy(FstCountingWriter* cw) {
+void idxFileDestroy(IdxFstFile* cw) {
// free wrt object: close fd or free mem
- fstCountingWriterFlush(cw);
- // writerCtxDestroy((WriterCtx *)(cw->wrt));
+ idxFileFlush(cw);
+ // idxFileCtxDestroy((IFileCtx *)(cw->wrt));
taosMemoryFree(cw);
}
-int fstCountingWriterWrite(FstCountingWriter* write, uint8_t* buf, uint32_t len) {
+int idxFileWrite(IdxFstFile* write, uint8_t* buf, uint32_t len) {
if (write == NULL) {
return 0;
}
// update checksum
// write data to file/socket or mem
- WriterCtx* ctx = write->wrt;
+ IFileCtx* ctx = write->wrt;
int nWrite = ctx->write(ctx, buf, len);
assert(nWrite == len);
@@ -192,42 +183,39 @@ int fstCountingWriterWrite(FstCountingWriter* write, uint8_t* buf, uint32_t len)
write->summer = taosCalcChecksum(write->summer, buf, len);
return len;
}
-int fstCountingWriterRead(FstCountingWriter* write, uint8_t* buf, uint32_t len) {
+int idxFileRead(IdxFstFile* write, uint8_t* buf, uint32_t len) {
if (write == NULL) {
return 0;
}
- WriterCtx* ctx = write->wrt;
- int nRead = ctx->read(ctx, buf, len);
- // assert(nRead == len);
- return nRead;
+ IFileCtx* ctx = write->wrt;
+ return ctx->read(ctx, buf, len);
}
-uint32_t fstCountingWriterMaskedCheckSum(FstCountingWriter* write) {
- // opt
+uint32_t idxFileMaskedCheckSum(IdxFstFile* write) {
+ //////
return write->summer;
}
-int fstCountingWriterFlush(FstCountingWriter* write) {
- WriterCtx* ctx = write->wrt;
+int idxFileFlush(IdxFstFile* write) {
+ IFileCtx* ctx = write->wrt;
ctx->flush(ctx);
- // write->wtr->flush
return 1;
}
-void fstCountingWriterPackUintIn(FstCountingWriter* writer, uint64_t n, uint8_t nBytes) {
+void idxFilePackUintIn(IdxFstFile* writer, uint64_t n, uint8_t nBytes) {
assert(1 <= nBytes && nBytes <= 8);
uint8_t* buf = taosMemoryCalloc(8, sizeof(uint8_t));
for (uint8_t i = 0; i < nBytes; i++) {
buf[i] = (uint8_t)n;
n = n >> 8;
}
- fstCountingWriterWrite(writer, buf, nBytes);
+ idxFileWrite(writer, buf, nBytes);
taosMemoryFree(buf);
return;
}
-uint8_t fstCountingWriterPackUint(FstCountingWriter* writer, uint64_t n) {
+uint8_t idxFilePackUint(IdxFstFile* writer, uint64_t n) {
uint8_t nBytes = packSize(n);
- fstCountingWriterPackUintIn(writer, n, nBytes);
+ idxFilePackUintIn(writer, n, nBytes);
return nBytes;
}
diff --git a/source/libs/index/src/indexFstNode.c b/source/libs/index/src/indexFstNode.c
index e11f9dd37dc7ef8afd26e898bcd2c9a08afa1e8c..7185e44f469ccf992ba41542fbfe9cddccae4ad9 100644
--- a/source/libs/index/src/indexFstNode.c
+++ b/source/libs/index/src/indexFstNode.c
@@ -95,7 +95,7 @@ void fstBuilderNodeCloneFrom(FstBuilderNode* dst, FstBuilderNode* src) {
}
}
-// bool fstBuilderNodeCompileTo(FstBuilderNode *b, FstCountingWriter *wrt, CompiledAddr lastAddr, CompiledAddr
+// bool fstBuilderNodeCompileTo(FstBuilderNode *b, IdxFile *wrt, CompiledAddr lastAddr, CompiledAddr
// startAddr) {
// size_t sz = taosArrayGetSize(b->trans);
diff --git a/source/libs/index/src/indexFstRegex.c b/source/libs/index/src/indexFstRegex.c
index 33eeae802e536a74c59748816ce09f1140dab0ff..e148f211f23a6acbf9bd81eed2dff13761a7800a 100644
--- a/source/libs/index/src/indexFstRegex.c
+++ b/source/libs/index/src/indexFstRegex.c
@@ -22,20 +22,26 @@ FstRegex *regexCreate(const char *str) {
if (regex == NULL) {
return NULL;
}
- int32_t sz = (int32_t)strlen(str);
- char * orig = taosMemoryCalloc(1, sz);
- memcpy(orig, str, sz);
- regex->orig = orig;
+ regex->orig = tstrdup(str);
// construct insts based on str
- SArray *insts = NULL;
-
+ SArray *insts = taosArrayInit(256, sizeof(uint8_t));
+ for (int i = 0; i < strlen(str); i++) {
+ uint8_t v = str[i];
+ taosArrayPush(insts, &v);
+ }
FstDfaBuilder *builder = dfaBuilderCreate(insts);
regex->dfa = dfaBuilderBuild(builder);
return regex;
}
+void regexDestroy(FstRegex *regex) {
+ if (regex == NULL) return;
+ taosMemoryFree(regex->orig);
+ taosMemoryFree(regex);
+}
+
uint32_t regexAutomStart(FstRegex *regex) {
///// no nothing
return 0;
diff --git a/source/libs/index/src/indexFstSparse.c b/source/libs/index/src/indexFstSparse.c
index e8ab3be2fe2d257544573d9fc39675b7bf86751b..60eb7afd90277def52d473a49461256c88608c04 100644
--- a/source/libs/index/src/indexFstSparse.c
+++ b/source/libs/index/src/indexFstSparse.c
@@ -15,14 +15,24 @@
#include "indexFstSparse.h"
+static void sparSetUtil(int32_t *buf, int32_t cap) {
+ for (int32_t i = 0; i < cap; i++) {
+ buf[i] = -1;
+ }
+}
FstSparseSet *sparSetCreate(int32_t sz) {
FstSparseSet *ss = taosMemoryCalloc(1, sizeof(FstSparseSet));
- if (ss = NULL) {
+ if (ss == NULL) {
return NULL;
}
- ss->dense = (uint32_t *)taosMemoryCalloc(sz, sizeof(uint32_t));
- ss->sparse = (uint32_t *)taosMemoryCalloc(sz, sizeof(uint32_t));
+ ss->dense = (int32_t *)taosMemoryMalloc(sz * sizeof(int32_t));
+ ss->sparse = (int32_t *)taosMemoryMalloc(sz * sizeof(int32_t));
+ sparSetUtil(ss->dense, sz);
+ sparSetUtil(ss->sparse, sz);
+
+ ss->cap = sz;
+
ss->size = 0;
return ss;
}
@@ -38,23 +48,39 @@ uint32_t sparSetLen(FstSparseSet *ss) {
// Get occupied size
return ss == NULL ? 0 : ss->size;
}
-uint32_t sparSetAdd(FstSparseSet *ss, uint32_t ip) {
+bool sparSetAdd(FstSparseSet *ss, int32_t ip, int32_t *idx) {
if (ss == NULL) {
- return 0;
+ return false;
+ }
+ if (ip >= ss->cap || ip < 0) {
+ return false;
}
uint32_t i = ss->size;
ss->dense[i] = ip;
ss->sparse[ip] = i;
ss->size += 1;
- return i;
+
+ if (idx != NULL) *idx = i;
+
+ return true;
}
-uint32_t sparSetGet(FstSparseSet *ss, uint32_t i) {
- // check later
- return ss->dense[i];
+bool sparSetGet(FstSparseSet *ss, int32_t idx, int32_t *ip) {
+ if (idx >= ss->cap || idx >= ss->size || idx < 0) {
+ return false;
+ }
+ int32_t val = ss->dense[idx];
+ if (ip != NULL) {
+ *ip = val;
+ }
+ return val == -1 ? false : true;
}
-bool sparSetContains(FstSparseSet *ss, uint32_t ip) {
- uint32_t i = ss->sparse[ip];
- if (i < ss->size && ss->dense[i] == ip) {
+bool sparSetContains(FstSparseSet *ss, int32_t ip) {
+ if (ip >= ss->cap || ip < 0) {
+ return false;
+ }
+ int32_t i = ss->sparse[ip];
+
+ if (i >= 0 && i < ss->cap && i < ss->size && ss->dense[i] == ip) {
return true;
} else {
return false;
@@ -64,5 +90,7 @@ void sparSetClear(FstSparseSet *ss) {
if (ss == NULL) {
return;
}
+ sparSetUtil(ss->dense, ss->cap);
+ sparSetUtil(ss->sparse, ss->cap);
ss->size = 0;
}
diff --git a/source/libs/index/src/indexFstUtil.c b/source/libs/index/src/indexFstUtil.c
index 5760b24900ef47e6a52419ade3d91cee9870709a..b1a919b365742791fc7daaae1f6ea47f9b012477 100644
--- a/source/libs/index/src/indexFstUtil.c
+++ b/source/libs/index/src/indexFstUtil.c
@@ -21,12 +21,12 @@ const CompiledAddr EMPTY_ADDRESS = 0;
const CompiledAddr NONE_ADDRESS = 1;
// This version number is written to every finite state transducer created by
-// this crate. When a finite state transducer is read, its version number is
+// this version. When a finite state transducer is read, its version number is
// checked against this value.
const uint64_t VERSION = 3;
+
// The threshold (in number of transitions) at which an index is created for
// a node's transitions. This speeds up lookup time at the expense of FST size
-
const uint64_t TRANS_INDEX_THRESHOLD = 32;
uint8_t packSize(uint64_t n) {
@@ -52,7 +52,6 @@ uint8_t packSize(uint64_t n) {
uint64_t unpackUint64(uint8_t* ch, uint8_t sz) {
uint64_t n = 0;
for (uint8_t i = 0; i < sz; i++) {
- //
n = n | (ch[i] << (8 * i));
}
return n;
@@ -75,7 +74,6 @@ CompiledAddr unpackDelta(char* data, uint64_t len, uint64_t nodeAddr) {
}
// fst slice func
-//
FstSlice fstSliceCreate(uint8_t* data, uint64_t len) {
FstString* str = (FstString*)taosMemoryMalloc(sizeof(FstString));
@@ -164,16 +162,3 @@ int fstSliceCompare(FstSlice* a, FstSlice* b) {
return 0;
}
}
-
-// FstStack* fstStackCreate(size_t elemSize, StackFreeElem freeFn) {
-// FstStack *s = taosMemoryCalloc(1, sizeof(FstStack));
-// if (s == NULL) { return NULL; }
-// s->
-// s->freeFn
-//
-//}
-// void *fstStackPush(FstStack *s, void *elem);
-// void *fstStackTop(FstStack *s);
-// size_t fstStackLen(FstStack *s);
-// void *fstStackGetAt(FstStack *s, size_t i);
-// void fstStackDestory(FstStack *);
diff --git a/source/libs/index/src/indexTfile.c b/source/libs/index/src/indexTfile.c
index d632540ee1b2a7ca73d446b4cdfcd4ea93eca749..56ebd9eb1806b223ef488518e03891beed076d0a 100644
--- a/source/libs/index/src/indexTfile.c
+++ b/source/libs/index/src/indexTfile.c
@@ -16,14 +16,14 @@
#include "index.h"
#include "indexComm.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
+#include "indexFstFile.h"
#include "indexUtil.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tcoding.h"
#include "tcompare.h"
-const static uint64_t tfileMagicNumber = 0xdb4775248b80fb57ull;
+const static uint64_t FILE_MAGIC_NUMBER = 0xdb4775248b80fb57ull;
typedef struct TFileFstIter {
FStmBuilder* fb;
@@ -103,7 +103,7 @@ TFileCache* tfileCacheCreate(const char* path) {
for (size_t i = 0; i < taosArrayGetSize(files); i++) {
char* file = taosArrayGetP(files, i);
- WriterCtx* wc = writerCtxCreate(TFile, file, true, 1024 * 1024 * 64);
+ IFileCtx* wc = idxFileCtxCreate(TFile, file, true, 1024 * 1024 * 64);
if (wc == NULL) {
indexError("failed to open index:%s", file);
goto End;
@@ -175,7 +175,7 @@ void tfileCachePut(TFileCache* tcache, ICacheKey* key, TFileReader* reader) {
tfileReaderRef(reader);
return;
}
-TFileReader* tfileReaderCreate(WriterCtx* ctx) {
+TFileReader* tfileReaderCreate(IFileCtx* ctx) {
TFileReader* reader = taosMemoryCalloc(1, sizeof(TFileReader));
if (reader == NULL) {
return NULL;
@@ -216,7 +216,7 @@ void tfileReaderDestroy(TFileReader* reader) {
} else {
indexInfo("%s is not removed", reader->ctx->file.buf);
}
- writerCtxDestroy(reader->ctx, reader->remove);
+ idxFileCtxDestroy(reader->ctx, reader->remove);
taosMemoryFree(reader);
}
@@ -457,7 +457,10 @@ static int32_t tfSearchCompareFunc_JSON(void* reader, SIndexTerm* tem, SIdxTRslt
} else if (0 != strncmp(ch, p, skip)) {
continue;
}
- cond = cmpFn(ch + skip, tem->colVal, IDX_TYPE_GET_TYPE(tem->colType));
+ char* tBuf = taosMemoryCalloc(1, sz + 1);
+ memcpy(tBuf, ch, sz);
+ cond = cmpFn(tBuf + skip, tem->colVal, IDX_TYPE_GET_TYPE(tem->colType));
+ taosMemoryFree(tBuf);
}
if (MATCH == cond) {
tfileReaderLoadTableIds((TFileReader*)reader, rt->out.out, tr->total);
@@ -490,7 +493,7 @@ TFileWriter* tfileWriterOpen(char* path, uint64_t suid, int64_t version, const c
char fullname[256] = {0};
tfileGenFileFullName(fullname, path, suid, colName, version);
// indexInfo("open write file name %s", fullname);
- WriterCtx* wcx = writerCtxCreate(TFile, fullname, false, 1024 * 1024 * 64);
+ IFileCtx* wcx = idxFileCtxCreate(TFile, fullname, false, 1024 * 1024 * 64);
if (wcx == NULL) {
return NULL;
}
@@ -507,18 +510,18 @@ TFileReader* tfileReaderOpen(char* path, uint64_t suid, int64_t version, const c
char fullname[256] = {0};
tfileGenFileFullName(fullname, path, suid, colName, version);
- WriterCtx* wc = writerCtxCreate(TFile, fullname, true, 1024 * 1024 * 1024);
+ IFileCtx* wc = idxFileCtxCreate(TFile, fullname, true, 1024 * 1024 * 1024);
if (wc == NULL) {
terrno = TAOS_SYSTEM_ERROR(errno);
indexError("failed to open readonly file: %s, reason: %s", fullname, terrstr());
return NULL;
}
- indexTrace("open read file name:%s, file size: %d", wc->file.buf, wc->file.size);
+ indexTrace("open read file name:%s, file size: %" PRId64 "", wc->file.buf, wc->file.size);
TFileReader* reader = tfileReaderCreate(wc);
return reader;
}
-TFileWriter* tfileWriterCreate(WriterCtx* ctx, TFileHeader* header) {
+TFileWriter* tfileWriterCreate(IFileCtx* ctx, TFileHeader* header) {
TFileWriter* tw = taosMemoryCalloc(1, sizeof(TFileWriter));
if (tw == NULL) {
indexError("index: %" PRIu64 " failed to alloc TFilerWriter", header->suid);
@@ -545,9 +548,6 @@ int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
taosArraySortPWithExt((SArray*)(data), tfileValueCompare, &fn);
}
- int32_t bufLimit = 64 * 4096, offset = 0;
- // char* buf = taosMemoryCalloc(1, sizeof(char) * bufLimit);
- // char* p = buf;
int32_t sz = taosArrayGetSize((SArray*)data);
int32_t fstOffset = tw->offset;
@@ -561,6 +561,9 @@ int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
}
tfileWriteFstOffset(tw, fstOffset);
+ int32_t cap = 4 * 1024;
+ char* buf = taosMemoryCalloc(1, cap);
+
for (size_t i = 0; i < sz; i++) {
TFileValue* v = taosArrayGetP((SArray*)data, i);
@@ -568,14 +571,18 @@ int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
// check buf has enough space or not
int32_t ttsz = TF_TABLE_TATOAL_SIZE(tbsz);
- char* buf = taosMemoryCalloc(1, ttsz * sizeof(char));
+ if (cap < ttsz) {
+ cap = ttsz;
+ buf = (char*)taosMemoryRealloc(buf, cap);
+ }
char* p = buf;
tfileSerialTableIdsToBuf(p, v->tableId);
tw->ctx->write(tw->ctx, buf, ttsz);
v->offset = tw->offset;
tw->offset += ttsz;
- taosMemoryFree(buf);
+ memset(buf, 0, cap);
}
+ taosMemoryFree(buf);
tw->fb = fstBuilderCreate(tw->ctx, 0);
if (tw->fb == NULL) {
@@ -609,14 +616,14 @@ void tfileWriterClose(TFileWriter* tw) {
if (tw == NULL) {
return;
}
- writerCtxDestroy(tw->ctx, false);
+ idxFileCtxDestroy(tw->ctx, false);
taosMemoryFree(tw);
}
void tfileWriterDestroy(TFileWriter* tw) {
if (tw == NULL) {
return;
}
- writerCtxDestroy(tw->ctx, false);
+ idxFileCtxDestroy(tw->ctx, false);
taosMemoryFree(tw);
}
@@ -866,13 +873,13 @@ static int tfileWriteData(TFileWriter* write, TFileValue* tval) {
//}
}
static int tfileWriteFooter(TFileWriter* write) {
- char buf[sizeof(tfileMagicNumber) + 1] = {0};
+ char buf[sizeof(FILE_MAGIC_NUMBER) + 1] = {0};
void* pBuf = (void*)buf;
- taosEncodeFixedU64((void**)(void*)&pBuf, tfileMagicNumber);
+ taosEncodeFixedU64((void**)(void*)&pBuf, FILE_MAGIC_NUMBER);
int nwrite = write->ctx->write(write->ctx, buf, (int32_t)strlen(buf));
indexInfo("tfile write footer size: %d", write->ctx->size(write->ctx));
- assert(nwrite == sizeof(tfileMagicNumber));
+ assert(nwrite == sizeof(FILE_MAGIC_NUMBER));
return nwrite;
}
static int tfileReaderLoadHeader(TFileReader* reader) {
@@ -892,11 +899,11 @@ static int tfileReaderLoadHeader(TFileReader* reader) {
return 0;
}
static int tfileReaderLoadFst(TFileReader* reader) {
- WriterCtx* ctx = reader->ctx;
- int size = ctx->size(ctx);
+ IFileCtx* ctx = reader->ctx;
+ int size = ctx->size(ctx);
// current load fst into memory, refactor it later
- int fstSize = size - reader->header.fstOffset - sizeof(tfileMagicNumber);
+ int fstSize = size - reader->header.fstOffset - sizeof(FILE_MAGIC_NUMBER);
char* buf = taosMemoryCalloc(1, fstSize);
if (buf == NULL) {
return -1;
@@ -905,8 +912,9 @@ static int tfileReaderLoadFst(TFileReader* reader) {
int64_t ts = taosGetTimestampUs();
int32_t nread = ctx->readFrom(ctx, buf, fstSize, reader->header.fstOffset);
int64_t cost = taosGetTimestampUs() - ts;
- indexInfo("nread = %d, and fst offset=%d, fst size: %d, filename: %s, file size: %d, time cost: %" PRId64 "us", nread,
- reader->header.fstOffset, fstSize, ctx->file.buf, ctx->file.size, cost);
+ indexInfo("nread = %d, and fst offset=%d, fst size: %d, filename: %s, file size: %" PRId64 ", time cost: %" PRId64
+ "us",
+ nread, reader->header.fstOffset, fstSize, ctx->file.buf, ctx->file.size, cost);
// we assuse fst size less than FST_MAX_SIZE
assert(nread > 0 && nread <= fstSize);
@@ -919,7 +927,7 @@ static int tfileReaderLoadFst(TFileReader* reader) {
}
static int tfileReaderLoadTableIds(TFileReader* reader, int32_t offset, SArray* result) {
// TODO(yihao): opt later
- WriterCtx* ctx = reader->ctx;
+ IFileCtx* ctx = reader->ctx;
// add block cache
char block[4096] = {0};
int32_t nread = ctx->readFrom(ctx, block, sizeof(block), offset);
@@ -952,12 +960,11 @@ static int tfileReaderLoadTableIds(TFileReader* reader, int32_t offset, SArray*
}
static int tfileReaderVerify(TFileReader* reader) {
// just validate header and Footer, file corrupted also shuild be verified later
- WriterCtx* ctx = reader->ctx;
+ IFileCtx* ctx = reader->ctx;
uint64_t tMagicNumber = 0;
-
- char buf[sizeof(tMagicNumber) + 1] = {0};
- int size = ctx->size(ctx);
+ char buf[sizeof(tMagicNumber) + 1] = {0};
+ int size = ctx->size(ctx);
if (size < sizeof(tMagicNumber) || size <= sizeof(reader->header)) {
return -1;
@@ -966,25 +973,25 @@ static int tfileReaderVerify(TFileReader* reader) {
}
taosDecodeFixedU64(buf, &tMagicNumber);
- return tMagicNumber == tfileMagicNumber ? 0 : -1;
+ return tMagicNumber == FILE_MAGIC_NUMBER ? 0 : -1;
}
-void tfileReaderRef(TFileReader* reader) {
- if (reader == NULL) {
+void tfileReaderRef(TFileReader* rd) {
+ if (rd == NULL) {
return;
}
- int ref = T_REF_INC(reader);
+ int ref = T_REF_INC(rd);
UNUSED(ref);
}
-void tfileReaderUnRef(TFileReader* reader) {
- if (reader == NULL) {
+void tfileReaderUnRef(TFileReader* rd) {
+ if (rd == NULL) {
return;
}
- int ref = T_REF_DEC(reader);
+ int ref = T_REF_DEC(rd);
if (ref == 0) {
// do nothing
- tfileReaderDestroy(reader);
+ tfileReaderDestroy(rd);
}
}
diff --git a/source/libs/index/test/CMakeLists.txt b/source/libs/index/test/CMakeLists.txt
index 040460ae5c9662404182b93780075cc88cb93c57..b3eca280032e56004e649b2d2cef44ec1672d8ac 100644
--- a/source/libs/index/test/CMakeLists.txt
+++ b/source/libs/index/test/CMakeLists.txt
@@ -1,110 +1,177 @@
-add_executable(idxTest "")
-add_executable(idxFstTest "")
-add_executable(idxFstUT "")
-add_executable(idxUtilUT "")
-add_executable(idxJsonUT "")
+IF(NOT TD_DARWIN)
+ add_executable(idxTest "")
+ add_executable(idxFstTest "")
+ add_executable(idxFstUT "")
+ add_executable(idxUtilUT "")
+ add_executable(idxJsonUT "")
+ add_executable(idxFstUtilUT "")
-target_sources(idxTest
- PRIVATE
- "indexTests.cc"
-)
-target_sources(idxFstTest
- PRIVATE
- "fstTest.cc"
-)
+ target_sources(idxTest
+ PRIVATE
+ "indexTests.cc"
+ )
+ target_sources(idxFstTest
+ PRIVATE
+ "fstTest.cc"
+ )
-target_sources(idxFstUT
- PRIVATE
- "fstUT.cc"
-)
-target_sources(idxUtilUT
- PRIVATE
- "utilUT.cc"
-)
+ target_sources(idxFstUT
+ PRIVATE
+ "fstUT.cc"
+ )
+ target_sources(idxUtilUT
+ PRIVATE
+ "utilUT.cc"
+ )
-target_sources(idxJsonUT
- PRIVATE
- "jsonUT.cc"
-)
-target_include_directories (idxTest
- PUBLIC
+ target_sources(idxJsonUT
+ PRIVATE
+ "jsonUT.cc"
+ )
+ target_sources(idxFstUtilUT
+ PRIVATE
+ "fstUtilUT.cc"
+ )
+
+ target_include_directories (idxTest
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
+ target_include_directories (idxFstTest
+ PUBLIC
"${TD_SOURCE_DIR}/include/libs/index"
"${CMAKE_CURRENT_SOURCE_DIR}/../inc"
-)
-target_include_directories (idxFstTest
- PUBLIC
- "${TD_SOURCE_DIR}/include/libs/index"
- "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
-)
+ )
+ target_sources(idxJsonUT
+ PRIVATE
+ "jsonUT.cc"
+ )
+ target_include_directories (idxTest
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
+ target_include_directories (idxFstTest
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
-target_include_directories (idxFstUT
- PUBLIC
- "${TD_SOURCE_DIR}/include/libs/index"
- "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
-)
+ target_include_directories (idxFstUT
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
-target_include_directories (idxUtilUT
- PUBLIC
- "${TD_SOURCE_DIR}/include/libs/index"
- "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
-)
+ target_include_directories (idxUtilUT
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
-target_include_directories (idxJsonUT
- PUBLIC
- "${TD_SOURCE_DIR}/include/libs/index"
- "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
-)
-target_link_libraries (idxTest
- os
- util
- common
- gtest_main
- index
-)
-target_link_libraries (idxFstTest
- os
- util
- common
- gtest_main
- index
-)
-target_link_libraries (idxFstUT
- os
- util
- common
- gtest_main
- index
-)
+ target_include_directories (idxJsonUT
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
+ target_include_directories (idxFstUtilUT
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
+
+ target_link_libraries (idxTest
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_link_libraries (idxFstTest
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_link_libraries (idxFstUT
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_include_directories (idxJsonUT
+ PUBLIC
+ "${TD_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+ )
+ target_link_libraries (idxTest
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_link_libraries (idxFstTest
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_link_libraries (idxFstUT
+ os
+ util
+ common
+ gtest_main
+ index
+ )
-target_link_libraries (idxUtilUT
- os
- util
- common
- gtest_main
- index
-)
+ target_link_libraries (idxUtilUT
+ os
+ util
+ common
+ gtest_main
+ index
+ )
-target_link_libraries (idxJsonUT
- os
- util
- common
- gtest_main
- index
-)
+ target_link_libraries (idxJsonUT
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+ target_link_libraries (idxFstUtilUT
+ os
+ util
+ common
+ gtest_main
+ index
+ )
+
+ add_test(
+ NAME idxJsonUT
+ COMMAND idxJsonUT
+ )
+ add_test(
+ NAME idxFstUtilUT
+ COMMAND idxFstUtilUT
+
+ )
-add_test(
- NAME idxtest
- COMMAND idxTest
-)
-add_test(
- NAME idxJsonUT
- COMMAND idxJsonUT
-)
-add_test(
- NAME idxUtilUT
- COMMAND idxUtilUT
-)
-add_test(
- NAME idxFstUT
- COMMAND idxFstUT
-)
+ add_test(
+ NAME idxtest
+ COMMAND idxTest
+ )
+ add_test(
+ NAME idxUtilUT
+ COMMAND idxUtilUT
+ )
+ add_test(
+ NAME idxFstUT
+ COMMAND idxFstUT
+ )
+ENDIF ()
diff --git a/source/libs/index/test/fstTest.cc b/source/libs/index/test/fstTest.cc
index 332b7370df59db3aa21c44a83f1ee06c0250186d..7109c65e852de9e3065079055ca01868faecb8f5 100644
--- a/source/libs/index/test/fstTest.cc
+++ b/source/libs/index/test/fstTest.cc
@@ -7,7 +7,6 @@
#include "index.h"
#include "indexCache.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "indexTfile.h"
@@ -20,7 +19,7 @@ class FstWriter {
public:
FstWriter() {
taosRemoveFile(fileName.c_str());
- _wc = writerCtxCreate(TFile, fileName.c_str(), false, 64 * 1024 * 1024);
+ _wc = idxFileCtxCreate(TFile, fileName.c_str(), false, 64 * 1024 * 1024);
_b = fstBuilderCreate(_wc, 0);
}
bool Put(const std::string& key, uint64_t val) {
@@ -38,25 +37,25 @@ class FstWriter {
fstBuilderFinish(_b);
fstBuilderDestroy(_b);
- writerCtxDestroy(_wc, false);
+ idxFileCtxDestroy(_wc, false);
}
private:
FstBuilder* _b;
- WriterCtx* _wc;
+ IFileCtx* _wc;
};
class FstReadMemory {
public:
FstReadMemory(int32_t size, const std::string& fileName = TD_TMP_DIR_PATH "tindex.tindex") {
- _wc = writerCtxCreate(TFile, fileName.c_str(), true, 64 * 1024);
- _w = fstCountingWriterCreate(_wc);
+ _wc = idxFileCtxCreate(TFile, fileName.c_str(), true, 64 * 1024);
+ _w = idxFileCreate(_wc);
_size = size;
memset((void*)&_s, 0, sizeof(_s));
}
bool init() {
char* buf = (char*)taosMemoryCalloc(1, sizeof(char) * _size);
- int nRead = fstCountingWriterRead(_w, (uint8_t*)buf, _size);
+ int nRead = idxFileRead(_w, (uint8_t*)buf, _size);
if (nRead <= 0) {
return false;
}
@@ -141,18 +140,18 @@ class FstReadMemory {
}
~FstReadMemory() {
- fstCountingWriterDestroy(_w);
+ idxFileDestroy(_w);
fstDestroy(_fst);
fstSliceDestroy(&_s);
- writerCtxDestroy(_wc, false);
+ idxFileCtxDestroy(_wc, false);
}
private:
- FstCountingWriter* _w;
- Fst* _fst;
- FstSlice _s;
- WriterCtx* _wc;
- int32_t _size;
+ IdxFstFile* _w;
+ Fst* _fst;
+ FstSlice _s;
+ IFileCtx* _wc;
+ int32_t _size;
};
#define L 100
diff --git a/source/libs/index/test/fstUT.cc b/source/libs/index/test/fstUT.cc
index b9388e62f7dc0f979c930f92d44edcf17c767a87..b8663dd9f207510c1c0d489273dc154331f70e87 100644
--- a/source/libs/index/test/fstUT.cc
+++ b/source/libs/index/test/fstUT.cc
@@ -8,7 +8,6 @@
#include "index.h"
#include "indexCache.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "indexTfile.h"
@@ -40,7 +39,7 @@ static void EnvCleanup() {}
class FstWriter {
public:
FstWriter() {
- _wc = writerCtxCreate(TFile, tindex, false, 64 * 1024 * 1024);
+ _wc = idxFileCtxCreate(TFile, tindex, false, 64 * 1024 * 1024);
_b = fstBuilderCreate(_wc, 0);
}
bool Put(const std::string& key, uint64_t val) {
@@ -58,25 +57,25 @@ class FstWriter {
fstBuilderFinish(_b);
fstBuilderDestroy(_b);
- writerCtxDestroy(_wc, false);
+ idxFileCtxDestroy(_wc, false);
}
private:
FstBuilder* _b;
- WriterCtx* _wc;
+ IFileCtx* _wc;
};
class FstReadMemory {
public:
FstReadMemory(size_t size) {
- _wc = writerCtxCreate(TFile, tindex, true, 64 * 1024);
- _w = fstCountingWriterCreate(_wc);
+ _wc = idxFileCtxCreate(TFile, tindex, true, 64 * 1024);
+ _w = idxFileCreate(_wc);
_size = size;
memset((void*)&_s, 0, sizeof(_s));
}
bool init() {
char* buf = (char*)taosMemoryCalloc(1, sizeof(char) * _size);
- int nRead = fstCountingWriterRead(_w, (uint8_t*)buf, _size);
+ int nRead = idxFileRead(_w, (uint8_t*)buf, _size);
if (nRead <= 0) {
return false;
}
@@ -130,18 +129,18 @@ class FstReadMemory {
}
~FstReadMemory() {
- fstCountingWriterDestroy(_w);
+ idxFileDestroy(_w);
fstDestroy(_fst);
fstSliceDestroy(&_s);
- writerCtxDestroy(_wc, false);
+ idxFileCtxDestroy(_wc, false);
}
private:
- FstCountingWriter* _w;
- Fst* _fst;
- FstSlice _s;
- WriterCtx* _wc;
- size_t _size;
+ IdxFstFile* _w;
+ Fst* _fst;
+ FstSlice _s;
+ IFileCtx* _wc;
+ size_t _size;
};
class FstWriterEnv : public ::testing::Test {
diff --git a/source/libs/index/test/fstUtilUT.cc b/source/libs/index/test/fstUtilUT.cc
new file mode 100644
index 0000000000000000000000000000000000000000..593a312c9eeafd2af7adba670dbe5fba833a5c49
--- /dev/null
+++ b/source/libs/index/test/fstUtilUT.cc
@@ -0,0 +1,112 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "index.h"
+#include "indexCache.h"
+#include "indexFst.h"
+#include "indexFstDfa.h"
+#include "indexFstRegex.h"
+#include "indexFstSparse.h"
+#include "indexFstUtil.h"
+#include "indexInt.h"
+#include "indexTfile.h"
+#include "tglobal.h"
+#include "tlog.h"
+#include "tskiplist.h"
+#include "tutil.h"
+class FstUtilEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ SArray *inst = taosArrayInit(4, sizeof(char));
+ builder = dfaBuilderCreate(inst);
+ }
+ virtual void TearDown() { dfaBuilderDestroy(builder); }
+
+ FstDfaBuilder *builder;
+};
+
+class FstRegexEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() { regex = regexCreate("test"); }
+ virtual void TearDown() { regexDestroy(regex); }
+ FstRegex *regex;
+};
+
+class FstSparseSetEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() { set = sparSetCreate(256); }
+ virtual void TearDown() {
+ // tear down
+ sparSetDestroy(set);
+ }
+ void ReBuild(int32_t sz) {
+ sparSetDestroy(set);
+ set = sparSetCreate(sz);
+ }
+ FstSparseSet *set;
+};
+
+// test FstDfaBuilder
+TEST_F(FstUtilEnv, test1) {
+ // test
+}
+TEST_F(FstUtilEnv, test2) {
+ // test
+}
+TEST_F(FstUtilEnv, test3) {
+ // test
+}
+TEST_F(FstUtilEnv, test4) {
+ // test
+}
+
+// test FstRegex
+
+TEST_F(FstRegexEnv, test1) {
+ //
+ EXPECT_EQ(regex != NULL, true);
+}
+TEST_F(FstRegexEnv, test2) {}
+TEST_F(FstRegexEnv, test3) {}
+TEST_F(FstRegexEnv, test4) {}
+
+// test FstSparseSet
+TEST_F(FstSparseSetEnv, test1) {
+ for (int8_t i = 0; i < 20; i++) {
+ int32_t val = -1;
+ bool succ = sparSetAdd(set, 'a' + i, &val);
+ }
+ EXPECT_EQ(sparSetLen(set), 20);
+ for (int8_t i = 0; i < 20; i++) {
+ int val = -1;
+ bool find = sparSetGet(set, i, &val);
+ EXPECT_EQ(find, true);
+ EXPECT_EQ(val, i + 'a');
+ }
+ for (int8_t i = 'a'; i < 'a' + 20; i++) {
+ EXPECT_EQ(sparSetContains(set, i), true);
+ }
+
+ for (int8_t i = 'A'; i < 20; i++) {
+ EXPECT_EQ(sparSetContains(set, 'A'), false);
+ }
+
+ for (int i = 512; i < 1000; i++) {
+ EXPECT_EQ(sparSetAdd(set, i, NULL), false);
+
+ EXPECT_EQ(sparSetGet(set, i, NULL), false);
+ EXPECT_EQ(sparSetContains(set, i), false);
+ }
+ sparSetClear(set);
+
+ for (int i = 'a'; i < 'a' + 20; i++) {
+ EXPECT_EQ(sparSetGet(set, i, NULL), false);
+ }
+ for (int i = 1000; i < 2000; i++) {
+ EXPECT_EQ(sparSetGet(set, i, NULL), false);
+ }
+}
diff --git a/source/libs/index/test/indexTests.cc b/source/libs/index/test/indexTests.cc
index e18297cd2589b4d69b8cd4cb855b2300ffd1df24..6b2020501462513b2a6b9b8e4aa1ff13dd55265f 100644
--- a/source/libs/index/test/indexTests.cc
+++ b/source/libs/index/test/indexTests.cc
@@ -20,7 +20,6 @@
#include "index.h"
#include "indexCache.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "indexTfile.h"
@@ -51,7 +50,7 @@ class DebugInfo {
class FstWriter {
public:
FstWriter() {
- _wc = writerCtxCreate(TFile, TD_TMP_DIR_PATH "tindex", false, 64 * 1024 * 1024);
+ _wc = idxFileCtxCreate(TFile, TD_TMP_DIR_PATH "tindex", false, 64 * 1024 * 1024);
_b = fstBuilderCreate(NULL, 0);
}
bool Put(const std::string& key, uint64_t val) {
@@ -64,25 +63,25 @@ class FstWriter {
fstBuilderFinish(_b);
fstBuilderDestroy(_b);
- writerCtxDestroy(_wc, false);
+ idxFileCtxDestroy(_wc, false);
}
private:
FstBuilder* _b;
- WriterCtx* _wc;
+ IFileCtx* _wc;
};
class FstReadMemory {
public:
FstReadMemory(size_t size) {
- _wc = writerCtxCreate(TFile, TD_TMP_DIR_PATH "tindex", true, 64 * 1024);
- _w = fstCountingWriterCreate(_wc);
+ _wc = idxFileCtxCreate(TFile, TD_TMP_DIR_PATH "tindex", true, 64 * 1024);
+ _w = idxFileCreate(_wc);
_size = size;
memset((void*)&_s, 0, sizeof(_s));
}
bool init() {
char* buf = (char*)taosMemoryCalloc(1, sizeof(char) * _size);
- int nRead = fstCountingWriterRead(_w, (uint8_t*)buf, _size);
+ int nRead = idxFileRead(_w, (uint8_t*)buf, _size);
if (nRead <= 0) {
return false;
}
@@ -124,18 +123,18 @@ class FstReadMemory {
}
~FstReadMemory() {
- fstCountingWriterDestroy(_w);
+ idxFileDestroy(_w);
fstDestroy(_fst);
fstSliceDestroy(&_s);
- writerCtxDestroy(_wc, true);
+ idxFileCtxDestroy(_wc, true);
}
private:
- FstCountingWriter* _w;
- Fst* _fst;
- FstSlice _s;
- WriterCtx* _wc;
- size_t _size;
+ IdxFstFile* _w;
+ Fst* _fst;
+ FstSlice _s;
+ IFileCtx* _wc;
+ size_t _size;
};
#define L 100
@@ -392,13 +391,13 @@ class TFileObj {
fileName_ = path;
- WriterCtx* ctx = writerCtxCreate(TFile, path.c_str(), false, 64 * 1024 * 1024);
+ IFileCtx* ctx = idxFileCtxCreate(TFile, path.c_str(), false, 64 * 1024 * 1024);
writer_ = tfileWriterCreate(ctx, &header);
return writer_ != NULL ? true : false;
}
bool InitReader() {
- WriterCtx* ctx = writerCtxCreate(TFile, fileName_.c_str(), true, 64 * 1024 * 1024);
+ IFileCtx* ctx = idxFileCtxCreate(TFile, fileName_.c_str(), true, 64 * 1024 * 1024);
reader_ = tfileReaderCreate(ctx);
return reader_ != NULL ? true : false;
}
diff --git a/source/libs/index/test/index_executor_tests.cpp b/source/libs/index/test/index_executor_tests.cpp
index b88ffe5b8bdb2058a66d1e56020206643c246e42..a0ac79a2976243a2097f3e4290951322b2b65f9a 100644
--- a/source/libs/index/test/index_executor_tests.cpp
+++ b/source/libs/index/test/index_executor_tests.cpp
@@ -86,7 +86,7 @@ void sifAppendReservedSlot(SArray *pBlockList, int16_t *dataBlockId, int16_t *sl
SColumnInfoData idata = {0};
idata.info = *colInfo;
- colInfoDataEnsureCapacity(&idata, 0, rows);
+ colInfoDataEnsureCapacity(&idata, rows);
taosArrayPush(res->pDataBlock, &idata);
diff --git a/source/libs/index/test/jsonUT.cc b/source/libs/index/test/jsonUT.cc
index 134fb53d2b5dcf57f39a6c3ec098592756bcb02d..c65949277e31877488aea3a987d35e4ae0730679 100644
--- a/source/libs/index/test/jsonUT.cc
+++ b/source/libs/index/test/jsonUT.cc
@@ -7,7 +7,6 @@
#include "index.h"
#include "indexCache.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "indexTfile.h"
diff --git a/source/libs/index/test/utilUT.cc b/source/libs/index/test/utilUT.cc
index 6858d313254b661fdc151f095cf9f6f07242c24c..323a6b4afae23ba08bec6dac080223c4c184ddad 100644
--- a/source/libs/index/test/utilUT.cc
+++ b/source/libs/index/test/utilUT.cc
@@ -8,7 +8,7 @@
#include "indexCache.h"
#include "indexComm.h"
#include "indexFst.h"
-#include "indexFstCountingWriter.h"
+#include "indexFstCommon.h"
#include "indexFstUtil.h"
#include "indexInt.h"
#include "indexTfile.h"
@@ -357,3 +357,11 @@ TEST_F(UtilEnv, TempResultExcept) {
idxTRsltMergeTo(relt, f);
EXPECT_EQ(taosArrayGetSize(f), 1);
}
+
+TEST_F(UtilEnv, testDictComm) {
+ int32_t count = COMMON_INPUTS_LEN;
+ for (int i = 0; i < 256; i++) {
+ uint8_t v = COMMON_INPUTS_INV[i];
+ EXPECT_EQ(COMMON_INPUTS[v], i);
+ }
+}
diff --git a/source/libs/monitor/src/monMain.c b/source/libs/monitor/src/monMain.c
index bf857ad718d27f1057529824cfd9cc53106a73bb..d387a432e13d12a55a03af089aab2228f6863ab0 100644
--- a/source/libs/monitor/src/monMain.c
+++ b/source/libs/monitor/src/monMain.c
@@ -201,6 +201,9 @@ static void monGenClusterJson(SMonInfo *pMonitor) {
tjsonAddStringToObject(pJson, "version", pInfo->version);
tjsonAddDoubleToObject(pJson, "master_uptime", pInfo->master_uptime);
tjsonAddDoubleToObject(pJson, "monitor_interval", pInfo->monitor_interval);
+ tjsonAddDoubleToObject(pJson, "dbs_total", pInfo->dbs_total);
+ tjsonAddDoubleToObject(pJson, "tbs_total", pInfo->tbs_total);
+ tjsonAddDoubleToObject(pJson, "stbs_total", pInfo->stbs_total);
tjsonAddDoubleToObject(pJson, "vgroups_total", pInfo->vgroups_total);
tjsonAddDoubleToObject(pJson, "vgroups_alive", pInfo->vgroups_alive);
tjsonAddDoubleToObject(pJson, "vnodes_total", pInfo->vnodes_total);
@@ -277,6 +280,27 @@ static void monGenVgroupJson(SMonInfo *pMonitor) {
}
}
+static void monGenStbJson(SMonInfo *pMonitor) {
+ SMonStbInfo *pInfo = &pMonitor->mmInfo.stb;
+ if (pMonitor->mmInfo.cluster.first_ep_dnode_id == 0) return;
+
+ SJson *pJson = tjsonAddArrayToObject(pMonitor->pJson, "stb_infos");
+ if (pJson == NULL) return;
+
+ for (int32_t i = 0; i < taosArrayGetSize(pInfo->stbs); ++i) {
+ SJson *pStbJson = tjsonCreateObject();
+ if (pStbJson == NULL) continue;
+ if (tjsonAddItemToArray(pJson, pStbJson) != 0) {
+ tjsonDelete(pStbJson);
+ continue;
+ }
+
+ SMonStbDesc *pStbDesc = taosArrayGet(pInfo->stbs, i);
+ tjsonAddStringToObject(pStbJson, "stb_name", pStbDesc->stb_name);
+ tjsonAddStringToObject(pStbJson, "database_name", pStbDesc->database_name);
+ }
+}
+
static void monGenGrantJson(SMonInfo *pMonitor) {
SMonGrantInfo *pInfo = &pMonitor->mmInfo.grant;
if (pMonitor->mmInfo.cluster.first_ep_dnode_id == 0) return;
@@ -524,6 +548,7 @@ void monSendReport() {
monGenBasicJson(pMonitor);
monGenClusterJson(pMonitor);
monGenVgroupJson(pMonitor);
+ monGenStbJson(pMonitor);
monGenGrantJson(pMonitor);
monGenDnodeJson(pMonitor);
monGenDiskJson(pMonitor);
diff --git a/source/libs/monitor/src/monMsg.c b/source/libs/monitor/src/monMsg.c
index a041b582a9eaafc0e8553262150c1a15e7edc469..8fa7e8860509ca473ad41b1c89efbf430f0c2649 100644
--- a/source/libs/monitor/src/monMsg.c
+++ b/source/libs/monitor/src/monMsg.c
@@ -102,6 +102,9 @@ int32_t tEncodeSMonClusterInfo(SEncoder *encoder, const SMonClusterInfo *pInfo)
if (tEncodeCStr(encoder, pInfo->version) < 0) return -1;
if (tEncodeFloat(encoder, pInfo->master_uptime) < 0) return -1;
if (tEncodeI32(encoder, pInfo->monitor_interval) < 0) return -1;
+ if (tEncodeI32(encoder, pInfo->dbs_total) < 0) return -1;
+ if (tEncodeI32(encoder, pInfo->stbs_total) < 0) return -1;
+ if (tEncodeI64(encoder, pInfo->tbs_total) < 0) return -1;
if (tEncodeI32(encoder, pInfo->vgroups_total) < 0) return -1;
if (tEncodeI32(encoder, pInfo->vgroups_alive) < 0) return -1;
if (tEncodeI32(encoder, pInfo->vnodes_total) < 0) return -1;
@@ -130,6 +133,9 @@ int32_t tDecodeSMonClusterInfo(SDecoder *decoder, SMonClusterInfo *pInfo) {
if (tDecodeCStrTo(decoder, pInfo->version) < 0) return -1;
if (tDecodeFloat(decoder, &pInfo->master_uptime) < 0) return -1;
if (tDecodeI32(decoder, &pInfo->monitor_interval) < 0) return -1;
+ if (tDecodeI32(decoder, &pInfo->dbs_total) < 0) return -1;
+ if (tDecodeI32(decoder, &pInfo->stbs_total) < 0) return -1;
+ if (tDecodeI64(decoder, &pInfo->tbs_total) < 0) return -1;
if (tDecodeI32(decoder, &pInfo->vgroups_total) < 0) return -1;
if (tDecodeI32(decoder, &pInfo->vgroups_alive) < 0) return -1;
if (tDecodeI32(decoder, &pInfo->vnodes_total) < 0) return -1;
@@ -203,6 +209,32 @@ int32_t tDecodeSMonVgroupInfo(SDecoder *decoder, SMonVgroupInfo *pInfo) {
return 0;
}
+int32_t tEncodeSMonStbInfo(SEncoder *encoder, const SMonStbInfo *pInfo) {
+ if (tEncodeI32(encoder, taosArrayGetSize(pInfo->stbs)) < 0) return -1;
+ for (int32_t i = 0; i < taosArrayGetSize(pInfo->stbs); ++i) {
+ SMonStbDesc *pDesc = taosArrayGet(pInfo->stbs, i);
+ if (tEncodeCStr(encoder, pDesc->stb_name) < 0) return -1;
+ if (tEncodeCStr(encoder, pDesc->database_name) < 0) return -1;
+ }
+ return 0;
+}
+
+int32_t tDecodeSMonStbInfo(SDecoder *decoder, SMonStbInfo *pInfo) {
+ int32_t arraySize = 0;
+ if (tDecodeI32(decoder, &arraySize) < 0) return -1;
+
+ pInfo->stbs = taosArrayInit(arraySize, sizeof(SMonStbDesc));
+ if (pInfo->stbs == NULL) return -1;
+
+ for (int32_t i = 0; i < arraySize; ++i) {
+ SMonStbDesc desc = {0};
+ if (tDecodeCStrTo(decoder, desc.stb_name) < 0) return -1;
+ if (tDecodeCStrTo(decoder, desc.database_name) < 0) return -1;
+ taosArrayPush(pInfo->stbs, &desc);
+ }
+ return 0;
+}
+
int32_t tEncodeSMonGrantInfo(SEncoder *encoder, const SMonGrantInfo *pInfo) {
if (tEncodeI32(encoder, pInfo->expire_time) < 0) return -1;
if (tEncodeI64(encoder, pInfo->timeseries_used) < 0) return -1;
@@ -224,6 +256,7 @@ int32_t tSerializeSMonMmInfo(void *buf, int32_t bufLen, SMonMmInfo *pInfo) {
if (tStartEncode(&encoder) < 0) return -1;
if (tEncodeSMonClusterInfo(&encoder, &pInfo->cluster) < 0) return -1;
if (tEncodeSMonVgroupInfo(&encoder, &pInfo->vgroup) < 0) return -1;
+ if (tEncodeSMonStbInfo(&encoder, &pInfo->stb) < 0) return -1;
if (tEncodeSMonGrantInfo(&encoder, &pInfo->grant) < 0) return -1;
if (tEncodeSMonSysInfo(&encoder, &pInfo->sys) < 0) return -1;
if (tEncodeSMonLogs(&encoder, &pInfo->log) < 0) return -1;
@@ -241,6 +274,7 @@ int32_t tDeserializeSMonMmInfo(void *buf, int32_t bufLen, SMonMmInfo *pInfo) {
if (tStartDecode(&decoder) < 0) return -1;
if (tDecodeSMonClusterInfo(&decoder, &pInfo->cluster) < 0) return -1;
if (tDecodeSMonVgroupInfo(&decoder, &pInfo->vgroup) < 0) return -1;
+ if (tDecodeSMonStbInfo(&decoder, &pInfo->stb) < 0) return -1;
if (tDecodeSMonGrantInfo(&decoder, &pInfo->grant) < 0) return -1;
if (tDecodeSMonSysInfo(&decoder, &pInfo->sys) < 0) return -1;
if (tDecodeSMonLogs(&decoder, &pInfo->log) < 0) return -1;
@@ -255,9 +289,11 @@ void tFreeSMonMmInfo(SMonMmInfo *pInfo) {
taosArrayDestroy(pInfo->cluster.mnodes);
taosArrayDestroy(pInfo->cluster.dnodes);
taosArrayDestroy(pInfo->vgroup.vgroups);
+ taosArrayDestroy(pInfo->stb.stbs);
pInfo->cluster.mnodes = NULL;
pInfo->cluster.dnodes = NULL;
pInfo->vgroup.vgroups = NULL;
+ pInfo->stb.stbs = NULL;
pInfo->log.logs = NULL;
}
diff --git a/source/libs/monitor/test/monTest.cpp b/source/libs/monitor/test/monTest.cpp
index 726b2aafe4c455db79fa3bdc8be744b66c1fa2ac..3f7b1b51da71b0b2e036427209b60c4eae2eee26 100644
--- a/source/libs/monitor/test/monTest.cpp
+++ b/source/libs/monitor/test/monTest.cpp
@@ -75,18 +75,18 @@ void MonitorTest::GetSysInfo(SMonSysInfo *pInfo) {
pInfo->cpu_engine = 2.1;
pInfo->cpu_system = 2.1;
pInfo->cpu_cores = 2;
- pInfo->mem_engine = 3.1;
- pInfo->mem_system = 3.2;
- pInfo->mem_total = 3.3;
- pInfo->disk_engine = 4.1;
- pInfo->disk_used = 4.2;
- pInfo->disk_total = 4.3;
- pInfo->net_in = 5.1;
- pInfo->net_out = 5.2;
- pInfo->io_read = 6.1;
- pInfo->io_write = 6.2;
- pInfo->io_read_disk = 7.1;
- pInfo->io_write_disk = 7.2;
+ pInfo->mem_engine = 3;
+ pInfo->mem_system = 3;
+ pInfo->mem_total = 3;
+ pInfo->disk_engine = 4;
+ pInfo->disk_used = 4;
+ pInfo->disk_total = 4;
+ pInfo->net_in = 5;
+ pInfo->net_out = 5;
+ pInfo->io_read = 6;
+ pInfo->io_write = 6;
+ pInfo->io_read_disk = 7;
+ pInfo->io_write_disk = 7;
}
void MonitorTest::GetClusterInfo(SMonClusterInfo *pInfo) {
diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c
index 5eaca60ea5d8c9f9439a7b9139789622ecad7dbf..e7109b5a87aedd9024eb99376befe20e241e9c13 100644
--- a/source/libs/nodes/src/nodesCloneFuncs.c
+++ b/source/libs/nodes/src/nodesCloneFuncs.c
@@ -18,6 +18,7 @@
#include "querynodes.h"
#include "taos.h"
#include "taoserror.h"
+#include "tdatablock.h"
#define COPY_SCALAR_FIELD(fldname) \
do { \
@@ -41,8 +42,7 @@
} \
(pDst)->fldname = strdup((pSrc)->fldname); \
if (NULL == (pDst)->fldname) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
+ return TSDB_CODE_OUT_OF_MEMORY; \
} \
} while (0)
@@ -53,8 +53,7 @@
} \
(pDst)->fldname = nodesCloneNode((pSrc)->fldname); \
if (NULL == (pDst)->fldname) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
+ return TSDB_CODE_OUT_OF_MEMORY; \
} \
} while (0)
@@ -65,8 +64,7 @@
} \
(pDst)->fldname = (nodePtrType)nodesCloneNode((SNode*)(pSrc)->fldname); \
if (NULL == (pDst)->fldname) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
+ return TSDB_CODE_OUT_OF_MEMORY; \
} \
} while (0)
@@ -77,8 +75,7 @@
} \
(pDst)->fldname = nodesCloneList((pSrc)->fldname); \
if (NULL == (pDst)->fldname) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
+ return TSDB_CODE_OUT_OF_MEMORY; \
} \
} while (0)
@@ -89,27 +86,26 @@
} \
(pDst)->fldname = cloneFunc((pSrc)->fldname); \
if (NULL == (pDst)->fldname) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
+ return TSDB_CODE_OUT_OF_MEMORY; \
} \
} while (0)
-#define COPY_BASE_OBJECT_FIELD(fldname, copyFunc) \
- do { \
- if (NULL == copyFunc(&((pSrc)->fldname), &((pDst)->fldname))) { \
- nodesDestroyNode((SNode*)pDst); \
- return NULL; \
- } \
+#define COPY_BASE_OBJECT_FIELD(fldname, copyFunc) \
+ do { \
+ if (TSDB_CODE_SUCCESS != copyFunc(&((pSrc)->fldname), &((pDst)->fldname))) { \
+ return TSDB_CODE_OUT_OF_MEMORY; \
+ } \
} while (0)
-static SNode* exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
+static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
COPY_OBJECT_FIELD(resType, sizeof(SDataType));
COPY_CHAR_ARRAY_FIELD(aliasName);
COPY_CHAR_ARRAY_FIELD(userAlias);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(orderAlias);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
+static int32_t columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_SCALAR_FIELD(tableId);
COPY_SCALAR_FIELD(tableType);
@@ -122,20 +118,21 @@ static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
COPY_CHAR_ARRAY_FIELD(colName);
COPY_SCALAR_FIELD(dataBlockId);
COPY_SCALAR_FIELD(slotId);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
+static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_CHAR_POINT_FIELD(literal);
COPY_SCALAR_FIELD(isDuration);
COPY_SCALAR_FIELD(translate);
COPY_SCALAR_FIELD(notReserved);
+ COPY_SCALAR_FIELD(isNull);
COPY_SCALAR_FIELD(placeholderNo);
COPY_SCALAR_FIELD(typeData);
COPY_SCALAR_FIELD(unit);
if (!pSrc->translate) {
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
switch (pSrc->node.resType.type) {
case TSDB_DATA_TYPE_BOOL:
@@ -164,55 +161,62 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
int32_t len = varDataTLen(pSrc->datum.p) + 1;
pDst->datum.p = taosMemoryCalloc(1, len);
if (NULL == pDst->datum.p) {
- nodesDestroyNode((SNode*)pDst);
- return NULL;
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ memcpy(pDst->datum.p, pSrc->datum.p, len);
+ break;
+ }
+ case TSDB_DATA_TYPE_JSON: {
+ int32_t len = getJsonValueLen(pSrc->datum.p);
+ pDst->datum.p = taosMemoryCalloc(1, len);
+ if (NULL == pDst->datum.p) {
+ return TSDB_CODE_OUT_OF_MEMORY;
}
memcpy(pDst->datum.p, pSrc->datum.p, len);
break;
}
- case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
case TSDB_DATA_TYPE_MEDIUMBLOB:
default:
break;
}
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
+static int32_t operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_SCALAR_FIELD(opType);
CLONE_NODE_FIELD(pLeft);
CLONE_NODE_FIELD(pRight);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
+static int32_t logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_SCALAR_FIELD(condType);
CLONE_NODE_LIST_FIELD(pParameterList);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
+static int32_t functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_CHAR_ARRAY_FIELD(functionName);
COPY_SCALAR_FIELD(funcId);
COPY_SCALAR_FIELD(funcType);
CLONE_NODE_LIST_FIELD(pParameterList);
COPY_SCALAR_FIELD(udfBufSize);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* tableNodeCopy(const STableNode* pSrc, STableNode* pDst) {
+static int32_t tableNodeCopy(const STableNode* pSrc, STableNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
COPY_CHAR_ARRAY_FIELD(dbName);
COPY_CHAR_ARRAY_FIELD(tableName);
COPY_CHAR_ARRAY_FIELD(tableAlias);
COPY_SCALAR_FIELD(precision);
COPY_SCALAR_FIELD(singleTable);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
static STableMeta* tableMetaClone(const STableMeta* pSrc) {
@@ -235,101 +239,103 @@ static SVgroupsInfo* vgroupsInfoClone(const SVgroupsInfo* pSrc) {
return pDst;
}
-static SNode* realTableNodeCopy(const SRealTableNode* pSrc, SRealTableNode* pDst) {
+static int32_t realTableNodeCopy(const SRealTableNode* pSrc, SRealTableNode* pDst) {
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
CLONE_OBJECT_FIELD(pMeta, tableMetaClone);
CLONE_OBJECT_FIELD(pVgroupList, vgroupsInfoClone);
COPY_CHAR_ARRAY_FIELD(qualDbName);
COPY_SCALAR_FIELD(ratio);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* tempTableNodeCopy(const STempTableNode* pSrc, STempTableNode* pDst) {
+static int32_t tempTableNodeCopy(const STempTableNode* pSrc, STempTableNode* pDst) {
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
CLONE_NODE_FIELD(pSubquery);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) {
+static int32_t joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) {
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
COPY_SCALAR_FIELD(joinType);
CLONE_NODE_FIELD(pLeft);
CLONE_NODE_FIELD(pRight);
CLONE_NODE_FIELD(pOnCond);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* targetNodeCopy(const STargetNode* pSrc, STargetNode* pDst) {
+static int32_t targetNodeCopy(const STargetNode* pSrc, STargetNode* pDst) {
COPY_SCALAR_FIELD(dataBlockId);
COPY_SCALAR_FIELD(slotId);
CLONE_NODE_FIELD(pExpr);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) {
+static int32_t groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) {
COPY_SCALAR_FIELD(groupingSetType);
CLONE_NODE_LIST_FIELD(pParameterList);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* orderByExprNodeCopy(const SOrderByExprNode* pSrc, SOrderByExprNode* pDst) {
+static int32_t orderByExprNodeCopy(const SOrderByExprNode* pSrc, SOrderByExprNode* pDst) {
CLONE_NODE_FIELD(pExpr);
COPY_SCALAR_FIELD(order);
COPY_SCALAR_FIELD(nullOrder);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
+static int32_t limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
COPY_SCALAR_FIELD(limit);
COPY_SCALAR_FIELD(offset);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* stateWindowNodeCopy(const SStateWindowNode* pSrc, SStateWindowNode* pDst) {
+static int32_t stateWindowNodeCopy(const SStateWindowNode* pSrc, SStateWindowNode* pDst) {
CLONE_NODE_FIELD(pCol);
CLONE_NODE_FIELD(pExpr);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* sessionWindowNodeCopy(const SSessionWindowNode* pSrc, SSessionWindowNode* pDst) {
+static int32_t sessionWindowNodeCopy(const SSessionWindowNode* pSrc, SSessionWindowNode* pDst) {
CLONE_NODE_FIELD_EX(pCol, SColumnNode*);
CLONE_NODE_FIELD_EX(pGap, SValueNode*);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* intervalWindowNodeCopy(const SIntervalWindowNode* pSrc, SIntervalWindowNode* pDst) {
+static int32_t intervalWindowNodeCopy(const SIntervalWindowNode* pSrc, SIntervalWindowNode* pDst) {
CLONE_NODE_FIELD(pCol);
CLONE_NODE_FIELD(pInterval);
CLONE_NODE_FIELD(pOffset);
CLONE_NODE_FIELD(pSliding);
CLONE_NODE_FIELD(pFill);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* nodeListNodeCopy(const SNodeListNode* pSrc, SNodeListNode* pDst) {
+static int32_t nodeListNodeCopy(const SNodeListNode* pSrc, SNodeListNode* pDst) {
COPY_OBJECT_FIELD(dataType, sizeof(SDataType));
CLONE_NODE_LIST_FIELD(pNodeList);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) {
+static int32_t fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) {
COPY_SCALAR_FIELD(mode);
CLONE_NODE_FIELD(pValues);
CLONE_NODE_FIELD(pWStartTs);
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
+static int32_t logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
CLONE_NODE_LIST_FIELD(pTargets);
CLONE_NODE_FIELD(pConditions);
CLONE_NODE_LIST_FIELD(pChildren);
COPY_SCALAR_FIELD(optimizedFlag);
COPY_SCALAR_FIELD(precision);
- return (SNode*)pDst;
+ CLONE_NODE_FIELD(pLimit);
+ CLONE_NODE_FIELD(pSlimit);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) {
+static int32_t logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pScanCols);
CLONE_NODE_LIST_FIELD(pScanPseudoCols);
@@ -351,68 +357,70 @@ static SNode* logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) {
COPY_SCALAR_FIELD(intervalUnit);
COPY_SCALAR_FIELD(slidingUnit);
CLONE_NODE_FIELD(pTagCond);
+ CLONE_NODE_FIELD(pTagIndexCond);
COPY_SCALAR_FIELD(triggerType);
COPY_SCALAR_FIELD(watermark);
- COPY_SCALAR_FIELD(tsColId);
- COPY_SCALAR_FIELD(filesFactor);
- CLONE_NODE_LIST_FIELD(pPartTags);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(igExpired);
+ CLONE_NODE_LIST_FIELD(pGroupTags);
+ COPY_SCALAR_FIELD(groupSort);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) {
+static int32_t logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(joinType);
+ CLONE_NODE_FIELD(pMergeCondition);
CLONE_NODE_FIELD(pOnConditions);
COPY_SCALAR_FIELD(isSingleTableJoin);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicAggCopy(const SAggLogicNode* pSrc, SAggLogicNode* pDst) {
+static int32_t logicAggCopy(const SAggLogicNode* pSrc, SAggLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pGroupKeys);
CLONE_NODE_LIST_FIELD(pAggFuncs);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicProjectCopy(const SProjectLogicNode* pSrc, SProjectLogicNode* pDst) {
+static int32_t logicProjectCopy(const SProjectLogicNode* pSrc, SProjectLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pProjections);
COPY_CHAR_ARRAY_FIELD(stmtName);
- COPY_SCALAR_FIELD(limit);
- COPY_SCALAR_FIELD(offset);
- COPY_SCALAR_FIELD(slimit);
- COPY_SCALAR_FIELD(soffset);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicVnodeModifCopy(const SVnodeModifyLogicNode* pSrc, SVnodeModifyLogicNode* pDst) {
+static int32_t logicVnodeModifCopy(const SVnodeModifyLogicNode* pSrc, SVnodeModifyLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(modifyType);
COPY_SCALAR_FIELD(msgType);
CLONE_NODE_FIELD(pAffectedRows);
COPY_SCALAR_FIELD(tableId);
+ COPY_SCALAR_FIELD(stableId);
COPY_SCALAR_FIELD(tableType);
COPY_CHAR_ARRAY_FIELD(tableFName);
COPY_OBJECT_FIELD(deleteTimeRange, sizeof(STimeWindow));
- return (SNode*)pDst;
+ CLONE_OBJECT_FIELD(pVgroupList, vgroupsInfoClone);
+ CLONE_NODE_LIST_FIELD(pInsertCols);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicExchangeCopy(const SExchangeLogicNode* pSrc, SExchangeLogicNode* pDst) {
+static int32_t logicExchangeCopy(const SExchangeLogicNode* pSrc, SExchangeLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(srcGroupId);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicMergeCopy(const SMergeLogicNode* pSrc, SMergeLogicNode* pDst) {
+static int32_t logicMergeCopy(const SMergeLogicNode* pSrc, SMergeLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pMergeKeys);
CLONE_NODE_LIST_FIELD(pInputs);
COPY_SCALAR_FIELD(numOfChannels);
COPY_SCALAR_FIELD(srcGroupId);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(groupSort);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* pDst) {
+static int32_t logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(winType);
CLONE_NODE_LIST_FIELD(pFuncs);
@@ -427,39 +435,40 @@ static SNode* logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* pD
CLONE_NODE_FIELD(pStateExpr);
COPY_SCALAR_FIELD(triggerType);
COPY_SCALAR_FIELD(watermark);
- COPY_SCALAR_FIELD(filesFactor);
+ COPY_SCALAR_FIELD(igExpired);
COPY_SCALAR_FIELD(windowAlgo);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicFillCopy(const SFillLogicNode* pSrc, SFillLogicNode* pDst) {
+static int32_t logicFillCopy(const SFillLogicNode* pSrc, SFillLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(mode);
CLONE_NODE_FIELD(pWStartTs);
CLONE_NODE_FIELD(pValues);
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicSortCopy(const SSortLogicNode* pSrc, SSortLogicNode* pDst) {
+static int32_t logicSortCopy(const SSortLogicNode* pSrc, SSortLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pSortKeys);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(groupSort);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicPartitionCopy(const SPartitionLogicNode* pSrc, SPartitionLogicNode* pDst) {
+static int32_t logicPartitionCopy(const SPartitionLogicNode* pSrc, SPartitionLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pPartitionKeys);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicIndefRowsFuncCopy(const SIndefRowsFuncLogicNode* pSrc, SIndefRowsFuncLogicNode* pDst) {
+static int32_t logicIndefRowsFuncCopy(const SIndefRowsFuncLogicNode* pSrc, SIndefRowsFuncLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pFuncs);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicInterpFuncCopy(const SInterpFuncLogicNode* pSrc, SInterpFuncLogicNode* pDst) {
+static int32_t logicInterpFuncCopy(const SInterpFuncLogicNode* pSrc, SInterpFuncLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
CLONE_NODE_LIST_FIELD(pFuncs);
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
@@ -467,26 +476,26 @@ static SNode* logicInterpFuncCopy(const SInterpFuncLogicNode* pSrc, SInterpFuncL
COPY_SCALAR_FIELD(fillMode);
CLONE_NODE_FIELD(pFillValues);
CLONE_NODE_FIELD(pTimeSeries);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* logicSubplanCopy(const SLogicSubplan* pSrc, SLogicSubplan* pDst) {
+static int32_t logicSubplanCopy(const SLogicSubplan* pSrc, SLogicSubplan* pDst) {
COPY_OBJECT_FIELD(id, sizeof(SSubplanId));
CLONE_NODE_FIELD_EX(pNode, SLogicNode*);
COPY_SCALAR_FIELD(subplanType);
COPY_SCALAR_FIELD(level);
COPY_SCALAR_FIELD(splitFlag);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiNodeCopy(const SPhysiNode* pSrc, SPhysiNode* pDst) {
+static int32_t physiNodeCopy(const SPhysiNode* pSrc, SPhysiNode* pDst) {
CLONE_NODE_FIELD_EX(pOutputDataBlockDesc, SDataBlockDescNode*);
CLONE_NODE_FIELD(pConditions);
CLONE_NODE_LIST_FIELD(pChildren);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiScanCopy(const SScanPhysiNode* pSrc, SScanPhysiNode* pDst) {
+static int32_t physiScanCopy(const SScanPhysiNode* pSrc, SScanPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, physiNodeCopy);
CLONE_NODE_LIST_FIELD(pScanCols);
CLONE_NODE_LIST_FIELD(pScanPseudoCols);
@@ -494,21 +503,21 @@ static SNode* physiScanCopy(const SScanPhysiNode* pSrc, SScanPhysiNode* pDst) {
COPY_SCALAR_FIELD(suid);
COPY_SCALAR_FIELD(tableType);
COPY_OBJECT_FIELD(tableName, sizeof(SName));
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiTagScanCopy(const STagScanPhysiNode* pSrc, STagScanPhysiNode* pDst) {
+static int32_t physiTagScanCopy(const STagScanPhysiNode* pSrc, STagScanPhysiNode* pDst) {
return physiScanCopy(pSrc, pDst);
}
-static SNode* physiTableScanCopy(const STableScanPhysiNode* pSrc, STableScanPhysiNode* pDst) {
+static int32_t physiTableScanCopy(const STableScanPhysiNode* pSrc, STableScanPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(scan, physiScanCopy);
COPY_OBJECT_FIELD(scanSeq[0], sizeof(uint8_t) * 2);
COPY_OBJECT_FIELD(scanRange, sizeof(STimeWindow));
COPY_SCALAR_FIELD(ratio);
COPY_SCALAR_FIELD(dataRequired);
CLONE_NODE_LIST_FIELD(pDynamicScanFuncs);
- CLONE_NODE_LIST_FIELD(pPartitionTags);
+ CLONE_NODE_LIST_FIELD(pGroupTags);
COPY_SCALAR_FIELD(interval);
COPY_SCALAR_FIELD(offset);
COPY_SCALAR_FIELD(sliding);
@@ -516,20 +525,19 @@ static SNode* physiTableScanCopy(const STableScanPhysiNode* pSrc, STableScanPhys
COPY_SCALAR_FIELD(slidingUnit);
COPY_SCALAR_FIELD(triggerType);
COPY_SCALAR_FIELD(watermark);
- COPY_SCALAR_FIELD(tsColId);
- COPY_SCALAR_FIELD(filesFactor);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(igExpired);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiSysTableScanCopy(const SSystemTableScanPhysiNode* pSrc, SSystemTableScanPhysiNode* pDst) {
+static int32_t physiSysTableScanCopy(const SSystemTableScanPhysiNode* pSrc, SSystemTableScanPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(scan, physiScanCopy);
COPY_OBJECT_FIELD(mgmtEpSet, sizeof(SEpSet));
COPY_SCALAR_FIELD(showRewrite);
COPY_SCALAR_FIELD(accountId);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiWindowCopy(const SWinodwPhysiNode* pSrc, SWinodwPhysiNode* pDst) {
+static int32_t physiWindowCopy(const SWinodwPhysiNode* pSrc, SWinodwPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, physiNodeCopy);
CLONE_NODE_LIST_FIELD(pExprs);
CLONE_NODE_LIST_FIELD(pFuncs);
@@ -537,52 +545,62 @@ static SNode* physiWindowCopy(const SWinodwPhysiNode* pSrc, SWinodwPhysiNode* pD
CLONE_NODE_FIELD(pTsEnd);
COPY_SCALAR_FIELD(triggerType);
COPY_SCALAR_FIELD(watermark);
- COPY_SCALAR_FIELD(filesFactor);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(igExpired);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiIntervalCopy(const SIntervalPhysiNode* pSrc, SIntervalPhysiNode* pDst) {
+static int32_t physiIntervalCopy(const SIntervalPhysiNode* pSrc, SIntervalPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(window, physiWindowCopy);
COPY_SCALAR_FIELD(interval);
COPY_SCALAR_FIELD(offset);
COPY_SCALAR_FIELD(sliding);
COPY_SCALAR_FIELD(intervalUnit);
COPY_SCALAR_FIELD(slidingUnit);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* physiSessionCopy(const SSessionWinodwPhysiNode* pSrc, SSessionWinodwPhysiNode* pDst) {
+static int32_t physiSessionCopy(const SSessionWinodwPhysiNode* pSrc, SSessionWinodwPhysiNode* pDst) {
COPY_BASE_OBJECT_FIELD(window, physiWindowCopy);
COPY_SCALAR_FIELD(gap);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) {
+static int32_t physiPartitionCopy(const SPartitionPhysiNode* pSrc, SPartitionPhysiNode* pDst) {
+ COPY_BASE_OBJECT_FIELD(node, physiNodeCopy);
+ CLONE_NODE_LIST_FIELD(pExprs);
+ CLONE_NODE_LIST_FIELD(pPartitionKeys);
+ CLONE_NODE_LIST_FIELD(pTargets);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) {
COPY_SCALAR_FIELD(dataBlockId);
CLONE_NODE_LIST_FIELD(pSlots);
COPY_SCALAR_FIELD(totalRowSize);
COPY_SCALAR_FIELD(outputRowSize);
COPY_SCALAR_FIELD(precision);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* slotDescCopy(const SSlotDescNode* pSrc, SSlotDescNode* pDst) {
+static int32_t slotDescCopy(const SSlotDescNode* pSrc, SSlotDescNode* pDst) {
COPY_SCALAR_FIELD(slotId);
COPY_OBJECT_FIELD(dataType, sizeof(SDataType));
COPY_SCALAR_FIELD(reserve);
COPY_SCALAR_FIELD(output);
COPY_SCALAR_FIELD(tag);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
-static SNode* downstreamSourceCopy(const SDownstreamSourceNode* pSrc, SDownstreamSourceNode* pDst) {
+static int32_t downstreamSourceCopy(const SDownstreamSourceNode* pSrc, SDownstreamSourceNode* pDst) {
COPY_OBJECT_FIELD(addr, sizeof(SQueryNodeAddr));
COPY_SCALAR_FIELD(taskId);
COPY_SCALAR_FIELD(schedId);
- return (SNode*)pDst;
+ COPY_SCALAR_FIELD(execId);
+ COPY_SCALAR_FIELD(fetchMsgType);
+ return TSDB_CODE_SUCCESS;
}
-static SNode* selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
+static int32_t selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
COPY_SCALAR_FIELD(isDistinct);
CLONE_NODE_LIST_FIELD(pProjectionList);
CLONE_NODE_FIELD(pFromTable);
@@ -597,117 +615,169 @@ static SNode* selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
COPY_CHAR_ARRAY_FIELD(stmtName);
COPY_SCALAR_FIELD(precision);
COPY_SCALAR_FIELD(isEmptyResult);
- COPY_SCALAR_FIELD(isTimeOrderQuery);
+ COPY_SCALAR_FIELD(isTimeLineResult);
COPY_SCALAR_FIELD(hasAggFuncs);
COPY_SCALAR_FIELD(hasRepeatScanFuncs);
- return (SNode*)pDst;
+ return TSDB_CODE_SUCCESS;
}
SNode* nodesCloneNode(const SNode* pNode) {
if (NULL == pNode) {
return NULL;
}
+
SNode* pDst = nodesMakeNode(nodeType(pNode));
if (NULL == pDst) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
+
+ int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN:
- return columnNodeCopy((const SColumnNode*)pNode, (SColumnNode*)pDst);
+ code = columnNodeCopy((const SColumnNode*)pNode, (SColumnNode*)pDst);
+ break;
case QUERY_NODE_VALUE:
- return valueNodeCopy((const SValueNode*)pNode, (SValueNode*)pDst);
+ code = valueNodeCopy((const SValueNode*)pNode, (SValueNode*)pDst);
+ break;
case QUERY_NODE_OPERATOR:
- return operatorNodeCopy((const SOperatorNode*)pNode, (SOperatorNode*)pDst);
+ code = operatorNodeCopy((const SOperatorNode*)pNode, (SOperatorNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_CONDITION:
- return logicConditionNodeCopy((const SLogicConditionNode*)pNode, (SLogicConditionNode*)pDst);
+ code = logicConditionNodeCopy((const SLogicConditionNode*)pNode, (SLogicConditionNode*)pDst);
+ break;
case QUERY_NODE_FUNCTION:
- return functionNodeCopy((const SFunctionNode*)pNode, (SFunctionNode*)pDst);
+ code = functionNodeCopy((const SFunctionNode*)pNode, (SFunctionNode*)pDst);
+ break;
case QUERY_NODE_REAL_TABLE:
- return realTableNodeCopy((const SRealTableNode*)pNode, (SRealTableNode*)pDst);
+ code = realTableNodeCopy((const SRealTableNode*)pNode, (SRealTableNode*)pDst);
+ break;
case QUERY_NODE_TEMP_TABLE:
- return tempTableNodeCopy((const STempTableNode*)pNode, (STempTableNode*)pDst);
+ code = tempTableNodeCopy((const STempTableNode*)pNode, (STempTableNode*)pDst);
+ break;
case QUERY_NODE_JOIN_TABLE:
- return joinTableNodeCopy((const SJoinTableNode*)pNode, (SJoinTableNode*)pDst);
+ code = joinTableNodeCopy((const SJoinTableNode*)pNode, (SJoinTableNode*)pDst);
+ break;
case QUERY_NODE_GROUPING_SET:
- return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
+ code = groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
+ break;
case QUERY_NODE_ORDER_BY_EXPR:
- return orderByExprNodeCopy((const SOrderByExprNode*)pNode, (SOrderByExprNode*)pDst);
+ code = orderByExprNodeCopy((const SOrderByExprNode*)pNode, (SOrderByExprNode*)pDst);
+ break;
case QUERY_NODE_LIMIT:
- return limitNodeCopy((const SLimitNode*)pNode, (SLimitNode*)pDst);
+ code = limitNodeCopy((const SLimitNode*)pNode, (SLimitNode*)pDst);
+ break;
case QUERY_NODE_STATE_WINDOW:
- return stateWindowNodeCopy((const SStateWindowNode*)pNode, (SStateWindowNode*)pDst);
+ code = stateWindowNodeCopy((const SStateWindowNode*)pNode, (SStateWindowNode*)pDst);
+ break;
case QUERY_NODE_SESSION_WINDOW:
- return sessionWindowNodeCopy((const SSessionWindowNode*)pNode, (SSessionWindowNode*)pDst);
+ code = sessionWindowNodeCopy((const SSessionWindowNode*)pNode, (SSessionWindowNode*)pDst);
+ break;
case QUERY_NODE_INTERVAL_WINDOW:
- return intervalWindowNodeCopy((const SIntervalWindowNode*)pNode, (SIntervalWindowNode*)pDst);
+ code = intervalWindowNodeCopy((const SIntervalWindowNode*)pNode, (SIntervalWindowNode*)pDst);
+ break;
case QUERY_NODE_NODE_LIST:
- return nodeListNodeCopy((const SNodeListNode*)pNode, (SNodeListNode*)pDst);
+ code = nodeListNodeCopy((const SNodeListNode*)pNode, (SNodeListNode*)pDst);
+ break;
case QUERY_NODE_FILL:
- return fillNodeCopy((const SFillNode*)pNode, (SFillNode*)pDst);
+ code = fillNodeCopy((const SFillNode*)pNode, (SFillNode*)pDst);
+ break;
case QUERY_NODE_TARGET:
- return targetNodeCopy((const STargetNode*)pNode, (STargetNode*)pDst);
+ code = targetNodeCopy((const STargetNode*)pNode, (STargetNode*)pDst);
+ break;
case QUERY_NODE_DATABLOCK_DESC:
- return dataBlockDescCopy((const SDataBlockDescNode*)pNode, (SDataBlockDescNode*)pDst);
+ code = dataBlockDescCopy((const SDataBlockDescNode*)pNode, (SDataBlockDescNode*)pDst);
+ break;
case QUERY_NODE_SLOT_DESC:
- return slotDescCopy((const SSlotDescNode*)pNode, (SSlotDescNode*)pDst);
+ code = slotDescCopy((const SSlotDescNode*)pNode, (SSlotDescNode*)pDst);
+ break;
case QUERY_NODE_DOWNSTREAM_SOURCE:
- return downstreamSourceCopy((const SDownstreamSourceNode*)pNode, (SDownstreamSourceNode*)pDst);
+ code = downstreamSourceCopy((const SDownstreamSourceNode*)pNode, (SDownstreamSourceNode*)pDst);
+ break;
case QUERY_NODE_LEFT_VALUE:
- return pDst;
+ code = TSDB_CODE_SUCCESS;
+ break;
case QUERY_NODE_SELECT_STMT:
- return selectStmtCopy((const SSelectStmt*)pNode, (SSelectStmt*)pDst);
+ code = selectStmtCopy((const SSelectStmt*)pNode, (SSelectStmt*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_SCAN:
- return logicScanCopy((const SScanLogicNode*)pNode, (SScanLogicNode*)pDst);
+ code = logicScanCopy((const SScanLogicNode*)pNode, (SScanLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_JOIN:
- return logicJoinCopy((const SJoinLogicNode*)pNode, (SJoinLogicNode*)pDst);
+ code = logicJoinCopy((const SJoinLogicNode*)pNode, (SJoinLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_AGG:
- return logicAggCopy((const SAggLogicNode*)pNode, (SAggLogicNode*)pDst);
+ code = logicAggCopy((const SAggLogicNode*)pNode, (SAggLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_PROJECT:
- return logicProjectCopy((const SProjectLogicNode*)pNode, (SProjectLogicNode*)pDst);
+ code = logicProjectCopy((const SProjectLogicNode*)pNode, (SProjectLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY:
- return logicVnodeModifCopy((const SVnodeModifyLogicNode*)pNode, (SVnodeModifyLogicNode*)pDst);
+ code = logicVnodeModifCopy((const SVnodeModifyLogicNode*)pNode, (SVnodeModifyLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
- return logicExchangeCopy((const SExchangeLogicNode*)pNode, (SExchangeLogicNode*)pDst);
+ code = logicExchangeCopy((const SExchangeLogicNode*)pNode, (SExchangeLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_MERGE:
- return logicMergeCopy((const SMergeLogicNode*)pNode, (SMergeLogicNode*)pDst);
+ code = logicMergeCopy((const SMergeLogicNode*)pNode, (SMergeLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_WINDOW:
- return logicWindowCopy((const SWindowLogicNode*)pNode, (SWindowLogicNode*)pDst);
+ code = logicWindowCopy((const SWindowLogicNode*)pNode, (SWindowLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_FILL:
- return logicFillCopy((const SFillLogicNode*)pNode, (SFillLogicNode*)pDst);
+ code = logicFillCopy((const SFillLogicNode*)pNode, (SFillLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_SORT:
- return logicSortCopy((const SSortLogicNode*)pNode, (SSortLogicNode*)pDst);
+ code = logicSortCopy((const SSortLogicNode*)pNode, (SSortLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_PARTITION:
- return logicPartitionCopy((const SPartitionLogicNode*)pNode, (SPartitionLogicNode*)pDst);
+ code = logicPartitionCopy((const SPartitionLogicNode*)pNode, (SPartitionLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC:
- return logicIndefRowsFuncCopy((const SIndefRowsFuncLogicNode*)pNode, (SIndefRowsFuncLogicNode*)pDst);
+ code = logicIndefRowsFuncCopy((const SIndefRowsFuncLogicNode*)pNode, (SIndefRowsFuncLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
- return logicInterpFuncCopy((const SInterpFuncLogicNode*)pNode, (SInterpFuncLogicNode*)pDst);
+ code = logicInterpFuncCopy((const SInterpFuncLogicNode*)pNode, (SInterpFuncLogicNode*)pDst);
+ break;
case QUERY_NODE_LOGIC_SUBPLAN:
- return logicSubplanCopy((const SLogicSubplan*)pNode, (SLogicSubplan*)pDst);
+ code = logicSubplanCopy((const SLogicSubplan*)pNode, (SLogicSubplan*)pDst);
+ break;
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
- return physiTagScanCopy((const STagScanPhysiNode*)pNode, (STagScanPhysiNode*)pDst);
+ code = physiTagScanCopy((const STagScanPhysiNode*)pNode, (STagScanPhysiNode*)pDst);
+ break;
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
- return physiTableScanCopy((const STableScanPhysiNode*)pNode, (STableScanPhysiNode*)pDst);
+ code = physiTableScanCopy((const STableScanPhysiNode*)pNode, (STableScanPhysiNode*)pDst);
+ break;
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
- return physiSysTableScanCopy((const SSystemTableScanPhysiNode*)pNode, (SSystemTableScanPhysiNode*)pDst);
+ code = physiSysTableScanCopy((const SSystemTableScanPhysiNode*)pNode, (SSystemTableScanPhysiNode*)pDst);
+ break;
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
- return physiIntervalCopy((const SIntervalPhysiNode*)pNode, (SIntervalPhysiNode*)pDst);
+ code = physiIntervalCopy((const SIntervalPhysiNode*)pNode, (SIntervalPhysiNode*)pDst);
+ break;
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION:
- return physiSessionCopy((const SSessionWinodwPhysiNode*)pNode, (SSessionWinodwPhysiNode*)pDst);
+ code = physiSessionCopy((const SSessionWinodwPhysiNode*)pNode, (SSessionWinodwPhysiNode*)pDst);
+ break;
+ case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
+ code = physiPartitionCopy((const SPartitionPhysiNode*)pNode, (SPartitionPhysiNode*)pDst);
+ break;
default:
break;
}
- nodesDestroyNode(pDst);
- nodesError("nodesCloneNode unknown node = %s", nodesNodeName(nodeType(pNode)));
- return NULL;
+
+ if (TSDB_CODE_SUCCESS != code) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ nodesDestroyNode(pDst);
+ nodesError("nodesCloneNode failed node = %s", nodesNodeName(nodeType(pNode)));
+ return NULL;
+ }
+ return pDst;
}
SNodeList* nodesCloneList(const SNodeList* pList) {
@@ -715,19 +785,15 @@ SNodeList* nodesCloneList(const SNodeList* pList) {
return NULL;
}
- SNodeList* pDst = nodesMakeList();
- if (NULL == pDst) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return NULL;
- }
- SNode* pNode;
+ SNodeList* pDst = NULL;
+ SNode* pNode;
FOREACH(pNode, pList) {
- SNode* pNewNode = nodesCloneNode(pNode);
- if (NULL == pNewNode) {
+ int32_t code = nodesListMakeStrictAppend(&pDst, nodesCloneNode(pNode));
+ if (TSDB_CODE_SUCCESS != code) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
nodesDestroyList(pDst);
return NULL;
}
- nodesListAppend(pDst, pNewNode);
}
return pDst;
}
diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c
index bde5159087634a2ad06b6b4a1e38ff06f7a32948..a50df01d44794b1958cb6e95949e13733500176b 100644
--- a/source/libs/nodes/src/nodesCodeFuncs.c
+++ b/source/libs/nodes/src/nodesCodeFuncs.c
@@ -19,6 +19,7 @@
#include "query.h"
#include "querynodes.h"
#include "taoserror.h"
+#include "tdatablock.h"
#include "tjson.h"
static int32_t nodeToJson(const void* pObj, SJson* pJson);
@@ -178,6 +179,8 @@ const char* nodesNodeName(ENodeType type) {
return "ShowVnodeStmt";
case QUERY_NODE_DELETE_STMT:
return "DeleteStmt";
+ case QUERY_NODE_INSERT_STMT:
+ return "InsertStmt";
case QUERY_NODE_LOGIC_PLAN_SCAN:
return "LogicScan";
case QUERY_NODE_LOGIC_PLAN_JOIN:
@@ -220,6 +223,10 @@ const char* nodesNodeName(ENodeType type) {
return "PhysiSystemTableScan";
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
return "PhysiBlockDistScan";
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
+ return "PhysiLastRowScan";
+ case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
+ return "PhysiTableMergeScan";
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
return "PhysiProject";
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
@@ -232,10 +239,12 @@ const char* nodesNodeName(ENodeType type) {
return "PhysiMerge";
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return "PhysiSort";
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT:
+ return "PhysiGroupSort";
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
return "PhysiHashInterval";
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
- return "PhysiMergeInterval";
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
+ return "PhysiMergeAlignedInterval";
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
return "PhysiStreamInterval";
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
@@ -266,6 +275,8 @@ const char* nodesNodeName(ENodeType type) {
return "PhysiDispatch";
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
return "PhysiInsert";
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
+ return "PhysiQueryInsert";
case QUERY_NODE_PHYSICAL_PLAN_DELETE:
return "PhysiDelete";
case QUERY_NODE_PHYSICAL_SUBPLAN:
@@ -489,6 +500,8 @@ static int32_t jsonToTableMeta(const SJson* pJson, void* pObj) {
static const char* jkLogicPlanTargets = "Targets";
static const char* jkLogicPlanConditions = "Conditions";
static const char* jkLogicPlanChildren = "Children";
+static const char* jkLogicPlanLimit = "Limit";
+static const char* jkLogicPlanSlimit = "SLimit";
static int32_t logicPlanNodeToJson(const void* pObj, SJson* pJson) {
const SLogicNode* pNode = (const SLogicNode*)pObj;
@@ -500,6 +513,12 @@ static int32_t logicPlanNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkLogicPlanChildren, pNode->pChildren);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkLogicPlanLimit, nodeToJson, pNode->pLimit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkLogicPlanSlimit, nodeToJson, pNode->pSlimit);
+ }
return code;
}
@@ -514,16 +533,51 @@ static int32_t jsonToLogicPlanNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkLogicPlanChildren, &pNode->pChildren);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkLogicPlanLimit, &pNode->pLimit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkLogicPlanSlimit, &pNode->pSlimit);
+ }
return code;
}
static const char* jkScanLogicPlanScanCols = "ScanCols";
static const char* jkScanLogicPlanScanPseudoCols = "ScanPseudoCols";
-static const char* jkScanLogicPlanTableId = "TableId";
static const char* jkScanLogicPlanTableType = "TableType";
+static const char* jkScanLogicPlanTableId = "TableId";
+static const char* jkScanLogicPlanStableId = "StableId";
+static const char* jkScanLogicPlanScanCount = "ScanCount";
+static const char* jkScanLogicPlanReverseScanCount = "ReverseScanCount";
static const char* jkScanLogicPlanTagCond = "TagCond";
-static const char* jkScanLogicPlanPartTags = "PartTags";
+static const char* jkScanLogicPlanGroupTags = "GroupTags";
+
+// typedef struct SScanLogicNode {
+// uint64_t stableId;
+// SVgroupsInfo* pVgroupList;
+// EScanType scanType;
+// uint8_t scanSeq[2]; // first is scan count, and second is reverse scan count
+// STimeWindow scanRange;
+// SName tableName;
+// bool showRewrite;
+// double ratio;
+// SNodeList* pDynamicScanFuncs;
+// int32_t dataRequired;
+// int64_t interval;
+// int64_t offset;
+// int64_t sliding;
+// int8_t intervalUnit;
+// int8_t slidingUnit;
+// SNode* pTagCond;
+// SNode* pTagIndexCond;
+// int8_t triggerType;
+// int64_t watermark;
+// int8_t igExpired;
+// SArray* pSmaIndexes;
+// SNodeList* pGroupTags;
+// bool groupSort;
+// } SScanLogicNode;
static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
@@ -535,17 +589,26 @@ static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkScanLogicPlanScanPseudoCols, pNode->pScanPseudoCols);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanTableType, pNode->tableType);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanTableId, pNode->tableId);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanTableType, pNode->tableType);
+ code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanStableId, pNode->stableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanScanCount, pNode->scanSeq[0]);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanReverseScanCount, pNode->scanSeq[1]);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkScanLogicPlanTagCond, nodeToJson, pNode->pTagCond);
}
if (TSDB_CODE_SUCCESS == code) {
- code = nodeListToJson(pJson, jkScanLogicPlanPartTags, pNode->pPartTags);
+ code = nodeListToJson(pJson, jkScanLogicPlanGroupTags, pNode->pGroupTags);
}
return code;
@@ -562,27 +625,32 @@ static int32_t jsonToLogicScanNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkScanLogicPlanScanPseudoCols, &pNode->pScanPseudoCols);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetTinyIntValue(pJson, jkScanLogicPlanTableType, &pNode->tableType);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUBigIntValue(pJson, jkScanLogicPlanTableId, &pNode->tableId);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetTinyIntValue(pJson, jkScanLogicPlanTableType, &pNode->tableType);
+ code = tjsonGetUBigIntValue(pJson, jkScanLogicPlanStableId, &pNode->stableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetUTinyIntValue(pJson, jkScanLogicPlanScanCount, &pNode->scanSeq[0]);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetUTinyIntValue(pJson, jkScanLogicPlanReverseScanCount, &pNode->scanSeq[1]);
}
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkScanLogicPlanTagCond, &pNode->pTagCond);
}
if (TSDB_CODE_SUCCESS == code) {
- code = jsonToNodeList(pJson, jkScanLogicPlanPartTags, &pNode->pPartTags);
+ code = jsonToNodeList(pJson, jkScanLogicPlanGroupTags, &pNode->pGroupTags);
}
return code;
}
static const char* jkProjectLogicPlanProjections = "Projections";
-static const char* jkProjectLogicPlanLimit = "Limit";
-static const char* jkProjectLogicPlanOffset = "Offset";
-static const char* jkProjectLogicPlanSlimit = "SLimit";
-static const char* jkProjectLogicPlanSoffset = "SOffset";
static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
@@ -591,18 +659,6 @@ static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkProjectLogicPlanProjections, pNode->pProjections);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanLimit, pNode->limit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanOffset, pNode->offset);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanSlimit, pNode->slimit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanSoffset, pNode->soffset);
- }
return code;
}
@@ -614,18 +670,6 @@ static int32_t jsonToLogicProjectNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkProjectLogicPlanProjections, &pNode->pProjections);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanLimit, &pNode->limit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanOffset, &pNode->offset);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanSlimit, &pNode->slimit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanSoffset, &pNode->soffset);
- }
return code;
}
@@ -1263,6 +1307,7 @@ static int32_t jsonToLogicPlan(const SJson* pJson, void* pObj) {
static const char* jkJoinLogicPlanJoinType = "JoinType";
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
+static const char* jkJoinLogicPlanMergeCondition = "MergeConditions";
static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) {
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
@@ -1271,6 +1316,9 @@ static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinLogicPlanJoinType, pNode->joinType);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkJoinLogicPlanMergeCondition, nodeToJson, pNode->pMergeCondition);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkJoinLogicPlanOnConditions, nodeToJson, pNode->pOnConditions);
}
@@ -1281,6 +1329,8 @@ static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) {
static const char* jkPhysiPlanOutputDataBlockDesc = "OutputDataBlockDesc";
static const char* jkPhysiPlanConditions = "Conditions";
static const char* jkPhysiPlanChildren = "Children";
+static const char* jkPhysiPlanLimit = "Limit";
+static const char* jkPhysiPlanSlimit = "SLimit";
static int32_t physicPlanNodeToJson(const void* pObj, SJson* pJson) {
const SPhysiNode* pNode = (const SPhysiNode*)pObj;
@@ -1292,6 +1342,12 @@ static int32_t physicPlanNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkPhysiPlanChildren, pNode->pChildren);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkPhysiPlanLimit, nodeToJson, pNode->pLimit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkPhysiPlanSlimit, nodeToJson, pNode->pSlimit);
+ }
return code;
}
@@ -1306,6 +1362,12 @@ static int32_t jsonToPhysicPlanNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkPhysiPlanChildren, &pNode->pChildren);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkPhysiPlanLimit, &pNode->pLimit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkPhysiPlanSlimit, &pNode->pSlimit);
+ }
return code;
}
@@ -1422,13 +1484,13 @@ static const char* jkTableScanPhysiPlanDynamicScanFuncs = "DynamicScanFuncs";
static const char* jkTableScanPhysiPlanInterval = "Interval";
static const char* jkTableScanPhysiPlanOffset = "Offset";
static const char* jkTableScanPhysiPlanSliding = "Sliding";
-static const char* jkTableScanPhysiPlanIntervalUnit = "intervalUnit";
-static const char* jkTableScanPhysiPlanSlidingUnit = "slidingUnit";
-static const char* jkTableScanPhysiPlanTriggerType = "triggerType";
-static const char* jkTableScanPhysiPlanWatermark = "watermark";
-static const char* jkTableScanPhysiPlanTsColId = "tsColId";
-static const char* jkTableScanPhysiPlanFilesFactor = "FilesFactor";
-static const char* jkTableScanPhysiPlanPartitionTags = "PartitionTags";
+static const char* jkTableScanPhysiPlanIntervalUnit = "IntervalUnit";
+static const char* jkTableScanPhysiPlanSlidingUnit = "SlidingUnit";
+static const char* jkTableScanPhysiPlanTriggerType = "TriggerType";
+static const char* jkTableScanPhysiPlanWatermark = "Watermark";
+static const char* jkTableScanPhysiPlanIgnoreExpired = "IgnoreExpired";
+static const char* jkTableScanPhysiPlanGroupTags = "GroupTags";
+static const char* jkTableScanPhysiPlanGroupSort = "GroupSort";
static int32_t physiTableScanNodeToJson(const void* pObj, SJson* pJson) {
const STableScanPhysiNode* pNode = (const STableScanPhysiNode*)pObj;
@@ -1477,13 +1539,13 @@ static int32_t physiTableScanNodeToJson(const void* pObj, SJson* pJson) {
code = tjsonAddIntegerToObject(pJson, jkTableScanPhysiPlanWatermark, pNode->watermark);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkTableScanPhysiPlanTsColId, pNode->tsColId);
+ code = tjsonAddIntegerToObject(pJson, jkTableScanPhysiPlanIgnoreExpired, pNode->igExpired);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddDoubleToObject(pJson, jkTableScanPhysiPlanFilesFactor, pNode->filesFactor);
+ code = nodeListToJson(pJson, jkTableScanPhysiPlanGroupTags, pNode->pGroupTags);
}
if (TSDB_CODE_SUCCESS == code) {
- code = nodeListToJson(pJson, jkTableScanPhysiPlanPartitionTags, pNode->pPartitionTags);
+ code = tjsonAddBoolToObject(pJson, jkTableScanPhysiPlanGroupSort, pNode->groupSort);
}
return code;
@@ -1509,40 +1571,40 @@ static int32_t jsonToPhysiTableScanNode(const SJson* pJson, void* pObj) {
code = tjsonGetDoubleValue(pJson, jkTableScanPhysiPlanRatio, &pNode->ratio);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanDataRequired, pNode->dataRequired, code);
+ code = tjsonGetIntValue(pJson, jkTableScanPhysiPlanDataRequired, &pNode->dataRequired);
}
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkTableScanPhysiPlanDynamicScanFuncs, &pNode->pDynamicScanFuncs);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanInterval, pNode->interval, code);
+ code = tjsonGetBigIntValue(pJson, jkTableScanPhysiPlanInterval, &pNode->interval);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanOffset, pNode->offset, code);
+ code = tjsonGetBigIntValue(pJson, jkTableScanPhysiPlanOffset, &pNode->offset);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanSliding, pNode->sliding, code);
+ code = tjsonGetBigIntValue(pJson, jkTableScanPhysiPlanSliding, &pNode->sliding);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanIntervalUnit, pNode->intervalUnit, code);
+ code = tjsonGetTinyIntValue(pJson, jkTableScanPhysiPlanIntervalUnit, &pNode->intervalUnit);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanSlidingUnit, pNode->slidingUnit, code);
+ code = tjsonGetTinyIntValue(pJson, jkTableScanPhysiPlanSlidingUnit, &pNode->slidingUnit);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanTriggerType, pNode->triggerType, code);
+ code = tjsonGetTinyIntValue(pJson, jkTableScanPhysiPlanTriggerType, &pNode->triggerType);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanWatermark, pNode->watermark, code);
+ code = tjsonGetBigIntValue(pJson, jkTableScanPhysiPlanWatermark, &pNode->watermark);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkTableScanPhysiPlanTsColId, pNode->tsColId, code);
+ code = tjsonGetTinyIntValue(pJson, jkTableScanPhysiPlanIgnoreExpired, &pNode->igExpired);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetDoubleValue(pJson, jkTableScanPhysiPlanFilesFactor, &pNode->filesFactor);
+ code = jsonToNodeList(pJson, jkTableScanPhysiPlanGroupTags, &pNode->pGroupTags);
}
if (TSDB_CODE_SUCCESS == code) {
- code = jsonToNodeList(pJson, jkTableScanPhysiPlanPartitionTags, &pNode->pPartitionTags);
+ code = tjsonGetBoolValue(pJson, jkTableScanPhysiPlanGroupSort, &pNode->groupSort);
}
return code;
@@ -1588,10 +1650,6 @@ static int32_t jsonToPhysiSysTableScanNode(const SJson* pJson, void* pObj) {
}
static const char* jkProjectPhysiPlanProjections = "Projections";
-static const char* jkProjectPhysiPlanLimit = "Limit";
-static const char* jkProjectPhysiPlanOffset = "Offset";
-static const char* jkProjectPhysiPlanSlimit = "SLimit";
-static const char* jkProjectPhysiPlanSoffset = "SOffset";
static int32_t physiProjectNodeToJson(const void* pObj, SJson* pJson) {
const SProjectPhysiNode* pNode = (const SProjectPhysiNode*)pObj;
@@ -1600,18 +1658,6 @@ static int32_t physiProjectNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkProjectPhysiPlanProjections, pNode->pProjections);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanLimit, pNode->limit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanOffset, pNode->offset);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanSlimit, pNode->slimit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanSoffset, pNode->soffset);
- }
return code;
}
@@ -1623,23 +1669,12 @@ static int32_t jsonToPhysiProjectNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkProjectPhysiPlanProjections, &pNode->pProjections);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanLimit, &pNode->limit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanOffset, &pNode->offset);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanSlimit, &pNode->slimit);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanSoffset, &pNode->soffset);
- }
return code;
}
static const char* jkJoinPhysiPlanJoinType = "JoinType";
+static const char* jkJoinPhysiPlanMergeCondition = "MergeCondition";
static const char* jkJoinPhysiPlanOnConditions = "OnConditions";
static const char* jkJoinPhysiPlanTargets = "Targets";
@@ -1650,6 +1685,9 @@ static int32_t physiJoinNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanJoinType, pNode->joinType);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkJoinPhysiPlanMergeCondition, nodeToJson, pNode->pMergeCondition);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkJoinPhysiPlanOnConditions, nodeToJson, pNode->pOnConditions);
}
@@ -1671,6 +1709,9 @@ static int32_t jsonToPhysiJoinNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkJoinPhysiPlanOnConditions, &pNode->pOnConditions);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkJoinPhysiPlanMergeCondition, &pNode->pMergeCondition);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkJoinPhysiPlanTargets, &pNode->pTargets);
}
@@ -1751,6 +1792,7 @@ static const char* jkMergePhysiPlanMergeKeys = "MergeKeys";
static const char* jkMergePhysiPlanTargets = "Targets";
static const char* jkMergePhysiPlanNumOfChannels = "NumOfChannels";
static const char* jkMergePhysiPlanSrcGroupId = "SrcGroupId";
+static const char* jkMergePhysiPlanGroupSort = "GroupSort";
static int32_t physiMergeNodeToJson(const void* pObj, SJson* pJson) {
const SMergePhysiNode* pNode = (const SMergePhysiNode*)pObj;
@@ -1768,6 +1810,9 @@ static int32_t physiMergeNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkMergePhysiPlanSrcGroupId, pNode->srcGroupId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddBoolToObject(pJson, jkMergePhysiPlanGroupSort, pNode->groupSort);
+ }
return code;
}
@@ -1788,6 +1833,9 @@ static int32_t jsonToPhysiMergeNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkMergePhysiPlanSrcGroupId, &pNode->srcGroupId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBoolValue(pJson, jkMergePhysiPlanGroupSort, &pNode->groupSort);
+ }
return code;
}
@@ -1836,7 +1884,7 @@ static const char* jkWindowPhysiPlanTsPk = "TsPk";
static const char* jkWindowPhysiPlanTsEnd = "TsEnd";
static const char* jkWindowPhysiPlanTriggerType = "TriggerType";
static const char* jkWindowPhysiPlanWatermark = "Watermark";
-static const char* jkWindowPhysiPlanFilesFactor = "FilesFactor";
+static const char* jkWindowPhysiPlanIgnoreExpired = "IgnoreExpired";
static int32_t physiWindowNodeToJson(const void* pObj, SJson* pJson) {
const SWinodwPhysiNode* pNode = (const SWinodwPhysiNode*)pObj;
@@ -1861,7 +1909,7 @@ static int32_t physiWindowNodeToJson(const void* pObj, SJson* pJson) {
code = tjsonAddIntegerToObject(pJson, jkWindowPhysiPlanWatermark, pNode->watermark);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddDoubleToObject(pJson, jkWindowPhysiPlanFilesFactor, pNode->filesFactor);
+ code = tjsonAddIntegerToObject(pJson, jkWindowPhysiPlanIgnoreExpired, pNode->igExpired);
}
return code;
@@ -1884,15 +1932,13 @@ static int32_t jsonToPhysiWindowNode(const SJson* pJson, void* pObj) {
code = jsonToNodeObject(pJson, jkWindowPhysiPlanTsEnd, (SNode**)&pNode->pTsEnd);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkWindowPhysiPlanTriggerType, pNode->triggerType, code);
- ;
+ code = tjsonGetTinyIntValue(pJson, jkWindowPhysiPlanTriggerType, &pNode->triggerType);
}
if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkWindowPhysiPlanWatermark, pNode->watermark, code);
- ;
+ code = tjsonGetBigIntValue(pJson, jkWindowPhysiPlanWatermark, &pNode->watermark);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetDoubleValue(pJson, jkWindowPhysiPlanFilesFactor, &pNode->filesFactor);
+ code = tjsonGetTinyIntValue(pJson, jkWindowPhysiPlanIgnoreExpired, &pNode->igExpired);
}
return code;
@@ -2217,6 +2263,72 @@ static int32_t physiDispatchNodeToJson(const void* pObj, SJson* pJson) { return
static int32_t jsonToPhysiDispatchNode(const SJson* pJson, void* pObj) { return jsonToPhysicDataSinkNode(pJson, pObj); }
+static const char* jkQueryInsertPhysiPlanInsertCols = "InsertCols";
+static const char* jkQueryInsertPhysiPlanStableId = "StableId";
+static const char* jkQueryInsertPhysiPlanTableId = "TableId";
+static const char* jkQueryInsertPhysiPlanTableType = "TableType";
+static const char* jkQueryInsertPhysiPlanTableFName = "TableFName";
+static const char* jkQueryInsertPhysiPlanVgId = "VgId";
+static const char* jkQueryInsertPhysiPlanEpSet = "EpSet";
+
+static int32_t physiQueryInsertNodeToJson(const void* pObj, SJson* pJson) {
+ const SQueryInserterNode* pNode = (const SQueryInserterNode*)pObj;
+
+ int32_t code = physicDataSinkNodeToJson(pObj, pJson);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodeListToJson(pJson, jkQueryInsertPhysiPlanInsertCols, pNode->pCols);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkQueryInsertPhysiPlanStableId, pNode->stableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkQueryInsertPhysiPlanTableId, pNode->tableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkQueryInsertPhysiPlanTableType, pNode->tableType);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddStringToObject(pJson, jkQueryInsertPhysiPlanTableFName, pNode->tableFName);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkQueryInsertPhysiPlanVgId, pNode->vgId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkQueryInsertPhysiPlanEpSet, epSetToJson, &pNode->epSet);
+ }
+
+ return code;
+}
+
+static int32_t jsonToPhysiQueryInsertNode(const SJson* pJson, void* pObj) {
+ SQueryInserterNode* pNode = (SQueryInserterNode*)pObj;
+
+ int32_t code = jsonToPhysicDataSinkNode(pJson, pObj);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeList(pJson, jkQueryInsertPhysiPlanInsertCols, &pNode->pCols);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetUBigIntValue(pJson, jkQueryInsertPhysiPlanStableId, &pNode->stableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetUBigIntValue(pJson, jkQueryInsertPhysiPlanTableId, &pNode->tableId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetTinyIntValue(pJson, jkQueryInsertPhysiPlanTableType, &pNode->tableType);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetStringValue(pJson, jkQueryInsertPhysiPlanTableFName, pNode->tableFName);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkQueryInsertPhysiPlanVgId, &pNode->vgId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonToObject(pJson, jkQueryInsertPhysiPlanEpSet, jsonToEpSet, &pNode->epSet);
+ }
+
+ return code;
+}
+
static const char* jkDeletePhysiPlanTableId = "TableId";
static const char* jkDeletePhysiPlanTableType = "TableType";
static const char* jkDeletePhysiPlanTableFName = "TableFName";
@@ -2320,10 +2432,12 @@ static const char* jkSubplanType = "SubplanType";
static const char* jkSubplanMsgType = "MsgType";
static const char* jkSubplanLevel = "Level";
static const char* jkSubplanDbFName = "DbFName";
+static const char* jkSubplanUser = "User";
static const char* jkSubplanNodeAddr = "NodeAddr";
static const char* jkSubplanRootNode = "RootNode";
static const char* jkSubplanDataSink = "DataSink";
static const char* jkSubplanTagCond = "TagCond";
+static const char* jkSubplanTagIndexCond = "TagIndexCond";
static int32_t subplanToJson(const void* pObj, SJson* pJson) {
const SSubplan* pNode = (const SSubplan*)pObj;
@@ -2341,6 +2455,9 @@ static int32_t subplanToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddStringToObject(pJson, jkSubplanDbFName, pNode->dbFName);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddStringToObject(pJson, jkSubplanUser, pNode->user);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkSubplanNodeAddr, queryNodeAddrToJson, &pNode->execNode);
}
@@ -2353,6 +2470,9 @@ static int32_t subplanToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkSubplanTagCond, nodeToJson, pNode->pTagCond);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkSubplanTagIndexCond, nodeToJson, pNode->pTagIndexCond);
+ }
return code;
}
@@ -2363,7 +2483,6 @@ static int32_t jsonToSubplan(const SJson* pJson, void* pObj) {
int32_t code = tjsonToObject(pJson, jkSubplanId, jsonToSubplanId, &pNode->id);
if (TSDB_CODE_SUCCESS == code) {
tjsonGetNumberValue(pJson, jkSubplanType, pNode->subplanType, code);
- ;
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkSubplanMsgType, &pNode->msgType);
@@ -2374,6 +2493,9 @@ static int32_t jsonToSubplan(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetStringValue(pJson, jkSubplanDbFName, pNode->dbFName);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetStringValue(pJson, jkSubplanUser, pNode->user);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToObject(pJson, jkSubplanNodeAddr, jsonToQueryNodeAddr, &pNode->execNode);
}
@@ -2386,6 +2508,9 @@ static int32_t jsonToSubplan(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkSubplanTagCond, (SNode**)&pNode->pTagCond);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkSubplanTagIndexCond, (SNode**)&pNode->pTagIndexCond);
+ }
return code;
}
@@ -2589,6 +2714,7 @@ static const char* jkValueLiteral = "Literal";
static const char* jkValueDuration = "Duration";
static const char* jkValueTranslate = "Translate";
static const char* jkValueNotReserved = "NotReserved";
+static const char* jkValueIsNull = "IsNull";
static const char* jkValueDatum = "Datum";
static int32_t datumToJson(const void* pObj, SJson* pJson) {
@@ -2634,7 +2760,18 @@ static int32_t datumToJson(const void* pObj, SJson* pJson) {
case TSDB_DATA_TYPE_VARBINARY:
code = tjsonAddStringToObject(pJson, jkValueDatum, varDataVal(pNode->datum.p));
break;
- case TSDB_DATA_TYPE_JSON:
+ case TSDB_DATA_TYPE_JSON: {
+ int32_t len = getJsonValueLen(pNode->datum.p);
+ char* buf = taosMemoryCalloc(len * 2 + 1, sizeof(char));
+ code = taosHexEncode(pNode->datum.p, buf, len);
+ if (code != TSDB_CODE_SUCCESS) {
+ taosMemoryFree(buf);
+ return TSDB_CODE_TSC_INVALID_VALUE;
+ }
+ code = tjsonAddStringToObject(pJson, jkValueDatum, buf);
+ taosMemoryFree(buf);
+ break;
+ }
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
@@ -2664,6 +2801,9 @@ static int32_t valueNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddBoolToObject(pJson, jkValueNotReserved, pNode->notReserved);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddBoolToObject(pJson, jkValueIsNull, pNode->isNull);
+ }
if (TSDB_CODE_SUCCESS == code && pNode->translate) {
code = datumToJson(pNode, pJson);
}
@@ -2757,7 +2897,30 @@ static int32_t jsonToDatum(const SJson* pJson, void* pObj) {
}
break;
}
- case TSDB_DATA_TYPE_JSON:
+ case TSDB_DATA_TYPE_JSON: {
+ pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes);
+ if (NULL == pNode->datum.p) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ break;
+ }
+ char* buf = taosMemoryCalloc(1, pNode->node.resType.bytes * 2 + 1);
+ if (NULL == buf) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ break;
+ }
+ code = tjsonGetStringValue(pJson, jkValueDatum, buf);
+ if (code != TSDB_CODE_SUCCESS) {
+ taosMemoryFree(buf);
+ break;
+ }
+ code = taosHexDecode(buf, pNode->datum.p, pNode->node.resType.bytes);
+ if (code != TSDB_CODE_SUCCESS) {
+ taosMemoryFree(buf);
+ break;
+ }
+ taosMemoryFree(buf);
+ break;
+ }
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
@@ -2788,6 +2951,9 @@ static int32_t jsonToValueNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBoolValue(pJson, jkValueNotReserved, &pNode->notReserved);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBoolValue(pJson, jkValueIsNull, &pNode->isNull);
+ }
if (TSDB_CODE_SUCCESS == code && pNode->translate) {
code = jsonToDatum(pJson, pNode);
}
@@ -3156,6 +3322,31 @@ static int32_t jsonToOrderByExprNode(const SJson* pJson, void* pObj) {
return code;
}
+static const char* jkLimitLimit = "Limit";
+static const char* jkLimitOffset = "Offset";
+
+static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
+ const SLimitNode* pNode = (const SLimitNode*)pObj;
+
+ int32_t code = tjsonAddIntegerToObject(pJson, jkLimitLimit, pNode->limit);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkLimitOffset, pNode->offset);
+ }
+
+ return code;
+}
+
+static int32_t jsonToLimitNode(const SJson* pJson, void* pObj) {
+ SLimitNode* pNode = (SLimitNode*)pObj;
+
+ int32_t code = tjsonGetBigIntValue(pJson, jkLimitLimit, &pNode->limit);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkLimitOffset, &pNode->offset);
+ }
+
+ return code;
+}
+
static const char* jkStateWindowCol = "StateWindowCol";
static const char* jkStateWindowExpr = "StateWindowExpr";
@@ -3356,6 +3547,7 @@ static const char* jkSlotDescSlotId = "SlotId";
static const char* jkSlotDescDataType = "DataType";
static const char* jkSlotDescReserve = "Reserve";
static const char* jkSlotDescOutput = "Output";
+static const char* jkSlotDescName = "Name";
static int32_t slotDescNodeToJson(const void* pObj, SJson* pJson) {
const SSlotDescNode* pNode = (const SSlotDescNode*)pObj;
@@ -3370,6 +3562,9 @@ static int32_t slotDescNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddBoolToObject(pJson, jkSlotDescOutput, pNode->output);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddStringToObject(pJson, jkSlotDescName, pNode->name);
+ }
return code;
}
@@ -3387,6 +3582,9 @@ static int32_t jsonToSlotDescNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBoolValue(pJson, jkSlotDescOutput, &pNode->output);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetStringValue(pJson, jkSlotDescName, pNode->name);
+ }
return code;
}
@@ -3394,6 +3592,8 @@ static int32_t jsonToSlotDescNode(const SJson* pJson, void* pObj) {
static const char* jkDownstreamSourceAddr = "Addr";
static const char* jkDownstreamSourceTaskId = "TaskId";
static const char* jkDownstreamSourceSchedId = "SchedId";
+static const char* jkDownstreamSourceExecId = "ExecId";
+static const char* jkDownstreamSourceFetchMsgType = "FetchMsgType";
static int32_t downstreamSourceNodeToJson(const void* pObj, SJson* pJson) {
const SDownstreamSourceNode* pNode = (const SDownstreamSourceNode*)pObj;
@@ -3405,6 +3605,12 @@ static int32_t downstreamSourceNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceSchedId, pNode->schedId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceExecId, pNode->execId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceFetchMsgType, pNode->fetchMsgType);
+ }
return code;
}
@@ -3419,6 +3625,12 @@ static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceSchedId, &pNode->schedId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkDownstreamSourceExecId, &pNode->execId);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkDownstreamSourceFetchMsgType, &pNode->fetchMsgType);
+ }
return code;
}
@@ -3448,7 +3660,7 @@ static int32_t databaseOptionsToJson(const void* pObj, SJson* pJson) {
int32_t code = tjsonAddIntegerToObject(pJson, jkDatabaseOptionsBuffer, pNode->buffer);
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkDatabaseOptionsCachelast, pNode->cachelast);
+ code = tjsonAddIntegerToObject(pJson, jkDatabaseOptionsCachelast, pNode->cacheLast);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkDatabaseOptionsCompressionLevel, pNode->compressionLevel);
@@ -3510,7 +3722,7 @@ static int32_t jsonToDatabaseOptions(const SJson* pJson, void* pObj) {
int32_t code = tjsonGetIntValue(pJson, jkDatabaseOptionsBuffer, &pNode->buffer);
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetTinyIntValue(pJson, jkDatabaseOptionsCachelast, &pNode->cachelast);
+ code = tjsonGetTinyIntValue(pJson, jkDatabaseOptionsCachelast, &pNode->cacheLast);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetTinyIntValue(pJson, jkDatabaseOptionsCompressionLevel, &pNode->compressionLevel);
@@ -3952,7 +4164,7 @@ static int32_t deleteStmtToJson(const void* pObj, SJson* pJson) {
code = tjsonAddObject(pJson, jkDeleteStmtCountFunc, nodeToJson, pNode->pCountFunc);
}
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddObject(pJson, jkDeleteStmtTagIndexCond, nodeToJson, pNode->pTagIndexCond);
+ code = tjsonAddObject(pJson, jkDeleteStmtTagIndexCond, nodeToJson, pNode->pTagCond);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkDeleteStmtTimeRangeStartKey, pNode->timeRange.skey);
@@ -3981,7 +4193,7 @@ static int32_t jsonToDeleteStmt(const SJson* pJson, void* pObj) {
code = jsonToNodeObject(pJson, jkDeleteStmtCountFunc, &pNode->pCountFunc);
}
if (TSDB_CODE_SUCCESS == code) {
- code = jsonToNodeObject(pJson, jkDeleteStmtTagIndexCond, &pNode->pTagIndexCond);
+ code = jsonToNodeObject(pJson, jkDeleteStmtTagIndexCond, &pNode->pTagCond);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkDeleteStmtTimeRangeStartKey, &pNode->timeRange.skey);
@@ -4022,7 +4234,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
case QUERY_NODE_ORDER_BY_EXPR:
return orderByExprNodeToJson(pObj, pJson);
case QUERY_NODE_LIMIT:
- break;
+ return limitNodeToJson(pObj, pJson);
case QUERY_NODE_STATE_WINDOW:
return stateWindowNodeToJson(pObj, pJson);
case QUERY_NODE_SESSION_WINDOW:
@@ -4105,6 +4317,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return logicPlanToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
return physiTagScanNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
@@ -4123,9 +4336,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
case QUERY_NODE_PHYSICAL_PLAN_MERGE:
return physiMergeNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_SORT:
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT:
return physiSortNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
@@ -4150,6 +4364,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return physiDispatchNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
break;
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
+ return physiQueryInsertNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_DELETE:
return physiDeleteNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_SUBPLAN:
@@ -4181,6 +4397,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToTempTableNode(pJson, pObj);
case QUERY_NODE_ORDER_BY_EXPR:
return jsonToOrderByExprNode(pJson, pObj);
+ case QUERY_NODE_LIMIT:
+ return jsonToLimitNode(pJson, pObj);
case QUERY_NODE_STATE_WINDOW:
return jsonToStateWindowNode(pJson, pObj);
case QUERY_NODE_SESSION_WINDOW:
@@ -4245,6 +4463,7 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToLogicPlan(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
return jsonToPhysiTagScanNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
@@ -4263,9 +4482,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
case QUERY_NODE_PHYSICAL_PLAN_MERGE:
return jsonToPhysiMergeNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_SORT:
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT:
return jsonToPhysiSortNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
@@ -4288,6 +4508,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToPhysiInterpFuncNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
return jsonToPhysiDispatchNode(pJson, pObj);
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
+ return jsonToPhysiQueryInsertNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_DELETE:
return jsonToPhysiDeleteNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_SUBPLAN:
diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c
index 1fb2db9f23f32847931e4963b12e323e88d916fe..b12e3b14c70d0ba471baf2172c16c6c7b5a617bc 100644
--- a/source/libs/nodes/src/nodesTraverseFuncs.c
+++ b/source/libs/nodes/src/nodesTraverseFuncs.c
@@ -470,6 +470,9 @@ static EDealRes dispatchPhysiPlan(SNode* pNode, ETraversalOrder order, FNodeWalk
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: {
SJoinPhysiNode* pJoin = (SJoinPhysiNode*)pNode;
res = walkPhysiNode((SPhysiNode*)pNode, order, walker, pContext);
+ if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
+ res = walkPhysiPlan(pJoin->pMergeCondition, order, walker, pContext);
+ }
if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
res = walkPhysiPlan(pJoin->pOnConditions, order, walker, pContext);
}
@@ -500,7 +503,8 @@ static EDealRes dispatchPhysiPlan(SNode* pNode, ETraversalOrder order, FNodeWalk
}
break;
}
- case QUERY_NODE_PHYSICAL_PLAN_SORT: {
+ case QUERY_NODE_PHYSICAL_PLAN_SORT:
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
SSortPhysiNode* pSort = (SSortPhysiNode*)pNode;
res = walkPhysiNode((SPhysiNode*)pNode, order, walker, pContext);
if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c
index ebacf5574f11bb03a56313fb2c373063c7915b95..b00b08a66d4835f0a01fdde843582910b0ac8f3d 100644
--- a/source/libs/nodes/src/nodesUtilFuncs.c
+++ b/source/libs/nodes/src/nodesUtilFuncs.c
@@ -19,6 +19,7 @@
#include "querynodes.h"
#include "taos.h"
#include "taoserror.h"
+#include "tdatablock.h"
#include "thash.h"
static SNode* makeNode(ENodeType type, size_t size) {
@@ -102,6 +103,10 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SDropDatabaseStmt));
case QUERY_NODE_ALTER_DATABASE_STMT:
return makeNode(type, sizeof(SAlterDatabaseStmt));
+ case QUERY_NODE_FLUSH_DATABASE_STMT:
+ return makeNode(type, sizeof(SFlushDatabaseStmt));
+ case QUERY_NODE_TRIM_DATABASE_STMT:
+ return makeNode(type, sizeof(STrimDatabaseStmt));
case QUERY_NODE_CREATE_TABLE_STMT:
return makeNode(type, sizeof(SCreateTableStmt));
case QUERY_NODE_CREATE_SUBTABLE_CLAUSE:
@@ -210,6 +215,7 @@ SNode* nodesMakeNode(ENodeType type) {
case QUERY_NODE_SHOW_VARIABLES_STMT:
case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
return makeNode(type, sizeof(SShowStmt));
case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
return makeNode(type, sizeof(SShowDnodeVariablesStmt));
@@ -227,6 +233,8 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SKillStmt));
case QUERY_NODE_DELETE_STMT:
return makeNode(type, sizeof(SDeleteStmt));
+ case QUERY_NODE_INSERT_STMT:
+ return makeNode(type, sizeof(SInsertStmt));
case QUERY_NODE_QUERY:
return makeNode(type, sizeof(SQuery));
case QUERY_NODE_LOGIC_PLAN_SCAN:
@@ -273,6 +281,8 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SSystemTableScanPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
return makeNode(type, sizeof(SBlockDistScanPhysiNode));
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
+ return makeNode(type, sizeof(SLastRowScanPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
return makeNode(type, sizeof(SProjectPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
@@ -285,10 +295,12 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SMergePhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return makeNode(type, sizeof(SSortPhysiNode));
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT:
+ return makeNode(type, sizeof(SGroupSortPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
return makeNode(type, sizeof(SIntervalPhysiNode));
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
- return makeNode(type, sizeof(SMergeIntervalPhysiNode));
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
+ return makeNode(type, sizeof(SMergeAlignedIntervalPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
return makeNode(type, sizeof(SStreamIntervalPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
@@ -319,6 +331,8 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SDataDispatcherNode));
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
return makeNode(type, sizeof(SDataInserterNode));
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
+ return makeNode(type, sizeof(SQueryInserterNode));
case QUERY_NODE_PHYSICAL_PLAN_DELETE:
return makeNode(type, sizeof(SDataDeleterNode));
case QUERY_NODE_PHYSICAL_SUBPLAN:
@@ -343,9 +357,11 @@ static void destroyVgDataBlockArray(SArray* pArray) {
}
static void destroyLogicNode(SLogicNode* pNode) {
- nodesDestroyList(pNode->pChildren);
- nodesDestroyNode(pNode->pConditions);
nodesDestroyList(pNode->pTargets);
+ nodesDestroyNode(pNode->pConditions);
+ nodesDestroyList(pNode->pChildren);
+ nodesDestroyNode(pNode->pLimit);
+ nodesDestroyNode(pNode->pSlimit);
}
static void destroyPhysiNode(SPhysiNode* pNode) {
@@ -365,10 +381,13 @@ static void destroyWinodwPhysiNode(SWinodwPhysiNode* pNode) {
static void destroyScanPhysiNode(SScanPhysiNode* pNode) {
destroyPhysiNode((SPhysiNode*)pNode);
nodesDestroyList(pNode->pScanCols);
+ nodesDestroyList(pNode->pScanPseudoCols);
}
static void destroyDataSinkNode(SDataSinkNode* pNode) { nodesDestroyNode((SNode*)pNode->pInputDataBlockDesc); }
+static void destroyExprNode(SExprNode* pExpr) { taosArrayDestroy(pExpr->pAssociation); }
+
void nodesDestroyNode(SNode* pNode) {
if (NULL == pNode) {
return;
@@ -376,9 +395,11 @@ void nodesDestroyNode(SNode* pNode) {
switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN: // pProjectRef is weak reference, no need to release
+ destroyExprNode((SExprNode*)pNode);
break;
case QUERY_NODE_VALUE: {
SValueNode* pValue = (SValueNode*)pNode;
+ destroyExprNode((SExprNode*)pNode);
taosMemoryFreeClear(pValue->literal);
if (IS_VAR_DATA_TYPE(pValue->node.resType.type)) {
taosMemoryFreeClear(pValue->datum.p);
@@ -387,14 +408,17 @@ void nodesDestroyNode(SNode* pNode) {
}
case QUERY_NODE_OPERATOR: {
SOperatorNode* pOp = (SOperatorNode*)pNode;
+ destroyExprNode((SExprNode*)pNode);
nodesDestroyNode(pOp->pLeft);
nodesDestroyNode(pOp->pRight);
break;
}
case QUERY_NODE_LOGIC_CONDITION:
+ destroyExprNode((SExprNode*)pNode);
nodesDestroyList(((SLogicConditionNode*)pNode)->pParameterList);
break;
case QUERY_NODE_FUNCTION:
+ destroyExprNode((SExprNode*)pNode);
nodesDestroyList(((SFunctionNode*)pNode)->pParameterList);
break;
case QUERY_NODE_REAL_TABLE: {
@@ -506,6 +530,9 @@ void nodesDestroyNode(SNode* pNode) {
nodesDestroyNode(pStmt->pWindow);
nodesDestroyList(pStmt->pGroupByList);
nodesDestroyNode(pStmt->pHaving);
+ nodesDestroyNode(pStmt->pRange);
+ nodesDestroyNode(pStmt->pEvery);
+ nodesDestroyNode(pStmt->pFill);
nodesDestroyList(pStmt->pOrderByList);
nodesDestroyNode((SNode*)pStmt->pLimit);
nodesDestroyNode((SNode*)pStmt->pSlimit);
@@ -522,6 +549,9 @@ void nodesDestroyNode(SNode* pNode) {
case QUERY_NODE_ALTER_DATABASE_STMT:
nodesDestroyNode((SNode*)((SAlterDatabaseStmt*)pNode)->pOptions);
break;
+ case QUERY_NODE_FLUSH_DATABASE_STMT: // no pointer field
+ case QUERY_NODE_TRIM_DATABASE_STMT: // no pointer field
+ break;
case QUERY_NODE_CREATE_TABLE_STMT: {
SCreateTableStmt* pStmt = (SCreateTableStmt*)pNode;
nodesDestroyList(pStmt->pCols);
@@ -642,7 +672,8 @@ void nodesDestroyNode(SNode* pNode) {
case QUERY_NODE_SHOW_SCORES_STMT:
case QUERY_NODE_SHOW_VARIABLES_STMT:
case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
- case QUERY_NODE_SHOW_TRANSACTIONS_STMT: {
+ case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT: {
SShowStmt* pStmt = (SShowStmt*)pNode;
nodesDestroyNode(pStmt->pDbName);
nodesDestroyNode(pStmt->pTbName);
@@ -655,7 +686,7 @@ void nodesDestroyNode(SNode* pNode) {
break;
case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
- taosMemoryFreeClear(((SShowCreateTableStmt*)pNode)->pMeta);
+ taosMemoryFreeClear(((SShowCreateTableStmt*)pNode)->pCfg);
break;
case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: // no pointer field
case QUERY_NODE_KILL_CONNECTION_STMT: // no pointer field
@@ -667,7 +698,14 @@ void nodesDestroyNode(SNode* pNode) {
nodesDestroyNode(pStmt->pFromTable);
nodesDestroyNode(pStmt->pWhere);
nodesDestroyNode(pStmt->pCountFunc);
- nodesDestroyNode(pStmt->pTagIndexCond);
+ nodesDestroyNode(pStmt->pTagCond);
+ break;
+ }
+ case QUERY_NODE_INSERT_STMT: {
+ SInsertStmt* pStmt = (SInsertStmt*)pNode;
+ nodesDestroyNode(pStmt->pTable);
+ nodesDestroyList(pStmt->pCols);
+ nodesDestroyNode(pStmt->pQuery);
break;
}
case QUERY_NODE_QUERY: {
@@ -686,12 +724,19 @@ void nodesDestroyNode(SNode* pNode) {
SScanLogicNode* pLogicNode = (SScanLogicNode*)pNode;
destroyLogicNode((SLogicNode*)pLogicNode);
nodesDestroyList(pLogicNode->pScanCols);
+ nodesDestroyList(pLogicNode->pScanPseudoCols);
taosMemoryFreeClear(pLogicNode->pVgroupList);
+ nodesDestroyList(pLogicNode->pDynamicScanFuncs);
+ nodesDestroyNode(pLogicNode->pTagCond);
+ nodesDestroyNode(pLogicNode->pTagIndexCond);
+ taosArrayDestroy(pLogicNode->pSmaIndexes);
+ nodesDestroyList(pLogicNode->pGroupTags);
break;
}
case QUERY_NODE_LOGIC_PLAN_JOIN: {
SJoinLogicNode* pLogicNode = (SJoinLogicNode*)pNode;
destroyLogicNode((SLogicNode*)pLogicNode);
+ nodesDestroyNode(pLogicNode->pMergeCondition);
nodesDestroyNode(pLogicNode->pOnConditions);
break;
}
@@ -762,6 +807,8 @@ void nodesDestroyNode(SNode* pNode) {
SInterpFuncLogicNode* pLogicNode = (SInterpFuncLogicNode*)pNode;
destroyLogicNode((SLogicNode*)pLogicNode);
nodesDestroyList(pLogicNode->pFuncs);
+ nodesDestroyNode(pLogicNode->pFillValues);
+ nodesDestroyNode(pLogicNode->pTimeSeries);
break;
}
case QUERY_NODE_LOGIC_SUBPLAN: {
@@ -776,13 +823,21 @@ void nodesDestroyNode(SNode* pNode) {
nodesDestroyList(((SQueryLogicPlan*)pNode)->pTopSubplans);
break;
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
- case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
- case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
- case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
destroyScanPhysiNode((SScanPhysiNode*)pNode);
break;
+ case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
+ case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN: {
+ STableScanPhysiNode* pPhyNode = (STableScanPhysiNode*)pNode;
+ destroyScanPhysiNode((SScanPhysiNode*)pNode);
+ nodesDestroyList(pPhyNode->pDynamicScanFuncs);
+ nodesDestroyList(pPhyNode->pGroupTags);
+ break;
+ }
case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
SProjectPhysiNode* pPhyNode = (SProjectPhysiNode*)pNode;
destroyPhysiNode((SPhysiNode*)pPhyNode);
@@ -792,6 +847,7 @@ void nodesDestroyNode(SNode* pNode) {
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: {
SJoinPhysiNode* pPhyNode = (SJoinPhysiNode*)pNode;
destroyPhysiNode((SPhysiNode*)pPhyNode);
+ nodesDestroyNode(pPhyNode->pMergeCondition);
nodesDestroyNode(pPhyNode->pOnConditions);
nodesDestroyList(pPhyNode->pTargets);
break;
@@ -817,15 +873,17 @@ void nodesDestroyNode(SNode* pNode) {
nodesDestroyList(pPhyNode->pTargets);
break;
}
- case QUERY_NODE_PHYSICAL_PLAN_SORT: {
+ case QUERY_NODE_PHYSICAL_PLAN_SORT:
+ case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
SSortPhysiNode* pPhyNode = (SSortPhysiNode*)pNode;
destroyPhysiNode((SPhysiNode*)pPhyNode);
nodesDestroyList(pPhyNode->pExprs);
nodesDestroyList(pPhyNode->pSortKeys);
+ nodesDestroyList(pPhyNode->pTargets);
break;
}
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
- case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
@@ -872,6 +930,8 @@ void nodesDestroyNode(SNode* pNode) {
destroyPhysiNode((SPhysiNode*)pPhyNode);
nodesDestroyList(pPhyNode->pExprs);
nodesDestroyList(pPhyNode->pFuncs);
+ nodesDestroyNode(pPhyNode->pFillValues);
+ nodesDestroyNode(pPhyNode->pTimeSeries);
break;
}
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
@@ -883,6 +943,11 @@ void nodesDestroyNode(SNode* pNode) {
taosMemoryFreeClear(pSink->pData);
break;
}
+ case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: {
+ SQueryInserterNode* pSink = (SQueryInserterNode*)pNode;
+ destroyDataSinkNode((SDataSinkNode*)pSink);
+ break;
+ }
case QUERY_NODE_PHYSICAL_PLAN_DELETE: {
SDataDeleterNode* pSink = (SDataDeleterNode*)pNode;
destroyDataSinkNode((SDataSinkNode*)pSink);
@@ -891,31 +956,17 @@ void nodesDestroyNode(SNode* pNode) {
}
case QUERY_NODE_PHYSICAL_SUBPLAN: {
SSubplan* pSubplan = (SSubplan*)pNode;
- nodesDestroyList(pSubplan->pChildren);
+ nodesClearList(pSubplan->pChildren);
nodesDestroyNode((SNode*)pSubplan->pNode);
nodesDestroyNode((SNode*)pSubplan->pDataSink);
+ nodesDestroyNode((SNode*)pSubplan->pTagCond);
+ nodesDestroyNode((SNode*)pSubplan->pTagIndexCond);
nodesClearList(pSubplan->pParents);
break;
}
- case QUERY_NODE_PHYSICAL_PLAN: {
- SQueryPlan* pPlan = (SQueryPlan*)pNode;
- if (NULL != pPlan->pSubplans) {
- // only need to destroy the top-level subplans, because they will recurse to all the subplans below
- bool first = true;
- SNode* pElement = NULL;
- FOREACH(pElement, pPlan->pSubplans) {
- if (first) {
- first = false;
- nodesDestroyNode(pElement);
- } else {
- nodesClearList(((SNodeListNode*)pElement)->pNodeList);
- taosMemoryFreeClear(pElement);
- }
- }
- nodesClearList(pPlan->pSubplans);
- }
+ case QUERY_NODE_PHYSICAL_PLAN:
+ nodesDestroyList(((SQueryPlan*)pNode)->pSubplans);
break;
- }
default:
break;
}
@@ -1083,6 +1134,16 @@ SNode* nodesListGetNode(SNodeList* pList, int32_t index) {
return NULL;
}
+SListCell* nodesListGetCell(SNodeList* pList, int32_t index) {
+ SNode* node;
+ FOREACH(node, pList) {
+ if (0 == index--) {
+ return cell;
+ }
+ }
+ return NULL;
+}
+
void nodesDestroyList(SNodeList* pList) {
if (NULL == pList) {
return;
@@ -1127,6 +1188,7 @@ void* nodesGetValueFromNode(SValueNode* pNode) {
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
+ case TSDB_DATA_TYPE_JSON:
return (void*)pNode->datum.p;
default:
break;
@@ -1188,6 +1250,7 @@ int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value) {
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
+ case TSDB_DATA_TYPE_JSON:
pNode->datum.p = (char*)value;
break;
default:
@@ -1354,6 +1417,17 @@ bool nodesIsRegularOp(const SOperatorNode* pOp) {
return false;
}
+bool nodesIsBitwiseOp(const SOperatorNode* pOp) {
+ switch (pOp->opType) {
+ case OP_TYPE_BIT_AND:
+ case OP_TYPE_BIT_OR:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
typedef struct SCollectColumnsCxt {
int32_t errCode;
const char* pTableAlias;
@@ -1428,16 +1502,53 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char*
return TSDB_CODE_SUCCESS;
}
+int32_t nodesCollectColumnsFromNode(SNode* node, const char* pTableAlias, ECollectColType type, SNodeList** pCols) {
+ if (NULL == pCols) {
+ return TSDB_CODE_FAILED;
+ }
+ SCollectColumnsCxt cxt = {
+ .errCode = TSDB_CODE_SUCCESS,
+ .pTableAlias = pTableAlias,
+ .collectType = type,
+ .pCols = (NULL == *pCols ? nodesMakeList() : *pCols),
+ .pColHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK)};
+ if (NULL == cxt.pCols || NULL == cxt.pColHash) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ *pCols = NULL;
+
+ nodesWalkExpr(node, collectColumns, &cxt);
+
+ taosHashCleanup(cxt.pColHash);
+ if (TSDB_CODE_SUCCESS != cxt.errCode) {
+ nodesDestroyList(cxt.pCols);
+ return cxt.errCode;
+ }
+ if (LIST_LENGTH(cxt.pCols) > 0) {
+ *pCols = cxt.pCols;
+ } else {
+ nodesDestroyList(cxt.pCols);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
typedef struct SCollectFuncsCxt {
int32_t errCode;
FFuncClassifier classifier;
SNodeList* pFuncs;
+ SHashObj* pAliasName;
} SCollectFuncsCxt;
static EDealRes collectFuncs(SNode* pNode, void* pContext) {
SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext;
- if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId)) {
- pCxt->errCode = nodesListStrictAppend(pCxt->pFuncs, nodesCloneNode(pNode));
+ if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId) &&
+ !(((SExprNode*)pNode)->orderAlias)) {
+ SExprNode* pExpr = (SExprNode*)pNode;
+ if (NULL == taosHashGet(pCxt->pAliasName, pExpr->aliasName, strlen(pExpr->aliasName))) {
+ pCxt->errCode = nodesListStrictAppend(pCxt->pFuncs, nodesCloneNode(pNode));
+ taosHashPut(pCxt->pAliasName, pExpr->aliasName, strlen(pExpr->aliasName), &pExpr, POINTER_BYTES);
+ }
return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
}
return DEAL_RES_CONTINUE;
@@ -1449,23 +1560,27 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, ESqlClause clause, FFuncClassifi
}
SCollectFuncsCxt cxt = {
- .errCode = TSDB_CODE_SUCCESS, .classifier = classifier, .pFuncs = (NULL == *pFuncs ? nodesMakeList() : *pFuncs)};
+ .errCode = TSDB_CODE_SUCCESS,
+ .classifier = classifier,
+ .pFuncs = (NULL == *pFuncs ? nodesMakeList() : *pFuncs),
+ .pAliasName = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, false)};
if (NULL == cxt.pFuncs) {
return TSDB_CODE_OUT_OF_MEMORY;
}
*pFuncs = NULL;
nodesWalkSelectStmt(pSelect, clause, collectFuncs, &cxt);
- if (TSDB_CODE_SUCCESS != cxt.errCode) {
- nodesDestroyList(cxt.pFuncs);
- return cxt.errCode;
- }
- if (LIST_LENGTH(cxt.pFuncs) > 0) {
- *pFuncs = cxt.pFuncs;
+ if (TSDB_CODE_SUCCESS == cxt.errCode) {
+ if (LIST_LENGTH(cxt.pFuncs) > 0) {
+ *pFuncs = cxt.pFuncs;
+ } else {
+ nodesDestroyList(cxt.pFuncs);
+ }
} else {
nodesDestroyList(cxt.pFuncs);
}
+ taosHashCleanup(cxt.pAliasName);
- return TSDB_CODE_SUCCESS;
+ return cxt.errCode;
}
typedef struct SCollectSpecialNodesCxt {
@@ -1577,6 +1692,11 @@ int32_t nodesGetOutputNumFromSlotList(SNodeList* pSlots) {
}
void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal) {
+ if (pNode->isNull) {
+ pVal->nType = TSDB_DATA_TYPE_NULL;
+ pVal->nLen = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
+ return;
+ }
pVal->nType = pNode->node.resType.type;
pVal->nLen = pNode->node.resType.bytes;
switch (pNode->node.resType.type) {
@@ -1610,6 +1730,10 @@ void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal) {
pVal->pz[pVal->nLen + VARSTR_HEADER_SIZE] = 0;
break;
case TSDB_DATA_TYPE_JSON:
+ pVal->nLen = getJsonValueLen(pNode->datum.p);
+ pVal->pz = taosMemoryMalloc(pVal->nLen);
+ memcpy(pVal->pz, pNode->datum.p, pVal->nLen);
+ break;
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
@@ -1645,6 +1769,7 @@ int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc) {
typedef struct SClassifyConditionCxt {
bool hasPrimaryKey;
bool hasTagIndexCol;
+ bool hasTagCol;
bool hasOtherCol;
} SClassifyConditionCxt;
@@ -1652,35 +1777,45 @@ static EDealRes classifyConditionImpl(SNode* pNode, void* pContext) {
SClassifyConditionCxt* pCxt = (SClassifyConditionCxt*)pContext;
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
SColumnNode* pCol = (SColumnNode*)pNode;
- if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId) {
+ if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && TSDB_SYSTEM_TABLE != pCol->tableType) {
pCxt->hasPrimaryKey = true;
} else if (pCol->hasIndex) {
pCxt->hasTagIndexCol = true;
+ pCxt->hasTagCol = true;
+ } else if (COLUMN_TYPE_TAG == pCol->colType || COLUMN_TYPE_TBNAME == pCol->colType) {
+ pCxt->hasTagCol = true;
} else {
pCxt->hasOtherCol = true;
}
- return *((bool*)pContext) ? DEAL_RES_CONTINUE : DEAL_RES_END;
}
return DEAL_RES_CONTINUE;
}
-typedef enum EConditionType { COND_TYPE_PRIMARY_KEY = 1, COND_TYPE_TAG_INDEX, COND_TYPE_NORMAL } EConditionType;
+typedef enum EConditionType {
+ COND_TYPE_PRIMARY_KEY = 1,
+ COND_TYPE_TAG_INDEX,
+ COND_TYPE_TAG,
+ COND_TYPE_NORMAL
+} EConditionType;
static EConditionType classifyCondition(SNode* pNode) {
SClassifyConditionCxt cxt = {.hasPrimaryKey = false, .hasTagIndexCol = false, .hasOtherCol = false};
nodesWalkExpr(pNode, classifyConditionImpl, &cxt);
return cxt.hasOtherCol ? COND_TYPE_NORMAL
- : (cxt.hasPrimaryKey && cxt.hasTagIndexCol
+ : (cxt.hasPrimaryKey && cxt.hasTagCol
? COND_TYPE_NORMAL
- : (cxt.hasPrimaryKey ? COND_TYPE_PRIMARY_KEY : COND_TYPE_TAG_INDEX));
+ : (cxt.hasPrimaryKey ? COND_TYPE_PRIMARY_KEY
+ : (cxt.hasTagIndexCol ? COND_TYPE_TAG_INDEX : COND_TYPE_TAG)));
}
-static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagCond, SNode** pOtherCond) {
+static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
+ SNode** pOtherCond) {
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(*pCondition);
int32_t code = TSDB_CODE_SUCCESS;
SNodeList* pPrimaryKeyConds = NULL;
+ SNodeList* pTagIndexConds = NULL;
SNodeList* pTagConds = NULL;
SNodeList* pOtherConds = NULL;
SNode* pCond = NULL;
@@ -1692,6 +1827,14 @@ static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, S
}
break;
case COND_TYPE_TAG_INDEX:
+ if (NULL != pTagIndexCond) {
+ code = nodesListMakeAppend(&pTagIndexConds, nodesCloneNode(pCond));
+ }
+ if (NULL != pTagCond) {
+ code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
+ }
+ break;
+ case COND_TYPE_TAG:
if (NULL != pTagCond) {
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
}
@@ -1709,11 +1852,15 @@ static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, S
}
SNode* pTempPrimaryKeyCond = NULL;
+ SNode* pTempTagIndexCond = NULL;
SNode* pTempTagCond = NULL;
SNode* pTempOtherCond = NULL;
if (TSDB_CODE_SUCCESS == code) {
code = nodesMergeConds(&pTempPrimaryKeyCond, &pPrimaryKeyConds);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesMergeConds(&pTempTagIndexCond, &pTagIndexConds);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = nodesMergeConds(&pTempTagCond, &pTagConds);
}
@@ -1725,6 +1872,9 @@ static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, S
if (NULL != pPrimaryKeyCond) {
*pPrimaryKeyCond = pTempPrimaryKeyCond;
}
+ if (NULL != pTagIndexCond) {
+ *pTagIndexCond = pTempTagIndexCond;
+ }
if (NULL != pTagCond) {
*pTagCond = pTempTagCond;
}
@@ -1735,9 +1885,11 @@ static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, S
*pCondition = NULL;
} else {
nodesDestroyList(pPrimaryKeyConds);
+ nodesDestroyList(pTagIndexConds);
nodesDestroyList(pTagConds);
nodesDestroyList(pOtherConds);
nodesDestroyNode(pTempPrimaryKeyCond);
+ nodesDestroyNode(pTempTagIndexCond);
nodesDestroyNode(pTempTagCond);
nodesDestroyNode(pTempOtherCond);
}
@@ -1745,10 +1897,11 @@ static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, S
return code;
}
-int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagCond, SNode** pOtherCond) {
+int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
+ SNode** pOtherCond) {
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pCondition) &&
LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pCondition)->condType) {
- return partitionLogicCond(pCondition, pPrimaryKeyCond, pTagCond, pOtherCond);
+ return partitionLogicCond(pCondition, pPrimaryKeyCond, pTagIndexCond, pTagCond, pOtherCond);
}
switch (classifyCondition(*pCondition)) {
@@ -1758,6 +1911,21 @@ int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode**
}
break;
case COND_TYPE_TAG_INDEX:
+ if (NULL != pTagIndexCond) {
+ *pTagIndexCond = *pCondition;
+ }
+ if (NULL != pTagCond) {
+ SNode* pTempCond = *pCondition;
+ if (NULL != pTagIndexCond) {
+ pTempCond = nodesCloneNode(*pCondition);
+ if (NULL == pTempCond) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+ *pTagCond = pTempCond;
+ }
+ break;
+ case COND_TYPE_TAG:
if (NULL != pTagCond) {
*pTagCond = *pCondition;
}
diff --git a/source/libs/parser/inc/parAst.h b/source/libs/parser/inc/parAst.h
index 2d9bb497626ea36030e6bd603b9e5695980b51d5..59fc69f768e2ba2c770603b366af473a2610c718 100644
--- a/source/libs/parser/inc/parAst.h
+++ b/source/libs/parser/inc/parAst.h
@@ -39,6 +39,7 @@ typedef struct SAstCreateContext {
typedef enum EDatabaseOptionType {
DB_OPTION_BUFFER = 1,
DB_OPTION_CACHELAST,
+ DB_OPTION_CACHELASTSIZE,
DB_OPTION_COMP,
DB_OPTION_DAYS,
DB_OPTION_FSYNC,
@@ -135,6 +136,8 @@ SNode* setAlterDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, SAlterOp
SNode* createCreateDatabaseStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pDbName, SNode* pOptions);
SNode* createDropDatabaseStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pDbName);
SNode* createAlterDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pOptions);
+SNode* createFlushDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName);
+SNode* createTrimDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName);
SNode* createDefaultTableOptions(SAstCreateContext* pCxt);
SNode* createAlterTableOptions(SAstCreateContext* pCxt);
SNode* setTableOption(SAstCreateContext* pCxt, SNode* pOptions, ETableOptionType type, void* pVal);
@@ -154,6 +157,7 @@ SNode* createAlterTableDropCol(SAstCreateContext* pCxt, SNode* pRealTable, int8_
SNode* createAlterTableRenameCol(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pOldColName,
SToken* pNewColName);
SNode* createAlterTableSetTag(SAstCreateContext* pCxt, SNode* pRealTable, SToken* pTagName, SNode* pVal);
+SNode* setAlterSuperTableType(SNode* pStmt);
SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName);
SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type);
SNode* createShowStmtWithCond(SAstCreateContext* pCxt, ENodeType type, SNode* pDbName, SNode* pTbName,
@@ -162,7 +166,7 @@ SNode* createShowCreateDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName);
SNode* createShowCreateTableStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable);
SNode* createShowTableDistributedStmt(SAstCreateContext* pCxt, SNode* pRealTable);
SNode* createShowDnodeVariablesStmt(SAstCreateContext* pCxt, SNode* pDnodeId);
-SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const SToken* pPassword);
+SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const SToken* pPassword, int8_t sysinfo);
SNode* createAlterUserStmt(SAstCreateContext* pCxt, SToken* pUserName, int8_t alterType, const SToken* pVal);
SNode* createDropUserStmt(SAstCreateContext* pCxt, SToken* pUserName);
SNode* createCreateDnodeStmt(SAstCreateContext* pCxt, const SToken* pFqdn, const SToken* pPort);
@@ -170,13 +174,17 @@ SNode* createDropDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode);
SNode* createAlterDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, const SToken* pConfig, const SToken* pValue);
SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool ignoreExists, SToken* pIndexName,
SToken* pTableName, SNodeList* pCols, SNode* pOptions);
-SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInterval, SNode* pOffset, SNode* pSliding);
-SNode* createDropIndexStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pIndexName, SToken* pTableName);
+SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInterval, SNode* pOffset, SNode* pSliding,
+ SNode* pStreamOptions);
+SNode* createDropIndexStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pIndexName);
SNode* createCreateComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDnodeId);
SNode* createDropComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDnodeId);
-SNode* createTopicOptions(SAstCreateContext* pCxt);
-SNode* createCreateTopicStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName, SNode* pQuery,
- const SToken* pSubDbName, SNode* pRealTable);
+SNode* createCreateTopicStmtUseQuery(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ SNode* pQuery);
+SNode* createCreateTopicStmtUseDb(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ const SToken* pSubDbName, bool withMeta);
+SNode* createCreateTopicStmtUseTable(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ SNode* pRealTable, bool withMeta);
SNode* createDropTopicStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pTopicName);
SNode* createDropCGroupStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pCGroupId,
const SToken* pTopicName);
@@ -205,6 +213,7 @@ SNode* createSyncdbStmt(SAstCreateContext* pCxt, const SToken* pDbName);
SNode* createGrantStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName);
SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName);
SNode* createDeleteStmt(SAstCreateContext* pCxt, SNode* pTable, SNode* pWhere);
+SNode* createInsertStmt(SAstCreateContext* pCxt, SNode* pTable, SNodeList* pCols, SNode* pQuery);
#ifdef __cplusplus
}
diff --git a/source/libs/parser/inc/parInsertData.h b/source/libs/parser/inc/parInsertData.h
index 167970838b60e054eb29bc1ad4fc20f2b2ddc38e..ea78735d5e3da99d3bece2f8a62cf611b3aa9aff 100644
--- a/source/libs/parser/inc/parInsertData.h
+++ b/source/libs/parser/inc/parInsertData.h
@@ -20,6 +20,7 @@
#include "os.h"
#include "tname.h"
#include "ttypes.h"
+#include "query.h"
#define IS_DATA_COL_ORDERED(spd) ((spd->orderStatus) == (int8_t)ORDER_STATUS_ORDERED)
diff --git a/source/libs/parser/inc/parUtil.h b/source/libs/parser/inc/parUtil.h
index e08f813c194a101f129b59677d65a405049505f6..896e2bc2398ebe50ed6deafe11d8e456403d8246 100644
--- a/source/libs/parser/inc/parUtil.h
+++ b/source/libs/parser/inc/parUtil.h
@@ -47,11 +47,13 @@ typedef struct SParseMetaCache {
SHashObj* pUserAuth; // key is SUserAuthInfo serialized string, element is bool indicating whether or not to pass
SHashObj* pUdf; // key is funcName, element is SFuncInfo*
SHashObj* pTableIndex; // key is tbFName, element is SArray*
+ SHashObj* pTableCfg; // key is tbFName, element is STableCfg*
SArray* pDnodes; // element is SEpSet
bool dnodeRequired;
} SParseMetaCache;
int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...);
+int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...);
int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg);
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr);
@@ -61,7 +63,6 @@ int32_t getNumOfColumns(const STableMeta* pTableMeta);
int32_t getNumOfTags(const STableMeta* pTableMeta);
STableComInfo getTableInfo(const STableMeta* pTableMeta);
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
-int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, SMsgBuf* pMsgBuf);
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen);
@@ -79,6 +80,7 @@ int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pD
int32_t reserveUserAuthInCacheExt(const char* pUser, const SName* pName, AUTH_TYPE type, SParseMetaCache* pMetaCache);
int32_t reserveUdfInCache(const char* pFunc, SParseMetaCache* pMetaCache);
int32_t reserveTableIndexInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache);
+int32_t reserveTableCfgInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache);
int32_t reserveDnodeRequiredInCache(SParseMetaCache* pMetaCache);
int32_t getTableMetaFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableMeta** pMeta);
int32_t getDbVgInfoFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SArray** pVgInfo);
@@ -90,6 +92,7 @@ int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, const char* pUser, con
bool* pPass);
int32_t getUdfInfoFromCache(SParseMetaCache* pMetaCache, const char* pFunc, SFuncInfo* pInfo);
int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes);
+int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput);
int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes);
void destoryParseMetaCache(SParseMetaCache* pMetaCache);
diff --git a/source/libs/parser/inc/sql.y b/source/libs/parser/inc/sql.y
index 54c46ecb5dcf06d1f9f3264820e0265580d36504..ddde20e8e947f90d387fa3a1048a40b1a13bf215 100644
--- a/source/libs/parser/inc/sql.y
+++ b/source/libs/parser/inc/sql.y
@@ -80,11 +80,18 @@ alter_account_option ::= CONNS literal.
alter_account_option ::= STATE literal. { }
/************************************************ create/alter/drop user **********************************************/
-cmd ::= CREATE USER user_name(A) PASS NK_STRING(B). { pCxt->pRootNode = createCreateUserStmt(pCxt, &A, &B); }
+cmd ::= CREATE USER user_name(A) PASS NK_STRING(B) sysinfo_opt(C). { pCxt->pRootNode = createCreateUserStmt(pCxt, &A, &B, C); }
cmd ::= ALTER USER user_name(A) PASS NK_STRING(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_PASSWD, &B); }
-cmd ::= ALTER USER user_name(A) PRIVILEGE NK_STRING(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_PRIVILEGES, &B); }
+//cmd ::= ALTER USER user_name(A) PRIVILEGE NK_STRING(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_PRIVILEGES, &B); }
+cmd ::= ALTER USER user_name(A) ENABLE NK_INTEGER(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_ENABLE, &B); }
+cmd ::= ALTER USER user_name(A) SYSINFO NK_INTEGER(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_SYSINFO, &B); }
cmd ::= DROP USER user_name(A). { pCxt->pRootNode = createDropUserStmt(pCxt, &A); }
+%type sysinfo_opt { int8_t }
+%destructor sysinfo_opt { }
+sysinfo_opt(A) ::= . { A = 1; }
+sysinfo_opt(A) ::= SYSINFO NK_INTEGER(B). { A = taosStr2Int8(B.z, NULL, 10); }
+
/************************************************ grant/revoke ********************************************************/
cmd ::= GRANT privileges(A) ON priv_level(B) TO user_name(C). { pCxt->pRootNode = createGrantStmt(pCxt, A, &B, &C); }
cmd ::= REVOKE privileges(A) ON priv_level(B) FROM user_name(C). { pCxt->pRootNode = createRevokeStmt(pCxt, A, &B, &C); }
@@ -150,6 +157,8 @@ cmd ::= CREATE DATABASE not_exists_opt(A) db_name(B) db_options(C).
cmd ::= DROP DATABASE exists_opt(A) db_name(B). { pCxt->pRootNode = createDropDatabaseStmt(pCxt, A, &B); }
cmd ::= USE db_name(A). { pCxt->pRootNode = createUseDatabaseStmt(pCxt, &A); }
cmd ::= ALTER DATABASE db_name(A) alter_db_options(B). { pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &A, B); }
+cmd ::= FLUSH DATABASE db_name(A). { pCxt->pRootNode = createFlushDatabaseStmt(pCxt, &A); }
+cmd ::= TRIM DATABASE db_name(A). { pCxt->pRootNode = createTrimDatabaseStmt(pCxt, &A); }
%type not_exists_opt { bool }
%destructor not_exists_opt { }
@@ -164,6 +173,7 @@ exists_opt(A) ::= .
db_options(A) ::= . { A = createDefaultDatabaseOptions(pCxt); }
db_options(A) ::= db_options(B) BUFFER NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_BUFFER, &C); }
db_options(A) ::= db_options(B) CACHELAST NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_CACHELAST, &C); }
+db_options(A) ::= db_options(B) CACHELASTSIZE NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_CACHELASTSIZE, &C); }
db_options(A) ::= db_options(B) COMP NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_COMP, &C); }
db_options(A) ::= db_options(B) DURATION NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_DAYS, &C); }
db_options(A) ::= db_options(B) DURATION NK_VARIABLE(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_DAYS, &C); }
@@ -190,6 +200,7 @@ alter_db_options(A) ::= alter_db_options(B) alter_db_option(C).
%destructor alter_db_option { }
alter_db_option(A) ::= BUFFER NK_INTEGER(B). { A.type = DB_OPTION_BUFFER; A.val = B; }
alter_db_option(A) ::= CACHELAST NK_INTEGER(B). { A.type = DB_OPTION_CACHELAST; A.val = B; }
+alter_db_option(A) ::= CACHELASTSIZE NK_INTEGER(B). { A.type = DB_OPTION_CACHELASTSIZE; A.val = B; }
alter_db_option(A) ::= FSYNC NK_INTEGER(B). { A.type = DB_OPTION_FSYNC; A.val = B; }
alter_db_option(A) ::= KEEP integer_list(B). { A.type = DB_OPTION_KEEP; A.pList = B; }
alter_db_option(A) ::= KEEP variable_list(B). { A.type = DB_OPTION_KEEP; A.pList = B; }
@@ -225,7 +236,7 @@ cmd ::= DROP TABLE multi_drop_clause(A).
cmd ::= DROP STABLE exists_opt(A) full_table_name(B). { pCxt->pRootNode = createDropSuperTableStmt(pCxt, A, B); }
cmd ::= ALTER TABLE alter_table_clause(A). { pCxt->pRootNode = A; }
-cmd ::= ALTER STABLE alter_table_clause(A). { pCxt->pRootNode = A; }
+cmd ::= ALTER STABLE alter_table_clause(A). { pCxt->pRootNode = setAlterSuperTableType(A); }
alter_table_clause(A) ::= full_table_name(B) alter_table_options(C). { A = createAlterTableModifyOptions(pCxt, B, C); }
alter_table_clause(A) ::=
@@ -252,7 +263,7 @@ multi_create_clause(A) ::= multi_create_clause(B) create_subtable_clause(C).
create_subtable_clause(A) ::=
not_exists_opt(B) full_table_name(C) USING full_table_name(D)
- specific_tags_opt(E) TAGS NK_LP literal_list(F) NK_RP table_options(G). { A = createCreateSubTableClause(pCxt, B, C, D, E, F, G); }
+ specific_cols_opt(E) TAGS NK_LP expression_list(F) NK_RP table_options(G). { A = createCreateSubTableClause(pCxt, B, C, D, E, F, G); }
%type multi_drop_clause { SNodeList* }
%destructor multi_drop_clause { nodesDestroyList($$); }
@@ -261,10 +272,10 @@ multi_drop_clause(A) ::= multi_drop_clause(B) drop_table_clause(C).
drop_table_clause(A) ::= exists_opt(B) full_table_name(C). { A = createDropTableClause(pCxt, B, C); }
-%type specific_tags_opt { SNodeList* }
-%destructor specific_tags_opt { nodesDestroyList($$); }
-specific_tags_opt(A) ::= . { A = NULL; }
-specific_tags_opt(A) ::= NK_LP col_name_list(B) NK_RP. { A = B; }
+%type specific_cols_opt { SNodeList* }
+%destructor specific_cols_opt { nodesDestroyList($$); }
+specific_cols_opt(A) ::= . { A = NULL; }
+specific_cols_opt(A) ::= NK_LP col_name_list(B) NK_RP. { A = B; }
full_table_name(A) ::= table_name(B). { A = createRealTableNode(pCxt, NULL, &B, NULL); }
full_table_name(A) ::= db_name(B) NK_DOT table_name(C). { A = createRealTableNode(pCxt, &B, &C, NULL); }
@@ -381,6 +392,8 @@ cmd ::= SHOW SNODES.
cmd ::= SHOW CLUSTER. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CLUSTER_STMT); }
cmd ::= SHOW TRANSACTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TRANSACTIONS_STMT); }
cmd ::= SHOW TABLE DISTRIBUTED full_table_name(A). { pCxt->pRootNode = createShowTableDistributedStmt(pCxt, A); }
+cmd ::= SHOW CONSUMERS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONSUMERS_STMT); }
+cmd ::= SHOW SUBSCRIPTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT); }
db_name_cond_opt(A) ::= . { A = createDefaultDatabaseCondValue(pCxt); }
db_name_cond_opt(A) ::= db_name(B) NK_DOT. { A = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &B); }
@@ -396,15 +409,15 @@ from_db_opt(A) ::= FROM db_name(B).
/************************************************ create index ********************************************************/
cmd ::= CREATE SMA INDEX not_exists_opt(D)
index_name(A) ON table_name(B) index_options(C). { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, D, &A, &B, NULL, C); }
-cmd ::= CREATE FULLTEXT INDEX not_exists_opt(D)
- index_name(A) ON table_name(B) NK_LP col_name_list(C) NK_RP. { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_FULLTEXT, D, &A, &B, C, NULL); }
-cmd ::= DROP INDEX exists_opt(C) index_name(A) ON table_name(B). { pCxt->pRootNode = createDropIndexStmt(pCxt, C, &A, &B); }
+//cmd ::= CREATE FULLTEXT INDEX not_exists_opt(D)
+// index_name(A) ON table_name(B) NK_LP col_name_list(C) NK_RP. { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_FULLTEXT, D, &A, &B, C, NULL); }
+cmd ::= DROP INDEX exists_opt(B) index_name(A). { pCxt->pRootNode = createDropIndexStmt(pCxt, B, &A); }
-index_options(A) ::= . { A = NULL; }
index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL
- NK_LP duration_literal(C) NK_RP sliding_opt(D). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), NULL, D); }
+ NK_LP duration_literal(C) NK_RP sliding_opt(D) sma_stream_opt(E). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), NULL, D, E); }
index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL
- NK_LP duration_literal(C) NK_COMMA duration_literal(D) NK_RP sliding_opt(E). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D), E); }
+ NK_LP duration_literal(C) NK_COMMA duration_literal(D) NK_RP sliding_opt(E)
+ sma_stream_opt(F). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D), E, F); }
%type func_list { SNodeList* }
%destructor func_list { nodesDestroyList($$); }
@@ -413,11 +426,19 @@ func_list(A) ::= func_list(B) NK_COMMA func(C).
func(A) ::= function_name(B) NK_LP expression_list(C) NK_RP. { A = createFunctionNode(pCxt, &B, C); }
+sma_stream_opt(A) ::= . { A = createStreamOptions(pCxt); }
+sma_stream_opt(A) ::= stream_options(B) WATERMARK duration_literal(C). { ((SStreamOptions*)B)->pWatermark = releaseRawExprNode(pCxt, C); A = B; }
+sma_stream_opt(A) ::= stream_options(B) MAX_DELAY duration_literal(C). { ((SStreamOptions*)B)->pDelay = releaseRawExprNode(pCxt, C); A = B; }
+
/************************************************ create/drop topic ***************************************************/
-cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS query_expression(C). { pCxt->pRootNode = createCreateTopicStmt(pCxt, A, &B, C, NULL, NULL); }
-cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS DATABASE db_name(C). { pCxt->pRootNode = createCreateTopicStmt(pCxt, A, &B, NULL, &C, NULL); }
-cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B)
- AS STABLE full_table_name(C). { pCxt->pRootNode = createCreateTopicStmt(pCxt, A, &B, NULL, NULL, C); }
+cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS query_expression(C). { pCxt->pRootNode = createCreateTopicStmtUseQuery(pCxt, A, &B, C); }
+cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS DATABASE db_name(C). { pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, A, &B, &C, false); }
+cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B)
+ WITH META AS DATABASE db_name(C). { pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, A, &B, &C, true); }
+cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B)
+ AS STABLE full_table_name(C). { pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, A, &B, C, false); }
+cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B)
+ WITH META AS STABLE full_table_name(C). { pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, A, &B, C, true); }
cmd ::= DROP TOPIC exists_opt(A) topic_name(B). { pCxt->pRootNode = createDropTopicStmt(pCxt, A, &B); }
cmd ::= DROP CONSUMER GROUP exists_opt(A) cgroup_name(B) ON topic_name(C). { pCxt->pRootNode = createDropCGroupStmt(pCxt, A, &B, &C); }
@@ -471,6 +492,7 @@ stream_options(A) ::= stream_options(B) TRIGGER AT_ONCE.
stream_options(A) ::= stream_options(B) TRIGGER WINDOW_CLOSE. { ((SStreamOptions*)B)->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; A = B; }
stream_options(A) ::= stream_options(B) TRIGGER MAX_DELAY duration_literal(C). { ((SStreamOptions*)B)->triggerType = STREAM_TRIGGER_MAX_DELAY; ((SStreamOptions*)B)->pDelay = releaseRawExprNode(pCxt, C); A = B; }
stream_options(A) ::= stream_options(B) WATERMARK duration_literal(C). { ((SStreamOptions*)B)->pWatermark = releaseRawExprNode(pCxt, C); A = B; }
+stream_options(A) ::= stream_options(B) IGNORE EXPIRED. { ((SStreamOptions*)B)->ignoreExpired = true; A = B; }
/************************************************ kill connection/query ***********************************************/
cmd ::= KILL CONNECTION NK_INTEGER(A). { pCxt->pRootNode = createKillStmt(pCxt, QUERY_NODE_KILL_CONNECTION_STMT, &A); }
@@ -497,6 +519,11 @@ cmd ::= DELETE FROM full_table_name(A) where_clause_opt(B).
/************************************************ select **************************************************************/
cmd ::= query_expression(A). { pCxt->pRootNode = A; }
+/************************************************ insert **************************************************************/
+cmd ::= INSERT INTO full_table_name(A)
+ NK_LP col_name_list(B) NK_RP query_expression(C). { pCxt->pRootNode = createInsertStmt(pCxt, A, B, C); }
+cmd ::= INSERT INTO full_table_name(A) query_expression(B). { pCxt->pRootNode = createInsertStmt(pCxt, A, NULL, B); }
+
/************************************************ literal *************************************************************/
literal(A) ::= NK_INTEGER(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B)); }
literal(A) ::= NK_FLOAT(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B)); }
@@ -531,6 +558,7 @@ signed_literal(A) ::= TIMESTAMP NK_STRING(B).
signed_literal(A) ::= duration_literal(B). { A = releaseRawExprNode(pCxt, B); }
signed_literal(A) ::= NULL(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &B); }
signed_literal(A) ::= literal_func(B). { A = releaseRawExprNode(pCxt, B); }
+signed_literal(A) ::= NK_QUESTION(B). { A = createPlaceholderValueNode(pCxt, &B); }
%type literal_list { SNodeList* }
%destructor literal_list { nodesDestroyList($$); }
@@ -627,6 +655,16 @@ expression(A) ::= column_reference(B) NK_ARROW NK_STRING(C).
SToken s = getTokenFromRawExprNode(pCxt, B);
A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, B), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &C)));
}
+expression(A) ::= expression(B) NK_BITAND expression(C). {
+ SToken s = getTokenFromRawExprNode(pCxt, B);
+ SToken e = getTokenFromRawExprNode(pCxt, C);
+ A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
+ }
+expression(A) ::= expression(B) NK_BITOR expression(C). {
+ SToken s = getTokenFromRawExprNode(pCxt, B);
+ SToken e = getTokenFromRawExprNode(pCxt, C);
+ A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
+ }
%type expression_list { SNodeList* }
%destructor expression_list { nodesDestroyList($$); }
@@ -639,10 +677,11 @@ column_reference(A) ::= table_name(B) NK_DOT column_name(C).
pseudo_column(A) ::= ROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
pseudo_column(A) ::= TBNAME(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
pseudo_column(A) ::= table_name(B) NK_DOT TBNAME(C). { A = createRawExprNodeExt(pCxt, &B, &C, createFunctionNode(pCxt, &C, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &B)))); }
-pseudo_column(A) ::= QSTARTTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
-pseudo_column(A) ::= QENDTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
-pseudo_column(A) ::= WSTARTTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
-pseudo_column(A) ::= WENDTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
+pseudo_column(A) ::= QSTART(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
+pseudo_column(A) ::= QEND(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
+pseudo_column(A) ::= QDURATION(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
+pseudo_column(A) ::= WSTART(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
+pseudo_column(A) ::= WEND(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
pseudo_column(A) ::= WDURATION(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
@@ -658,6 +697,12 @@ literal_func(A) ::= NOW(B).
noarg_func(A) ::= NOW(B). { A = B; }
noarg_func(A) ::= TODAY(B). { A = B; }
noarg_func(A) ::= TIMEZONE(B). { A = B; }
+noarg_func(A) ::= DATABASE(B). { A = B; }
+noarg_func(A) ::= CLIENT_VERSION(B). { A = B; }
+noarg_func(A) ::= SERVER_VERSION(B). { A = B; }
+noarg_func(A) ::= SERVER_STATUS(B). { A = B; }
+noarg_func(A) ::= CURRENT_USER(B). { A = B; }
+noarg_func(A) ::= USER(B). { A = B; }
%type star_func { SToken }
%destructor star_func { }
@@ -729,7 +774,7 @@ compare_op(A) ::= CONTAINS.
in_op(A) ::= IN. { A = OP_TYPE_IN; }
in_op(A) ::= NOT IN. { A = OP_TYPE_NOT_IN; }
-in_predicate_value(A) ::= NK_LP(C) expression_list(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, createNodeListNode(pCxt, B)); }
+in_predicate_value(A) ::= NK_LP(C) literal_list(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, createNodeListNode(pCxt, B)); }
/************************************************ boolean_value_expression ********************************************/
boolean_value_expression(A) ::= boolean_primary(B). { A = B; }
@@ -757,8 +802,9 @@ boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D).
common_expression(A) ::= expression(B). { A = B; }
common_expression(A) ::= boolean_value_expression(B). { A = B; }
-/************************************************ from_clause *********************************************************/
-from_clause(A) ::= FROM table_reference_list(B). { A = B; }
+/************************************************ from_clause_opt *********************************************************/
+from_clause_opt(A) ::= . { A = NULL; }
+from_clause_opt(A) ::= FROM table_reference_list(B). { A = B; }
table_reference_list(A) ::= table_reference(B). { A = B; }
table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, B, C, NULL); }
@@ -792,9 +838,9 @@ join_type(A) ::= INNER.
/************************************************ query_specification *************************************************/
query_specification(A) ::=
- SELECT set_quantifier_opt(B) select_list(C) from_clause(D) where_clause_opt(E)
- partition_by_clause_opt(F) range_opt(J) every_opt(K) fill_opt(L) twindow_clause_opt(G)
- group_by_clause_opt(H) having_clause_opt(I). {
+ SELECT set_quantifier_opt(B) select_list(C) from_clause_opt(D)
+ where_clause_opt(E) partition_by_clause_opt(F) range_opt(J) every_opt(K)
+ fill_opt(L) twindow_clause_opt(G) group_by_clause_opt(H) having_clause_opt(I). {
A = createSelectStmt(pCxt, B, C, D);
A = addWhereClause(pCxt, A, E);
A = addPartitionByClause(pCxt, A, F);
@@ -814,14 +860,10 @@ set_quantifier_opt(A) ::= ALL.
%type select_list { SNodeList* }
%destructor select_list { nodesDestroyList($$); }
-select_list(A) ::= NK_STAR. { A = NULL; }
-select_list(A) ::= select_sublist(B). { A = B; }
-
-%type select_sublist { SNodeList* }
-%destructor select_sublist { nodesDestroyList($$); }
-select_sublist(A) ::= select_item(B). { A = createNodeList(pCxt, B); }
-select_sublist(A) ::= select_sublist(B) NK_COMMA select_item(C). { A = addNodeToList(pCxt, B, C); }
+select_list(A) ::= select_item(B). { A = createNodeList(pCxt, B); }
+select_list(A) ::= select_list(B) NK_COMMA select_item(C). { A = addNodeToList(pCxt, B, C); }
+select_item(A) ::= NK_STAR(B). { A = createColumnNode(pCxt, NULL, &B); }
select_item(A) ::= common_expression(B). { A = releaseRawExprNode(pCxt, B); }
select_item(A) ::= common_expression(B) column_alias(C). { A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); }
select_item(A) ::= common_expression(B) AS column_alias(C). { A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); }
@@ -897,7 +939,11 @@ query_expression_body(A) ::=
query_primary(A) ::= query_specification(B). { A = B; }
query_primary(A) ::=
NK_LP query_expression_body(B)
- order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP. { A = B; }
+ order_by_clause_opt(C) slimit_clause_opt(D) limit_clause_opt(E) NK_RP. {
+ A = addOrderByClause(pCxt, B, C);
+ A = addSlimitClause(pCxt, A, D);
+ A = addLimitClause(pCxt, A, E);
+ }
%type order_by_clause_opt { SNodeList* }
%destructor order_by_clause_opt { nodesDestroyList($$); }
@@ -942,4 +988,4 @@ null_ordering_opt(A) ::= .
null_ordering_opt(A) ::= NULLS FIRST. { A = NULL_ORDER_FIRST; }
null_ordering_opt(A) ::= NULLS LAST. { A = NULL_ORDER_LAST; }
-%fallback ID NK_BITNOT INSERT VALUES IMPORT NK_SEMI FILE.
+%fallback ID NK_BITNOT VALUES IMPORT NK_SEMI FILE.
diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c
index 4fc5cf96e59a547737a0d758fac45fbc3b23bb45..a7806f5e34613170b2e5069810524258314ed758 100644
--- a/source/libs/parser/src/parAstCreater.c
+++ b/source/libs/parser/src/parAstCreater.c
@@ -339,6 +339,10 @@ SNode* createDefaultDatabaseCondValue(SAstCreateContext* pCxt) {
SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
CHECK_PARSER_STATUS(pCxt);
+ if (NULL == pCxt->pQueryCxt->pStmtCb) {
+ pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
+ return NULL;
+ }
SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
CHECK_OUT_OF_MEM(val);
val->literal = strndup(pLiteral->z, pLiteral->n);
@@ -385,6 +389,15 @@ SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType typ
SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight) {
CHECK_PARSER_STATUS(pCxt);
+ if (OP_TYPE_MINUS == type && QUERY_NODE_VALUE == nodeType(pLeft)) {
+ SValueNode* pVal = (SValueNode*)pLeft;
+ char* pNewLiteral = taosMemoryCalloc(1, strlen(pVal->literal) + 2);
+ CHECK_OUT_OF_MEM(pNewLiteral);
+ sprintf(pNewLiteral, "-%s", pVal->literal);
+ taosMemoryFree(pVal->literal);
+ pVal->literal = pNewLiteral;
+ return pLeft;
+ }
SOperatorNode* op = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR);
CHECK_OUT_OF_MEM(op);
op->opType = type;
@@ -585,7 +598,7 @@ SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) {
nodesDestroyNode((SNode*)fill);
CHECK_OUT_OF_MEM(fill->pWStartTs);
}
- strcpy(((SFunctionNode*)fill->pWStartTs)->functionName, "_wstartts");
+ strcpy(((SFunctionNode*)fill->pWStartTs)->functionName, "_wstart");
return (SNode*)fill;
}
@@ -656,6 +669,9 @@ SNode* addHavingClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pHaving) {
SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList) {
CHECK_PARSER_STATUS(pCxt);
+ if (NULL == pOrderByList) {
+ return pStmt;
+ }
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
((SSelectStmt*)pStmt)->pOrderByList = pOrderByList;
} else {
@@ -666,6 +682,9 @@ SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrder
SNode* addSlimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) {
CHECK_PARSER_STATUS(pCxt);
+ if (NULL == pSlimit) {
+ return pStmt;
+ }
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
((SSelectStmt*)pStmt)->pSlimit = (SLimitNode*)pSlimit;
}
@@ -674,6 +693,9 @@ SNode* addSlimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) {
SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit) {
CHECK_PARSER_STATUS(pCxt);
+ if (NULL == pLimit) {
+ return pStmt;
+ }
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
((SSelectStmt*)pStmt)->pLimit = (SLimitNode*)pLimit;
} else {
@@ -717,7 +739,8 @@ SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pPr
select->pProjectionList = pProjectionList;
select->pFromTable = pTable;
sprintf(select->stmtName, "%p", select);
- select->isTimeOrderQuery = true;
+ select->isTimeLineResult = true;
+ select->timeRange = TSWINDOW_INITIALIZER;
return (SNode*)select;
}
@@ -737,7 +760,8 @@ SNode* createDefaultDatabaseOptions(SAstCreateContext* pCxt) {
SDatabaseOptions* pOptions = (SDatabaseOptions*)nodesMakeNode(QUERY_NODE_DATABASE_OPTIONS);
CHECK_OUT_OF_MEM(pOptions);
pOptions->buffer = TSDB_DEFAULT_BUFFER_PER_VNODE;
- pOptions->cachelast = TSDB_DEFAULT_CACHE_LAST_ROW;
+ pOptions->cacheLast = TSDB_DEFAULT_CACHE_LAST;
+ pOptions->cacheLastSize = TSDB_DEFAULT_CACHE_LAST_SIZE;
pOptions->compressionLevel = TSDB_DEFAULT_COMP_LEVEL;
pOptions->daysPerFile = TSDB_DEFAULT_DAYS_PER_FILE;
pOptions->fsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
@@ -763,7 +787,8 @@ SNode* createAlterDatabaseOptions(SAstCreateContext* pCxt) {
SDatabaseOptions* pOptions = (SDatabaseOptions*)nodesMakeNode(QUERY_NODE_DATABASE_OPTIONS);
CHECK_OUT_OF_MEM(pOptions);
pOptions->buffer = -1;
- pOptions->cachelast = -1;
+ pOptions->cacheLast = -1;
+ pOptions->cacheLastSize = -1;
pOptions->compressionLevel = -1;
pOptions->daysPerFile = -1;
pOptions->fsyncPeriod = -1;
@@ -791,7 +816,10 @@ SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOpti
((SDatabaseOptions*)pOptions)->buffer = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
break;
case DB_OPTION_CACHELAST:
- ((SDatabaseOptions*)pOptions)->cachelast = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
+ ((SDatabaseOptions*)pOptions)->cacheLast = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
+ break;
+ case DB_OPTION_CACHELASTSIZE:
+ ((SDatabaseOptions*)pOptions)->cacheLastSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
break;
case DB_OPTION_COMP:
((SDatabaseOptions*)pOptions)->compressionLevel = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
@@ -903,6 +931,28 @@ SNode* createAlterDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode*
return (SNode*)pStmt;
}
+SNode* createFlushDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
+ CHECK_PARSER_STATUS(pCxt);
+ if (!checkDbName(pCxt, pDbName, false)) {
+ return NULL;
+ }
+ SFlushDatabaseStmt* pStmt = (SFlushDatabaseStmt*)nodesMakeNode(QUERY_NODE_FLUSH_DATABASE_STMT);
+ CHECK_OUT_OF_MEM(pStmt);
+ COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
+ return (SNode*)pStmt;
+}
+
+SNode* createTrimDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
+ CHECK_PARSER_STATUS(pCxt);
+ if (!checkDbName(pCxt, pDbName, false)) {
+ return NULL;
+ }
+ STrimDatabaseStmt* pStmt = (STrimDatabaseStmt*)nodesMakeNode(QUERY_NODE_TRIM_DATABASE_STMT);
+ CHECK_OUT_OF_MEM(pStmt);
+ COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
+ return (SNode*)pStmt;
+}
+
SNode* createDefaultTableOptions(SAstCreateContext* pCxt) {
CHECK_PARSER_STATUS(pCxt);
STableOptions* pOptions = (STableOptions*)nodesMakeNode(QUERY_NODE_TABLE_OPTIONS);
@@ -1127,6 +1177,11 @@ SNode* createAlterTableSetTag(SAstCreateContext* pCxt, SNode* pRealTable, SToken
return createAlterTableStmtFinalize(pRealTable, pStmt);
}
+SNode* setAlterSuperTableType(SNode* pStmt) {
+ setNodeType(pStmt, QUERY_NODE_ALTER_SUPER_TABLE_STMT);
+ return pStmt;
+}
+
SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
CHECK_PARSER_STATUS(pCxt);
if (!checkDbName(pCxt, pDbName, false)) {
@@ -1205,7 +1260,7 @@ SNode* createShowDnodeVariablesStmt(SAstCreateContext* pCxt, SNode* pDnodeId) {
return (SNode*)pStmt;
}
-SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const SToken* pPassword) {
+SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const SToken* pPassword, int8_t sysinfo) {
CHECK_PARSER_STATUS(pCxt);
char password[TSDB_USET_PASSWORD_LEN] = {0};
if (!checkUserName(pCxt, pUserName) || !checkPassword(pCxt, pPassword, password)) {
@@ -1215,6 +1270,7 @@ SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const ST
CHECK_OUT_OF_MEM(pStmt);
COPY_STRING_FORM_ID_TOKEN(pStmt->useName, pUserName);
strcpy(pStmt->password, password);
+ pStmt->sysinfo = sysinfo;
return (SNode*)pStmt;
}
@@ -1226,15 +1282,26 @@ SNode* createAlterUserStmt(SAstCreateContext* pCxt, SToken* pUserName, int8_t al
SAlterUserStmt* pStmt = (SAlterUserStmt*)nodesMakeNode(QUERY_NODE_ALTER_USER_STMT);
CHECK_OUT_OF_MEM(pStmt);
COPY_STRING_FORM_ID_TOKEN(pStmt->useName, pUserName);
- if (TSDB_ALTER_USER_PASSWD == alterType) {
- char password[TSDB_USET_PASSWORD_LEN] = {0};
- if (!checkPassword(pCxt, pVal, password)) {
- nodesDestroyNode((SNode*)pStmt);
- return NULL;
+ pStmt->alterType = alterType;
+ switch (alterType) {
+ case TSDB_ALTER_USER_PASSWD: {
+ char password[TSDB_USET_PASSWORD_LEN] = {0};
+ if (!checkPassword(pCxt, pVal, password)) {
+ nodesDestroyNode((SNode*)pStmt);
+ return NULL;
+ }
+ strcpy(pStmt->password, password);
+ break;
}
- strcpy(pStmt->password, password);
+ case TSDB_ALTER_USER_ENABLE:
+ pStmt->enable = taosStr2Int8(pVal->z, NULL, 10);
+ break;
+ case TSDB_ALTER_USER_SYSINFO:
+ pStmt->sysinfo = taosStr2Int8(pVal->z, NULL, 10);
+ break;
+ default:
+ break;
}
- pStmt->alterType = alterType;
return (SNode*)pStmt;
}
@@ -1305,8 +1372,8 @@ SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool igno
return (SNode*)pStmt;
}
-SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInterval, SNode* pOffset,
- SNode* pSliding) {
+SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInterval, SNode* pOffset, SNode* pSliding,
+ SNode* pStreamOptions) {
CHECK_PARSER_STATUS(pCxt);
SIndexOptions* pOptions = (SIndexOptions*)nodesMakeNode(QUERY_NODE_INDEX_OPTIONS);
CHECK_OUT_OF_MEM(pOptions);
@@ -1314,19 +1381,19 @@ SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInt
pOptions->pInterval = pInterval;
pOptions->pOffset = pOffset;
pOptions->pSliding = pSliding;
+ pOptions->pStreamOptions = pStreamOptions;
return (SNode*)pOptions;
}
-SNode* createDropIndexStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pIndexName, SToken* pTableName) {
+SNode* createDropIndexStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pIndexName) {
CHECK_PARSER_STATUS(pCxt);
- if (!checkIndexName(pCxt, pIndexName) || !checkTableName(pCxt, pTableName)) {
+ if (!checkDbName(pCxt, NULL, true) || !checkIndexName(pCxt, pIndexName)) {
return NULL;
}
SDropIndexStmt* pStmt = (SDropIndexStmt*)nodesMakeNode(QUERY_NODE_DROP_INDEX_STMT);
CHECK_OUT_OF_MEM(pStmt);
pStmt->ignoreNotExists = ignoreNotExists;
COPY_STRING_FORM_ID_TOKEN(pStmt->indexName, pIndexName);
- COPY_STRING_FORM_ID_TOKEN(pStmt->tableName, pTableName);
return (SNode*)pStmt;
}
@@ -1346,22 +1413,40 @@ SNode* createDropComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, cons
return (SNode*)pStmt;
}
-SNode* createCreateTopicStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName, SNode* pQuery,
- const SToken* pSubDbName, SNode* pRealTable) {
+SNode* createCreateTopicStmtUseQuery(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ SNode* pQuery) {
CHECK_PARSER_STATUS(pCxt);
SCreateTopicStmt* pStmt = (SCreateTopicStmt*)nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT);
CHECK_OUT_OF_MEM(pStmt);
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
pStmt->ignoreExists = ignoreExists;
- if (NULL != pRealTable) {
- strcpy(pStmt->subDbName, ((SRealTableNode*)pRealTable)->table.dbName);
- strcpy(pStmt->subSTbName, ((SRealTableNode*)pRealTable)->table.tableName);
- nodesDestroyNode(pRealTable);
- } else if (NULL != pSubDbName) {
- COPY_STRING_FORM_ID_TOKEN(pStmt->subDbName, pSubDbName);
- } else {
- pStmt->pQuery = pQuery;
- }
+ pStmt->pQuery = pQuery;
+ return (SNode*)pStmt;
+}
+
+SNode* createCreateTopicStmtUseDb(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ const SToken* pSubDbName, bool withMeta) {
+ CHECK_PARSER_STATUS(pCxt);
+ SCreateTopicStmt* pStmt = (SCreateTopicStmt*)nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT);
+ CHECK_OUT_OF_MEM(pStmt);
+ COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
+ pStmt->ignoreExists = ignoreExists;
+ COPY_STRING_FORM_ID_TOKEN(pStmt->subDbName, pSubDbName);
+ pStmt->withMeta = withMeta;
+ return (SNode*)pStmt;
+}
+
+SNode* createCreateTopicStmtUseTable(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName,
+ SNode* pRealTable, bool withMeta) {
+ CHECK_PARSER_STATUS(pCxt);
+ SCreateTopicStmt* pStmt = (SCreateTopicStmt*)nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT);
+ CHECK_OUT_OF_MEM(pStmt);
+ COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
+ pStmt->ignoreExists = ignoreExists;
+ pStmt->withMeta = withMeta;
+ strcpy(pStmt->subDbName, ((SRealTableNode*)pRealTable)->table.dbName);
+ strcpy(pStmt->subSTbName, ((SRealTableNode*)pRealTable)->table.tableName);
+ nodesDestroyNode(pRealTable);
return (SNode*)pStmt;
}
@@ -1618,3 +1703,18 @@ SNode* createDeleteStmt(SAstCreateContext* pCxt, SNode* pTable, SNode* pWhere) {
}
return (SNode*)pStmt;
}
+
+SNode* createInsertStmt(SAstCreateContext* pCxt, SNode* pTable, SNodeList* pCols, SNode* pQuery) {
+ CHECK_PARSER_STATUS(pCxt);
+ SInsertStmt* pStmt = (SInsertStmt*)nodesMakeNode(QUERY_NODE_INSERT_STMT);
+ CHECK_OUT_OF_MEM(pStmt);
+ pStmt->pTable = pTable;
+ pStmt->pCols = pCols;
+ pStmt->pQuery = pQuery;
+ if (QUERY_NODE_SELECT_STMT == nodeType(pQuery)) {
+ strcpy(((SSelectStmt*)pQuery)->stmtName, ((STableNode*)pTable)->tableAlias);
+ } else if (QUERY_NODE_SET_OPERATOR == nodeType(pQuery)) {
+ strcpy(((SSetOperator*)pQuery)->stmtName, ((STableNode*)pTable)->tableAlias);
+ }
+ return (SNode*)pStmt;
+}
diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c
index 131eccae247265b4c7e7d94f041031453f3b92a4..2060c3da4c0f3343bae442c5fe806db640a708d1 100644
--- a/source/libs/parser/src/parAstParser.c
+++ b/source/libs/parser/src/parAstParser.c
@@ -137,6 +137,9 @@ static int32_t collectMetaKeyFromRealTableImpl(SCollectMetaKeyCxt* pCxt, SRealTa
code = reserveTableIndexInCache(pCxt->pParseCxt->acctId, pRealTable->table.dbName, pRealTable->table.tableName,
pCxt->pMetaCache);
}
+ if (TSDB_CODE_SUCCESS == code && (0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_DNODE_VARIABLES))) {
+ code = reserveDnodeRequiredInCache(pCxt->pMetaCache);
+ }
return code;
}
@@ -192,6 +195,10 @@ static int32_t collectMetaKeyFromAlterDatabase(SCollectMetaKeyCxt* pCxt, SAlterD
return reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache);
}
+static int32_t collectMetaKeyFromFlushDatabase(SCollectMetaKeyCxt* pCxt, SFlushDatabaseStmt* pStmt) {
+ return reserveDbVgInfoInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache);
+}
+
static int32_t collectMetaKeyFromCreateTable(SCollectMetaKeyCxt* pCxt, SCreateTableStmt* pStmt) {
int32_t code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache);
if (TSDB_CODE_SUCCESS == code && NULL == pStmt->pTags) {
@@ -244,6 +251,10 @@ static int32_t collectMetaKeyFromAlterTable(SCollectMetaKeyCxt* pCxt, SAlterTabl
return code;
}
+static int32_t collectMetaKeyFromAlterStable(SCollectMetaKeyCxt* pCxt, SAlterTableStmt* pStmt) {
+ return reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache);
+}
+
static int32_t collectMetaKeyFromUseDatabase(SCollectMetaKeyCxt* pCxt, SUseDatabaseStmt* pStmt) {
return reserveDbVgVersionInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache);
}
@@ -259,6 +270,9 @@ static int32_t collectMetaKeyFromCreateIndex(SCollectMetaKeyCxt* pCxt, SCreateIn
if (TSDB_CODE_SUCCESS == code) {
code = reserveDbVgInfoInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->db, pCxt->pMetaCache);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->db, pCxt->pMetaCache);
+ }
}
return code;
}
@@ -377,6 +391,11 @@ static int32_t collectMetaKeyFromShowTopics(SCollectMetaKeyCxt* pCxt, SShowStmt*
pCxt->pMetaCache);
}
+static int32_t collectMetaKeyFromShowConsumers(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
+ return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_CONSUMERS,
+ pCxt->pMetaCache);
+}
+
static int32_t collectMetaKeyFromShowConnections(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_CONNECTIONS,
pCxt->pMetaCache);
@@ -411,7 +430,14 @@ static int32_t collectMetaKeyFromShowCreateDatabase(SCollectMetaKeyCxt* pCxt, SS
}
static int32_t collectMetaKeyFromShowCreateTable(SCollectMetaKeyCxt* pCxt, SShowCreateTableStmt* pStmt) {
- return reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache);
+ SName name = {.type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId};
+ strcpy(name.dbname, pStmt->dbName);
+ strcpy(name.tname, pStmt->tableName);
+ int32_t code = catalogRemoveTableMeta(pCxt->pParseCxt->pCatalog, &name);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = reserveTableCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache);
+ }
+ return code;
}
static int32_t collectMetaKeyFromShowApps(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
@@ -428,6 +454,14 @@ static int32_t collectMetaKeyFromDelete(SCollectMetaKeyCxt* pCxt, SDeleteStmt* p
return collectMetaKeyFromRealTableImpl(pCxt, (SRealTableNode*)pStmt->pFromTable, AUTH_TYPE_WRITE);
}
+static int32_t collectMetaKeyFromInsert(SCollectMetaKeyCxt* pCxt, SInsertStmt* pStmt) {
+ int32_t code = collectMetaKeyFromRealTableImpl(pCxt, (SRealTableNode*)pStmt->pTable, AUTH_TYPE_WRITE);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = collectMetaKeyFromQuery(pCxt, pStmt->pQuery);
+ }
+ return code;
+}
+
static int32_t collectMetaKeyFromShowBlockDist(SCollectMetaKeyCxt* pCxt, SShowTableDistributedStmt* pStmt) {
SName name = {.type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId};
strcpy(name.dbname, pStmt->dbName);
@@ -446,6 +480,11 @@ static int32_t collectMetaKeyFromShowBlockDist(SCollectMetaKeyCxt* pCxt, SShowTa
return code;
}
+static int32_t collectMetaKeyFromShowSubscriptions(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
+ return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_SUBSCRIPTIONS,
+ pCxt->pMetaCache);
+}
+
static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
pCxt->pStmt = pStmt;
switch (nodeType(pStmt)) {
@@ -455,6 +494,8 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
return collectMetaKeyFromSelect(pCxt, (SSelectStmt*)pStmt);
case QUERY_NODE_ALTER_DATABASE_STMT:
return collectMetaKeyFromAlterDatabase(pCxt, (SAlterDatabaseStmt*)pStmt);
+ case QUERY_NODE_FLUSH_DATABASE_STMT:
+ return collectMetaKeyFromFlushDatabase(pCxt, (SFlushDatabaseStmt*)pStmt);
case QUERY_NODE_CREATE_TABLE_STMT:
return collectMetaKeyFromCreateTable(pCxt, (SCreateTableStmt*)pStmt);
case QUERY_NODE_CREATE_MULTI_TABLE_STMT:
@@ -463,6 +504,8 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
return collectMetaKeyFromDropTable(pCxt, (SDropTableStmt*)pStmt);
case QUERY_NODE_ALTER_TABLE_STMT:
return collectMetaKeyFromAlterTable(pCxt, (SAlterTableStmt*)pStmt);
+ case QUERY_NODE_ALTER_SUPER_TABLE_STMT:
+ return collectMetaKeyFromAlterStable(pCxt, (SAlterTableStmt*)pStmt);
case QUERY_NODE_USE_DATABASE_STMT:
return collectMetaKeyFromUseDatabase(pCxt, (SUseDatabaseStmt*)pStmt);
case QUERY_NODE_CREATE_INDEX_STMT:
@@ -507,6 +550,8 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
return collectMetaKeyFromShowVgroups(pCxt, (SShowStmt*)pStmt);
case QUERY_NODE_SHOW_TOPICS_STMT:
return collectMetaKeyFromShowTopics(pCxt, (SShowStmt*)pStmt);
+ case QUERY_NODE_SHOW_CONSUMERS_STMT:
+ return collectMetaKeyFromShowConsumers(pCxt, (SShowStmt*)pStmt);
case QUERY_NODE_SHOW_CONNECTIONS_STMT:
return collectMetaKeyFromShowConnections(pCxt, (SShowStmt*)pStmt);
case QUERY_NODE_SHOW_QUERIES_STMT:
@@ -526,8 +571,12 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
return collectMetaKeyFromShowTransactions(pCxt, (SShowStmt*)pStmt);
case QUERY_NODE_DELETE_STMT:
return collectMetaKeyFromDelete(pCxt, (SDeleteStmt*)pStmt);
+ case QUERY_NODE_INSERT_STMT:
+ return collectMetaKeyFromInsert(pCxt, (SInsertStmt*)pStmt);
case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT:
return collectMetaKeyFromShowBlockDist(pCxt, (SShowTableDistributedStmt*)pStmt);
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
+ return collectMetaKeyFromShowSubscriptions(pCxt, (SShowStmt*)pStmt);
default:
break;
}
diff --git a/source/libs/parser/src/parAuthenticator.c b/source/libs/parser/src/parAuthenticator.c
index 068ac4c94d2fb84e5a5992b5744d13f876cc5d75..befc822808c7b50eeaea5753a61bb10ffef81523 100644
--- a/source/libs/parser/src/parAuthenticator.c
+++ b/source/libs/parser/src/parAuthenticator.c
@@ -39,7 +39,7 @@ static int32_t checkAuth(SAuthCxt* pCxt, const char* pDbName, AUTH_TYPE type) {
if (NULL != pCxt->pMetaCache) {
code = getUserAuthFromCache(pCxt->pMetaCache, pParseCxt->pUser, dbFname, type, &pass);
} else {
- SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter,
+ SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter,
.requestId = pParseCxt->requestId,
.requestObjRefId = pParseCxt->requestRid,
.mgmtEps = pParseCxt->mgmtEpSet};
@@ -88,6 +88,14 @@ static int32_t authDelete(SAuthCxt* pCxt, SDeleteStmt* pDelete) {
return checkAuth(pCxt, ((SRealTableNode*)pDelete->pFromTable)->table.dbName, AUTH_TYPE_WRITE);
}
+static int32_t authInsert(SAuthCxt* pCxt, SInsertStmt* pInsert) {
+ int32_t code = checkAuth(pCxt, ((SRealTableNode*)pInsert->pTable)->table.dbName, AUTH_TYPE_WRITE);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = authQuery(pCxt, pInsert->pQuery);
+ }
+ return code;
+}
+
static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) {
switch (nodeType(pStmt)) {
case QUERY_NODE_SET_OPERATOR:
@@ -98,6 +106,8 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) {
return authDropUser(pCxt, (SDropUserStmt*)pStmt);
case QUERY_NODE_DELETE_STMT:
return authDelete(pCxt, (SDeleteStmt*)pStmt);
+ case QUERY_NODE_INSERT_STMT:
+ return authInsert(pCxt, (SInsertStmt*)pStmt);
default:
break;
}
diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c
index 22d7afd6424a291e397a5a206f822ddadd1e2bc8..68a60e0b35f54a2a12a7cb9b5e1c506f8b6a2a7b 100644
--- a/source/libs/parser/src/parCalcConst.c
+++ b/source/libs/parser/src/parCalcConst.c
@@ -166,7 +166,7 @@ static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bo
return code;
}
-static int32_t calcConstProject(SNode* pProject, SNode** pNew) {
+static int32_t calcConstProject(SNode* pProject, bool dual, SNode** pNew) {
SArray* pAssociation = NULL;
if (NULL != ((SExprNode*)pProject)->pAssociation) {
pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation);
@@ -175,36 +175,60 @@ static int32_t calcConstProject(SNode* pProject, SNode** pNew) {
}
}
- int32_t code = scalarCalculateConstants(pProject, pNew);
+ char aliasName[TSDB_COL_NAME_LEN] = {0};
+ strcpy(aliasName, ((SExprNode*)pProject)->aliasName);
+ int32_t code = TSDB_CODE_SUCCESS;
+ if (dual) {
+ code = scalarCalculateConstantsFromDual(pProject, pNew);
+ } else {
+ code = scalarCalculateConstants(pProject, pNew);
+ }
if (TSDB_CODE_SUCCESS == code && QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
+ strcpy(((SExprNode*)*pNew)->aliasName, aliasName);
int32_t size = taosArrayGetSize(pAssociation);
for (int32_t i = 0; i < size; ++i) {
SNode** pCol = taosArrayGetP(pAssociation, i);
+ nodesDestroyNode(*pCol);
*pCol = nodesCloneNode(*pNew);
if (NULL == *pCol) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ break;
}
}
}
+ taosArrayDestroy(pAssociation);
return code;
}
-static bool isUselessCol(bool hasSelectValFunc, SExprNode* pProj) {
- if (hasSelectValFunc && QUERY_NODE_FUNCTION == nodeType(pProj) && fmIsSelectFunc(((SFunctionNode*)pProj)->funcId)) {
+static bool isUselessCol(SExprNode* pProj) {
+ if (QUERY_NODE_FUNCTION == nodeType(pProj) && !fmIsScalarFunc(((SFunctionNode*)pProj)->funcId)) {
return false;
}
return NULL == ((SExprNode*)pProj)->pAssociation;
}
+static SNode* createConstantValue() {
+ SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ if (NULL == pVal) {
+ return NULL;
+ }
+ pVal->node.resType.type = TSDB_DATA_TYPE_INT;
+ pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
+ const int32_t val = 1;
+ nodesSetValueNodeValue(pVal, (void*)&val);
+ pVal->translate = true;
+ return (SNode*)pVal;
+}
+
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
SNode* pProj = NULL;
WHERE_EACH(pProj, pSelect->pProjectionList) {
- if (subquery && isUselessCol(pSelect->hasSelectValFunc, (SExprNode*)pProj)) {
+ if (subquery && !pSelect->isDistinct && isUselessCol((SExprNode*)pProj)) {
ERASE_NODE(pSelect->pProjectionList);
continue;
}
SNode* pNew = NULL;
- int32_t code = calcConstProject(pProj, &pNew);
+ int32_t code = calcConstProject(pProj, (NULL == pSelect->pFromTable), &pNew);
if (TSDB_CODE_SUCCESS == code) {
REPLACE_NODE(pNew);
} else {
@@ -212,6 +236,9 @@ static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelec
}
WHERE_NEXT;
}
+ if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
+ return nodesListStrictAppend(pSelect->pProjectionList, createConstantValue());
+ }
return TSDB_CODE_SUCCESS;
}
@@ -227,12 +254,16 @@ static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
}
}
}
- DESTORY_LIST(pSelect->pGroupByList);
+ NODES_DESTORY_LIST(pSelect->pGroupByList);
}
return code;
}
-static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
+static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
+ return calcConstProjections(pCxt, pSelect, subquery);
+}
+
+static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
code = calcConstProjections(pCxt, pSelect, subquery);
@@ -258,6 +289,14 @@ static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bo
return code;
}
+static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
+ if (NULL == pSelect->pFromTable) {
+ return calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
+ } else {
+ return calcConstSelectFrom(pCxt, pSelect, subquery);
+ }
+}
+
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
@@ -266,6 +305,14 @@ static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
return code;
}
+static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) {
+ int32_t code = calcConstFromTable(pCxt, pInsert->pTable);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = calcConstQuery(pCxt, pInsert->pQuery, false);
+ }
+ return code;
+}
+
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pStmt)) {
@@ -286,6 +333,9 @@ static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subque
case QUERY_NODE_DELETE_STMT:
code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
break;
+ case QUERY_NODE_INSERT_STMT:
+ code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
+ break;
default:
break;
}
diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c
index c8b78fcc8bf6acfc242a975014ef2d11b38c4d23..005a7f919a82a19dd8b7e0a59e963303c3b61ee3 100644
--- a/source/libs/parser/src/parInsert.c
+++ b/source/libs/parser/src/parInsert.c
@@ -48,6 +48,12 @@
pSql += sToken.n; \
} while (TK_NK_SPACE == sToken.type)
+typedef struct SInsertParseBaseContext {
+ SParseContext* pComCxt;
+ char* pSql;
+ SMsgBuf msg;
+} SInsertParseBaseContext;
+
typedef struct SInsertParseContext {
SParseContext* pComCxt; // input
char* pSql; // input
@@ -65,8 +71,16 @@ typedef struct SInsertParseContext {
SVnodeModifOpStmt* pOutput;
SStmtCallback* pStmtCb;
SParseMetaCache* pMetaCache;
+ char sTableName[TSDB_TABLE_NAME_LEN];
} SInsertParseContext;
+typedef struct SInsertParseSyntaxCxt {
+ SParseContext* pComCxt;
+ char* pSql;
+ SMsgBuf msg;
+ SParseMetaCache* pMetaCache;
+} SInsertParseSyntaxCxt;
+
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
@@ -97,7 +111,7 @@ typedef struct SMemParam {
static int32_t skipInsertInto(char** pSql, SMsgBuf* pMsg) {
SToken sToken;
NEXT_TOKEN(*pSql, sToken);
- if (TK_INSERT != sToken.type) {
+ if (TK_INSERT != sToken.type && TK_IMPORT != sToken.type) {
return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", sToken.z);
}
NEXT_TOKEN(*pSql, sToken);
@@ -107,86 +121,6 @@ static int32_t skipInsertInto(char** pSql, SMsgBuf* pMsg) {
return TSDB_CODE_SUCCESS;
}
-static int32_t parserValidateIdToken(SToken* pToken) {
- if (pToken == NULL || pToken->z == NULL || pToken->type != TK_NK_ID) {
- return TSDB_CODE_TSC_INVALID_OPERATION;
- }
-
- // it is a token quoted with escape char '`'
- if (pToken->z[0] == TS_ESCAPE_CHAR && pToken->z[pToken->n - 1] == TS_ESCAPE_CHAR) {
- return TSDB_CODE_SUCCESS;
- }
-
- char* sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true);
- if (sep == NULL) { // It is a single part token, not a complex type
- if (isNumber(pToken)) {
- return TSDB_CODE_TSC_INVALID_OPERATION;
- }
-
- strntolower(pToken->z, pToken->z, pToken->n);
- } else { // two part
- int32_t oldLen = pToken->n;
- char* pStr = pToken->z;
-
- if (pToken->type == TK_NK_SPACE) {
- pToken->n = (uint32_t)strtrim(pToken->z);
- }
-
- pToken->n = tGetToken(pToken->z, &pToken->type);
- if (pToken->z[pToken->n] != TS_PATH_DELIMITER[0]) {
- return TSDB_CODE_TSC_INVALID_OPERATION;
- }
-
- if (pToken->type != TK_NK_ID) {
- return TSDB_CODE_TSC_INVALID_OPERATION;
- }
-
- int32_t firstPartLen = pToken->n;
-
- pToken->z = sep + 1;
- pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1);
- int32_t len = tGetToken(pToken->z, &pToken->type);
- if (len != pToken->n || pToken->type != TK_NK_ID) {
- return TSDB_CODE_TSC_INVALID_OPERATION;
- }
-
- // re-build the whole name string
- if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) {
- // first part do not have quote do nothing
- } else {
- pStr[firstPartLen] = TS_PATH_DELIMITER[0];
- memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n);
- uint32_t offset = (uint32_t)(pToken->z - (pStr + firstPartLen + 1));
- memset(pToken->z + pToken->n - offset, ' ', offset);
- }
-
- pToken->n += (firstPartLen + sizeof(TS_PATH_DELIMITER[0]));
- pToken->z = pStr;
-
- strntolower(pToken->z, pToken->z, pToken->n);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-static int32_t buildName(SInsertParseContext* pCxt, SToken* pStname, char* fullDbName, char* tableName) {
- if (parserValidateIdToken(pStname) != TSDB_CODE_SUCCESS) {
- return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pStname->z);
- }
-
- char* p = strnchr(pStname->z, TS_PATH_DELIMITER[0], pStname->n, false);
- if (NULL != p) { // db.table
- int32_t n = sprintf(fullDbName, "%d.", pCxt->pComCxt->acctId);
- strncpy(fullDbName + n, pStname->z, p - pStname->z);
- strncpy(tableName, p + 1, pStname->n - (p - pStname->z) - 1);
- } else {
- snprintf(fullDbName, TSDB_DB_FNAME_LEN, "%d.%s", pCxt->pComCxt->acctId, pCxt->pComCxt->db);
- strncpy(tableName, pStname->z, pStname->n);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
static int32_t createSName(SName* pName, SToken* pTableName, int32_t acctId, const char* dbName, SMsgBuf* pMsgBuf) {
const char* msg1 = "name too long";
const char* msg2 = "invalid database name";
@@ -200,7 +134,10 @@ static int32_t createSName(SName* pName, SToken* pTableName, int32_t acctId, con
assert(*p == TS_PATH_DELIMITER[0]);
int32_t dbLen = p - pTableName->z;
- char name[TSDB_DB_FNAME_LEN] = {0};
+ if (dbLen <= 0) {
+ return buildInvalidOperationMsg(pMsgBuf, msg2);
+ }
+ char name[TSDB_DB_FNAME_LEN] = {0};
strncpy(name, pTableName->z, dbLen);
dbLen = strdequote(name);
@@ -257,7 +194,7 @@ static int32_t checkAuth(SInsertParseContext* pCxt, char* pDbFname, bool* pPass)
if (pBasicCtx->async) {
return getUserAuthFromCache(pCxt->pMetaCache, pBasicCtx->pUser, pDbFname, AUTH_TYPE_WRITE, pPass);
}
- SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
+ SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
.requestId = pBasicCtx->requestId,
.requestObjRefId = pBasicCtx->requestRid,
.mgmtEps = pBasicCtx->mgmtEpSet};
@@ -270,11 +207,11 @@ static int32_t getTableSchema(SInsertParseContext* pCxt, SName* pTbName, bool is
if (pBasicCtx->async) {
return getTableMetaFromCache(pCxt->pMetaCache, pTbName, pTableMeta);
}
- SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
+ SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
.requestId = pBasicCtx->requestId,
.requestObjRefId = pBasicCtx->requestRid,
.mgmtEps = pBasicCtx->mgmtEpSet};
-
+
if (isStb) {
return catalogGetSTableMeta(pBasicCtx->pCatalog, &conn, pTbName, pTableMeta);
}
@@ -286,7 +223,7 @@ static int32_t getTableVgroup(SInsertParseContext* pCxt, SName* pTbName, SVgroup
if (pBasicCtx->async) {
return getTableVgroupFromCache(pCxt->pMetaCache, pTbName, pVg);
}
- SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
+ SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
.requestId = pBasicCtx->requestId,
.requestObjRefId = pBasicCtx->requestRid,
.mgmtEps = pBasicCtx->mgmtEpSet};
@@ -322,7 +259,7 @@ static int32_t getDBCfg(SInsertParseContext* pCxt, const char* pDbFName, SDbCfgI
if (pBasicCtx->async) {
CHECK_CODE(getDbCfgFromCache(pCxt->pMetaCache, pDbFName, pInfo));
} else {
- SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
+ SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
.requestId = pBasicCtx->requestId,
.requestObjRefId = pBasicCtx->requestRid,
.mgmtEps = pBasicCtx->mgmtEpSet};
@@ -783,11 +720,11 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo*
pColIdx[i].schemaColIdx = pColList->boundColumns[i];
pColIdx[i].boundIdx = i;
}
- qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar);
+ taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar);
for (col_id_t i = 0; i < pColList->numOfBound; ++i) {
pColIdx[i].finalIdx = i;
}
- qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar);
+ taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar);
}
if (pColList->numOfCols > pColList->numOfBound) {
@@ -798,11 +735,13 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo*
return TSDB_CODE_SUCCESS;
}
-static void buildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid) {
+static void buildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid, const char* sname, SArray* tagName) {
pTbReq->type = TD_CHILD_TABLE;
pTbReq->name = strdup(tname);
pTbReq->ctb.suid = suid;
+ if(sname) pTbReq->ctb.name = strdup(sname);
pTbReq->ctb.pTag = (uint8_t*)pTag;
+ pTbReq->ctb.tagName = taosArrayDup(tagName);
pTbReq->commentLen = -1;
return;
@@ -822,6 +761,7 @@ static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16
return TSDB_CODE_SUCCESS;
}
+// strcpy(val->colName, pSchema->name);
val->cid = pSchema->colId;
val->type = pSchema->type;
@@ -965,11 +905,11 @@ static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16
case TSDB_DATA_TYPE_NCHAR: {
int32_t output = 0;
- void* p = taosMemoryCalloc(1, pToken->n * TSDB_NCHAR_SIZE);
+ void* p = taosMemoryCalloc(1, pSchema->bytes - VARSTR_HEADER_SIZE);
if (p == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), pToken->n * TSDB_NCHAR_SIZE, &output)) {
+ if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), pSchema->bytes - VARSTR_HEADER_SIZE, &output)) {
if (errno == E2BIG) {
taosMemoryFree(p);
return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
@@ -1000,6 +940,7 @@ static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16
static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint8_t precision, const char* tName) {
int32_t code = TSDB_CODE_SUCCESS;
SArray* pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal));
+ SArray* tagName = taosArrayInit(8, TSDB_COL_NAME_LEN);
SToken sToken;
bool isParseBindParam = false;
bool isJson = false;
@@ -1029,6 +970,10 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint
taosMemoryFree(tmpTokenBuf);
goto end;
}
+
+ if (!isNullStr(&sToken)) {
+ taosArrayPush(tagName, pTagSchema->name);
+ }
if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
if (sToken.n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
code = buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", sToken.z);
@@ -1068,7 +1013,7 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint
goto end;
}
- buildCreateTbReq(&pCxt->createTblReq, tName, pTag, pCxt->pTableMeta->suid);
+ buildCreateTbReq(&pCxt->createTblReq, tName, pTag, pCxt->pTableMeta->suid, pCxt->sTableName, tagName);
end:
for (int i = 0; i < taosArrayGetSize(pTagVals); ++i) {
@@ -1078,18 +1023,10 @@ end:
}
}
taosArrayDestroy(pTagVals);
+ taosArrayDestroy(tagName);
return code;
}
-static int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst) {
- *pDst = taosMemoryMalloc(TABLE_META_SIZE(pSrc));
- if (NULL == *pDst) {
- return TSDB_CODE_TSC_OUT_OF_MEMORY;
- }
- memcpy(*pDst, pSrc, TABLE_META_SIZE(pSrc));
- return TSDB_CODE_SUCCESS;
-}
-
static int32_t storeTableMeta(SInsertParseContext* pCxt, SHashObj* pHash, SName* pTableName, const char* pName,
int32_t len, STableMeta* pMeta) {
SVgroupInfo vg;
@@ -1107,11 +1044,50 @@ static int32_t storeTableMeta(SInsertParseContext* pCxt, SHashObj* pHash, SName*
return taosHashPut(pHash, pName, len, &pBackup, POINTER_BYTES);
}
+static int32_t skipParentheses(SInsertParseSyntaxCxt* pCxt) {
+ SToken sToken;
+ int32_t expectRightParenthesis = 1;
+ while (1) {
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ if (TK_NK_LP == sToken.type) {
+ ++expectRightParenthesis;
+ } else if (TK_NK_RP == sToken.type && 0 == --expectRightParenthesis) {
+ break;
+ }
+ if (0 == sToken.n) {
+ return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
+ }
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t skipBoundColumns(SInsertParseSyntaxCxt* pCxt) { return skipParentheses(pCxt); }
+
+static int32_t ignoreBoundColumns(SInsertParseContext* pCxt) {
+ SInsertParseSyntaxCxt cxt = {.pComCxt = pCxt->pComCxt, .pSql = pCxt->pSql, .msg = pCxt->msg, .pMetaCache = NULL};
+ int32_t code = skipBoundColumns(&cxt);
+ pCxt->pSql = cxt.pSql;
+ return code;
+}
+
+static int32_t skipUsingClause(SInsertParseSyntaxCxt* pCxt);
+
+// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
+static int32_t ignoreAutoCreateTableClause(SInsertParseContext* pCxt) {
+ SToken sToken;
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ SInsertParseSyntaxCxt cxt = {.pComCxt = pCxt->pComCxt, .pSql = pCxt->pSql, .msg = pCxt->msg, .pMetaCache = NULL};
+ int32_t code = skipUsingClause(&cxt);
+ pCxt->pSql = cxt.pSql;
+ return code;
+}
+
// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
static int32_t parseUsingClause(SInsertParseContext* pCxt, SName* name, char* tbFName) {
int32_t len = strlen(tbFName);
STableMeta** pMeta = taosHashGet(pCxt->pSubTableHashObj, tbFName, len);
if (NULL != pMeta) {
+ CHECK_CODE(ignoreAutoCreateTableClause(pCxt));
return cloneTableMeta(*pMeta, &pCxt->pTableMeta);
}
@@ -1123,6 +1099,7 @@ static int32_t parseUsingClause(SInsertParseContext* pCxt, SName* name, char* tb
createSName(&sname, &sToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
char dbFName[TSDB_DB_FNAME_LEN];
tNameGetFullDbName(&sname, dbFName);
+ strcpy(pCxt->sTableName, sname.tname);
CHECK_CODE(getSTableMeta(pCxt, &sname, dbFName));
if (TSDB_SUPER_TABLE != pCxt->pTableMeta->tableType) {
@@ -1291,15 +1268,78 @@ static int32_t parseValuesClause(SInsertParseContext* pCxt, STableDataBlocks* da
return TSDB_CODE_SUCCESS;
}
-void destroyCreateSubTbReq(SVCreateTbReq* pReq) {
- taosMemoryFreeClear(pReq->name);
- taosMemoryFreeClear(pReq->ctb.pTag);
+static int32_t parseCsvFile(SInsertParseContext* pCxt, TdFilePtr fp, STableDataBlocks* pDataBlock, int maxRows,
+ int32_t* numOfRows) {
+ STableComInfo tinfo = getTableInfo(pDataBlock->pTableMeta);
+ int32_t extendedRowSize = getExtendedRowSize(pDataBlock);
+ CHECK_CODE(initRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo));
+
+ (*numOfRows) = 0;
+ char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // used for deleting Escape character: \\, \', \"
+ char* pLine = NULL;
+ int64_t readLen = 0;
+ while ((readLen = taosGetLineFile(fp, &pLine)) != -1) {
+ if (('\r' == pLine[readLen - 1]) || ('\n' == pLine[readLen - 1])) {
+ pLine[--readLen] = '\0';
+ }
+
+ if (readLen == 0) {
+ continue;
+ }
+
+ if ((*numOfRows) >= maxRows || pDataBlock->size + extendedRowSize >= pDataBlock->nAllocSize) {
+ int32_t tSize;
+ CHECK_CODE(allocateMemIfNeed(pDataBlock, extendedRowSize, &tSize));
+ ASSERT(tSize >= maxRows);
+ maxRows = tSize;
+ }
+
+ strtolower(pLine, pLine);
+ char* pRawSql = pCxt->pSql;
+ pCxt->pSql = pLine;
+ bool gotRow = false;
+ CHECK_CODE(parseOneRow(pCxt, pDataBlock, tinfo.precision, &gotRow, tmpTokenBuf));
+ if (gotRow) {
+ pDataBlock->size += extendedRowSize; // len;
+ (*numOfRows)++;
+ }
+ pCxt->pSql = pRawSql;
+ }
+
+ if (0 == (*numOfRows) && (!TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
+ return buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t parseDataFromFile(SInsertParseContext* pCxt, SToken filePath, STableDataBlocks* dataBuf) {
+ char filePathStr[TSDB_FILENAME_LEN] = {0};
+ strncpy(filePathStr, filePath.z, filePath.n);
+ TdFilePtr fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM);
+ if (NULL == fp) {
+ return TAOS_SYSTEM_ERROR(errno);
+ }
+
+ int32_t maxNumOfRows;
+ CHECK_CODE(allocateMemIfNeed(dataBuf, getExtendedRowSize(dataBuf), &maxNumOfRows));
+
+ int32_t numOfRows = 0;
+ CHECK_CODE(parseCsvFile(pCxt, fp, dataBuf, maxNumOfRows, &numOfRows));
+
+ SSubmitBlk* pBlocks = (SSubmitBlk*)(dataBuf->pData);
+ if (TSDB_CODE_SUCCESS != setBlockInfo(pBlocks, dataBuf, numOfRows)) {
+ return buildInvalidOperationMsg(&pCxt->msg, "too many rows in sql, total number of rows should be less than 32767");
+ }
+
+ dataBuf->numOfTables = 1;
+ pCxt->totalNum += numOfRows;
+ return TSDB_CODE_SUCCESS;
}
static void destroyInsertParseContextForTable(SInsertParseContext* pCxt) {
taosMemoryFreeClear(pCxt->pTableMeta);
destroyBoundColumnInfo(&pCxt->tags);
- destroyCreateSubTbReq(&pCxt->createTblReq);
+ tdDestroySVCreateTbReq(&pCxt->createTblReq);
}
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
@@ -1315,15 +1355,6 @@ static void destroyInsertParseContext(SInsertParseContext* pCxt) {
destroyBlockArrayList(pCxt->pVgDataBlocks);
}
-static int32_t checkSchemalessDb(SInsertParseContext* pCxt, char* pDbName) {
-// SDbCfgInfo pInfo = {0};
-// char fullName[TSDB_TABLE_FNAME_LEN];
-// snprintf(fullName, sizeof(fullName), "%d.%s", pCxt->pComCxt->acctId, pDbName);
-// CHECK_CODE(getDBCfg(pCxt, fullName, &pInfo));
-// return pInfo.schemaless ? TSDB_CODE_SML_INVALID_DB_CONF : TSDB_CODE_SUCCESS;
- return TSDB_CODE_SUCCESS;
-}
-
// tb_name
// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
// [(field1_name, ...)]
@@ -1377,20 +1408,35 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
SName name;
CHECK_CODE(createSName(&name, &tbnameToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg));
- CHECK_CODE(checkSchemalessDb(pCxt, name.dbname));
-
tNameExtractFullName(&name, tbFName);
CHECK_CODE(taosHashPut(pCxt->pTableNameHashObj, tbFName, strlen(tbFName), &name, sizeof(SName)));
char dbFName[TSDB_DB_FNAME_LEN];
tNameGetFullDbName(&name, dbFName);
CHECK_CODE(taosHashPut(pCxt->pDbFNameHashObj, dbFName, strlen(dbFName), dbFName, sizeof(dbFName)));
+ bool existedUsing = false;
// USING clause
if (TK_USING == sToken.type) {
+ existedUsing = true;
CHECK_CODE(parseUsingClause(pCxt, &name, tbFName));
NEXT_TOKEN(pCxt->pSql, sToken);
autoCreateTbl = true;
- } else {
+ }
+
+ char* pBoundColsStart = NULL;
+ if (TK_NK_LP == sToken.type) {
+ // pSql -> field1_name, ...)
+ pBoundColsStart = pCxt->pSql;
+ CHECK_CODE(ignoreBoundColumns(pCxt));
+ // CHECK_CODE(parseBoundColumns(pCxt, &dataBuf->boundColumnInfo, getTableColumnSchema(pCxt->pTableMeta)));
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ }
+
+ if (TK_USING == sToken.type) {
+ CHECK_CODE(parseUsingClause(pCxt, &name, tbFName));
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ autoCreateTbl = true;
+ } else if (!existedUsing) {
CHECK_CODE(getTableMeta(pCxt, &name, dbFName));
}
@@ -1399,10 +1445,11 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
sizeof(SSubmitBlk), getTableInfo(pCxt->pTableMeta).rowSize, pCxt->pTableMeta,
&dataBuf, NULL, &pCxt->createTblReq));
- if (TK_NK_LP == sToken.type) {
- // pSql -> field1_name, ...)
+ if (NULL != pBoundColsStart) {
+ char* pCurrPos = pCxt->pSql;
+ pCxt->pSql = pBoundColsStart;
CHECK_CODE(parseBoundColumns(pCxt, &dataBuf->boundColumnInfo, getTableColumnSchema(pCxt->pTableMeta)));
- NEXT_TOKEN(pCxt->pSql, sToken);
+ pCxt->pSql = pCurrPos;
}
if (TK_VALUES == sToken.type) {
@@ -1421,7 +1468,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
if (0 == sToken.n || (TK_NK_STRING != sToken.type && TK_NK_ID != sToken.type)) {
return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", sToken.z);
}
- // todo
+ CHECK_CODE(parseDataFromFile(pCxt, sToken, dataBuf));
pCxt->pOutput->insertType = TSDB_QUERY_TYPE_FILE_INSERT;
tbNum++;
@@ -1438,7 +1485,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
}
memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
(*pCxt->pStmtCb->setInfoFn)(pCxt->pStmtCb->pStmt, pCxt->pTableMeta, tags, tbFName, autoCreateTbl,
- pCxt->pVgroupsHashObj, pCxt->pTableBlockHashObj);
+ pCxt->pVgroupsHashObj, pCxt->pTableBlockHashObj, pCxt->sTableName);
memset(&pCxt->tags, 0, sizeof(pCxt->tags));
pCxt->pVgroupsHashObj = NULL;
@@ -1467,6 +1514,7 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery, SParseMetaCache
.pSql = (char*)pContext->pSql,
.msg = {.buf = pContext->pMsg, .len = pContext->msgLen},
.pTableMeta = NULL,
+ .createTblReq = {0},
.pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
.pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
.pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
@@ -1542,32 +1590,6 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery, SParseMetaCache
return code;
}
-typedef struct SInsertParseSyntaxCxt {
- SParseContext* pComCxt;
- char* pSql;
- SMsgBuf msg;
- SParseMetaCache* pMetaCache;
-} SInsertParseSyntaxCxt;
-
-static int32_t skipParentheses(SInsertParseSyntaxCxt* pCxt) {
- SToken sToken;
- int32_t expectRightParenthesis = 1;
- while (1) {
- NEXT_TOKEN(pCxt->pSql, sToken);
- if (TK_NK_LP == sToken.type) {
- ++expectRightParenthesis;
- } else if (TK_NK_RP == sToken.type && 0 == --expectRightParenthesis) {
- break;
- }
- if (0 == sToken.n) {
- return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
- }
- }
- return TSDB_CODE_SUCCESS;
-}
-
-static int32_t skipBoundColumns(SInsertParseSyntaxCxt* pCxt) { return skipParentheses(pCxt); }
-
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
static int32_t skipValuesClause(SInsertParseSyntaxCxt* pCxt) {
int32_t numOfRows = 0;
@@ -1656,15 +1678,15 @@ static int32_t parseInsertBodySyntax(SInsertParseSyntaxCxt* pCxt) {
SToken tbnameToken = sToken;
NEXT_TOKEN(pCxt->pSql, sToken);
+ bool existedUsing = false;
// USING clause
if (TK_USING == sToken.type) {
+ existedUsing = true;
CHECK_CODE(collectAutoCreateTableMetaKey(pCxt, &tbnameToken));
NEXT_TOKEN(pCxt->pSql, sToken);
CHECK_CODE(collectTableMetaKey(pCxt, &sToken));
CHECK_CODE(skipUsingClause(pCxt));
NEXT_TOKEN(pCxt->pSql, sToken);
- } else {
- CHECK_CODE(collectTableMetaKey(pCxt, &tbnameToken));
}
if (TK_NK_LP == sToken.type) {
@@ -1673,6 +1695,17 @@ static int32_t parseInsertBodySyntax(SInsertParseSyntaxCxt* pCxt) {
NEXT_TOKEN(pCxt->pSql, sToken);
}
+ if (TK_USING == sToken.type && !existedUsing) {
+ existedUsing = true;
+ CHECK_CODE(collectAutoCreateTableMetaKey(pCxt, &tbnameToken));
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ CHECK_CODE(collectTableMetaKey(pCxt, &sToken));
+ CHECK_CODE(skipUsingClause(pCxt));
+ NEXT_TOKEN(pCxt->pSql, sToken);
+ } else {
+ CHECK_CODE(collectTableMetaKey(pCxt, &tbnameToken));
+ }
+
if (TK_VALUES == sToken.type) {
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
CHECK_CODE(skipValuesClause(pCxt));
@@ -1762,7 +1795,7 @@ int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash
return TSDB_CODE_SUCCESS;
}
-int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tName, TAOS_MULTI_BIND* bind,
+int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName, TAOS_MULTI_BIND* bind,
char* msgBuf, int32_t msgBufLen) {
STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock;
SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen};
@@ -1776,8 +1809,13 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tN
return buildInvalidOperationMsg(&pBuf, "out of memory");
}
+ SArray* tagName = taosArrayInit(8, TSDB_COL_NAME_LEN);
+ if (!tagName) {
+ return buildInvalidOperationMsg(&pBuf, "out of memory");
+ }
+
int32_t code = TSDB_CODE_SUCCESS;
- SSchema* pSchema = pDataBlock->pTableMeta->schema;
+ SSchema* pSchema = getTableTagSchema(pDataBlock->pTableMeta);
bool isJson = false;
STag* pTag = NULL;
@@ -1792,6 +1830,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tN
if (IS_VAR_DATA_TYPE(pTagSchema->type)) {
colLen = bind[c].length[0];
}
+ taosArrayPush(tagName, pTagSchema->name);
if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
if (colLen > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
code = buildSyntaxErrMsg(&pBuf, "json string too long than 4095", bind[c].buffer);
@@ -1808,6 +1847,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tN
}
} else {
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
+// strcpy(val.colName, pTagSchema->name);
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
val.pData = (uint8_t*)bind[c].buffer;
val.nData = colLen;
@@ -1844,9 +1884,9 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tN
}
SVCreateTbReq tbReq = {0};
- buildCreateTbReq(&tbReq, tName, pTag, suid);
+ buildCreateTbReq(&tbReq, tName, pTag, suid, sTableName, tagName);
code = buildCreateTbMsg(pDataBlock, &tbReq);
- destroyCreateSubTbReq(&tbReq);
+ tdDestroySVCreateTbReq(&tbReq);
end:
for (int i = 0; i < taosArrayGetSize(pTagArray); ++i) {
@@ -1856,6 +1896,7 @@ end:
}
}
taosArrayDestroy(pTagArray);
+ taosArrayDestroy(tagName);
return code;
}
@@ -2110,7 +2151,7 @@ typedef struct SmlExecHandle {
static void smlDestroyTableHandle(void* pHandle) {
SmlExecTableHandle* handle = (SmlExecTableHandle*)pHandle;
destroyBoundColumnInfo(&handle->tags);
- destroyCreateSubTbReq(&handle->createTblReq);
+ tdDestroySVCreateTbReq(&handle->createTblReq);
}
static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SSchema* pSchema) {
@@ -2171,11 +2212,11 @@ static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SS
pColIdx[i].schemaColIdx = pColList->boundColumns[i];
pColIdx[i].boundIdx = i;
}
- qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar);
+ taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar);
for (col_id_t i = 0; i < pColList->numOfBound; ++i) {
pColIdx[i].finalIdx = i;
}
- qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar);
+ taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar);
}
if (pColList->numOfCols > pColList->numOfBound) {
@@ -2196,18 +2237,24 @@ static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SS
* @param msg
* @return int32_t
*/
-static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* pSchema, STag** ppTag, SMsgBuf* msg) {
+static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* pSchema, STag** ppTag, SArray** tagName, SMsgBuf* msg) {
SArray* pTagArray = taosArrayInit(tags->numOfBound, sizeof(STagVal));
if (!pTagArray) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
+ *tagName = taosArrayInit(8, TSDB_COL_NAME_LEN);
+ if (!*tagName) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
int32_t code = TSDB_CODE_SUCCESS;
for (int i = 0; i < tags->numOfBound; ++i) {
SSchema* pTagSchema = &pSchema[tags->boundColumns[i]];
SSmlKv* kv = taosArrayGetP(cols, i);
+ taosArrayPush(*tagName, pTagSchema->name);
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
+// strcpy(val.colName, pTagSchema->name);
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
val.pData = (uint8_t*)kv->value;
val.nData = kv->length;
@@ -2251,7 +2298,7 @@ end:
}
int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols, bool format, STableMeta* pTableMeta,
- char* tableName, char* msgBuf, int16_t msgBufLen) {
+ char* tableName, const char* sTableName, int32_t sTableNameLen, char* msgBuf, int16_t msgBufLen) {
SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen};
SSmlExecHandle* smlHandle = (SSmlExecHandle*)handle;
@@ -2264,12 +2311,19 @@ int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols
return ret;
}
STag* pTag = NULL;
- ret = smlBuildTagRow(tags, &smlHandle->tableExecHandle.tags, pTagsSchema, &pTag, &pBuf);
+ SArray* tagName = NULL;
+ ret = smlBuildTagRow(tags, &smlHandle->tableExecHandle.tags, pTagsSchema, &pTag, &tagName, &pBuf);
if (ret != TSDB_CODE_SUCCESS) {
+ taosArrayDestroy(tagName);
return ret;
}
- buildCreateTbReq(&smlHandle->tableExecHandle.createTblReq, tableName, pTag, pTableMeta->suid);
+ buildCreateTbReq(&smlHandle->tableExecHandle.createTblReq, tableName, pTag, pTableMeta->suid, NULL, tagName);
+ taosArrayDestroy(tagName);
+
+ smlHandle->tableExecHandle.createTblReq.ctb.name = taosMemoryMalloc(sTableNameLen + 1);
+ memcpy(smlHandle->tableExecHandle.createTblReq.ctb.name, sTableName, sTableNameLen);
+ smlHandle->tableExecHandle.createTblReq.ctb.name[sTableNameLen] = 0;
STableDataBlocks* pDataBlock = NULL;
ret = getDataBlockFromList(smlHandle->pBlockHash, &pTableMeta->uid, sizeof(pTableMeta->uid),
diff --git a/source/libs/parser/src/parInsertData.c b/source/libs/parser/src/parInsertData.c
index 2b505d4bf793e277afbe98e668ddf177d74a3925..290c65de1219936928fec9636cdd4eaf398bc286 100644
--- a/source/libs/parser/src/parInsertData.c
+++ b/source/libs/parser/src/parInsertData.c
@@ -26,6 +26,7 @@
typedef struct SBlockKeyTuple {
TSKEY skey;
void* payloadAddr;
+ int16_t index;
} SBlockKeyTuple;
typedef struct SBlockKeyInfo {
@@ -36,7 +37,6 @@ typedef struct SBlockKeyInfo {
static int32_t rowDataCompar(const void* lhs, const void* rhs) {
TSKEY left = *(TSKEY*)lhs;
TSKEY right = *(TSKEY*)rhs;
-
if (left == right) {
return 0;
} else {
@@ -44,6 +44,16 @@ static int32_t rowDataCompar(const void* lhs, const void* rhs) {
}
}
+static int32_t rowDataComparStable(const void* lhs, const void* rhs) {
+ TSKEY left = *(TSKEY*)lhs;
+ TSKEY right = *(TSKEY*)rhs;
+ if (left == right) {
+ return ((SBlockKeyTuple*)lhs)->index - ((SBlockKeyTuple*)rhs)->index;
+ } else {
+ return left > right ? 1 : -1;
+ }
+}
+
void setBoundColumnInfo(SParsedDataColInfo* pColList, SSchema* pSchema, col_id_t numOfCols) {
pColList->numOfCols = numOfCols;
pColList->numOfBound = numOfCols;
@@ -285,7 +295,7 @@ void sortRemoveDataBlockDupRowsRaw(STableDataBlocks* dataBuf) {
char* pBlockData = pBlocks->data;
// todo. qsort is unstable, if timestamp is same, should get the last one
- qsort(pBlockData, pBlocks->numOfRows, dataBuf->rowSize, rowDataCompar);
+ taosSort(pBlockData, pBlocks->numOfRows, dataBuf->rowSize, rowDataCompar);
int32_t i = 0;
int32_t j = 1;
@@ -343,6 +353,7 @@ int sortRemoveDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKey
while (n < nRows) {
pBlkKeyTuple->skey = TD_ROW_KEY((STSRow*)pBlockData);
pBlkKeyTuple->payloadAddr = pBlockData;
+ pBlkKeyTuple->index = n;
// next loop
pBlockData += extendedRowSize;
@@ -354,7 +365,7 @@ int sortRemoveDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKey
pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
// todo. qsort is unstable, if timestamp is same, should get the last one
- qsort(pBlkKeyTuple, nRows, sizeof(SBlockKeyTuple), rowDataCompar);
+ taosSort(pBlkKeyTuple, nRows, sizeof(SBlockKeyTuple), rowDataComparStable);
pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
int32_t i = 0;
@@ -619,6 +630,17 @@ int32_t qCloneStmtDataBlock(void** pDst, void* pSrc) {
memcpy(*pDst, pSrc, sizeof(STableDataBlocks));
((STableDataBlocks*)(*pDst))->cloned = true;
+ STableDataBlocks* pBlock = (STableDataBlocks*)(*pDst);
+ if (pBlock->pTableMeta) {
+ void *pNewMeta = taosMemoryMalloc(TABLE_META_SIZE(pBlock->pTableMeta));
+ if (NULL == pNewMeta) {
+ taosMemoryFreeClear(*pDst);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ memcpy(pNewMeta, pBlock->pTableMeta, TABLE_META_SIZE(pBlock->pTableMeta));
+ pBlock->pTableMeta = pNewMeta;
+ }
+
return qResetStmtDataBlock(*pDst, false);
}
diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c
index 21f227b7eac945d5e2ff6dafc5c90fa211df3200..0d176cef0951b757496c613b7c50b7a0bb7264b3 100644
--- a/source/libs/parser/src/parTokenizer.c
+++ b/source/libs/parser/src/parTokenizer.c
@@ -29,207 +29,224 @@ typedef struct SKeyword {
// clang-format off
// keywords in sql string
static SKeyword keywordTable[] = {
- {"ACCOUNT", TK_ACCOUNT},
- {"ACCOUNTS", TK_ACCOUNTS},
- {"ADD", TK_ADD},
- {"AGGREGATE", TK_AGGREGATE},
- {"ALL", TK_ALL},
- {"ALTER", TK_ALTER},
- {"ANALYZE", TK_ANALYZE},
- {"AND", TK_AND},
- {"APPS", TK_APPS},
- {"AS", TK_AS},
- {"ASC", TK_ASC},
- {"AT_ONCE", TK_AT_ONCE},
- {"BALANCE", TK_BALANCE},
- {"BETWEEN", TK_BETWEEN},
- {"BINARY", TK_BINARY},
- {"BIGINT", TK_BIGINT},
- {"BNODE", TK_BNODE},
- {"BNODES", TK_BNODES},
- {"BOOL", TK_BOOL},
- {"BUFFER", TK_BUFFER},
- {"BUFSIZE", TK_BUFSIZE},
- {"BY", TK_BY},
- {"CACHE", TK_CACHE},
- {"CACHELAST", TK_CACHELAST},
- {"CAST", TK_CAST},
- {"CLUSTER", TK_CLUSTER},
- {"COLUMN", TK_COLUMN},
- {"COMMENT", TK_COMMENT},
- {"COMP", TK_COMP},
- {"COMPACT", TK_COMPACT},
- {"CONNS", TK_CONNS},
- {"CONNECTION", TK_CONNECTION},
- {"CONNECTIONS", TK_CONNECTIONS},
- {"CONSUMER", TK_CONSUMER},
- {"COUNT", TK_COUNT},
- {"CREATE", TK_CREATE},
- {"CONTAINS", TK_CONTAINS},
- {"DATABASE", TK_DATABASE},
- {"DATABASES", TK_DATABASES},
- {"DBS", TK_DBS},
- {"DELETE", TK_DELETE},
- {"DESC", TK_DESC},
- {"DESCRIBE", TK_DESCRIBE},
- {"DISTINCT", TK_DISTINCT},
- {"DISTRIBUTED", TK_DISTRIBUTED},
- {"DNODE", TK_DNODE},
- {"DNODES", TK_DNODES},
- {"DOUBLE", TK_DOUBLE},
- {"DROP", TK_DROP},
- {"DURATION", TK_DURATION},
- {"EXISTS", TK_EXISTS},
- {"EXPLAIN", TK_EXPLAIN},
- {"EVERY", TK_EVERY},
- {"FILL", TK_FILL},
- {"FIRST", TK_FIRST},
- {"FLOAT", TK_FLOAT},
- {"FROM", TK_FROM},
- {"FSYNC", TK_FSYNC},
- {"FUNCTION", TK_FUNCTION},
- {"FUNCTIONS", TK_FUNCTIONS},
- {"GRANT", TK_GRANT},
- {"GRANTS", TK_GRANTS},
- {"GROUP", TK_GROUP},
- {"HAVING", TK_HAVING},
- {"IF", TK_IF},
- {"IMPORT", TK_IMPORT},
- {"IN", TK_IN},
- {"INDEX", TK_INDEX},
- {"INDEXES", TK_INDEXES},
- {"INNER", TK_INNER},
- {"INT", TK_INT},
- {"INSERT", TK_INSERT},
- {"INTEGER", TK_INTEGER},
- {"INTERVAL", TK_INTERVAL},
- {"INTO", TK_INTO},
- {"IS", TK_IS},
- {"JOIN", TK_JOIN},
- {"JSON", TK_JSON},
- {"KEEP", TK_KEEP},
- {"KILL", TK_KILL},
- {"LAST", TK_LAST},
- {"LAST_ROW", TK_LAST_ROW},
- {"LICENCE", TK_LICENCE},
- {"LIKE", TK_LIKE},
- {"LIMIT", TK_LIMIT},
- {"LINEAR", TK_LINEAR},
- {"LOCAL", TK_LOCAL},
- {"MATCH", TK_MATCH},
- {"MAXROWS", TK_MAXROWS},
- {"MAX_DELAY", TK_MAX_DELAY},
- {"MERGE", TK_MERGE},
- {"MINROWS", TK_MINROWS},
- {"MINUS", TK_MINUS},
- {"MNODE", TK_MNODE},
- {"MNODES", TK_MNODES},
- {"MODIFY", TK_MODIFY},
- {"MODULES", TK_MODULES},
- {"NCHAR", TK_NCHAR},
- {"NEXT", TK_NEXT},
- {"NMATCH", TK_NMATCH},
- {"NONE", TK_NONE},
- {"NOT", TK_NOT},
- {"NOW", TK_NOW},
- {"NULL", TK_NULL},
- {"NULLS", TK_NULLS},
- {"OFFSET", TK_OFFSET},
- {"ON", TK_ON},
- {"OR", TK_OR},
- {"ORDER", TK_ORDER},
- {"OUTPUTTYPE", TK_OUTPUTTYPE},
- {"PARTITION", TK_PARTITION},
- {"PASS", TK_PASS},
- {"PAGES", TK_PAGES},
- {"PAGESIZE", TK_PAGESIZE},
- {"PORT", TK_PORT},
- {"PPS", TK_PPS},
- {"PRECISION", TK_PRECISION},
- {"PRIVILEGE", TK_PRIVILEGE},
- {"PREV", TK_PREV},
- {"QNODE", TK_QNODE},
- {"QNODES", TK_QNODES},
- {"QTIME", TK_QTIME},
- {"QUERIES", TK_QUERIES},
- {"QUERY", TK_QUERY},
- {"RANGE", TK_RANGE},
- {"RATIO", TK_RATIO},
- {"READ", TK_READ},
- {"REDISTRIBUTE", TK_REDISTRIBUTE},
- {"RENAME", TK_RENAME},
- {"REPLICA", TK_REPLICA},
- {"RESET", TK_RESET},
- {"RETENTIONS", TK_RETENTIONS},
- {"REVOKE", TK_REVOKE},
- {"ROLLUP", TK_ROLLUP},
- {"SCHEMALESS", TK_SCHEMALESS},
- {"SCORES", TK_SCORES},
- {"SELECT", TK_SELECT},
- {"SESSION", TK_SESSION},
- {"SET", TK_SET},
- {"SHOW", TK_SHOW},
- {"SINGLE_STABLE", TK_SINGLE_STABLE},
- {"SLIDING", TK_SLIDING},
- {"SLIMIT", TK_SLIMIT},
- {"SMA", TK_SMA},
- {"SMALLINT", TK_SMALLINT},
- {"SNODE", TK_SNODE},
- {"SNODES", TK_SNODES},
- {"SOFFSET", TK_SOFFSET},
- {"SPLIT", TK_SPLIT},
- {"STABLE", TK_STABLE},
- {"STABLES", TK_STABLES},
- {"STATE", TK_STATE},
- {"STATE_WINDOW", TK_STATE_WINDOW},
- {"STORAGE", TK_STORAGE},
- {"STREAM", TK_STREAM},
- {"STREAMS", TK_STREAMS},
- {"STRICT", TK_STRICT},
- {"SYNCDB", TK_SYNCDB},
- {"TABLE", TK_TABLE},
- {"TABLES", TK_TABLES},
- {"TAG", TK_TAG},
- {"TAGS", TK_TAGS},
- {"TBNAME", TK_TBNAME},
- {"TIMESTAMP", TK_TIMESTAMP},
- {"TIMEZONE", TK_TIMEZONE},
- {"TINYINT", TK_TINYINT},
- {"TO", TK_TO},
- {"TODAY", TK_TODAY},
- {"TOPIC", TK_TOPIC},
- {"TOPICS", TK_TOPICS},
- {"TRANSACTION", TK_TRANSACTION},
- {"TRANSACTIONS", TK_TRANSACTIONS},
- {"TRIGGER", TK_TRIGGER},
- {"TSERIES", TK_TSERIES},
- {"TTL", TK_TTL},
- {"UNION", TK_UNION},
- {"UNSIGNED", TK_UNSIGNED},
- {"USE", TK_USE},
- {"USER", TK_USER},
- {"USERS", TK_USERS},
- {"USING", TK_USING},
- {"VALUE", TK_VALUE},
- {"VALUES", TK_VALUES},
- {"VARCHAR", TK_VARCHAR},
- {"VARIABLES", TK_VARIABLES},
- {"VERBOSE", TK_VERBOSE},
- {"VGROUP", TK_VGROUP},
- {"VGROUPS", TK_VGROUPS},
- {"VNODES", TK_VNODES},
- {"WAL", TK_WAL},
- {"WATERMARK", TK_WATERMARK},
- {"WHERE", TK_WHERE},
- {"WINDOW_CLOSE", TK_WINDOW_CLOSE},
- {"WRITE", TK_WRITE},
- {"_C0", TK_ROWTS},
- {"_QENDTS", TK_QENDTS},
- {"_QSTARTTS", TK_QSTARTTS},
- {"_ROWTS", TK_ROWTS},
- {"_WDURATION", TK_WDURATION},
- {"_WENDTS", TK_WENDTS},
- {"_WSTARTTS", TK_WSTARTTS},
+ {"ACCOUNT", TK_ACCOUNT},
+ {"ACCOUNTS", TK_ACCOUNTS},
+ {"ADD", TK_ADD},
+ {"AGGREGATE", TK_AGGREGATE},
+ {"ALL", TK_ALL},
+ {"ALTER", TK_ALTER},
+ {"ANALYZE", TK_ANALYZE},
+ {"AND", TK_AND},
+ {"APPS", TK_APPS},
+ {"AS", TK_AS},
+ {"ASC", TK_ASC},
+ {"AT_ONCE", TK_AT_ONCE},
+ {"BALANCE", TK_BALANCE},
+ {"BETWEEN", TK_BETWEEN},
+ {"BINARY", TK_BINARY},
+ {"BIGINT", TK_BIGINT},
+ {"BNODE", TK_BNODE},
+ {"BNODES", TK_BNODES},
+ {"BOOL", TK_BOOL},
+ {"BUFFER", TK_BUFFER},
+ {"BUFSIZE", TK_BUFSIZE},
+ {"BY", TK_BY},
+ {"CACHE", TK_CACHE},
+ {"CACHELAST", TK_CACHELAST},
+ {"CACHELASTSIZE", TK_CACHELASTSIZE},
+ {"CAST", TK_CAST},
+ {"CLIENT_VERSION", TK_CLIENT_VERSION},
+ {"CLUSTER", TK_CLUSTER},
+ {"COLUMN", TK_COLUMN},
+ {"COMMENT", TK_COMMENT},
+ {"COMP", TK_COMP},
+ {"COMPACT", TK_COMPACT},
+ {"CONNS", TK_CONNS},
+ {"CONNECTION", TK_CONNECTION},
+ {"CONNECTIONS", TK_CONNECTIONS},
+ {"CONSUMER", TK_CONSUMER},
+ {"CONSUMERS", TK_CONSUMERS},
+ {"CONTAINS", TK_CONTAINS},
+ {"COUNT", TK_COUNT},
+ {"CREATE", TK_CREATE},
+ {"CURRENT_USER", TK_CURRENT_USER},
+ {"DATABASE", TK_DATABASE},
+ {"DATABASES", TK_DATABASES},
+ {"DBS", TK_DBS},
+ {"DELETE", TK_DELETE},
+ {"DESC", TK_DESC},
+ {"DESCRIBE", TK_DESCRIBE},
+ {"DISTINCT", TK_DISTINCT},
+ {"DISTRIBUTED", TK_DISTRIBUTED},
+ {"DNODE", TK_DNODE},
+ {"DNODES", TK_DNODES},
+ {"DOUBLE", TK_DOUBLE},
+ {"DROP", TK_DROP},
+ {"DURATION", TK_DURATION},
+ {"ENABLE", TK_ENABLE},
+ {"EXISTS", TK_EXISTS},
+ {"EXPIRED", TK_EXPIRED},
+ {"EXPLAIN", TK_EXPLAIN},
+ {"EVERY", TK_EVERY},
+ {"FILE", TK_FILE},
+ {"FILL", TK_FILL},
+ {"FIRST", TK_FIRST},
+ {"FLOAT", TK_FLOAT},
+ {"FLUSH", TK_FLUSH},
+ {"FROM", TK_FROM},
+ {"FSYNC", TK_FSYNC},
+ {"FUNCTION", TK_FUNCTION},
+ {"FUNCTIONS", TK_FUNCTIONS},
+ {"GRANT", TK_GRANT},
+ {"GRANTS", TK_GRANTS},
+ {"GROUP", TK_GROUP},
+ {"HAVING", TK_HAVING},
+ {"IF", TK_IF},
+ {"IGNORE", TK_IGNORE},
+ {"IMPORT", TK_IMPORT},
+ {"IN", TK_IN},
+ {"INDEX", TK_INDEX},
+ {"INDEXES", TK_INDEXES},
+ {"INNER", TK_INNER},
+ {"INT", TK_INT},
+ {"INSERT", TK_INSERT},
+ {"INTEGER", TK_INTEGER},
+ {"INTERVAL", TK_INTERVAL},
+ {"INTO", TK_INTO},
+ {"IS", TK_IS},
+ {"JOIN", TK_JOIN},
+ {"JSON", TK_JSON},
+ {"KEEP", TK_KEEP},
+ {"KILL", TK_KILL},
+ {"LAST", TK_LAST},
+ {"LAST_ROW", TK_LAST_ROW},
+ {"LICENCE", TK_LICENCE},
+ {"LIKE", TK_LIKE},
+ {"LIMIT", TK_LIMIT},
+ {"LINEAR", TK_LINEAR},
+ {"LOCAL", TK_LOCAL},
+ {"MATCH", TK_MATCH},
+ {"MAXROWS", TK_MAXROWS},
+ {"MAX_DELAY", TK_MAX_DELAY},
+ {"MERGE", TK_MERGE},
+ {"META", TK_META},
+ {"MINROWS", TK_MINROWS},
+ {"MINUS", TK_MINUS},
+ {"MNODE", TK_MNODE},
+ {"MNODES", TK_MNODES},
+ {"MODIFY", TK_MODIFY},
+ {"MODULES", TK_MODULES},
+ {"NCHAR", TK_NCHAR},
+ {"NEXT", TK_NEXT},
+ {"NMATCH", TK_NMATCH},
+ {"NONE", TK_NONE},
+ {"NOT", TK_NOT},
+ {"NOW", TK_NOW},
+ {"NULL", TK_NULL},
+ {"NULLS", TK_NULLS},
+ {"OFFSET", TK_OFFSET},
+ {"ON", TK_ON},
+ {"OR", TK_OR},
+ {"ORDER", TK_ORDER},
+ {"OUTPUTTYPE", TK_OUTPUTTYPE},
+ {"PARTITION", TK_PARTITION},
+ {"PASS", TK_PASS},
+ {"PAGES", TK_PAGES},
+ {"PAGESIZE", TK_PAGESIZE},
+ {"PORT", TK_PORT},
+ {"PPS", TK_PPS},
+ {"PRECISION", TK_PRECISION},
+ // {"PRIVILEGE", TK_PRIVILEGE},
+ {"PREV", TK_PREV},
+ {"QNODE", TK_QNODE},
+ {"QNODES", TK_QNODES},
+ {"QTIME", TK_QTIME},
+ {"QUERIES", TK_QUERIES},
+ {"QUERY", TK_QUERY},
+ {"RANGE", TK_RANGE},
+ {"RATIO", TK_RATIO},
+ {"READ", TK_READ},
+ {"REDISTRIBUTE", TK_REDISTRIBUTE},
+ {"RENAME", TK_RENAME},
+ {"REPLICA", TK_REPLICA},
+ {"RESET", TK_RESET},
+ {"RETENTIONS", TK_RETENTIONS},
+ {"REVOKE", TK_REVOKE},
+ {"ROLLUP", TK_ROLLUP},
+ {"SCHEMALESS", TK_SCHEMALESS},
+ {"SCORES", TK_SCORES},
+ {"SELECT", TK_SELECT},
+ {"SERVER_STATUS", TK_SERVER_STATUS},
+ {"SERVER_VERSION", TK_SERVER_VERSION},
+ {"SESSION", TK_SESSION},
+ {"SET", TK_SET},
+ {"SHOW", TK_SHOW},
+ {"SINGLE_STABLE", TK_SINGLE_STABLE},
+ {"SLIDING", TK_SLIDING},
+ {"SLIMIT", TK_SLIMIT},
+ {"SMA", TK_SMA},
+ {"SMALLINT", TK_SMALLINT},
+ {"SNODE", TK_SNODE},
+ {"SNODES", TK_SNODES},
+ {"SOFFSET", TK_SOFFSET},
+ {"SPLIT", TK_SPLIT},
+ {"STABLE", TK_STABLE},
+ {"STABLES", TK_STABLES},
+ {"STATE", TK_STATE},
+ {"STATE_WINDOW", TK_STATE_WINDOW},
+ {"STORAGE", TK_STORAGE},
+ {"STREAM", TK_STREAM},
+ {"STREAMS", TK_STREAMS},
+ {"STRICT", TK_STRICT},
+ {"SUBSCRIPTIONS", TK_SUBSCRIPTIONS},
+ {"SYNCDB", TK_SYNCDB},
+ {"SYSINFO", TK_SYSINFO},
+ {"TABLE", TK_TABLE},
+ {"TABLES", TK_TABLES},
+ {"TAG", TK_TAG},
+ {"TAGS", TK_TAGS},
+ {"TBNAME", TK_TBNAME},
+ {"TIMESTAMP", TK_TIMESTAMP},
+ {"TIMEZONE", TK_TIMEZONE},
+ {"TINYINT", TK_TINYINT},
+ {"TO", TK_TO},
+ {"TODAY", TK_TODAY},
+ {"TOPIC", TK_TOPIC},
+ {"TOPICS", TK_TOPICS},
+ {"TRANSACTION", TK_TRANSACTION},
+ {"TRANSACTIONS", TK_TRANSACTIONS},
+ {"TRIGGER", TK_TRIGGER},
+ {"TRIM", TK_TRIM},
+ {"TSERIES", TK_TSERIES},
+ {"TTL", TK_TTL},
+ {"UNION", TK_UNION},
+ {"UNSIGNED", TK_UNSIGNED},
+ {"USE", TK_USE},
+ {"USER", TK_USER},
+ {"USERS", TK_USERS},
+ {"USING", TK_USING},
+ {"VALUE", TK_VALUE},
+ {"VALUES", TK_VALUES},
+ {"VARCHAR", TK_VARCHAR},
+ {"VARIABLES", TK_VARIABLES},
+ {"VERBOSE", TK_VERBOSE},
+ {"VGROUP", TK_VGROUP},
+ {"VGROUPS", TK_VGROUPS},
+ {"VNODES", TK_VNODES},
+ {"WAL", TK_WAL},
+ {"WATERMARK", TK_WATERMARK},
+ {"WHERE", TK_WHERE},
+ {"WINDOW_CLOSE", TK_WINDOW_CLOSE},
+ {"WITH", TK_WITH},
+ {"WRITE", TK_WRITE},
+ {"_C0", TK_ROWTS},
+ {"_QDURATION", TK_QDURATION},
+ {"_QEND", TK_QEND},
+ {"_QSTART", TK_QSTART},
+ {"_ROWTS", TK_ROWTS},
+ {"_WDURATION", TK_WDURATION},
+ {"_WEND", TK_WEND},
+ {"_WSTART", TK_WSTART},
// {"ID", TK_ID},
// {"STRING", TK_STRING},
// {"EQ", TK_EQ},
@@ -279,7 +296,6 @@ static SKeyword keywordTable[] = {
// {"END", TK_END},
// {"FAIL", TK_FAIL},
// {"FOR", TK_FOR},
- // {"IGNORE", TK_IGNORE},
// {"IMMEDIATE", TK_IMMEDIATE},
// {"INITIALLY", TK_INITIALLY},
// {"INSTEAD", TK_INSTEAD},
diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c
index fa0a66820f17f7960c3e680626e0897831d25cb7..d108e86df15f5e63d8b513953e86264bf743ce23 100644
--- a/source/libs/parser/src/parTranslater.c
+++ b/source/libs/parser/src/parTranslater.c
@@ -35,8 +35,7 @@ typedef struct STranslateContext {
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
int32_t currLevel;
ESqlClause currClause;
- SSelectStmt* pCurrSelectStmt;
- SSetOperator* pCurrSetOperator;
+ SNode* pCurrStmt;
SCmdMsgInfo* pCmdMsg;
SHashObj* pDbs;
SHashObj* pTables;
@@ -78,14 +77,6 @@ static int32_t addNamespace(STranslateContext* pCxt, void* pTable) {
return TSDB_CODE_SUCCESS;
}
-static SName* toName(int32_t acctId, const char* pDbName, const char* pTableName, SName* pName) {
- pName->type = TSDB_TABLE_NAME_T;
- pName->acctId = acctId;
- strcpy(pName->dbname, pDbName);
- strcpy(pName->tname, pTableName);
- return pName;
-}
-
static int32_t collectUseDatabaseImpl(const char* pFullDbName, SHashObj* pDbs) {
SFullDatabaseName name = {0};
strcpy(name.fullDbName, pFullDbName);
@@ -122,8 +113,8 @@ static int32_t getTableMetaImpl(STranslateContext* pCxt, const SName* pName, STa
}
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogGetTableMeta error, code:%s, dbName:%s, tbName:%s", tstrerror(code), pName->dbname,
- pName->tname);
+ parserError("0x%" PRIx64 " catalogGetTableMeta error, code:%s, dbName:%s, tbName:%s", pCxt->pParseCxt->requestId,
+ tstrerror(code), pName->dbname, pName->tname);
}
return code;
}
@@ -133,6 +124,30 @@ static int32_t getTableMeta(STranslateContext* pCxt, const char* pDbName, const
return getTableMetaImpl(pCxt, toName(pCxt->pParseCxt->acctId, pDbName, pTableName, &name), pMeta);
}
+static int32_t getTableCfg(STranslateContext* pCxt, const SName* pName, STableCfg** pCfg) {
+ SParseContext* pParCxt = pCxt->pParseCxt;
+ int32_t code = collectUseDatabase(pName, pCxt->pDbs);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = collectUseTable(pName, pCxt->pTables);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ if (pParCxt->async) {
+ code = getTableCfgFromCache(pCxt->pMetaCache, pName, pCfg);
+ } else {
+ SRequestConnInfo conn = {.pTrans = pParCxt->pTransporter,
+ .requestId = pParCxt->requestId,
+ .requestObjRefId = pParCxt->requestRid,
+ .mgmtEps = pParCxt->mgmtEpSet};
+ code = catalogRefreshGetTableCfg(pParCxt->pCatalog, &conn, pName, pCfg);
+ }
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ parserError("0x%" PRIx64 " catalogRefreshGetTableCfg error, code:%s, dbName:%s, tbName:%s",
+ pCxt->pParseCxt->requestId, tstrerror(code), pName->dbname, pName->tname);
+ }
+ return code;
+}
+
static int32_t refreshGetTableMeta(STranslateContext* pCxt, const char* pDbName, const char* pTableName,
STableMeta** pMeta) {
SParseContext* pParCxt = pCxt->pParseCxt;
@@ -150,8 +165,8 @@ static int32_t refreshGetTableMeta(STranslateContext* pCxt, const char* pDbName,
code = catalogRefreshGetTableMeta(pParCxt->pCatalog, &conn, &name, pMeta, false);
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogRefreshGetTableMeta error, code:%s, dbName:%s, tbName:%s", tstrerror(code), pDbName,
- pTableName);
+ parserError("0x%" PRIx64 " catalogRefreshGetTableMeta error, code:%s, dbName:%s, tbName:%s",
+ pCxt->pParseCxt->requestId, tstrerror(code), pDbName, pTableName);
}
return code;
}
@@ -173,7 +188,8 @@ static int32_t getDBVgInfoImpl(STranslateContext* pCxt, const SName* pName, SArr
}
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogGetDBVgInfo error, code:%s, dbFName:%s", tstrerror(code), fullDbName);
+ parserError("0x%" PRIx64 " catalogGetDBVgInfo error, code:%s, dbFName:%s", pCxt->pParseCxt->requestId,
+ tstrerror(code), fullDbName);
}
return code;
}
@@ -204,8 +220,8 @@ static int32_t getTableHashVgroupImpl(STranslateContext* pCxt, const SName* pNam
}
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogGetTableHashVgroup error, code:%s, dbName:%s, tbName:%s", tstrerror(code), pName->dbname,
- pName->tname);
+ parserError("0x%" PRIx64 " catalogGetTableHashVgroup error, code:%s, dbName:%s, tbName:%s",
+ pCxt->pParseCxt->requestId, tstrerror(code), pName->dbname, pName->tname);
}
return code;
}
@@ -228,7 +244,8 @@ static int32_t getDBVgVersion(STranslateContext* pCxt, const char* pDbFName, int
}
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogGetDBVgVersion error, code:%s, dbFName:%s", tstrerror(code), pDbFName);
+ parserError("0x%" PRIx64 " catalogGetDBVgVersion error, code:%s, dbFName:%s", pCxt->pParseCxt->requestId,
+ tstrerror(code), pDbFName);
}
return code;
}
@@ -253,7 +270,8 @@ static int32_t getDBCfg(STranslateContext* pCxt, const char* pDbName, SDbCfgInfo
}
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("catalogGetDBCfg error, code:%s, dbFName:%s", tstrerror(code), dbFname);
+ parserError("0x%" PRIx64 " catalogGetDBCfg error, code:%s, dbFName:%s", pCxt->pParseCxt->requestId, tstrerror(code),
+ dbFname);
}
return code;
}
@@ -280,6 +298,10 @@ static int32_t getUdfInfo(STranslateContext* pCxt, SFunctionNode* pFunc) {
pFunc->udfBufSize = funcInfo.bufSize;
tFreeSFuncInfo(&funcInfo);
}
+ if (TSDB_CODE_SUCCESS != code) {
+ parserError("0x%" PRIx64 " catalogGetUdfInfo error, code:%s, funcName:%s", pCxt->pParseCxt->requestId,
+ tstrerror(code), pFunc->functionName);
+ }
return code;
}
@@ -300,7 +322,8 @@ static int32_t getTableIndex(STranslateContext* pCxt, const SName* pName, SArray
code = catalogGetTableIndex(pParCxt->pCatalog, &conn, pName, pIndexes);
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("getTableIndex error, code:%s, dbName:%s, tbName:%s", tstrerror(code), pName->dbname, pName->tname);
+ parserError("0x%" PRIx64 " getTableIndex error, code:%s, dbName:%s, tbName:%s", pCxt->pParseCxt->requestId,
+ tstrerror(code), pName->dbname, pName->tname);
}
return code;
}
@@ -318,7 +341,7 @@ static int32_t getDnodeList(STranslateContext* pCxt, SArray** pDnodes) {
code = catalogGetDnodeList(pParCxt->pCatalog, &conn, pDnodes);
}
if (TSDB_CODE_SUCCESS != code) {
- parserError("getDnodeList error, code:%s", tstrerror(code));
+ parserError("0x%" PRIx64 " getDnodeList error, code:%s", pCxt->pParseCxt->requestId, tstrerror(code));
}
return code;
}
@@ -373,6 +396,34 @@ static void destroyTranslateContext(STranslateContext* pCxt) {
taosHashCleanup(pCxt->pTables);
}
+static bool isSelectStmt(SNode* pCurrStmt) {
+ return NULL != pCurrStmt && QUERY_NODE_SELECT_STMT == nodeType(pCurrStmt);
+}
+
+static bool isSetOperator(SNode* pCurrStmt) {
+ return NULL != pCurrStmt && QUERY_NODE_SET_OPERATOR == nodeType(pCurrStmt);
+}
+
+static SNodeList* getProjectListFromCurrStmt(SNode* pCurrStmt) {
+ if (isSelectStmt(pCurrStmt)) {
+ return ((SSelectStmt*)pCurrStmt)->pProjectionList;
+ }
+ if (isSetOperator(pCurrStmt)) {
+ return ((SSetOperator*)pCurrStmt)->pProjectionList;
+ }
+ return NULL;
+}
+
+static uint8_t getPrecisionFromCurrStmt(SNode* pCurrStmt, uint8_t defaultVal) {
+ if (isSelectStmt(pCurrStmt)) {
+ return ((SSelectStmt*)pCurrStmt)->precision;
+ }
+ if (isSetOperator(pCurrStmt)) {
+ return ((SSetOperator*)pCurrStmt)->precision;
+ }
+ return defaultVal;
+}
+
static bool isAliasColumn(const SNode* pNode) {
return (QUERY_NODE_COLUMN == nodeType(pNode) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]));
}
@@ -389,6 +440,10 @@ static bool isTimelineFunc(const SNode* pNode) {
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId));
}
+static bool isImplicitTsFunc(const SNode* pNode) {
+ return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsImplicitTsFunc(((SFunctionNode*)pNode)->funcId));
+}
+
static bool isScanPseudoColumnFunc(const SNode* pNode) {
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsScanPseudoColumnFunc(((SFunctionNode*)pNode)->funcId));
}
@@ -402,15 +457,14 @@ static bool isVectorFunc(const SNode* pNode) {
}
static bool isDistinctOrderBy(STranslateContext* pCxt) {
- return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrSelectStmt->isDistinct);
+ return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && isSelectStmt(pCxt->pCurrStmt) &&
+ ((SSelectStmt*)pCxt->pCurrStmt)->isDistinct);
}
-static bool belongTable(const char* currentDb, const SColumnNode* pCol, const STableNode* pTable) {
+static bool belongTable(const SColumnNode* pCol, const STableNode* pTable) {
int cmp = 0;
if ('\0' != pCol->dbName[0]) {
cmp = strcmp(pCol->dbName, pTable->dbName);
- } else {
- cmp = (QUERY_NODE_REAL_TABLE == nodeType(pTable) ? strcmp(currentDb, pTable->dbName) : 0);
}
if (0 == cmp) {
cmp = strcmp(pCol->tableAlias, pTable->tableAlias);
@@ -427,6 +481,35 @@ static SNodeList* getProjectList(const SNode* pNode) {
return NULL;
}
+static bool isTimeLineQuery(SNode* pStmt) {
+ if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
+ return ((SSelectStmt*)pStmt)->isTimeLineResult;
+ } else {
+ return false;
+ }
+}
+
+static bool isPrimaryKeyImpl(SNode* pExpr) {
+ if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
+ return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId);
+ } else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
+ SFunctionNode* pFunc = (SFunctionNode*)pExpr;
+ if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
+ return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0));
+ } else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool isPrimaryKey(STempTableNode* pTable, SNode* pExpr) {
+ if (!isTimeLineQuery(pTable->pSubquery)) {
+ return false;
+ }
+ return isPrimaryKeyImpl(pExpr);
+}
+
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, int32_t tagFlag,
SColumnNode* pCol) {
strcpy(pCol->dbName, pTable->table.dbName);
@@ -448,7 +531,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p
}
}
-static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) {
+static void setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) {
SColumnNode* pCol = *pColRef;
// pCol->pProjectRef = (SNode*)pExpr;
@@ -456,15 +539,8 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol
pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
}
taosArrayPush(pExpr->pAssociation, &pColRef);
- if (NULL != pTable) {
- strcpy(pCol->tableAlias, pTable->tableAlias);
- } else if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
- SColumnNode* pProjCol = (SColumnNode*)pExpr;
- strcpy(pCol->tableAlias, pProjCol->tableAlias);
- pCol->tableId = pProjCol->tableId;
- pCol->colId = pProjCol->colId;
- pCol->colType = pProjCol->colType;
- }
+ strcpy(pCol->tableAlias, pTable->table.tableAlias);
+ pCol->colId = isPrimaryKey(pTable, (SNode*)pExpr) ? PRIMARYKEY_TIMESTAMP_COL_ID : 0;
strcpy(pCol->colName, pExpr->aliasName);
if ('\0' == pCol->node.aliasName[0]) {
strcpy(pCol->node.aliasName, pCol->colName);
@@ -472,11 +548,11 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol
pCol->node.resType = pExpr->resType;
}
-static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* pTable, SNodeList* pList) {
+static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* pTable, bool igTags, SNodeList* pList) {
if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
- int32_t nums =
- pMeta->tableInfo.numOfColumns + ((TSDB_SUPER_TABLE == pMeta->tableType) ? pMeta->tableInfo.numOfTags : 0);
+ int32_t nums = pMeta->tableInfo.numOfColumns +
+ (igTags ? 0 : ((TSDB_SUPER_TABLE == pMeta->tableType) ? pMeta->tableInfo.numOfTags : 0));
for (int32_t i = 0; i < nums; ++i) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
@@ -486,15 +562,17 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p
nodesListAppend(pList, (SNode*)pCol);
}
} else {
- SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery);
- SNode* pNode;
+ STempTableNode* pTempTable = (STempTableNode*)pTable;
+ SNodeList* pProjectList = getProjectList(pTempTable->pSubquery);
+ SNode* pNode;
FOREACH(pNode, pProjectList) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
}
- setColumnInfoByExpr(pTable, (SExprNode*)pNode, &pCol);
nodesListAppend(pList, (SNode*)pCol);
+ SListCell* pCell = nodesListGetCell(pList, LIST_LENGTH(pList) - 1);
+ setColumnInfoByExpr(pTempTable, (SExprNode*)pNode, (SColumnNode**)&pCell->pNode);
}
}
return TSDB_CODE_SUCCESS;
@@ -504,35 +582,6 @@ static bool isInternalPrimaryKey(const SColumnNode* pCol) {
return PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && 0 == strcmp(pCol->colName, PK_TS_COL_INTERNAL_NAME);
}
-static bool isTimeOrderQuery(SNode* pStmt) {
- if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
- return ((SSelectStmt*)pStmt)->isTimeOrderQuery;
- } else {
- return false;
- }
-}
-
-static bool isPrimaryKeyImpl(STempTableNode* pTable, SNode* pExpr) {
- if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
- return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId);
- } else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
- SFunctionNode* pFunc = (SFunctionNode*)pExpr;
- if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
- return isPrimaryKeyImpl(pTable, nodesListGetNode(pFunc->pParameterList, 0));
- } else if (FUNCTION_TYPE_WSTARTTS == pFunc->funcType || FUNCTION_TYPE_WENDTS == pFunc->funcType) {
- return true;
- }
- }
- return false;
-}
-
-static bool isPrimaryKey(STempTableNode* pTable, SNode* pExpr) {
- if (!isTimeOrderQuery(pTable->pSubquery)) {
- return false;
- }
- return isPrimaryKeyImpl(pTable, pExpr);
-}
-
static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, const STableNode* pTable,
bool* pFound) {
SColumnNode* pCol = *pColRef;
@@ -553,18 +602,19 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef,
}
}
} else {
- SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery);
- SNode* pNode;
+ STempTableNode* pTempTable = (STempTableNode*)pTable;
+ SNodeList* pProjectList = getProjectList(pTempTable->pSubquery);
+ SNode* pNode;
FOREACH(pNode, pProjectList) {
SExprNode* pExpr = (SExprNode*)pNode;
if (0 == strcmp(pCol->colName, pExpr->aliasName)) {
if (*pFound) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
}
- setColumnInfoByExpr(pTable, pExpr, pColRef);
+ setColumnInfoByExpr(pTempTable, pExpr, pColRef);
*pFound = true;
- } else if (isPrimaryKey((STempTableNode*)pTable, pNode) && isInternalPrimaryKey(pCol)) {
- setColumnInfoByExpr(pTable, pExpr, pColRef);
+ } else if (isPrimaryKey(pTempTable, pNode) && isInternalPrimaryKey(pCol)) {
+ setColumnInfoByExpr(pTempTable, pExpr, pColRef);
*pFound = true;
}
}
@@ -578,7 +628,7 @@ static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode**
bool foundTable = false;
for (size_t i = 0; i < nums; ++i) {
STableNode* pTable = taosArrayGetP(pTables, i);
- if (belongTable(pCxt->pParseCxt->db, (*pCol), pTable)) {
+ if (belongTable((*pCol), pTable)) {
foundTable = true;
bool foundCol = false;
pCxt->errCode = findAndSetColumn(pCxt, pCol, pTable, &foundCol);
@@ -621,7 +671,7 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod
}
if (!found) {
if (isInternalPk) {
- if (NULL != pCxt->pCurrSelectStmt && NULL != pCxt->pCurrSelectStmt->pWindow) {
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pWindow) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY);
}
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_INTERNAL_PK);
@@ -632,18 +682,8 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod
return DEAL_RES_CONTINUE;
}
-static SNodeList* getProjectListFromCxt(STranslateContext* pCxt) {
- if (NULL != pCxt->pCurrSelectStmt) {
- return pCxt->pCurrSelectStmt->pProjectionList;
- } else if (NULL != pCxt->pCurrSetOperator) {
- return pCxt->pCurrSetOperator->pProjectionList;
- } else {
- return NULL;
- }
-}
-
static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** pCol, bool* pFound) {
- SNodeList* pProjectionList = getProjectListFromCxt(pCxt);
+ SNodeList* pProjectionList = getProjectListFromCurrStmt(pCxt->pCurrStmt);
SNode* pNode;
FOREACH(pNode, pProjectionList) {
SExprNode* pExpr = (SExprNode*)pNode;
@@ -665,6 +705,10 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p
}
static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) {
+ if (NULL == pCxt->pCurrStmt || isSelectStmt(pCxt->pCurrStmt) && NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, (*pCol)->colName);
+ }
+
// count(*)/first(*)/last(*) and so on
if (0 == strcmp((*pCol)->colName, "*")) {
return DEAL_RES_CONTINUE;
@@ -679,7 +723,11 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) {
res = translateColumnUseAlias(pCxt, pCol, &found);
}
if (DEAL_RES_ERROR != res && !found) {
- res = translateColumnWithoutPrefix(pCxt, pCol);
+ if (isSetOperator(pCxt->pCurrStmt)) {
+ res = generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, (*pCol)->colName);
+ } else {
+ res = translateColumnWithoutPrefix(pCxt, pCol);
+ }
}
}
return res;
@@ -726,120 +774,165 @@ static int32_t parseBoolFromValueNode(STranslateContext* pCxt, SValueNode* pVal)
}
}
-static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SDataType targetDt) {
- uint8_t precision = (NULL != pCxt->pCurrSelectStmt ? pCxt->pCurrSelectStmt->precision : targetDt.precision);
- pVal->node.resType.precision = precision;
- if (pVal->placeholderNo > 0) {
- return DEAL_RES_CONTINUE;
+static EDealRes translateDurationValue(STranslateContext* pCxt, SValueNode* pVal) {
+ if (parseNatualDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &pVal->unit,
+ pVal->node.resType.precision) != TSDB_CODE_SUCCESS) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- if (pVal->isDuration) {
- if (parseNatualDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &pVal->unit, precision) !=
- TSDB_CODE_SUCCESS) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
- }
- *(int64_t*)&pVal->typeData = pVal->datum.i;
- } else {
- switch (targetDt.type) {
- case TSDB_DATA_TYPE_NULL:
- break;
- case TSDB_DATA_TYPE_BOOL:
- if (TSDB_CODE_SUCCESS != parseBoolFromValueNode(pCxt, pVal)) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
- }
- *(bool*)&pVal->typeData = pVal->datum.b;
- break;
- case TSDB_DATA_TYPE_TINYINT: {
- pVal->datum.i = taosStr2Int64(pVal->literal, NULL, 10);
- *(int8_t*)&pVal->typeData = pVal->datum.i;
- break;
+ *(int64_t*)&pVal->typeData = pVal->datum.i;
+ return DEAL_RES_CONTINUE;
+}
+
+static EDealRes translateNormalValue(STranslateContext* pCxt, SValueNode* pVal, SDataType targetDt, bool strict) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ switch (targetDt.type) {
+ case TSDB_DATA_TYPE_BOOL:
+ if (TSDB_CODE_SUCCESS != parseBoolFromValueNode(pCxt, pVal)) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_SMALLINT: {
- pVal->datum.i = taosStr2Int64(pVal->literal, NULL, 10);
- *(int16_t*)&pVal->typeData = pVal->datum.i;
- break;
+ *(bool*)&pVal->typeData = pVal->datum.b;
+ break;
+ case TSDB_DATA_TYPE_TINYINT: {
+ code = toInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.i);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_TINYINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_INT: {
- pVal->datum.i = taosStr2Int64(pVal->literal, NULL, 10);
- *(int32_t*)&pVal->typeData = pVal->datum.i;
- break;
+ *(int8_t*)&pVal->typeData = pVal->datum.i;
+ break;
+ }
+ case TSDB_DATA_TYPE_SMALLINT: {
+ code = toInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.i);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_SMALLINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_BIGINT: {
- pVal->datum.i = taosStr2Int64(pVal->literal, NULL, 10);
- *(int64_t*)&pVal->typeData = pVal->datum.i;
- break;
+ *(int16_t*)&pVal->typeData = pVal->datum.i;
+ break;
+ }
+ case TSDB_DATA_TYPE_INT: {
+ code = toInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.i);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_INT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_UTINYINT: {
- pVal->datum.u = taosStr2UInt64(pVal->literal, NULL, 10);
- *(uint8_t*)&pVal->typeData = pVal->datum.u;
- break;
+ *(int32_t*)&pVal->typeData = pVal->datum.i;
+ break;
+ }
+ case TSDB_DATA_TYPE_BIGINT: {
+ code = toInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.i);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_BIGINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_USMALLINT: {
- pVal->datum.u = taosStr2UInt64(pVal->literal, NULL, 10);
- *(uint16_t*)&pVal->typeData = pVal->datum.u;
- break;
+ *(int64_t*)&pVal->typeData = pVal->datum.i;
+ break;
+ }
+ case TSDB_DATA_TYPE_UTINYINT: {
+ code = toUInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.u);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_UTINYINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_UINT: {
- pVal->datum.u = taosStr2UInt64(pVal->literal, NULL, 10);
- *(uint32_t*)&pVal->typeData = pVal->datum.u;
- break;
+ *(uint8_t*)&pVal->typeData = pVal->datum.u;
+ break;
+ }
+ case TSDB_DATA_TYPE_USMALLINT: {
+ code = toUInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.u);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_USMALLINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_UBIGINT: {
- pVal->datum.u = taosStr2UInt64(pVal->literal, NULL, 10);
- *(uint64_t*)&pVal->typeData = pVal->datum.u;
- break;
+ *(uint16_t*)&pVal->typeData = pVal->datum.u;
+ break;
+ }
+ case TSDB_DATA_TYPE_UINT: {
+ code = toUInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.u);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_UINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_FLOAT: {
- pVal->datum.d = taosStr2Double(pVal->literal, NULL);
- *(float*)&pVal->typeData = pVal->datum.d;
- break;
+ *(uint32_t*)&pVal->typeData = pVal->datum.u;
+ break;
+ }
+ case TSDB_DATA_TYPE_UBIGINT: {
+ code = toUInteger(pVal->literal, strlen(pVal->literal), 10, &pVal->datum.u);
+ if (strict && (TSDB_CODE_SUCCESS != code || !IS_VALID_UBIGINT(pVal->datum.i))) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_DOUBLE: {
- pVal->datum.d = taosStr2Double(pVal->literal, NULL);
- *(double*)&pVal->typeData = pVal->datum.d;
- break;
+ *(uint64_t*)&pVal->typeData = pVal->datum.u;
+ break;
+ }
+ case TSDB_DATA_TYPE_FLOAT: {
+ pVal->datum.d = taosStr2Double(pVal->literal, NULL);
+ *(float*)&pVal->typeData = pVal->datum.d;
+ break;
+ }
+ case TSDB_DATA_TYPE_DOUBLE: {
+ pVal->datum.d = taosStr2Double(pVal->literal, NULL);
+ *(double*)&pVal->typeData = pVal->datum.d;
+ break;
+ }
+ case TSDB_DATA_TYPE_VARCHAR:
+ case TSDB_DATA_TYPE_VARBINARY: {
+ if (strict && (pVal->node.resType.bytes > targetDt.bytes - VARSTR_HEADER_SIZE)) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_VARCHAR:
- case TSDB_DATA_TYPE_VARBINARY: {
- pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
- if (NULL == pVal->datum.p) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
- }
- int32_t len = TMIN(targetDt.bytes - VARSTR_HEADER_SIZE, pVal->node.resType.bytes);
- varDataSetLen(pVal->datum.p, len);
- strncpy(varDataVal(pVal->datum.p), pVal->literal, len);
- break;
+ pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
+ if (NULL == pVal->datum.p) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
}
- case TSDB_DATA_TYPE_TIMESTAMP: {
- if (TSDB_CODE_SUCCESS != parseTimeFromValueNode(pCxt, pVal)) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
- }
- *(int64_t*)&pVal->typeData = pVal->datum.i;
- break;
+ int32_t len = TMIN(targetDt.bytes - VARSTR_HEADER_SIZE, pVal->node.resType.bytes);
+ varDataSetLen(pVal->datum.p, len);
+ strncpy(varDataVal(pVal->datum.p), pVal->literal, len);
+ break;
+ }
+ case TSDB_DATA_TYPE_TIMESTAMP: {
+ if (TSDB_CODE_SUCCESS != parseTimeFromValueNode(pCxt, pVal)) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
- case TSDB_DATA_TYPE_NCHAR: {
- pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
- if (NULL == pVal->datum.p) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
- }
-
- int32_t len = 0;
- if (!taosMbsToUcs4(pVal->literal, strlen(pVal->literal), (TdUcs4*)varDataVal(pVal->datum.p),
- targetDt.bytes - VARSTR_HEADER_SIZE, &len)) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
- }
- varDataSetLen(pVal->datum.p, len);
- break;
+ *(int64_t*)&pVal->typeData = pVal->datum.i;
+ break;
+ }
+ case TSDB_DATA_TYPE_NCHAR: {
+ pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
+ if (NULL == pVal->datum.p) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
}
- case TSDB_DATA_TYPE_DECIMAL:
- case TSDB_DATA_TYPE_BLOB:
+
+ int32_t len = 0;
+ if (!taosMbsToUcs4(pVal->literal, strlen(pVal->literal), (TdUcs4*)varDataVal(pVal->datum.p),
+ targetDt.bytes - VARSTR_HEADER_SIZE, &len)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
- default:
- break;
+ }
+ varDataSetLen(pVal->datum.p, len);
+ break;
}
+ case TSDB_DATA_TYPE_DECIMAL:
+ case TSDB_DATA_TYPE_BLOB:
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
+ default:
+ break;
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SDataType targetDt, bool strict) {
+ if (pVal->placeholderNo > 0 || pVal->isNull) {
+ return DEAL_RES_CONTINUE;
+ }
+
+ if (TSDB_DATA_TYPE_NULL == pVal->node.resType.type) {
+ pVal->translate = true;
+ pVal->isNull = true;
+ return DEAL_RES_CONTINUE;
+ }
+
+ pVal->node.resType.precision = getPrecisionFromCurrStmt(pCxt->pCurrStmt, targetDt.precision);
+
+ EDealRes res = DEAL_RES_CONTINUE;
+ if (pVal->isDuration) {
+ res = translateDurationValue(pCxt, pVal);
+ } else {
+ res = translateNormalValue(pCxt, pVal, targetDt, strict);
}
pVal->node.resType = targetDt;
+ pVal->node.resType.scale = pVal->unit;
pVal->translate = true;
- return DEAL_RES_CONTINUE;
+ return res;
}
static int32_t calcTypeBytes(SDataType dt) {
@@ -855,7 +948,11 @@ static int32_t calcTypeBytes(SDataType dt) {
static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
SDataType dt = pVal->node.resType;
dt.bytes = calcTypeBytes(dt);
- return translateValueImpl(pCxt, pVal, dt);
+ return translateValueImpl(pCxt, pVal, dt, false);
+}
+
+static int32_t doTranslateValue(STranslateContext* pCxt, SValueNode* pVal) {
+ return DEAL_RES_ERROR == translateValue(pCxt, pVal) ? pCxt->errCode : TSDB_CODE_SUCCESS;
}
static bool isMultiResFunc(SNode* pNode) {
@@ -873,120 +970,11 @@ static bool isMultiResFunc(SNode* pNode) {
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
}
-static int32_t rewriteNegativeOperator(SNode** pOp) {
- SNode* pRes = NULL;
- int32_t code = scalarCalculateConstants(*pOp, &pRes);
- if (TSDB_CODE_SUCCESS == code) {
- *pOp = pRes;
- }
- return code;
-}
-
-static EDealRes translateUnaryOperator(STranslateContext* pCxt, SOperatorNode** pOpRef) {
- SOperatorNode* pOp = *pOpRef;
- if (OP_TYPE_MINUS == pOp->opType) {
- if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
- }
- pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
- pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
-
- pCxt->errCode = rewriteNegativeOperator((SNode**)pOpRef);
- } else {
- pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
- pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
- }
- return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
-}
-
-static EDealRes translateArithmeticOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
- SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
- SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
- if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
- }
- if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
- (TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
- (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
- }
-
- if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) ||
- (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) ||
- (TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) ||
- (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) {
- pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
- pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
- } else {
- pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
- pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
- }
- return DEAL_RES_CONTINUE;
-}
-
static bool dataTypeEqual(const SDataType* l, const SDataType* r) {
return (l->type == r->type && l->bytes == r->bytes && l->precision == r->precision && l->scale == r->scale);
}
-static EDealRes translateComparisonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
- SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
- SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
- if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
- }
- if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
- SNodeListNode* pRight = (SNodeListNode*)pOp->pRight;
- bool first = true;
- SDataType targetDt = {0};
- SNode* pNode = NULL;
- FOREACH(pNode, pRight->pNodeList) {
- SDataType dt = ((SExprNode*)pNode)->resType;
- if (first) {
- targetDt = dt;
- if (targetDt.type != TSDB_DATA_TYPE_NULL) {
- first = false;
- }
- } else if (dt.type != targetDt.type && dt.type != TSDB_DATA_TYPE_NULL) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pNode)->aliasName);
- } else if (dt.bytes > targetDt.bytes) {
- targetDt.bytes = dt.bytes;
- }
- }
- pRight->dataType = targetDt;
- }
- if (nodesIsRegularOp(pOp)) {
- if (!IS_VAR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
- }
- if (QUERY_NODE_VALUE != nodeType(pOp->pRight) ||
- ((!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) &&
- (((SExprNode*)(pOp->pRight))->resType.type != TSDB_DATA_TYPE_NULL))) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
- }
- }
- pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
- pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
- return DEAL_RES_CONTINUE;
-}
-
-static EDealRes translateJsonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
- SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
- SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
- if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
- }
- if (pOp->opType == OP_TYPE_JSON_GET_VALUE) {
- pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
- } else if (pOp->opType == OP_TYPE_JSON_CONTAINS) {
- pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
- }
- pOp->node.resType.bytes = tDataTypes[pOp->node.resType.type].bytes;
- return DEAL_RES_CONTINUE;
-}
-
-static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode** pOpRef) {
- SOperatorNode* pOp = *pOpRef;
-
+static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
if (isMultiResFunc(pOp->pLeft)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
}
@@ -994,15 +982,10 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode** pOpRe
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
- if (nodesIsUnaryOp(pOp)) {
- return translateUnaryOperator(pCxt, pOpRef);
- } else if (nodesIsArithmeticOp(pOp)) {
- return translateArithmeticOperator(pCxt, pOp);
- } else if (nodesIsComparisonOp(pOp)) {
- return translateComparisonOperator(pCxt, pOp);
- } else if (nodesIsJsonOp(pOp)) {
- return translateJsonOperator(pCxt, pOp);
+ if (TSDB_CODE_SUCCESS != scalarGetOperatorResultType(pOp)) {
+ return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pOp->node.aliasName);
}
+
return DEAL_RES_CONTINUE;
}
@@ -1056,6 +1039,8 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
}
static int32_t getFuncInfo(STranslateContext* pCxt, SFunctionNode* pFunc) {
+ // the time precision of the function execution environment
+ pFunc->node.resType.precision = getPrecisionFromCurrStmt(pCxt->pCurrStmt, TSDB_TIME_PRECISION_MILLI);
int32_t code = fmGetFuncInfo(pFunc, pCxt->msgBuf.buf, pCxt->msgBuf.len);
if (TSDB_CODE_FUNC_NOT_BUILTIN_FUNTION == code) {
code = getUdfInfo(pCxt, pFunc);
@@ -1073,7 +1058,7 @@ static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (hasInvalidFuncNesting(pFunc->pParameterList)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AGG_FUNC_NESTING);
}
- if (NULL != pCxt->pCurrSelectStmt && pCxt->pCurrSelectStmt->hasIndefiniteRowsFunc) {
+ if (isSelectStmt(pCxt->pCurrStmt) && ((SSelectStmt*)pCxt->pCurrStmt)->hasIndefiniteRowsFunc) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
}
@@ -1088,7 +1073,8 @@ static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionN
return TSDB_CODE_SUCCESS;
}
if (0 == LIST_LENGTH(pFunc->pParameterList)) {
- if (QUERY_NODE_REAL_TABLE != nodeType(pCxt->pCurrSelectStmt->pFromTable)) {
+ if (!isSelectStmt(pCxt->pCurrStmt) ||
+ QUERY_NODE_REAL_TABLE != nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TBNAME);
}
} else {
@@ -1106,8 +1092,8 @@ static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNod
if (!fmIsIndefiniteRowsFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
- if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrSelectStmt->hasIndefiniteRowsFunc ||
- pCxt->pCurrSelectStmt->hasAggFuncs) {
+ if (!isSelectStmt(pCxt->pCurrStmt) || SQL_CLAUSE_SELECT != pCxt->currClause ||
+ ((SSelectStmt*)pCxt->pCurrStmt)->hasIndefiniteRowsFunc || ((SSelectStmt*)pCxt->pCurrStmt)->hasAggFuncs) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
}
if (hasInvalidFuncNesting(pFunc->pParameterList)) {
@@ -1116,13 +1102,20 @@ static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNod
return TSDB_CODE_SUCCESS;
}
+static bool hasFillClause(SNode* pCurrStmt) {
+ if (!isSelectStmt(pCurrStmt)) {
+ return false;
+ }
+ SSelectStmt* pSelect = (SSelectStmt*)pCurrStmt;
+ return NULL != pSelect->pWindow && QUERY_NODE_INTERVAL_WINDOW == nodeType(pSelect->pWindow) &&
+ NULL != ((SIntervalWindowNode*)pSelect->pWindow)->pFill;
+}
+
static int32_t translateForbidFillFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (!fmIsForbidFillFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
- if (NULL != pCxt->pCurrSelectStmt->pWindow &&
- QUERY_NODE_INTERVAL_WINDOW == nodeType(pCxt->pCurrSelectStmt->pWindow) &&
- NULL != ((SIntervalWindowNode*)pCxt->pCurrSelectStmt->pWindow)->pFill) {
+ if (hasFillClause(pCxt->pCurrStmt)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC, pFunc->functionName);
}
return TSDB_CODE_SUCCESS;
@@ -1132,7 +1125,7 @@ static int32_t translateWindowPseudoColumnFunc(STranslateContext* pCxt, SFunctio
if (!fmIsWindowPseudoColumnFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
- if (NULL == pCxt->pCurrSelectStmt->pWindow) {
+ if (!isSelectStmt(pCxt->pCurrStmt) || NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pWindow) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_WINDOW_PC);
}
return TSDB_CODE_SUCCESS;
@@ -1142,7 +1135,7 @@ static int32_t translateForbidWindowFunc(STranslateContext* pCxt, SFunctionNode*
if (!fmIsForbidWindowFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
- if (NULL != pCxt->pCurrSelectStmt->pWindow) {
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pWindow) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC, pFunc->functionName);
}
return TSDB_CODE_SUCCESS;
@@ -1162,58 +1155,236 @@ static int32_t translateForbidGroupByFunc(STranslateContext* pCxt, SFunctionNode
if (!fmIsForbidGroupByFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
- if (NULL != pCxt->pCurrSelectStmt->pGroupByList) {
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pGroupByList) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC, pFunc->functionName);
}
return TSDB_CODE_SUCCESS;
}
-static void setFuncClassification(SSelectStmt* pSelect, SFunctionNode* pFunc) {
- if (NULL != pSelect) {
+static int32_t translateRepeatScanFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
+ if (!fmIsRepeatScanFunc(pFunc->funcId)) {
+ return TSDB_CODE_SUCCESS;
+ }
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable) {
+ SNode* pTable = ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable;
+ if (QUERY_NODE_REAL_TABLE == nodeType(pTable) &&
+ (TSDB_CHILD_TABLE == ((SRealTableNode*)pTable)->pMeta->tableType ||
+ TSDB_NORMAL_TABLE == ((SRealTableNode*)pTable)->pMeta->tableType)) {
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_SUPPORT_SINGLE_TABLE,
+ "%s is only supported in single table query", pFunc->functionName);
+}
+
+static void setFuncClassification(SNode* pCurrStmt, SFunctionNode* pFunc) {
+ if (NULL != pCurrStmt && QUERY_NODE_SELECT_STMT == nodeType(pCurrStmt)) {
+ SSelectStmt* pSelect = (SSelectStmt*)pCurrStmt;
pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId);
pSelect->hasRepeatScanFuncs = pSelect->hasRepeatScanFuncs ? true : fmIsRepeatScanFunc(pFunc->funcId);
pSelect->hasIndefiniteRowsFunc = pSelect->hasIndefiniteRowsFunc ? true : fmIsIndefiniteRowsFunc(pFunc->funcId);
+ if (fmIsSelectFunc(pFunc->funcId)) {
+ pSelect->hasSelectFunc = true;
+ ++(pSelect->selectFuncNum);
+ } else if (fmIsVectorFunc(pFunc->funcId)) {
+ pSelect->hasOtherVectorFunc = true;
+ }
pSelect->hasUniqueFunc = pSelect->hasUniqueFunc ? true : (FUNCTION_TYPE_UNIQUE == pFunc->funcType);
pSelect->hasTailFunc = pSelect->hasTailFunc ? true : (FUNCTION_TYPE_TAIL == pFunc->funcType);
pSelect->hasInterpFunc = pSelect->hasInterpFunc ? true : (FUNCTION_TYPE_INTERP == pFunc->funcType);
+ pSelect->hasLastRowFunc = pSelect->hasLastRowFunc ? true : (FUNCTION_TYPE_LAST_ROW == pFunc->funcType);
+ pSelect->hasTimeLineFunc = pSelect->hasLastRowFunc ? true : fmIsTimelineFunc(pFunc->funcId);
+ }
+}
+
+static int32_t rewriteFuncToValue(STranslateContext* pCxt, char* pLiteral, SNode** pNode) {
+ SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
+ if (NULL == pVal) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ strcpy(pVal->node.aliasName, ((SExprNode*)*pNode)->aliasName);
+ pVal->node.resType = ((SExprNode*)*pNode)->resType;
+ if (NULL == pLiteral) {
+ pVal->isNull = true;
+ } else {
+ pVal->literal = pLiteral;
+ if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
+ pVal->node.resType.bytes = strlen(pLiteral);
+ }
+ }
+ if (DEAL_RES_ERROR != translateValue(pCxt, pVal)) {
+ *pNode = (SNode*)pVal;
+ } else {
+ nodesDestroyNode((SNode*)pVal);
+ }
+ return pCxt->errCode;
+}
+
+static int32_t rewriteDatabaseFunc(STranslateContext* pCxt, SNode** pNode) {
+ char* pCurrDb = NULL;
+ if (NULL != pCxt->pParseCxt->db) {
+ pCurrDb = taosMemoryStrDup((void*)pCxt->pParseCxt->db);
+ if (NULL == pCurrDb) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+ return rewriteFuncToValue(pCxt, pCurrDb, pNode);
+}
+
+static int32_t rewriteClentVersionFunc(STranslateContext* pCxt, SNode** pNode) {
+ char* pVer = taosMemoryStrDup((void*)version);
+ if (NULL == pVer) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ return rewriteFuncToValue(pCxt, pVer, pNode);
+}
+
+static int32_t rewriteServerVersionFunc(STranslateContext* pCxt, SNode** pNode) {
+ char* pVer = taosMemoryStrDup((void*)pCxt->pParseCxt->svrVer);
+ if (NULL == pVer) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ return rewriteFuncToValue(pCxt, pVer, pNode);
+}
+
+static int32_t rewriteServerStatusFunc(STranslateContext* pCxt, SNode** pNode) {
+ if (pCxt->pParseCxt->nodeOffline) {
+ return TSDB_CODE_RPC_NETWORK_UNAVAIL;
+ }
+ char* pStatus = taosMemoryStrDup((void*)"1");
+ return rewriteFuncToValue(pCxt, pStatus, pNode);
+}
+
+static int32_t rewriteUserFunc(STranslateContext* pCxt, SNode** pNode) {
+ char userConn[TSDB_USER_LEN + 1 + TSDB_FQDN_LEN] = {0}; // format 'user@host'
+ int32_t len = snprintf(userConn, sizeof(userConn), "%s@", pCxt->pParseCxt->pUser);
+ taosGetFqdn(userConn + len);
+ char* pUserConn = taosMemoryStrDup((void*)userConn);
+ if (NULL == pUserConn) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ return rewriteFuncToValue(pCxt, pUserConn, pNode);
+}
+
+static int32_t rewriteSystemInfoFunc(STranslateContext* pCxt, SNode** pNode) {
+ switch (((SFunctionNode*)*pNode)->funcType) {
+ case FUNCTION_TYPE_DATABASE:
+ return rewriteDatabaseFunc(pCxt, pNode);
+ case FUNCTION_TYPE_CLIENT_VERSION:
+ return rewriteClentVersionFunc(pCxt, pNode);
+ case FUNCTION_TYPE_SERVER_VERSION:
+ return rewriteServerVersionFunc(pCxt, pNode);
+ case FUNCTION_TYPE_SERVER_STATUS:
+ return rewriteServerStatusFunc(pCxt, pNode);
+ case FUNCTION_TYPE_CURRENT_USER:
+ case FUNCTION_TYPE_USER:
+ return rewriteUserFunc(pCxt, pNode);
+ default:
+ break;
+ }
+ return TSDB_CODE_PAR_INTERNAL_ERROR;
+}
+
+static int32_t translateNoramlFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
+ int32_t code = translateAggFunc(pCxt, pFunc);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateScanPseudoColumnFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateIndefiniteRowsFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateForbidFillFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateWindowPseudoColumnFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateForbidWindowFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateForbidStreamFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateForbidGroupByFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateRepeatScanFunc(pCxt, pFunc);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ setFuncClassification(pCxt->pCurrStmt, pFunc);
+ }
+ return code;
+}
+
+static int32_t rewriteQueryTimeFunc(STranslateContext* pCxt, int64_t val, SNode** pNode) {
+ if (INT64_MIN == val || INT64_MAX == val) {
+ return rewriteFuncToValue(pCxt, NULL, pNode);
+ }
+
+ char* pStr = taosMemoryCalloc(1, 20);
+ if (NULL == pStr) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ snprintf(pStr, 20, "%" PRId64 "", val);
+ return rewriteFuncToValue(pCxt, pStr, pNode);
+}
+
+static int32_t rewriteQstartFunc(STranslateContext* pCxt, SNode** pNode) {
+ return rewriteQueryTimeFunc(pCxt, ((SSelectStmt*)pCxt->pCurrStmt)->timeRange.skey, pNode);
+}
+
+static int32_t rewriteQendFunc(STranslateContext* pCxt, SNode** pNode) {
+ return rewriteQueryTimeFunc(pCxt, ((SSelectStmt*)pCxt->pCurrStmt)->timeRange.ekey, pNode);
+}
+
+static int32_t rewriteQdurationFunc(STranslateContext* pCxt, SNode** pNode) {
+ STimeWindow range = ((SSelectStmt*)pCxt->pCurrStmt)->timeRange;
+ if (INT64_MIN == range.skey || INT64_MAX == range.ekey) {
+ return rewriteQueryTimeFunc(pCxt, INT64_MIN, pNode);
+ }
+ return rewriteQueryTimeFunc(pCxt, range.ekey - range.skey + 1, pNode);
+}
+
+static int32_t rewriteClientPseudoColumnFunc(STranslateContext* pCxt, SNode** pNode) {
+ if (NULL == pCxt->pCurrStmt || QUERY_NODE_SELECT_STMT != nodeType(pCxt->pCurrStmt) ||
+ pCxt->currClause <= SQL_CLAUSE_WHERE) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, "Illegal pseudo column");
+ }
+ switch (((SFunctionNode*)*pNode)->funcType) {
+ case FUNCTION_TYPE_QSTART:
+ return rewriteQstartFunc(pCxt, pNode);
+ case FUNCTION_TYPE_QEND:
+ return rewriteQendFunc(pCxt, pNode);
+ case FUNCTION_TYPE_QDURATION:
+ return rewriteQdurationFunc(pCxt, pNode);
+ default:
+ break;
}
+ return TSDB_CODE_PAR_INTERNAL_ERROR;
}
-static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
+static int32_t translateFunctionImpl(STranslateContext* pCxt, SFunctionNode** pFunc) {
+ if (fmIsSystemInfoFunc((*pFunc)->funcId)) {
+ return rewriteSystemInfoFunc(pCxt, (SNode**)pFunc);
+ }
+ if (fmIsClientPseudoColumnFunc((*pFunc)->funcId)) {
+ return rewriteClientPseudoColumnFunc(pCxt, (SNode**)pFunc);
+ }
+ return translateNoramlFunction(pCxt, *pFunc);
+}
+
+static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode** pFunc) {
SNode* pParam = NULL;
- FOREACH(pParam, pFunc->pParameterList) {
+ FOREACH(pParam, (*pFunc)->pParameterList) {
if (isMultiResFunc(pParam)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pParam)->aliasName);
}
}
- pCxt->errCode = getFuncInfo(pCxt, pFunc);
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateAggFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateScanPseudoColumnFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateIndefiniteRowsFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateForbidFillFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateWindowPseudoColumnFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateForbidWindowFunc(pCxt, pFunc);
- }
+ pCxt->errCode = getFuncInfo(pCxt, *pFunc);
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateForbidStreamFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode = translateForbidGroupByFunc(pCxt, pFunc);
- }
- if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- setFuncClassification(pCxt->pCurrSelectStmt, pFunc);
+ pCxt->errCode = translateFunctionImpl(pCxt, pFunc);
}
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
}
@@ -1236,9 +1407,9 @@ static EDealRes doTranslateExpr(SNode** pNode, void* pContext) {
case QUERY_NODE_VALUE:
return translateValue(pCxt, (SValueNode*)*pNode);
case QUERY_NODE_OPERATOR:
- return translateOperator(pCxt, (SOperatorNode**)pNode);
+ return translateOperator(pCxt, (SOperatorNode*)*pNode);
case QUERY_NODE_FUNCTION:
- return translateFunction(pCxt, (SFunctionNode*)*pNode);
+ return translateFunction(pCxt, (SFunctionNode**)pNode);
case QUERY_NODE_LOGIC_CONDITION:
return translateLogicCond(pCxt, (SLogicConditionNode*)*pNode);
case QUERY_NODE_TEMP_TABLE:
@@ -1261,9 +1432,9 @@ static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) {
static SNodeList* getGroupByList(STranslateContext* pCxt) {
if (isDistinctOrderBy(pCxt)) {
- return pCxt->pCurrSelectStmt->pProjectionList;
+ return ((SSelectStmt*)pCxt->pCurrStmt)->pProjectionList;
}
- return pCxt->pCurrSelectStmt->pGroupByList;
+ return ((SSelectStmt*)pCxt->pCurrStmt)->pGroupByList;
}
static SNode* getGroupByNode(SNode* pNode) {
@@ -1277,16 +1448,12 @@ static int32_t getGroupByErrorCode(STranslateContext* pCxt) {
if (isDistinctOrderBy(pCxt)) {
return TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION;
}
- return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION;
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pGroupByList) {
+ return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION;
+ }
+ return TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN;
}
-typedef struct SCheckExprForGroupByCxt {
- STranslateContext* pTranslateCxt;
- int32_t selectFuncNum;
- bool hasSelectValFunc;
- bool hasOtherAggFunc;
-} SCheckExprForGroupByCxt;
-
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) {
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
if (NULL == pFunc) {
@@ -1297,73 +1464,79 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode
strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
- pCxt->errCode == getFuncInfo(pCxt, pFunc);
+ pCxt->errCode = getFuncInfo(pCxt, pFunc);
}
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
*pNode = (SNode*)pFunc;
- pCxt->pCurrSelectStmt->hasSelectValFunc = true;
+ ((SSelectStmt*)pCxt->pCurrStmt)->hasSelectValFunc = true;
} else {
nodesDestroyNode((SNode*)pFunc);
}
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
}
+static EDealRes rewriteExprToGroupKeyFunc(STranslateContext* pCxt, SNode** pNode) {
+ SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
+ }
+
+ strcpy(pFunc->functionName, "_group_key");
+ strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
+ pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
+ if (TSDB_CODE_SUCCESS == pCxt->errCode) {
+ *pNode = (SNode*)pFunc;
+ pCxt->errCode = fmGetFuncInfo(pFunc, pCxt->msgBuf.buf, pCxt->msgBuf.len);
+ }
+
+ return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
+}
+
static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
- SCheckExprForGroupByCxt* pCxt = (SCheckExprForGroupByCxt*)pContext;
+ STranslateContext* pCxt = (STranslateContext*)pContext;
+ SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
return DEAL_RES_CONTINUE;
}
- if (isSelectFunc(*pNode)) {
- ++(pCxt->selectFuncNum);
- } else if (isAggFunc(*pNode)) {
- pCxt->hasOtherAggFunc = true;
- }
- if ((pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) || (pCxt->hasOtherAggFunc && pCxt->hasSelectValFunc)) {
- return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
- }
- if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) {
+ if (isVectorFunc(*pNode) && !isDistinctOrderBy(pCxt)) {
return DEAL_RES_IGNORE_CHILD;
}
- SNode* pGroupNode;
- FOREACH(pGroupNode, getGroupByList(pCxt->pTranslateCxt)) {
+ SNode* pGroupNode = NULL;
+ FOREACH(pGroupNode, getGroupByList(pCxt)) {
if (nodesEqualNode(getGroupByNode(pGroupNode), *pNode)) {
return DEAL_RES_IGNORE_CHILD;
}
}
+ SNode* pPartKey = NULL;
+ FOREACH(pPartKey, pSelect->pPartitionByList) {
+ if (nodesEqualNode(pPartKey, *pNode)) {
+ return rewriteExprToGroupKeyFunc(pCxt, pNode);
+ }
+ }
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
- if (pCxt->selectFuncNum > 1 || pCxt->hasOtherAggFunc) {
- return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
+ if (pSelect->selectFuncNum > 1 || pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) {
+ return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt));
} else {
- pCxt->hasSelectValFunc = true;
- return rewriteColToSelectValFunc(pCxt->pTranslateCxt, pNode);
+ return rewriteColToSelectValFunc(pCxt, pNode);
}
}
- if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) {
- return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
+ if (isVectorFunc(*pNode) && isDistinctOrderBy(pCxt)) {
+ return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt));
}
return DEAL_RES_CONTINUE;
}
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) {
- SCheckExprForGroupByCxt cxt = {
- .pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
- nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt);
- if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
- }
+ nodesRewriteExpr(pNode, doCheckExprForGroupBy, pCxt);
return pCxt->errCode;
}
-static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) {
- if (NULL == getGroupByList(pCxt)) {
+static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect, SNodeList* pList) {
+ if (NULL == getGroupByList(pCxt) && NULL == pSelect->pWindow) {
return TSDB_CODE_SUCCESS;
}
- SCheckExprForGroupByCxt cxt = {
- .pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
- nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt);
- if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
- }
+ nodesRewriteExprs(pList, doCheckExprForGroupBy, pCxt);
return pCxt->errCode;
}
@@ -1387,56 +1560,51 @@ static int32_t rewriteColsToSelectValFunc(STranslateContext* pCxt, SSelectStmt*
typedef struct CheckAggColCoexistCxt {
STranslateContext* pTranslateCxt;
- bool existAggFunc;
bool existCol;
- bool existIndefiniteRowsFunc;
- int32_t selectFuncNum;
- bool existOtherAggFunc;
} CheckAggColCoexistCxt;
-static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
+static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) {
CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext;
- if (isSelectFunc(pNode)) {
- ++(pCxt->selectFuncNum);
- } else if (isAggFunc(pNode)) {
- pCxt->existOtherAggFunc = true;
- }
- if (isAggFunc(pNode)) {
- pCxt->existAggFunc = true;
+ if (isVectorFunc(*pNode)) {
return DEAL_RES_IGNORE_CHILD;
}
- if (isIndefiniteRowsFunc(pNode)) {
- pCxt->existIndefiniteRowsFunc = true;
- return DEAL_RES_IGNORE_CHILD;
+ SNode* pPartKey = NULL;
+ FOREACH(pPartKey, ((SSelectStmt*)pCxt->pTranslateCxt->pCurrStmt)->pPartitionByList) {
+ if (nodesEqualNode(pPartKey, *pNode)) {
+ return rewriteExprToGroupKeyFunc(pCxt->pTranslateCxt, pNode);
+ }
}
- if (isScanPseudoColumnFunc(pNode) || QUERY_NODE_COLUMN == nodeType(pNode)) {
+ if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
pCxt->existCol = true;
}
return DEAL_RES_CONTINUE;
}
static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) {
- if (NULL != pSelect->pGroupByList) {
+ if (NULL != pSelect->pGroupByList || NULL != pSelect->pWindow ||
+ (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc && !pSelect->hasInterpFunc)) {
return TSDB_CODE_SUCCESS;
}
- CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt,
- .existAggFunc = false,
- .existCol = false,
- .existIndefiniteRowsFunc = false,
- .selectFuncNum = 0,
- .existOtherAggFunc = false};
- nodesWalkExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
+ CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt, .existCol = false};
+ nodesRewriteExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
if (!pSelect->isDistinct) {
- nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
+ nodesRewriteExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
}
- if (1 == cxt.selectFuncNum && !cxt.existOtherAggFunc) {
+ if (1 == pSelect->selectFuncNum && !pSelect->hasOtherVectorFunc) {
return rewriteColsToSelectValFunc(pCxt, pSelect);
}
- if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
+ if (cxt.existCol) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SINGLE_GROUP);
}
- if (cxt.existIndefiniteRowsFunc && cxt.existCol) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t checkWindowFuncCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) {
+ if (NULL == pSelect->pWindow) {
+ return TSDB_CODE_SUCCESS;
+ }
+ if (NULL != pSelect->pWindow && !pSelect->hasAggFuncs) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN);
}
return TSDB_CODE_SUCCESS;
}
@@ -1568,7 +1736,8 @@ static uint8_t getStmtPrecision(SNode* pStmt) {
static bool stmtIsSingleTable(SNode* pStmt) {
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
- return ((STableNode*)((SSelectStmt*)pStmt)->pFromTable)->singleTable;
+ SSelectStmt* pSelect = (SSelectStmt*)pStmt;
+ return NULL == pSelect->pFromTable || ((STableNode*)pSelect->pFromTable)->singleTable;
}
return false;
}
@@ -1596,8 +1765,8 @@ static int32_t setTableIndex(STranslateContext* pCxt, SName* pName, SRealTableNo
if (pCxt->createStream || QUERY_SMA_OPTIMIZE_DISABLE == tsQuerySmaOptimize) {
return TSDB_CODE_SUCCESS;
}
- if (NULL != pCxt->pCurrSelectStmt && NULL != pCxt->pCurrSelectStmt->pWindow &&
- QUERY_NODE_INTERVAL_WINDOW == nodeType(pCxt->pCurrSelectStmt->pWindow)) {
+ if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pWindow &&
+ QUERY_NODE_INTERVAL_WINDOW == nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pWindow)) {
return getTableIndex(pCxt, pName, &pRealTable->pSmaIndexes);
}
return TSDB_CODE_SUCCESS;
@@ -1662,7 +1831,7 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
return code;
}
-static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
+static int32_t createAllColumns(STranslateContext* pCxt, bool igTags, SNodeList** pCols) {
*pCols = nodesMakeList();
if (NULL == *pCols) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
@@ -1671,7 +1840,7 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
size_t nums = taosArrayGetSize(pTables);
for (size_t i = 0; i < nums; ++i) {
STableNode* pTable = taosArrayGetP(pTables, i);
- int32_t code = createColumnsByTable(pCxt, pTable, *pCols);
+ int32_t code = createColumnsByTable(pCxt, pTable, igTags, *pCols);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
@@ -1708,7 +1877,7 @@ static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) {
return (SNode*)pFunc;
}
-static int32_t createTableAllCols(STranslateContext* pCxt, SColumnNode* pCol, SNodeList** pOutput) {
+static int32_t createTableAllCols(STranslateContext* pCxt, SColumnNode* pCol, bool igTags, SNodeList** pOutput) {
STableNode* pTable = NULL;
int32_t code = findTable(pCxt, pCol->tableAlias, &pTable);
if (TSDB_CODE_SUCCESS == code && NULL == *pOutput) {
@@ -1718,7 +1887,7 @@ static int32_t createTableAllCols(STranslateContext* pCxt, SColumnNode* pCol, SN
}
}
if (TSDB_CODE_SUCCESS == code) {
- code = createColumnsByTable(pCxt, pTable, *pOutput);
+ code = createColumnsByTable(pCxt, pTable, igTags, *pOutput);
}
return code;
}
@@ -1740,11 +1909,9 @@ static int32_t createMultiResFuncsParas(STranslateContext* pCxt, SNodeList* pSrc
SNode* pPara = NULL;
FOREACH(pPara, pSrcParas) {
if (isStar(pPara)) {
- code = createAllColumns(pCxt, &pExprs);
- // The syntax definition ensures that * and other parameters do not appear at the same time
- break;
+ code = createAllColumns(pCxt, true, &pExprs);
} else if (isTableStar(pPara)) {
- code = createTableAllCols(pCxt, (SColumnNode*)pPara, &pExprs);
+ code = createTableAllCols(pCxt, (SColumnNode*)pPara, true, &pExprs);
} else {
code = nodesListMakeStrictAppend(&pExprs, nodesCloneNode(pPara));
}
@@ -1793,42 +1960,43 @@ static int32_t createMultiResFuncsFromStar(STranslateContext* pCxt, SFunctionNod
code = createMultiResFuncs(pSrcFunc, pExprs, pOutput);
}
- if (TSDB_CODE_SUCCESS != code) {
- nodesDestroyList(pExprs);
- }
-
+ nodesDestroyList(pExprs);
return code;
}
static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
- if (NULL == pSelect->pProjectionList) { // select * ...
- return createAllColumns(pCxt, &pSelect->pProjectionList);
- } else {
- SNode* pNode = NULL;
- WHERE_EACH(pNode, pSelect->pProjectionList) {
- int32_t code = TSDB_CODE_SUCCESS;
- if (isMultiResFunc(pNode)) {
- SNodeList* pFuncs = NULL;
- code = createMultiResFuncsFromStar(pCxt, (SFunctionNode*)pNode, &pFuncs);
- if (TSDB_CODE_SUCCESS == code) {
- INSERT_LIST(pSelect->pProjectionList, pFuncs);
- ERASE_NODE(pSelect->pProjectionList);
- continue;
- }
- } else if (isTableStar(pNode)) {
- SNodeList* pCols = NULL;
- code = createTableAllCols(pCxt, (SColumnNode*)pNode, &pCols);
- if (TSDB_CODE_SUCCESS == code) {
- INSERT_LIST(pSelect->pProjectionList, pCols);
- ERASE_NODE(pSelect->pProjectionList);
- continue;
- }
+ SNode* pNode = NULL;
+ WHERE_EACH(pNode, pSelect->pProjectionList) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if (isStar(pNode)) {
+ SNodeList* pCols = NULL;
+ code = createAllColumns(pCxt, false, &pCols);
+ if (TSDB_CODE_SUCCESS == code) {
+ INSERT_LIST(pSelect->pProjectionList, pCols);
+ ERASE_NODE(pSelect->pProjectionList);
+ continue;
}
- if (TSDB_CODE_SUCCESS != code) {
- return code;
+ } else if (isMultiResFunc(pNode)) {
+ SNodeList* pFuncs = NULL;
+ code = createMultiResFuncsFromStar(pCxt, (SFunctionNode*)pNode, &pFuncs);
+ if (TSDB_CODE_SUCCESS == code) {
+ INSERT_LIST(pSelect->pProjectionList, pFuncs);
+ ERASE_NODE(pSelect->pProjectionList);
+ continue;
}
- WHERE_NEXT;
+ } else if (isTableStar(pNode)) {
+ SNodeList* pCols = NULL;
+ code = createTableAllCols(pCxt, (SColumnNode*)pNode, false, &pCols);
+ if (TSDB_CODE_SUCCESS == code) {
+ INSERT_LIST(pSelect->pProjectionList, pCols);
+ ERASE_NODE(pSelect->pProjectionList);
+ continue;
+ }
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ return code;
}
+ WHERE_NEXT;
}
return TSDB_CODE_SUCCESS;
}
@@ -1907,7 +2075,7 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
code = translateExprList(pCxt, pSelect->pOrderByList);
if (TSDB_CODE_SUCCESS == code) {
- code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
+ code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pOrderByList);
}
}
return code;
@@ -1920,7 +2088,7 @@ static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect
code = translateStar(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
- code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
+ code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pProjectionList);
}
return code;
}
@@ -1943,7 +2111,7 @@ static int32_t translateGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
}
if (NULL != pSelect->pGroupByList) {
pCxt->currClause = SQL_CLAUSE_GROUP_BY;
- pSelect->isTimeOrderQuery = false;
+ pSelect->isTimeLineResult = false;
return translateExprList(pCxt, pSelect->pGroupByList);
}
return TSDB_CODE_SUCCESS;
@@ -1959,7 +2127,7 @@ static int32_t getTimeRange(SNode** pPrimaryKeyCond, STimeWindow* pTimeRange, bo
return code;
}
-static int32_t getFillTimeRange(STranslateContext* pCxt, SNode* pWhere, STimeWindow* pTimeRange) {
+static int32_t getQueryTimeRange(STranslateContext* pCxt, SNode* pWhere, STimeWindow* pTimeRange) {
if (NULL == pWhere) {
*pTimeRange = TSWINDOW_INITIALIZER;
return TSDB_CODE_SUCCESS;
@@ -1971,7 +2139,7 @@ static int32_t getFillTimeRange(STranslateContext* pCxt, SNode* pWhere, STimeWin
}
SNode* pPrimaryKeyCond = NULL;
- nodesPartitionCond(&pCond, &pPrimaryKeyCond, NULL, NULL);
+ nodesPartitionCond(&pCond, &pPrimaryKeyCond, NULL, NULL, NULL);
int32_t code = TSDB_CODE_SUCCESS;
if (NULL != pPrimaryKeyCond) {
@@ -2005,9 +2173,9 @@ static int32_t checkFill(STranslateContext* pCxt, SFillNode* pFill, SValueNode*
if (TIME_IS_VAR_DURATION(pInterval->unit)) {
int64_t f = 1;
if (pInterval->unit == 'n') {
- f = 30L * MILLISECOND_PER_DAY;
+ f = 30LL * MILLISECOND_PER_DAY;
} else if (pInterval->unit == 'y') {
- f = 365L * MILLISECOND_PER_DAY;
+ f = 365LL * MILLISECOND_PER_DAY;
}
intervalRange = pInterval->datum.i * f;
} else {
@@ -2020,16 +2188,13 @@ static int32_t checkFill(STranslateContext* pCxt, SFillNode* pFill, SValueNode*
return TSDB_CODE_SUCCESS;
}
-static int32_t translateFill(STranslateContext* pCxt, SNode* pWhere, SIntervalWindowNode* pInterval) {
+static int32_t translateFill(STranslateContext* pCxt, SSelectStmt* pSelect, SIntervalWindowNode* pInterval) {
if (NULL == pInterval->pFill) {
return TSDB_CODE_SUCCESS;
}
- int32_t code = getFillTimeRange(pCxt, pWhere, &(((SFillNode*)pInterval->pFill)->timeRange));
- if (TSDB_CODE_SUCCESS == code) {
- code = checkFill(pCxt, (SFillNode*)pInterval->pFill, (SValueNode*)pInterval->pInterval);
- }
- return code;
+ ((SFillNode*)pInterval->pFill)->timeRange = pSelect->timeRange;
+ return checkFill(pCxt, (SFillNode*)pInterval->pFill, (SValueNode*)pInterval->pInterval);
}
static int64_t getMonthsFromTimeVal(int64_t val, int32_t fromPrecision, char unit) {
@@ -2054,14 +2219,28 @@ static int64_t getMonthsFromTimeVal(int64_t val, int32_t fromPrecision, char uni
return -1;
}
+static const char* getPrecisionStr(uint8_t precision) {
+ switch (precision) {
+ case TSDB_TIME_PRECISION_MILLI:
+ return TSDB_TIME_PRECISION_MILLI_STR;
+ case TSDB_TIME_PRECISION_MICRO:
+ return TSDB_TIME_PRECISION_MICRO_STR;
+ case TSDB_TIME_PRECISION_NANO:
+ return TSDB_TIME_PRECISION_NANO_STR;
+ default:
+ break;
+ }
+ return "unknown";
+}
+
static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode* pInterval) {
uint8_t precision = ((SColumnNode*)pInterval->pCol)->node.resType.precision;
SValueNode* pInter = (SValueNode*)pInterval->pInterval;
bool valInter = TIME_IS_VAR_DURATION(pInter->unit);
- if (pInter->datum.i <= 0 ||
- (!valInter && convertTimePrecision(pInter->datum.i, precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime)) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTER_VALUE_TOO_SMALL, tsMinIntervalTime);
+ if (pInter->datum.i <= 0 || (!valInter && pInter->datum.i < tsMinIntervalTime)) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTER_VALUE_TOO_SMALL, tsMinIntervalTime,
+ getPrecisionStr(precision));
}
if (NULL != pInterval->pOffset) {
@@ -2102,7 +2281,7 @@ static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode*
static int32_t translateIntervalWindow(STranslateContext* pCxt, SSelectStmt* pSelect, SIntervalWindowNode* pInterval) {
int32_t code = checkIntervalWindow(pCxt, pInterval);
if (TSDB_CODE_SUCCESS == code) {
- code = translateFill(pCxt, pSelect->pWhere, pInterval);
+ code = translateFill(pCxt, pSelect, pInterval);
}
return code;
}
@@ -2119,9 +2298,6 @@ static EDealRes checkStateExpr(SNode* pNode, void* pContext) {
if (COLUMN_TYPE_TAG == pCol->colType) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_STATE_WIN_COL);
}
- if (TSDB_SUPER_TABLE == pCol->tableType) {
- return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_STATE_WIN_TABLE);
- }
}
return DEAL_RES_CONTINUE;
}
@@ -2200,7 +2376,7 @@ static int32_t translateInterpFill(STranslateContext* pCxt, SSelectStmt* pSelect
code = translateExpr(pCxt, &pSelect->pFill);
}
if (TSDB_CODE_SUCCESS == code) {
- code = getFillTimeRange(pCxt, pSelect->pRange, &(((SFillNode*)pSelect->pFill)->timeRange));
+ code = getQueryTimeRange(pCxt, pSelect->pRange, &(((SFillNode*)pSelect->pFill)->timeRange));
}
if (TSDB_CODE_SUCCESS == code) {
code = checkFill(pCxt, (SFillNode*)pSelect->pFill, (SValueNode*)pSelect->pEvery);
@@ -2232,9 +2408,13 @@ static int32_t translatePartitionBy(STranslateContext* pCxt, SNodeList* pPartiti
return translateExprList(pCxt, pPartitionByList);
}
-static int32_t translateWhere(STranslateContext* pCxt, SNode** pWhere) {
+static int32_t translateWhere(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->currClause = SQL_CLAUSE_WHERE;
- return translateExpr(pCxt, pWhere);
+ int32_t code = translateExpr(pCxt, &pSelect->pWhere);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = getQueryTimeRange(pCxt, pSelect->pWhere, &pSelect->timeRange);
+ }
+ return code;
}
static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) {
@@ -2280,9 +2460,9 @@ static int32_t createPrimaryKeyCol(STranslateContext* pCxt, SNode** pPrimaryKey)
return code;
}
-static EDealRes rewriteTimelineFuncImpl(SNode* pNode, void* pContext) {
+static EDealRes appendTsForImplicitTsFuncImpl(SNode* pNode, void* pContext) {
STranslateContext* pCxt = pContext;
- if (isTimelineFunc(pNode)) {
+ if (isImplicitTsFunc(pNode)) {
SFunctionNode* pFunc = (SFunctionNode*)pNode;
SNode* pPrimaryKey = NULL;
pCxt->errCode = createPrimaryKeyCol(pCxt, &pPrimaryKey);
@@ -2294,8 +2474,8 @@ static EDealRes rewriteTimelineFuncImpl(SNode* pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
-static int32_t rewriteTimelineFunc(STranslateContext* pCxt, SSelectStmt* pSelect) {
- nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, rewriteTimelineFuncImpl, pCxt);
+static int32_t appendTsForImplicitTsFunc(STranslateContext* pCxt, SSelectStmt* pSelect) {
+ nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, appendTsForImplicitTsFuncImpl, pCxt);
return pCxt->errCode;
}
@@ -2316,122 +2496,10 @@ static EDealRes rewriteSeletcValueFunc(STranslateContext* pCxt, SNode** pNode) {
nodesDestroyNode(*pNode);
*pNode = (SNode*)pFirst;
pCxt->errCode = fmGetFuncInfo(pFirst, pCxt->msgBuf.buf, pCxt->msgBuf.len);
- pCxt->pCurrSelectStmt->hasAggFuncs = true;
+ ((SSelectStmt*)pCxt->pCurrStmt)->hasAggFuncs = true;
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
}
-static EDealRes rewriteUniqueFunc(SNode** pNode, void* pContext) {
- SRwriteUniqueCxt* pCxt = pContext;
- if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
- SFunctionNode* pFunc = (SFunctionNode*)*pNode;
- if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
- SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
- NODES_CLEAR_LIST(pFunc->pParameterList);
- strcpy(((SExprNode*)pExpr)->aliasName, ((SExprNode*)*pNode)->aliasName);
- nodesDestroyNode(*pNode);
- *pNode = pExpr;
- pCxt->pExpr = pExpr;
- return DEAL_RES_IGNORE_CHILD;
- } else if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
- return rewriteSeletcValueFunc(pCxt->pTranslateCxt, pNode);
- }
- }
- return DEAL_RES_CONTINUE;
-}
-
-static SNode* createGroupingSet(SNode* pExpr) {
- SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
- if (NULL == pGroupingSet) {
- return NULL;
- }
- pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
- if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, nodesCloneNode(pExpr))) {
- nodesDestroyNode((SNode*)pGroupingSet);
- return NULL;
- }
- return (SNode*)pGroupingSet;
-}
-
-static int32_t rewriteUniqueStmt(STranslateContext* pCxt, SSelectStmt* pSelect) {
- if (!pSelect->hasUniqueFunc) {
- return TSDB_CODE_SUCCESS;
- }
-
- SRwriteUniqueCxt cxt = {.pTranslateCxt = pCxt, .pExpr = NULL};
- nodesRewriteExprs(pSelect->pProjectionList, rewriteUniqueFunc, &cxt);
- if (TSDB_CODE_SUCCESS == cxt.pTranslateCxt->errCode) {
- cxt.pTranslateCxt->errCode = nodesListMakeStrictAppend(&pSelect->pGroupByList, createGroupingSet(cxt.pExpr));
- }
- pSelect->hasIndefiniteRowsFunc = false;
- return cxt.pTranslateCxt->errCode;
-}
-
-typedef struct SRwriteTailCxt {
- STranslateContext* pTranslateCxt;
- int64_t limit;
- int64_t offset;
-} SRwriteTailCxt;
-
-static EDealRes rewriteTailFunc(SNode** pNode, void* pContext) {
- SRwriteTailCxt* pCxt = pContext;
- if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
- SFunctionNode* pFunc = (SFunctionNode*)*pNode;
- if (FUNCTION_TYPE_TAIL == pFunc->funcType) {
- pCxt->limit = ((SValueNode*)nodesListGetNode(pFunc->pParameterList, 1))->datum.i;
- if (3 == LIST_LENGTH(pFunc->pParameterList)) {
- pCxt->offset = ((SValueNode*)nodesListGetNode(pFunc->pParameterList, 2))->datum.i;
- }
- SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
- strcpy(((SExprNode*)pExpr)->aliasName, ((SExprNode*)*pNode)->aliasName);
- NODES_CLEAR_LIST(pFunc->pParameterList);
- nodesDestroyNode(*pNode);
- *pNode = pExpr;
- return DEAL_RES_IGNORE_CHILD;
- }
- }
- return DEAL_RES_CONTINUE;
-}
-
-static int32_t createLimieNode(SRwriteTailCxt* pCxt, SLimitNode** pOutput) {
- *pOutput = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT);
- if (NULL == *pOutput) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- (*pOutput)->limit = pCxt->limit;
- (*pOutput)->offset = pCxt->offset;
- return TSDB_CODE_SUCCESS;
-}
-
-static SNode* createOrderByExpr(STranslateContext* pCxt) {
- SOrderByExprNode* pOrder = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR);
- if (NULL == pOrder) {
- return NULL;
- }
- pCxt->errCode = createPrimaryKeyCol(pCxt, &pOrder->pExpr);
- if (TSDB_CODE_SUCCESS != pCxt->errCode) {
- nodesDestroyNode((SNode*)pOrder);
- return NULL;
- }
- pOrder->order = ORDER_DESC;
- pOrder->nullOrder = NULL_ORDER_FIRST;
- return (SNode*)pOrder;
-}
-
-static int32_t rewriteTailStmt(STranslateContext* pCxt, SSelectStmt* pSelect) {
- if (!pSelect->hasTailFunc) {
- return TSDB_CODE_SUCCESS;
- }
-
- SRwriteTailCxt cxt = {.pTranslateCxt = pCxt, .limit = -1, .offset = -1};
- nodesRewriteExprs(pSelect->pProjectionList, rewriteTailFunc, &cxt);
- int32_t code = nodesListMakeStrictAppend(&pSelect->pOrderByList, createOrderByExpr(pCxt));
- if (TSDB_CODE_SUCCESS == code) {
- code = createLimieNode(&cxt, &pSelect->pLimit);
- }
- pSelect->hasIndefiniteRowsFunc = false;
- return code;
-}
-
typedef struct SReplaceOrderByAliasCxt {
STranslateContext* pTranslateCxt;
SNodeList* pProjectionList;
@@ -2450,6 +2518,7 @@ static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) {
pCxt->pTranslateCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
return DEAL_RES_ERROR;
}
+ ((SExprNode*)pNew)->orderAlias = true;
nodesDestroyNode(*pNode);
*pNode = pNew;
return DEAL_RES_CONTINUE;
@@ -2465,12 +2534,18 @@ static int32_t replaceOrderByAlias(STranslateContext* pCxt, SNodeList* pProjecti
return pCxt->errCode;
}
-static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
- pCxt->pCurrSelectStmt = pSelect;
+static int32_t translateSelectWithoutFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
+ pCxt->pCurrStmt = (SNode*)pSelect;
+ pCxt->currClause = SQL_CLAUSE_SELECT;
+ return translateExprList(pCxt, pSelect->pProjectionList);
+}
+
+static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
+ pCxt->pCurrStmt = (SNode*)pSelect;
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
pSelect->precision = ((STableNode*)pSelect->pFromTable)->precision;
- code = translateWhere(pCxt, &pSelect->pWhere);
+ code = translateWhere(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = translatePartitionBy(pCxt, pSelect->pPartitionByList);
@@ -2494,19 +2569,16 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
code = checkAggColCoexist(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
- code = checkLimit(pCxt, pSelect);
+ code = checkWindowFuncCoexist(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
- code = translateInterp(pCxt, pSelect);
+ code = checkLimit(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
- code = rewriteUniqueStmt(pCxt, pSelect);
+ code = translateInterp(pCxt, pSelect);
}
- // if (TSDB_CODE_SUCCESS == code) {
- // code = rewriteTailStmt(pCxt, pSelect);
- // }
if (TSDB_CODE_SUCCESS == code) {
- code = rewriteTimelineFunc(pCxt, pSelect);
+ code = appendTsForImplicitTsFunc(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = replaceOrderByAlias(pCxt, pSelect->pProjectionList, pSelect->pOrderByList);
@@ -2514,6 +2586,14 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
return code;
}
+static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
+ if (NULL == pSelect->pFromTable) {
+ return translateSelectWithoutFrom(pCxt, pSelect);
+ } else {
+ return translateSelectFrom(pCxt, pSelect);
+ }
+}
+
static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
@@ -2588,8 +2668,7 @@ static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pS
if (TSDB_CODE_SUCCESS == code) {
if (other) {
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
- pCxt->pCurrSelectStmt = NULL;
- pCxt->pCurrSetOperator = pSetOperator;
+ pCxt->pCurrStmt = (SNode*)pSetOperator;
code = translateExprList(pCxt, pSetOperator->pOrderByList);
}
}
@@ -2599,6 +2678,13 @@ static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pS
return code;
}
+static int32_t checkSetOperLimit(STranslateContext* pCxt, SLimitNode* pLimit) {
+ if ((NULL != pLimit && pLimit->offset < 0)) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t translateSetOperator(STranslateContext* pCxt, SSetOperator* pSetOperator) {
int32_t code = translateQuery(pCxt, pSetOperator->pLeft);
if (TSDB_CODE_SUCCESS == code) {
@@ -2614,6 +2700,9 @@ static int32_t translateSetOperator(STranslateContext* pCxt, SSetOperator* pSetO
if (TSDB_CODE_SUCCESS == code) {
code = translateSetOperOrderBy(pCxt, pSetOperator);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = checkSetOperLimit(pCxt, (SLimitNode*)pSetOperator->pLimit);
+ }
return code;
}
@@ -2625,7 +2714,7 @@ static int32_t partitionDeleteWhere(STranslateContext* pCxt, SDeleteStmt* pDelet
SNode* pPrimaryKeyCond = NULL;
SNode* pOtherCond = NULL;
- int32_t code = nodesPartitionCond(&pDelete->pWhere, &pPrimaryKeyCond, &pDelete->pTagIndexCond, &pOtherCond);
+ int32_t code = nodesPartitionCond(&pDelete->pWhere, &pPrimaryKeyCond, NULL, &pDelete->pTagCond, &pOtherCond);
if (TSDB_CODE_SUCCESS == code && NULL != pOtherCond) {
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DELETE_WHERE);
}
@@ -2642,7 +2731,8 @@ static int32_t partitionDeleteWhere(STranslateContext* pCxt, SDeleteStmt* pDelet
}
static int32_t translateDeleteWhere(STranslateContext* pCxt, SDeleteStmt* pDelete) {
- int32_t code = translateWhere(pCxt, &pDelete->pWhere);
+ pCxt->currClause = SQL_CLAUSE_WHERE;
+ int32_t code = translateExpr(pCxt, &pDelete->pWhere);
if (TSDB_CODE_SUCCESS == code) {
code = partitionDeleteWhere(pCxt, pDelete);
}
@@ -2650,6 +2740,7 @@ static int32_t translateDeleteWhere(STranslateContext* pCxt, SDeleteStmt* pDelet
}
static int32_t translateDelete(STranslateContext* pCxt, SDeleteStmt* pDelete) {
+ pCxt->pCurrStmt = (SNode*)pDelete;
int32_t code = translateFrom(pCxt, pDelete->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
code = translateDeleteWhere(pCxt, pDelete);
@@ -2661,12 +2752,102 @@ static int32_t translateDelete(STranslateContext* pCxt, SDeleteStmt* pDelete) {
return code;
}
+static int32_t translateInsertCols(STranslateContext* pCxt, SInsertStmt* pInsert) {
+ if (NULL == pInsert->pCols) {
+ return createAllColumns(pCxt, false, &pInsert->pCols);
+ }
+ return translateExprList(pCxt, pInsert->pCols);
+}
+
+static int32_t translateInsertQuery(STranslateContext* pCxt, SInsertStmt* pInsert) {
+ int32_t code = resetTranslateNamespace(pCxt);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateQuery(pCxt, pInsert->pQuery);
+ }
+ return code;
+}
+
+static int32_t addOrderByPrimaryKeyToQueryImpl(STranslateContext* pCxt, SNode* pPrimaryKeyExpr,
+ SNodeList** pOrderByList) {
+ SOrderByExprNode* pOrderByExpr = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR);
+ if (NULL == pOrderByExpr) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ pOrderByExpr->nullOrder = NULL_ORDER_FIRST;
+ pOrderByExpr->order = ORDER_ASC;
+ pOrderByExpr->pExpr = nodesCloneNode(pPrimaryKeyExpr);
+ if (NULL == pOrderByExpr->pExpr) {
+ nodesDestroyNode((SNode*)pOrderByExpr);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ ((SExprNode*)pOrderByExpr->pExpr)->orderAlias = true;
+ NODES_DESTORY_LIST(*pOrderByList);
+ return nodesListMakeStrictAppend(pOrderByList, (SNode*)pOrderByExpr);
+}
+
+static int32_t addOrderByPrimaryKeyToQuery(STranslateContext* pCxt, SNode* pPrimaryKeyExpr, SNode* pStmt) {
+ if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
+ return addOrderByPrimaryKeyToQueryImpl(pCxt, pPrimaryKeyExpr, &((SSelectStmt*)pStmt)->pOrderByList);
+ }
+ return addOrderByPrimaryKeyToQueryImpl(pCxt, pPrimaryKeyExpr, &((SSetOperator*)pStmt)->pOrderByList);
+}
+
+static int32_t translateInsertProject(STranslateContext* pCxt, SInsertStmt* pInsert) {
+ SNodeList* pProjects = getProjectList(pInsert->pQuery);
+ if (LIST_LENGTH(pInsert->pCols) != LIST_LENGTH(pProjects)) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of columns");
+ }
+
+ SNode* pPrimaryKeyExpr = NULL;
+ SNode* pBoundCol = NULL;
+ SNode* pProj = NULL;
+ FORBOTH(pBoundCol, pInsert->pCols, pProj, pProjects) {
+ SColumnNode* pCol = (SColumnNode*)pBoundCol;
+ SExprNode* pExpr = (SExprNode*)pProj;
+ if (!dataTypeEqual(&pCol->node.resType, &pExpr->resType)) {
+ SNode* pFunc = NULL;
+ int32_t code = createCastFunc(pCxt, pProj, pCol->node.resType, &pFunc);
+ if (TSDB_CODE_SUCCESS != code) {
+ return code;
+ }
+ REPLACE_LIST2_NODE(pFunc);
+ pExpr = (SExprNode*)pFunc;
+ }
+ snprintf(pExpr->aliasName, sizeof(pExpr->aliasName), "%s", pCol->colName);
+ if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId) {
+ pPrimaryKeyExpr = pProj;
+ }
+ }
+
+ if (NULL == pPrimaryKeyExpr) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM,
+ "Primary timestamp column can not be null");
+ }
+
+ return addOrderByPrimaryKeyToQuery(pCxt, pPrimaryKeyExpr, pInsert->pQuery);
+}
+
+static int32_t translateInsert(STranslateContext* pCxt, SInsertStmt* pInsert) {
+ pCxt->pCurrStmt = (SNode*)pInsert;
+ int32_t code = translateFrom(pCxt, pInsert->pTable);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateInsertCols(pCxt, pInsert);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateInsertQuery(pCxt, pInsert);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateInsertProject(pCxt, pInsert);
+ }
+ return code;
+}
+
static int64_t getUnitPerMinute(uint8_t precision) {
switch (precision) {
case TSDB_TIME_PRECISION_MILLI:
return MILLISECOND_PER_MINUTE;
case TSDB_TIME_PRECISION_MICRO:
- return MILLISECOND_PER_MINUTE * 1000L;
+ return MILLISECOND_PER_MINUTE * 1000LL;
case TSDB_TIME_PRECISION_NANO:
return NANOSECOND_PER_MINUTE;
default:
@@ -2725,7 +2906,8 @@ static int32_t buildCreateDbReq(STranslateContext* pCxt, SCreateDatabaseStmt* pS
pReq->compression = pStmt->pOptions->compressionLevel;
pReq->replications = pStmt->pOptions->replica;
pReq->strict = pStmt->pOptions->strict;
- pReq->cacheLastRow = pStmt->pOptions->cachelast;
+ pReq->cacheLast = pStmt->pOptions->cacheLast;
+ pReq->cacheLastSize = pStmt->pOptions->cacheLastSize;
pReq->schemaless = pStmt->pOptions->schemaless;
pReq->ignoreExist = pStmt->ignoreExists;
return buildCreateDbRetentions(pStmt->pOptions->pRetentions, pReq);
@@ -2886,8 +3068,11 @@ static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName
int32_t code =
checkRangeOption(pCxt, "buffer", pOptions->buffer, TSDB_MIN_BUFFER_PER_VNODE, TSDB_MAX_BUFFER_PER_VNODE);
if (TSDB_CODE_SUCCESS == code) {
- code = checkRangeOption(pCxt, "cacheLast", pOptions->cachelast, TSDB_MIN_DB_CACHE_LAST_ROW,
- TSDB_MAX_DB_CACHE_LAST_ROW);
+ code = checkRangeOption(pCxt, "cacheLast", pOptions->cacheLast, TSDB_MIN_DB_CACHE_LAST, TSDB_MAX_DB_CACHE_LAST);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = checkRangeOption(pCxt, "cacheLastSize", pOptions->cacheLastSize, TSDB_MIN_DB_CACHE_LAST_SIZE,
+ TSDB_MAX_DB_CACHE_LAST_SIZE);
}
if (TSDB_CODE_SUCCESS == code) {
code = checkRangeOption(pCxt, "compression", pOptions->compressionLevel, TSDB_MIN_COMP_LEVEL, TSDB_MAX_COMP_LEVEL);
@@ -3000,6 +3185,7 @@ static void buildAlterDbReq(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt,
pReq->buffer = pStmt->pOptions->buffer;
pReq->pageSize = -1;
pReq->pages = pStmt->pOptions->pages;
+ pReq->cacheLastSize = -1;
pReq->daysPerFile = -1;
pReq->daysToKeep0 = pStmt->pOptions->keep[0];
pReq->daysToKeep1 = pStmt->pOptions->keep[1];
@@ -3007,7 +3193,8 @@ static void buildAlterDbReq(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt,
pReq->fsyncPeriod = pStmt->pOptions->fsyncPeriod;
pReq->walLevel = pStmt->pOptions->walLevel;
pReq->strict = pStmt->pOptions->strict;
- pReq->cacheLastRow = pStmt->pOptions->cachelast;
+ pReq->cacheLast = pStmt->pOptions->cacheLast;
+ pReq->cacheLastSize = pStmt->pOptions->cacheLastSize;
pReq->replications = pStmt->pOptions->replica;
return;
}
@@ -3024,6 +3211,14 @@ static int32_t translateAlterDatabase(STranslateContext* pCxt, SAlterDatabaseStm
return buildCmdMsg(pCxt, TDMT_MND_ALTER_DB, (FSerializeFunc)tSerializeSAlterDbReq, &alterReq);
}
+static int32_t translateTrimDatabase(STranslateContext* pCxt, STrimDatabaseStmt* pStmt) {
+ STrimDbReq req = {0};
+ SName name = {0};
+ tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName));
+ tNameGetFullDbName(&name, req.db);
+ return buildCmdMsg(pCxt, TDMT_MND_TRIM_DB, (FSerializeFunc)tSerializeSTrimDbReq, &req);
+}
+
static int32_t columnDefNodeToField(SNodeList* pList, SArray** pArray) {
*pArray = taosArrayInit(LIST_LENGTH(pList), sizeof(SField));
SNode* pNode;
@@ -3077,13 +3272,30 @@ static bool validRollupFunc(const char* pFunc) {
return false;
}
-static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs) {
+static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs, bool createStable,
+ SDbCfgInfo* pDbCfg) {
if (NULL == pFuncs) {
+ if (NULL != pDbCfg->pRetensions) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION,
+ "To create a super table in databases configured with the 'RETENTIONS' option, "
+ "the 'ROLLUP' option must be present");
+ }
return TSDB_CODE_SUCCESS;
}
- if (1 != LIST_LENGTH(pFuncs) || !validRollupFunc(((SFunctionNode*)nodesListGetNode(pFuncs, 0))->functionName)) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROLLUP_OPTION);
+ if (!createStable || NULL == pDbCfg->pRetensions) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION,
+ "Invalid option rollup: Only supported for create super table in databases "
+ "configured with the 'RETENTIONS' option");
+ }
+ if (1 != LIST_LENGTH(pFuncs)) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROLLUP_OPTION,
+ "Invalid option rollup: only one function is allowed");
+ }
+ const char* pFunc = ((SFunctionNode*)nodesListGetNode(pFuncs, 0))->functionName;
+ if (!validRollupFunc(pFunc)) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROLLUP_OPTION,
+ "Invalid option rollup: %s function is not supported", pFunc);
}
return TSDB_CODE_SUCCESS;
}
@@ -3109,9 +3321,9 @@ static int32_t checkTableTagsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
}
if (TSDB_CODE_SUCCESS == code) {
- if ((TSDB_DATA_TYPE_VARCHAR == pTag->dataType.type && pTag->dataType.bytes > TSDB_MAX_BINARY_LEN) ||
- (TSDB_DATA_TYPE_NCHAR == pTag->dataType.type && pTag->dataType.bytes > TSDB_MAX_NCHAR_LEN)) {
- code = code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
+ if ((TSDB_DATA_TYPE_VARCHAR == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_BINARY_LEN) ||
+ (TSDB_DATA_TYPE_NCHAR == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_NCHAR_LEN)) {
+ code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
}
}
if (TSDB_CODE_SUCCESS == code) {
@@ -3131,11 +3343,11 @@ static int32_t checkTableTagsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
return code;
}
-static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, SNodeList* pCols) {
+static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, int32_t ntags, SNodeList* pCols) {
int32_t ncols = LIST_LENGTH(pCols);
if (ncols < TSDB_MIN_COLUMNS) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
- } else if (ncols > TSDB_MAX_COLUMNS) {
+ } else if (ncols + ntags > TSDB_MAX_COLUMNS) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TOO_MANY_COLUMNS);
}
@@ -3191,7 +3403,7 @@ static int32_t checkTableSchema(STranslateContext* pCxt, SCreateTableStmt* pStmt
int32_t code = checkTableTagsSchema(pCxt, pHash, pStmt->pTags);
if (TSDB_CODE_SUCCESS == code) {
- code = checkTableColsSchema(pCxt, pHash, pStmt->pCols);
+ code = checkTableColsSchema(pCxt, pHash, LIST_LENGTH(pStmt->pTags), pStmt->pCols);
}
taosHashCleanup(pHash);
@@ -3220,11 +3432,18 @@ static int32_t getTableMaxDelayOption(STranslateContext* pCxt, SValueNode* pVal,
pMaxDelay);
}
-static int32_t checkTableMaxDelayOption(STranslateContext* pCxt, STableOptions* pOptions) {
+static int32_t checkTableMaxDelayOption(STranslateContext* pCxt, STableOptions* pOptions, bool createStable,
+ SDbCfgInfo* pDbCfg) {
if (NULL == pOptions->pMaxDelay) {
return TSDB_CODE_SUCCESS;
}
+ if (!createStable || NULL == pDbCfg->pRetensions) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION,
+ "Invalid option maxdelay: Only supported for create super table in databases "
+ "configured with the 'RETENTIONS' option");
+ }
+
if (LIST_LENGTH(pOptions->pMaxDelay) > 2) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION, "maxdelay");
}
@@ -3243,11 +3462,18 @@ static int32_t getTableWatermarkOption(STranslateContext* pCxt, SValueNode* pVal
pMaxDelay);
}
-static int32_t checkTableWatermarkOption(STranslateContext* pCxt, STableOptions* pOptions) {
+static int32_t checkTableWatermarkOption(STranslateContext* pCxt, STableOptions* pOptions, bool createStable,
+ SDbCfgInfo* pDbCfg) {
if (NULL == pOptions->pWatermark) {
return TSDB_CODE_SUCCESS;
}
+ if (!createStable || NULL == pDbCfg->pRetensions) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION,
+ "Invalid option watermark: Only supported for create super table in databases "
+ "configured with the 'RETENTIONS' option");
+ }
+
if (LIST_LENGTH(pOptions->pWatermark) > 2) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION, "watermark");
}
@@ -3261,13 +3487,22 @@ static int32_t checkTableWatermarkOption(STranslateContext* pCxt, STableOptions*
return code;
}
-static int32_t checkCreateTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
- int32_t code = checkTableMaxDelayOption(pCxt, pStmt->pOptions);
+static int32_t checkCreateTable(STranslateContext* pCxt, SCreateTableStmt* pStmt, bool createStable) {
+ SDbCfgInfo dbCfg = {0};
+ int32_t code = getDBCfg(pCxt, pStmt->dbName, &dbCfg);
+ if (TSDB_CODE_SUCCESS == code && !createStable && NULL != dbCfg.pRetensions) {
+ code = generateSyntaxErrMsgExt(
+ &pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TABLE_OPTION,
+ "Only super table creation is supported in databases configured with the 'RETENTIONS' option");
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = checkTableMaxDelayOption(pCxt, pStmt->pOptions, createStable, &dbCfg);
+ }
if (TSDB_CODE_SUCCESS == code) {
- code = checkTableWatermarkOption(pCxt, pStmt->pOptions);
+ code = checkTableWatermarkOption(pCxt, pStmt->pOptions, createStable, &dbCfg);
}
if (TSDB_CODE_SUCCESS == code) {
- code = checkTableRollupOption(pCxt, pStmt->pOptions->pRollupFuncs);
+ code = checkTableRollupOption(pCxt, pStmt->pOptions->pRollupFuncs, createStable, &dbCfg);
}
if (TSDB_CODE_SUCCESS == code) {
code = checkTableSmaOption(pCxt, pStmt);
@@ -3324,7 +3559,7 @@ static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, ch
nodesDestroyNode((SNode*)pSelect);
return TSDB_CODE_OUT_OF_MEMORY;
}
- strcpy(pFunc->functionName, "_wstartts");
+ strcpy(pFunc->functionName, "_wstart");
nodesListPushFront(pSelect->pProjectionList, (SNode*)pFunc);
SNode* pProject = NULL;
FOREACH(pProject, pSelect->pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#%p", pProject); }
@@ -3503,26 +3738,40 @@ static int32_t buildRollupAst(STranslateContext* pCxt, SCreateTableStmt* pStmt,
return code;
}
+static int32_t buildRollupFuncs(SNodeList* pFuncs, SArray** pArray) {
+ if (NULL == pFuncs) {
+ return TSDB_CODE_SUCCESS;
+ }
+ *pArray = taosArrayInit(LIST_LENGTH(pFuncs), TSDB_FUNC_NAME_LEN);
+ SNode* pNode;
+ FOREACH(pNode, pFuncs) { taosArrayPush(*pArray, ((SFunctionNode*)pNode)->functionName); }
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStmt, SMCreateStbReq* pReq) {
pReq->igExists = pStmt->ignoreExists;
pReq->delay1 = pStmt->pOptions->maxDelay1;
pReq->delay2 = pStmt->pOptions->maxDelay2;
pReq->watermark1 = pStmt->pOptions->watermark1;
pReq->watermark2 = pStmt->pOptions->watermark2;
- // pReq->ttl = pStmt->pOptions->ttl;
+ pReq->colVer = 1;
+ pReq->tagVer = 1;
+ pReq->source = TD_REQ_FROM_APP;
columnDefNodeToField(pStmt->pCols, &pReq->pColumns);
columnDefNodeToField(pStmt->pTags, &pReq->pTags);
pReq->numOfColumns = LIST_LENGTH(pStmt->pCols);
pReq->numOfTags = LIST_LENGTH(pStmt->pTags);
if (pStmt->pOptions->commentNull == false) {
- pReq->comment = strdup(pStmt->pOptions->comment);
- if (NULL == pReq->comment) {
+ pReq->pComment = strdup(pStmt->pOptions->comment);
+ if (NULL == pReq->pComment) {
return TSDB_CODE_OUT_OF_MEMORY;
}
pReq->commentLen = strlen(pStmt->pOptions->comment);
} else {
pReq->commentLen = -1;
}
+ buildRollupFuncs(pStmt->pOptions->pRollupFuncs, &pReq->pFuncs);
+ pReq->numOfFuncs = taosArrayGetSize(pReq->pFuncs);
SName tableName;
tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), pReq->name);
@@ -3535,7 +3784,7 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm
static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
SMCreateStbReq createReq = {0};
- int32_t code = checkCreateTable(pCxt, pStmt);
+ int32_t code = checkCreateTable(pCxt, pStmt, true);
if (TSDB_CODE_SUCCESS == code) {
code = buildCreateStbReq(pCxt, pStmt, &createReq);
}
@@ -3622,35 +3871,73 @@ static int32_t buildAlterSuperTableReq(STranslateContext* pCxt, SAlterTableStmt*
return TSDB_CODE_SUCCESS;
}
-static SSchema* getColSchema(STableMeta* pTableMeta, const char* pTagName) {
+static SSchema* getColSchema(STableMeta* pTableMeta, const char* pColName) {
int32_t numOfFields = getNumOfTags(pTableMeta) + getNumOfColumns(pTableMeta);
for (int32_t i = 0; i < numOfFields; ++i) {
- SSchema* pTagSchema = pTableMeta->schema + i;
- if (0 == strcmp(pTagName, pTagSchema->name)) {
- return pTagSchema;
+ SSchema* pSchema = pTableMeta->schema + i;
+ if (0 == strcmp(pColName, pSchema->name)) {
+ return pSchema;
+ }
+ }
+ return NULL;
+}
+
+static SSchema* getTagSchema(STableMeta* pTableMeta, const char* pTagName) {
+ int32_t numOfTags = getNumOfTags(pTableMeta);
+ SSchema* pTagsSchema = getTableTagSchema(pTableMeta);
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ SSchema* pSchema = pTagsSchema + i;
+ if (0 == strcmp(pTagName, pSchema->name)) {
+ return pSchema;
}
}
return NULL;
}
-static int32_t checkAlterSuperTable(STranslateContext* pCxt, SAlterTableStmt* pStmt) {
- if (TSDB_ALTER_TABLE_UPDATE_TAG_VAL == pStmt->alterType || TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME == pStmt->alterType) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
+static int32_t checkAlterSuperTable(STranslateContext* pCxt, SAlterTableStmt* pStmt) {
+ if (TSDB_ALTER_TABLE_UPDATE_TAG_VAL == pStmt->alterType || TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME == pStmt->alterType) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE,
+ "Set tag value only available for child table");
+ }
+
+ if (pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_OPTIONS && -1 != pStmt->pOptions->ttl) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
+ }
+
+ if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
+ }
+
+ if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_COLUMN) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COL_JSON);
+ }
+
+ STableMeta* pTableMeta = NULL;
+ int32_t code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pTableMeta);
+ if (TSDB_CODE_SUCCESS != code) {
+ return code;
+ }
+
+ SSchema* pTagsSchema = getTableTagSchema(pTableMeta);
+ if (getNumOfTags(pTableMeta) == 1 && pTagsSchema->type == TSDB_DATA_TYPE_JSON &&
+ (pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG || pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG ||
+ pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_TAG_BYTES)) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
}
+
if (TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType ||
TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType) {
- STableMeta* pTableMeta = NULL;
- int32_t code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pTableMeta);
- if (TSDB_CODE_SUCCESS == code) {
- SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
- if (NULL == pSchema) {
- code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName);
- } else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type ||
- pSchema->bytes >= calcTypeBytes(pStmt->dataType)) {
- code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL);
- }
+ if (TSDB_SUPER_TABLE != pTableMeta->tableType) {
+ return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "Table is not super table");
+ }
+
+ SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
+ if (NULL == pSchema) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName);
+ } else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type ||
+ pSchema->bytes >= calcTypeBytes(pStmt->dataType)) {
+ return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL);
}
- return code;
}
return TSDB_CODE_SUCCESS;
}
@@ -3685,7 +3972,7 @@ static int32_t translateCreateUser(STranslateContext* pCxt, SCreateUserStmt* pSt
strcpy(createReq.user, pStmt->useName);
createReq.createType = 0;
createReq.superUser = 0;
- createReq.sysInfo = 1;
+ createReq.sysInfo = pStmt->sysinfo;
createReq.enable = 1;
strcpy(createReq.pass, pStmt->password);
@@ -3697,6 +3984,8 @@ static int32_t translateAlterUser(STranslateContext* pCxt, SAlterUserStmt* pStmt
strcpy(alterReq.user, pStmt->useName);
alterReq.alterType = pStmt->alterType;
alterReq.superUser = 0;
+ alterReq.enable = pStmt->enable;
+ alterReq.sysInfo = pStmt->sysinfo;
strcpy(alterReq.pass, pStmt->password);
if (NULL != pCxt->pParseCxt->db) {
strcpy(alterReq.dbname, pCxt->pParseCxt->db);
@@ -3796,6 +4085,18 @@ static int32_t buildCreateSmaReq(STranslateContext* pCxt, SCreateIndexStmt* pStm
(NULL != pStmt->pOptions->pSliding ? ((SValueNode*)pStmt->pOptions->pSliding)->datum.i : pReq->interval);
pReq->slidingUnit =
(NULL != pStmt->pOptions->pSliding ? ((SValueNode*)pStmt->pOptions->pSliding)->unit : pReq->intervalUnit);
+ if (NULL != pStmt->pOptions->pStreamOptions) {
+ SStreamOptions* pStreamOpt = (SStreamOptions*)pStmt->pOptions->pStreamOptions;
+ pReq->maxDelay = (NULL != pStreamOpt->pDelay ? ((SValueNode*)pStreamOpt->pDelay)->datum.i : -1);
+ pReq->watermark = (NULL != pStreamOpt->pWatermark ? ((SValueNode*)pStreamOpt->pWatermark)->datum.i
+ : TSDB_DEFAULT_ROLLUP_WATERMARK);
+ if (pReq->watermark < TSDB_MIN_ROLLUP_WATERMARK) {
+ pReq->watermark = TSDB_MIN_ROLLUP_WATERMARK;
+ }
+ if (pReq->watermark > TSDB_MAX_ROLLUP_WATERMARK) {
+ pReq->watermark = TSDB_MAX_ROLLUP_WATERMARK;
+ }
+ }
int32_t code = getSmaIndexDstVgId(pCxt, pStmt->tableName, &pReq->dstVgId);
if (TSDB_CODE_SUCCESS == code) {
@@ -3808,17 +4109,42 @@ static int32_t buildCreateSmaReq(STranslateContext* pCxt, SCreateIndexStmt* pStm
return code;
}
-static int32_t translateCreateSmaIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) {
- if (DEAL_RES_ERROR == translateValue(pCxt, (SValueNode*)pStmt->pOptions->pInterval) ||
- (NULL != pStmt->pOptions->pOffset &&
- DEAL_RES_ERROR == translateValue(pCxt, (SValueNode*)pStmt->pOptions->pOffset)) ||
- (NULL != pStmt->pOptions->pSliding &&
- DEAL_RES_ERROR == translateValue(pCxt, (SValueNode*)pStmt->pOptions->pSliding))) {
- return pCxt->errCode;
+static int32_t checkCreateSmaIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) {
+ SDbCfgInfo dbCfg = {0};
+ int32_t code = getDBCfg(pCxt, pCxt->pParseCxt->db, &dbCfg);
+ if (TSDB_CODE_SUCCESS == code && NULL != dbCfg.pRetensions) {
+ code = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_SMA_INDEX,
+ "Tables configured with the 'ROLLUP' option do not support creating sma index");
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = doTranslateValue(pCxt, (SValueNode*)pStmt->pOptions->pInterval);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pOptions->pOffset) {
+ code = doTranslateValue(pCxt, (SValueNode*)pStmt->pOptions->pOffset);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pOptions->pSliding) {
+ code = doTranslateValue(pCxt, (SValueNode*)pStmt->pOptions->pSliding);
+ }
+
+ if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pOptions->pStreamOptions) {
+ SStreamOptions* pStreamOpt = (SStreamOptions*)pStmt->pOptions->pStreamOptions;
+ if (NULL != pStreamOpt->pWatermark) {
+ code = doTranslateValue(pCxt, (SValueNode*)pStreamOpt->pWatermark);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pStreamOpt->pDelay) {
+ code = doTranslateValue(pCxt, (SValueNode*)pStreamOpt->pDelay);
+ }
}
+ return code;
+}
+
+static int32_t translateCreateSmaIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) {
SMCreateSmaReq createSmaReq = {0};
- int32_t code = buildCreateSmaReq(pCxt, pStmt, &createSmaReq);
+ int32_t code = checkCreateSmaIndex(pCxt, pStmt);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = buildCreateSmaReq(pCxt, pStmt, &createSmaReq);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = buildCmdMsg(pCxt, TDMT_MND_CREATE_SMA, (FSerializeFunc)tSerializeSMCreateSmaReq, &createSmaReq);
}
@@ -3851,36 +4177,11 @@ static int32_t translateCreateIndex(STranslateContext* pCxt, SCreateIndexStmt* p
}
static int32_t translateDropIndex(STranslateContext* pCxt, SDropIndexStmt* pStmt) {
- SEncoder encoder = {0};
- int32_t contLen = 0;
- SVDropTSmaReq dropSmaReq = {0};
- strcpy(dropSmaReq.indexName, pStmt->indexName);
-
- pCxt->pCmdMsg = taosMemoryMalloc(sizeof(SCmdMsgInfo));
- if (NULL == pCxt->pCmdMsg) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- int32_t ret = 0;
- tEncodeSize(tEncodeSVDropTSmaReq, &dropSmaReq, contLen, ret);
- if (ret < 0) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet;
- pCxt->pCmdMsg->msgType = TDMT_VND_DROP_SMA;
- pCxt->pCmdMsg->msgLen = contLen;
- pCxt->pCmdMsg->pMsg = taosMemoryMalloc(pCxt->pCmdMsg->msgLen);
- if (NULL == pCxt->pCmdMsg->pMsg) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- void* pBuf = pCxt->pCmdMsg->pMsg;
- if (tEncodeSVDropTSmaReq(&encoder, &dropSmaReq) < 0) {
- tEncoderClear(&encoder);
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- tEncoderClear(&encoder);
- return TSDB_CODE_SUCCESS;
+ SMDropSmaReq dropSmaReq = {0};
+ SName name;
+ tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pCxt->pParseCxt->db, pStmt->indexName, &name), dropSmaReq.name);
+ dropSmaReq.igNotExists = pStmt->ignoreNotExists;
+ return buildCmdMsg(pCxt, TDMT_MND_DROP_SMA, (FSerializeFunc)tSerializeSMDropSmaReq, &dropSmaReq);
}
static int16_t getCreateComponentNodeMsgType(ENodeType type) {
@@ -3932,6 +4233,7 @@ static int32_t buildCreateTopicReq(STranslateContext* pCxt, SCreateTopicStmt* pS
tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->topicName, strlen(pStmt->topicName));
tNameGetFullDbName(&name, pReq->name);
pReq->igExists = pStmt->ignoreExists;
+ pReq->withMeta = pStmt->withMeta;
pReq->sql = strdup(pCxt->pParseCxt->pSql);
if (NULL == pReq->sql) {
@@ -4082,6 +4384,39 @@ static void getSourceDatabase(SNode* pStmt, int32_t acctId, char* pDbFName) {
tNameGetFullDbName(&name, pDbFName);
}
+static int32_t addWstartTsToCreateStreamQuery(SNode* pStmt) {
+ SSelectStmt* pSelect = (SSelectStmt*)pStmt;
+ SNode* pProj = nodesListGetNode(pSelect->pProjectionList, 0);
+ if (NULL == pSelect->pWindow ||
+ (QUERY_NODE_FUNCTION == nodeType(pProj) && 0 == strcmp("_wstart", ((SFunctionNode*)pProj)->functionName))) {
+ return TSDB_CODE_SUCCESS;
+ }
+ SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ strcpy(pFunc->functionName, "_wstart");
+ strcpy(pFunc->node.aliasName, pFunc->functionName);
+ int32_t code = nodesListPushFront(pSelect->pProjectionList, (SNode*)pFunc);
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyNode((SNode*)pFunc);
+ }
+ return code;
+}
+
+static int32_t buildCreateStreamQuery(STranslateContext* pCxt, SNode* pStmt, SCMCreateStreamReq* pReq) {
+ pCxt->createStream = true;
+ int32_t code = addWstartTsToCreateStreamQuery(pStmt);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateQuery(pCxt, pStmt);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ getSourceDatabase(pStmt, pCxt->pParseCxt->acctId, pReq->sourceDB);
+ code = nodesNodeToString(pStmt, false, &pReq->ast, NULL);
+ }
+ return code;
+}
+
static int32_t buildCreateStreamReq(STranslateContext* pCxt, SCreateStreamStmt* pStmt, SCMCreateStreamReq* pReq) {
pReq->igExists = pStmt->ignoreExists;
@@ -4095,13 +4430,7 @@ static int32_t buildCreateStreamReq(STranslateContext* pCxt, SCreateStreamStmt*
tNameExtractFullName(&name, pReq->targetStbFullName);
}
- pCxt->createStream = true;
- int32_t code = translateQuery(pCxt, pStmt->pQuery);
- if (TSDB_CODE_SUCCESS == code) {
- getSourceDatabase(pStmt->pQuery, pCxt->pParseCxt->acctId, pReq->sourceDB);
- code = nodesNodeToString(pStmt->pQuery, false, &pReq->ast, NULL);
- }
-
+ int32_t code = buildCreateStreamQuery(pCxt, pStmt->pQuery, pReq);
if (TSDB_CODE_SUCCESS == code) {
pReq->sql = strdup(pCxt->pParseCxt->pSql);
if (NULL == pReq->sql) {
@@ -4113,6 +4442,7 @@ static int32_t buildCreateStreamReq(STranslateContext* pCxt, SCreateStreamStmt*
pReq->triggerType = pStmt->pOptions->triggerType;
pReq->maxDelay = (NULL != pStmt->pOptions->pDelay ? ((SValueNode*)pStmt->pOptions->pDelay)->datum.i : 0);
pReq->watermark = (NULL != pStmt->pOptions->pWatermark ? ((SValueNode*)pStmt->pOptions->pWatermark)->datum.i : 0);
+ pReq->igExpired = pStmt->pOptions->ignoreExpired;
}
return code;
@@ -4287,6 +4617,11 @@ static int32_t translateSplitVgroup(STranslateContext* pCxt, SSplitVgroupStmt* p
return buildCmdMsg(pCxt, TDMT_MND_SPLIT_VGROUP, (FSerializeFunc)tSerializeSSplitVgroupReq, &req);
}
+static int32_t translateShowVariables(STranslateContext* pCxt, SShowStmt* pStmt) {
+ SShowVariablesReq req = {0};
+ return buildCmdMsg(pCxt, TDMT_MND_SHOW_VARIABLES, (FSerializeFunc)tSerializeSShowVariablesReq, &req);
+}
+
static int32_t translateShowCreateDatabase(STranslateContext* pCxt, SShowCreateDatabaseStmt* pStmt) {
pStmt->pCfg = taosMemoryCalloc(1, sizeof(SDbCfgInfo));
if (NULL == pStmt->pCfg) {
@@ -4296,7 +4631,10 @@ static int32_t translateShowCreateDatabase(STranslateContext* pCxt, SShowCreateD
}
static int32_t translateShowCreateTable(STranslateContext* pCxt, SShowCreateTableStmt* pStmt) {
- return getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pStmt->pMeta);
+ SName name;
+ toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &name);
+
+ return getTableCfg(pCxt, &name, (STableCfg**)&pStmt->pCfg);
}
static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
@@ -4311,6 +4649,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
case QUERY_NODE_DELETE_STMT:
code = translateDelete(pCxt, (SDeleteStmt*)pNode);
break;
+ case QUERY_NODE_INSERT_STMT:
+ code = translateInsert(pCxt, (SInsertStmt*)pNode);
+ break;
case QUERY_NODE_CREATE_DATABASE_STMT:
code = translateCreateDatabase(pCxt, (SCreateDatabaseStmt*)pNode);
break;
@@ -4320,6 +4661,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
case QUERY_NODE_ALTER_DATABASE_STMT:
code = translateAlterDatabase(pCxt, (SAlterDatabaseStmt*)pNode);
break;
+ case QUERY_NODE_TRIM_DATABASE_STMT:
+ code = translateTrimDatabase(pCxt, (STrimDatabaseStmt*)pNode);
+ break;
case QUERY_NODE_CREATE_TABLE_STMT:
code = translateCreateSuperTable(pCxt, (SCreateTableStmt*)pNode);
break;
@@ -4330,6 +4674,7 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
code = translateDropSuperTable(pCxt, (SDropSuperTableStmt*)pNode);
break;
case QUERY_NODE_ALTER_TABLE_STMT:
+ case QUERY_NODE_ALTER_SUPER_TABLE_STMT:
code = translateAlterSuperTable(pCxt, (SAlterTableStmt*)pNode);
break;
case QUERY_NODE_CREATE_USER_STMT:
@@ -4428,6 +4773,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
case QUERY_NODE_SPLIT_VGROUP_STMT:
code = translateSplitVgroup(pCxt, (SSplitVgroupStmt*)pNode);
break;
+ case QUERY_NODE_SHOW_VARIABLES_STMT:
+ code = translateShowVariables(pCxt, (SShowStmt*)pNode);
+ break;
case QUERY_NODE_SHOW_CREATE_DATABASE_STMT:
code = translateShowCreateDatabase(pCxt, (SShowCreateDatabaseStmt*)pNode);
break;
@@ -4443,12 +4791,12 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
++(pCxt->currLevel);
- ESqlClause currClause = pCxt->currClause;
- SSelectStmt* pCurrStmt = pCxt->pCurrSelectStmt;
- int32_t code = translateQuery(pCxt, pNode);
+ ESqlClause currClause = pCxt->currClause;
+ SNode* pCurrStmt = pCxt->pCurrStmt;
+ int32_t code = translateQuery(pCxt, pNode);
--(pCxt->currLevel);
pCxt->currClause = currClause;
- pCxt->pCurrSelectStmt = pCurrStmt;
+ pCxt->pCurrStmt = pCurrStmt;
return code;
}
@@ -4463,8 +4811,13 @@ static int32_t extractQueryResultSchema(const SNodeList* pProjections, int32_t*
int32_t index = 0;
FOREACH(pNode, pProjections) {
SExprNode* pExpr = (SExprNode*)pNode;
- (*pSchema)[index].type = pExpr->resType.type;
- (*pSchema)[index].bytes = pExpr->resType.bytes;
+ if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
+ (*pSchema)[index].type = TSDB_DATA_TYPE_VARCHAR;
+ (*pSchema)[index].bytes = 0;
+ } else {
+ (*pSchema)[index].type = pExpr->resType.type;
+ (*pSchema)[index].bytes = pExpr->resType.bytes;
+ }
(*pSchema)[index].colId = index + 1;
if ('\0' != pExpr->userAlias[0]) {
strcpy((*pSchema)[index].name, pExpr->userAlias);
@@ -4553,6 +4906,24 @@ static int32_t extractShowCreateTableResultSchema(int32_t* numOfCols, SSchema**
return TSDB_CODE_SUCCESS;
}
+static int32_t extractShowVariablesResultSchema(int32_t* numOfCols, SSchema** pSchema) {
+ *numOfCols = 2;
+ *pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema));
+ if (NULL == (*pSchema)) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ (*pSchema)[0].type = TSDB_DATA_TYPE_BINARY;
+ (*pSchema)[0].bytes = TSDB_CONFIG_OPTION_LEN;
+ strcpy((*pSchema)[0].name, "name");
+
+ (*pSchema)[1].type = TSDB_DATA_TYPE_BINARY;
+ (*pSchema)[1].bytes = TSDB_CONFIG_VALUE_LEN;
+ strcpy((*pSchema)[1].name, "value");
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t extractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
if (NULL == pRoot) {
return TSDB_CODE_SUCCESS;
@@ -4571,6 +4942,9 @@ int32_t extractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pS
case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
return extractShowCreateTableResultSchema(numOfCols, pSchema);
+ case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
+ case QUERY_NODE_SHOW_VARIABLES_STMT:
+ return extractShowVariablesResultSchema(numOfCols, pSchema);
default:
break;
}
@@ -4604,6 +4978,8 @@ static const char* getSysDbName(ENodeType type) {
case QUERY_NODE_SHOW_STREAMS_STMT:
case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
case QUERY_NODE_SHOW_APPS_STMT:
+ case QUERY_NODE_SHOW_CONSUMERS_STMT:
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
return TSDB_PERFORMANCE_SCHEMA_DB;
default:
break;
@@ -4659,12 +5035,25 @@ static const char* getSysTableName(ENodeType type) {
return TSDB_PERFS_TABLE_APPS;
case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
return TSDB_INS_TABLE_DNODE_VARIABLES;
+ case QUERY_NODE_SHOW_CONSUMERS_STMT:
+ return TSDB_PERFS_TABLE_CONSUMERS;
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
+ return TSDB_PERFS_TABLE_SUBSCRIPTIONS;
default:
break;
}
return NULL;
}
+static SNode* createStarCol() {
+ SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
+ if (NULL == pCol) {
+ return NULL;
+ }
+ strcpy(pCol->colName, "*");
+ return (SNode*)pCol;
+}
+
static int32_t createSimpleSelectStmt(const char* pDb, const char* pTable, SSelectStmt** pStmt) {
SSelectStmt* pSelect = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT);
if (NULL == pSelect) {
@@ -4682,6 +5071,11 @@ static int32_t createSimpleSelectStmt(const char* pDb, const char* pTable, SSele
strcpy(pRealTable->table.tableAlias, pTable);
pSelect->pFromTable = (SNode*)pRealTable;
+ if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pSelect->pProjectionList, createStarCol())) {
+ nodesDestroyNode((SNode*)pSelect);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
*pStmt = pSelect;
return TSDB_CODE_SUCCESS;
@@ -4830,6 +5224,7 @@ static int32_t rewriteShowTableDist(STranslateContext* pCxt, SQuery* pQuery) {
SSelectStmt* pStmt = NULL;
int32_t code = createSelectStmtForShowTableDist((SShowTableDistributedStmt*)pQuery->pRoot, &pStmt);
if (TSDB_CODE_SUCCESS == code) {
+ NODES_DESTORY_LIST(pStmt->pProjectionList);
code = nodesListMakeStrictAppend(&pStmt->pProjectionList, createBlockDistFunc());
}
if (TSDB_CODE_SUCCESS == code) {
@@ -4848,6 +5243,7 @@ typedef struct SVgroupCreateTableBatch {
static void destroyCreateTbReq(SVCreateTbReq* pReq) {
taosMemoryFreeClear(pReq->name);
+ taosMemoryFreeClear(pReq->comment);
taosMemoryFreeClear(pReq->ntb.schemaRow.pSchema);
}
@@ -4865,6 +5261,7 @@ static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt*
if (pStmt->pOptions->commentNull == false) {
req.comment = strdup(pStmt->pOptions->comment);
if (NULL == req.comment) {
+ destroyCreateTbReq(&req);
return TSDB_CODE_OUT_OF_MEMORY;
}
req.commentLen = strlen(pStmt->pOptions->comment);
@@ -4931,23 +5328,27 @@ static int32_t serializeVgroupCreateTableBatch(SVgroupCreateTableBatch* pTbBatch
return TSDB_CODE_SUCCESS;
}
-static void destroyCreateTbReqBatch(SVgroupCreateTableBatch* pTbBatch) {
- size_t size = taosArrayGetSize(pTbBatch->req.pArray);
+static void destroyCreateTbReqBatch(void* data) {
+ SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*)data;
+ size_t size = taosArrayGetSize(pTbBatch->req.pArray);
for (int32_t i = 0; i < size; ++i) {
SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i);
taosMemoryFreeClear(pTableReq->name);
+ taosMemoryFreeClear(pTableReq->comment);
if (pTableReq->type == TSDB_NORMAL_TABLE) {
taosMemoryFreeClear(pTableReq->ntb.schemaRow.pSchema);
} else if (pTableReq->type == TSDB_CHILD_TABLE) {
taosMemoryFreeClear(pTableReq->ctb.pTag);
+ taosMemoryFreeClear(pTableReq->ctb.name);
+ taosArrayDestroy(pTableReq->ctb.tagName);
}
}
taosArrayDestroy(pTbBatch->req.pArray);
}
-static int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray) {
+int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray) {
SVnodeModifOpStmt* pNewStmt = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT);
if (pNewStmt == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -4992,7 +5393,7 @@ static int32_t buildCreateTableDataBlock(int32_t acctId, const SCreateTableStmt*
static int32_t rewriteCreateTable(STranslateContext* pCxt, SQuery* pQuery) {
SCreateTableStmt* pStmt = (SCreateTableStmt*)pQuery->pRoot;
- int32_t code = checkCreateTable(pCxt, pStmt);
+ int32_t code = checkCreateTable(pCxt, pStmt, false);
SVgroupInfo info = {0};
if (TSDB_CODE_SUCCESS == code) {
code = getTableHashVgroup(pCxt, pStmt->dbName, pStmt->tableName, &info);
@@ -5012,11 +5413,11 @@ static int32_t rewriteCreateTable(STranslateContext* pCxt, SQuery* pQuery) {
}
static void addCreateTbReqIntoVgroup(int32_t acctId, SHashObj* pVgroupHashmap, SCreateSubTableClause* pStmt,
- const STag* pTag, uint64_t suid, SVgroupInfo* pVgInfo) {
- char dbFName[TSDB_DB_FNAME_LEN] = {0};
- SName name = {.type = TSDB_DB_NAME_T, .acctId = acctId};
- strcpy(name.dbname, pStmt->dbName);
- tNameGetFullDbName(&name, dbFName);
+ const STag* pTag, uint64_t suid, const char* sTableNmae, SVgroupInfo* pVgInfo, SArray* tagName) {
+// char dbFName[TSDB_DB_FNAME_LEN] = {0};
+// SName name = {.type = TSDB_DB_NAME_T, .acctId = acctId};
+// strcpy(name.dbname, pStmt->dbName);
+// tNameGetFullDbName(&name, dbFName);
struct SVCreateTbReq req = {0};
req.type = TD_CHILD_TABLE;
@@ -5029,7 +5430,9 @@ static void addCreateTbReqIntoVgroup(int32_t acctId, SHashObj* pVgroupHashmap, S
req.commentLen = -1;
}
req.ctb.suid = suid;
+ req.ctb.name = strdup(sTableNmae);
req.ctb.pTag = (uint8_t*)pTag;
+ req.ctb.tagName = taosArrayDup(tagName);
if (pStmt->ignoreExists) {
req.flags |= TD_CREATE_IF_NOT_EXISTS;
}
@@ -5049,30 +5452,62 @@ static void addCreateTbReqIntoVgroup(int32_t acctId, SHashObj* pVgroupHashmap, S
}
}
-static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* pFunc, SValueNode** pVal) {
- int32_t code = getFuncInfo(pCxt, pFunc);
+static SDataType schemaToDataType(uint8_t precision, SSchema* pSchema) {
+ SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = precision, .scale = 0};
+ return dt;
+}
+
+static int32_t createCastFuncForTag(STranslateContext* pCxt, SNode* pNode, SDataType dt, SNode** pCast) {
+ SNode* pExpr = nodesCloneNode(pNode);
+ if (NULL == pExpr) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ int32_t code = translateExpr(pCxt, &pExpr);
if (TSDB_CODE_SUCCESS == code) {
- code = scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal);
+ code = createCastFunc(pCxt, pExpr, dt, pCast);
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyNode(pExpr);
}
return code;
}
-static SDataType schemaToDataType(uint8_t precision, SSchema* pSchema) {
- SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = precision, .scale = 0};
- return dt;
+static int32_t createTagValFromExpr(STranslateContext* pCxt, SDataType targetDt, SNode* pNode, SValueNode** pVal) {
+ SNode* pCast = NULL;
+ int32_t code = createCastFuncForTag(pCxt, pNode, targetDt, &pCast);
+ SNode* pNew = NULL;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = scalarCalculateConstants(pCast, &pNew);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ pCast = pNew;
+ if (QUERY_NODE_VALUE != nodeType(pCast)) {
+ code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pNode)->aliasName);
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pVal = (SValueNode*)pCast;
+ } else {
+ nodesDestroyNode(pCast);
+ }
+ return code;
+}
+
+static int32_t createTagValFromVal(STranslateContext* pCxt, SDataType targetDt, SNode* pNode, SValueNode** pVal) {
+ *pVal = (SValueNode*)nodesCloneNode(pNode);
+ if (NULL == *pVal) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ return DEAL_RES_ERROR == translateValueImpl(pCxt, *pVal, targetDt, true) ? pCxt->errCode : TSDB_CODE_SUCCESS;
}
-static int32_t translateTagVal(STranslateContext* pCxt, uint8_t precision, SSchema* pSchema, SNode* pNode,
- SValueNode** pVal) {
- if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
- return createValueFromFunction(pCxt, (SFunctionNode*)pNode, pVal);
- } else if (QUERY_NODE_VALUE == nodeType(pNode)) {
- return (DEAL_RES_ERROR == translateValueImpl(pCxt, (SValueNode*)pNode, schemaToDataType(precision, pSchema))
- ? pCxt->errCode
- : TSDB_CODE_SUCCESS);
+static int32_t createTagVal(STranslateContext* pCxt, uint8_t precision, SSchema* pSchema, SNode* pNode,
+ SValueNode** pVal) {
+ if (QUERY_NODE_VALUE == nodeType(pNode)) {
+ return createTagValFromVal(pCxt, schemaToDataType(precision, pSchema), pNode, pVal);
} else {
- // return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pNode)->aliasName);
- return TSDB_CODE_FAILED;
+ return createTagValFromExpr(pCxt, schemaToDataType(precision, pSchema), pNode, pVal);
}
}
@@ -5089,6 +5524,7 @@ static int32_t buildNormalTagVal(STranslateContext* pCxt, SSchema* pTagSchema, S
if (pVal->node.resType.type != TSDB_DATA_TYPE_NULL) {
void* nodeVal = nodesGetValueFromNode(pVal);
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
+// strcpy(val.colName, pTagSchema->name);
if (IS_VAR_DATA_TYPE(pTagSchema->type)) {
val.pData = varDataVal(nodeVal);
val.nData = varDataLen(nodeVal);
@@ -5101,7 +5537,7 @@ static int32_t buildNormalTagVal(STranslateContext* pCxt, SSchema* pTagSchema, S
}
static int32_t buildKVRowForBindTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta,
- STag** ppTag) {
+ STag** ppTag, SArray* tagName) {
int32_t numOfTags = getNumOfTags(pSuperTableMeta);
if (LIST_LENGTH(pStmt->pValsOfTags) != LIST_LENGTH(pStmt->pSpecificTags) ||
numOfTags < LIST_LENGTH(pStmt->pValsOfTags)) {
@@ -5112,122 +5548,104 @@ static int32_t buildKVRowForBindTags(STranslateContext* pCxt, SCreateSubTableCla
if (NULL == pTagArray) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- int32_t code = TSDB_CODE_SUCCESS;
- SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta);
- SNode * pTag = NULL, *pNode = NULL;
- bool isJson = false;
+
+ int32_t code = TSDB_CODE_SUCCESS;
+
+ bool isJson = false;
+ SNodeList* pVals = NULL;
+ SNode * pTag = NULL, *pNode = NULL;
FORBOTH(pTag, pStmt->pSpecificTags, pNode, pStmt->pValsOfTags) {
SColumnNode* pCol = (SColumnNode*)pTag;
- SSchema* pSchema = NULL;
- for (int32_t i = 0; i < numOfTags; ++i) {
- if (0 == strcmp(pCol->colName, pTagSchema[i].name)) {
- pSchema = pTagSchema + i;
- break;
- }
- }
+ SSchema* pSchema = getTagSchema(pSuperTableMeta, pCol->colName);
if (NULL == pSchema) {
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAG_NAME, pCol->colName);
- goto end;
}
SValueNode* pVal = NULL;
- code = translateTagVal(pCxt, pSuperTableMeta->tableInfo.precision, pSchema, pNode, &pVal);
- if (TSDB_CODE_SUCCESS != code) {
- goto end;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = createTagVal(pCxt, pSuperTableMeta->tableInfo.precision, pSchema, pNode, &pVal);
}
-
- if (NULL == pVal) {
- pVal = (SValueNode*)pNode;
- } else {
- REPLACE_LIST2_NODE(pVal);
+ if (TSDB_CODE_SUCCESS == code) {
+ if (pSchema->type == TSDB_DATA_TYPE_JSON) {
+ isJson = true;
+ code = buildJsonTagVal(pCxt, pSchema, pVal, pTagArray, ppTag);
+ taosArrayPush(tagName, pCol->colName);
+ } else if (pVal->node.resType.type != TSDB_DATA_TYPE_NULL) {
+ code = buildNormalTagVal(pCxt, pSchema, pVal, pTagArray);
+ taosArrayPush(tagName, pCol->colName);
+ }
}
-
- if (pSchema->type == TSDB_DATA_TYPE_JSON) {
- isJson = true;
- code = buildJsonTagVal(pCxt, pSchema, pVal, pTagArray, ppTag);
- } else if (pVal->node.resType.type != TSDB_DATA_TYPE_NULL) {
- code = buildNormalTagVal(pCxt, pSchema, pVal, pTagArray);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeAppend(&pVals, (SNode*)pVal);
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
}
}
- if (!isJson) code = tTagNew(pTagArray, 1, false, ppTag);
-
-end:
- if (isJson) {
- for (int i = 0; i < taosArrayGetSize(pTagArray); ++i) {
- STagVal* p = (STagVal*)taosArrayGet(pTagArray, i);
- if (IS_VAR_DATA_TYPE(p->type)) {
- taosMemoryFree(p->pData);
- }
- }
+ if (TSDB_CODE_SUCCESS == code && !isJson) {
+ code = tTagNew(pTagArray, 1, false, ppTag);
}
+
+ nodesDestroyList(pVals);
taosArrayDestroy(pTagArray);
- return TSDB_CODE_SUCCESS;
+ return code;
}
static int32_t buildKVRowForAllTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta,
- STag** ppTag) {
+ STag** ppTag, SArray* tagName) {
if (getNumOfTags(pSuperTableMeta) != LIST_LENGTH(pStmt->pValsOfTags)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
}
- SSchema* pTagSchemas = getTableTagSchema(pSuperTableMeta);
- SNode* pNode;
- int32_t code = TSDB_CODE_SUCCESS;
- int32_t index = 0;
- SArray* pTagArray = taosArrayInit(LIST_LENGTH(pStmt->pValsOfTags), sizeof(STagVal));
- if (!pTagArray) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_TSC_OUT_OF_MEMORY);
+ SArray* pTagArray = taosArrayInit(LIST_LENGTH(pStmt->pValsOfTags), sizeof(STagVal));
+ if (NULL == pTagArray) {
+ return TSDB_CODE_OUT_OF_MEMORY;
}
- bool isJson = false;
+ int32_t code = TSDB_CODE_SUCCESS;
+
+ bool isJson = false;
+ int32_t index = 0;
+ SSchema* pTagSchemas = getTableTagSchema(pSuperTableMeta);
+ SNodeList* pVals = NULL;
+ SNode* pNode;
FOREACH(pNode, pStmt->pValsOfTags) {
SValueNode* pVal = NULL;
SSchema* pTagSchema = pTagSchemas + index;
- code = translateTagVal(pCxt, pSuperTableMeta->tableInfo.precision, pTagSchema, pNode, &pVal);
- if (TSDB_CODE_SUCCESS != code) {
- goto end;
+ code = createTagVal(pCxt, pSuperTableMeta->tableInfo.precision, pTagSchema, pNode, &pVal);
+ if (TSDB_CODE_SUCCESS == code) {
+ if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
+ isJson = true;
+ code = buildJsonTagVal(pCxt, pTagSchema, pVal, pTagArray, ppTag);
+ taosArrayPush(tagName, pTagSchema->name);
+ } else if (pVal->node.resType.type != TSDB_DATA_TYPE_NULL && !pVal->isNull) {
+ char* tmpVal = nodesGetValueFromNode(pVal);
+ STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
+// strcpy(val.colName, pTagSchema->name);
+ if (IS_VAR_DATA_TYPE(pTagSchema->type)) {
+ val.pData = varDataVal(tmpVal);
+ val.nData = varDataLen(tmpVal);
+ } else {
+ memcpy(&val.i64, tmpVal, pTagSchema->bytes);
+ }
+ taosArrayPush(pTagArray, &val);
+ taosArrayPush(tagName, pTagSchema->name);
+ }
}
- if (NULL == pVal) {
- pVal = (SValueNode*)pNode;
- } else {
- REPLACE_NODE(pVal);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeAppend(&pVals, (SNode*)pVal);
}
- if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
- if (pVal->literal && strlen(pVal->literal) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
- code = buildSyntaxErrMsg(&pCxt->msgBuf, "json string too long than 4095", pVal->literal);
- goto end;
- }
-
- isJson = true;
- code = parseJsontoTagData(pVal->literal, pTagArray, ppTag, &pCxt->msgBuf);
- if (code != TSDB_CODE_SUCCESS) {
- goto end;
- }
- } else if (pVal->node.resType.type != TSDB_DATA_TYPE_NULL) {
- char* tmpVal = nodesGetValueFromNode(pVal);
- STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
- if (IS_VAR_DATA_TYPE(pTagSchema->type)) {
- val.pData = varDataVal(tmpVal);
- val.nData = varDataLen(tmpVal);
- } else {
- memcpy(&val.i64, tmpVal, pTagSchema->bytes);
- }
- taosArrayPush(pTagArray, &val);
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
}
++index;
}
- if (!isJson) code = tTagNew(pTagArray, 1, false, ppTag);
-end:
- if (isJson) {
- for (int i = 0; i < taosArrayGetSize(pTagArray); ++i) {
- STagVal* p = (STagVal*)taosArrayGet(pTagArray, i);
- if (IS_VAR_DATA_TYPE(p->type)) {
- taosMemoryFree(p->pData);
- }
- }
+ if (TSDB_CODE_SUCCESS == code && !isJson) {
+ code = tTagNew(pTagArray, 1, false, ppTag);
}
+ nodesDestroyList(pVals);
taosArrayDestroy(pTagArray);
return code;
}
@@ -5247,12 +5665,13 @@ static int32_t rewriteCreateSubTable(STranslateContext* pCxt, SCreateSubTableCla
}
STag* pTag = NULL;
+ SArray* tagName = taosArrayInit(8, TSDB_COL_NAME_LEN);
if (TSDB_CODE_SUCCESS == code) {
if (NULL != pStmt->pSpecificTags) {
- code = buildKVRowForBindTags(pCxt, pStmt, pSuperTableMeta, &pTag);
+ code = buildKVRowForBindTags(pCxt, pStmt, pSuperTableMeta, &pTag, tagName);
} else {
- code = buildKVRowForAllTags(pCxt, pStmt, pSuperTableMeta, &pTag);
+ code = buildKVRowForAllTags(pCxt, pStmt, pSuperTableMeta, &pTag, tagName);
}
}
@@ -5261,14 +5680,15 @@ static int32_t rewriteCreateSubTable(STranslateContext* pCxt, SCreateSubTableCla
code = getTableHashVgroup(pCxt, pStmt->dbName, pStmt->tableName, &info);
}
if (TSDB_CODE_SUCCESS == code) {
- addCreateTbReqIntoVgroup(pCxt->pParseCxt->acctId, pVgroupHashmap, pStmt, pTag, pSuperTableMeta->uid, &info);
+ addCreateTbReqIntoVgroup(pCxt->pParseCxt->acctId, pVgroupHashmap, pStmt, pTag, pSuperTableMeta->uid, pStmt->useTableName, &info, tagName);
}
+ taosArrayDestroy(tagName);
taosMemoryFreeClear(pSuperTableMeta);
return code;
}
-static SArray* serializeVgroupsCreateTableBatch(int32_t acctId, SHashObj* pVgroupHashmap) {
+SArray* serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap) {
SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*));
if (NULL == pBufArray) {
return NULL;
@@ -5283,7 +5703,6 @@ static SArray* serializeVgroupsCreateTableBatch(int32_t acctId, SHashObj* pVgrou
}
serializeVgroupCreateTableBatch(pTbBatch, pBufArray);
- destroyCreateTbReqBatch(pTbBatch);
} while (true);
return pBufArray;
@@ -5297,6 +5716,7 @@ static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery)
return TSDB_CODE_OUT_OF_MEMORY;
}
+ taosHashSetFreeFp(pVgroupHashmap, destroyCreateTbReqBatch);
int32_t code = TSDB_CODE_SUCCESS;
SNode* pNode;
FOREACH(pNode, pStmt->pSubTables) {
@@ -5308,7 +5728,7 @@ static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery)
}
}
- SArray* pBufArray = serializeVgroupsCreateTableBatch(pCxt->pParseCxt->acctId, pVgroupHashmap);
+ SArray* pBufArray = serializeVgroupsCreateTableBatch(pVgroupHashmap);
taosHashCleanup(pVgroupHashmap);
if (NULL == pBufArray) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -5368,7 +5788,10 @@ over:
return code;
}
-static void destroyDropTbReqBatch(SVgroupDropTableBatch* pTbBatch) { taosArrayDestroy(pTbBatch->req.pArray); }
+static void destroyDropTbReqBatch(void* data) {
+ SVgroupDropTableBatch* pTbBatch = (SVgroupDropTableBatch*)data;
+ taosArrayDestroy(pTbBatch->req.pArray);
+}
static int32_t serializeVgroupDropTableBatch(SVgroupDropTableBatch* pTbBatch, SArray* pBufArray) {
int tlen;
@@ -5402,7 +5825,7 @@ static int32_t serializeVgroupDropTableBatch(SVgroupDropTableBatch* pTbBatch, SA
return TSDB_CODE_SUCCESS;
}
-static SArray* serializeVgroupsDropTableBatch(int32_t acctId, SHashObj* pVgroupHashmap) {
+SArray* serializeVgroupsDropTableBatch(SHashObj* pVgroupHashmap) {
SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*));
if (NULL == pBufArray) {
return NULL;
@@ -5417,7 +5840,6 @@ static SArray* serializeVgroupsDropTableBatch(int32_t acctId, SHashObj* pVgroupH
}
serializeVgroupDropTableBatch(pTbBatch, pBufArray);
- destroyDropTbReqBatch(pTbBatch);
} while (true);
return pBufArray;
@@ -5431,6 +5853,7 @@ static int32_t rewriteDropTable(STranslateContext* pCxt, SQuery* pQuery) {
return TSDB_CODE_OUT_OF_MEMORY;
}
+ taosHashSetFreeFp(pVgroupHashmap, destroyDropTbReqBatch);
bool isSuperTable = false;
SNode* pNode;
FOREACH(pNode, pStmt->pTables) {
@@ -5449,7 +5872,7 @@ static int32_t rewriteDropTable(STranslateContext* pCxt, SQuery* pQuery) {
return TSDB_CODE_SUCCESS;
}
- SArray* pBufArray = serializeVgroupsDropTableBatch(pCxt->pParseCxt->acctId, pVgroupHashmap);
+ SArray* pBufArray = serializeVgroupsDropTableBatch(pVgroupHashmap);
taosHashCleanup(pVgroupHashmap);
if (NULL == pBufArray) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -5470,17 +5893,13 @@ static int32_t buildUpdateTagValReq(STranslateContext* pCxt, SAlterTableStmt* pS
return TSDB_CODE_OUT_OF_MEMORY;
}
- if (DEAL_RES_ERROR ==
- translateValueImpl(pCxt, pStmt->pVal, schemaToDataType(pTableMeta->tableInfo.precision, pSchema))) {
+ SDataType targetDt = schemaToDataType(pTableMeta->tableInfo.precision, pSchema);
+ if (DEAL_RES_ERROR == translateValueImpl(pCxt, pStmt->pVal, targetDt, true)) {
return pCxt->errCode;
}
- if (IS_VAR_DATA_TYPE(pSchema->type) && strlen(pStmt->pVal->literal) > pSchema->bytes) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pStmt->pVal->literal);
- }
-
- pReq->isNull = (TSDB_DATA_TYPE_NULL == pStmt->pVal->node.resType.type);
- if (pStmt->pVal->node.resType.type == TSDB_DATA_TYPE_JSON) {
+ pReq->tagType = targetDt.type;
+ if (targetDt.type == TSDB_DATA_TYPE_JSON) {
if (pStmt->pVal->literal &&
strlen(pStmt->pVal->literal) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
return buildSyntaxErrMsg(&pCxt->msgBuf, "json string too long than 4095", pStmt->pVal->literal);
@@ -5508,6 +5927,7 @@ static int32_t buildUpdateTagValReq(STranslateContext* pCxt, SAlterTableStmt* pS
pReq->pTagVal = (uint8_t*)pTag;
pStmt->pVal->datum.p = (char*)pTag; // for free
} else {
+ pReq->isNull = (TSDB_DATA_TYPE_NULL == pStmt->pVal->node.resType.type);
pReq->nTagVal = pStmt->pVal->node.resType.bytes;
pReq->pTagVal = nodesGetValueFromNode(pStmt->pVal);
@@ -5534,7 +5954,8 @@ static int32_t buildAddColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, S
pReq->type = pStmt->dataType.type;
pReq->flags = COL_SMA_ON;
- pReq->bytes = pStmt->dataType.bytes;
+ // pReq->bytes = pStmt->dataType.bytes;
+ pReq->bytes = calcTypeBytes(pStmt->dataType);
return TSDB_CODE_SUCCESS;
}
@@ -5561,7 +5982,7 @@ static int32_t buildDropColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt,
static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta,
SVAlterTbReq* pReq) {
pReq->colModBytes = calcTypeBytes(pStmt->dataType);
-
+ pReq->colModType = pStmt->dataType.type;
SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
if (NULL == pSchema) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName);
@@ -5724,15 +6145,6 @@ static int32_t rewriteAlterTableImpl(STranslateContext* pCxt, SAlterTableStmt* p
}
if (TSDB_SUPER_TABLE == pTableMeta->tableType) {
- SSchema* pTagsSchema = getTableTagSchema(pTableMeta);
- if (getNumOfTags(pTableMeta) == 1 && pTagsSchema->type == TSDB_DATA_TYPE_JSON &&
- (pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG || pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG ||
- pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_TAG_BYTES)) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
- }
- if (pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_OPTIONS && -1 != pStmt->pOptions->ttl) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
- }
return TSDB_CODE_SUCCESS;
} else if (TSDB_CHILD_TABLE != pTableMeta->tableType && TSDB_NORMAL_TABLE != pTableMeta->tableType) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
@@ -5755,10 +6167,6 @@ static int32_t rewriteAlterTableImpl(STranslateContext* pCxt, SAlterTableStmt* p
static int32_t rewriteAlterTable(STranslateContext* pCxt, SQuery* pQuery) {
SAlterTableStmt* pStmt = (SAlterTableStmt*)pQuery->pRoot;
- if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG) {
- return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
- }
-
if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_COLUMN) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COL_JSON);
}
@@ -5772,6 +6180,67 @@ static int32_t rewriteAlterTable(STranslateContext* pCxt, SQuery* pQuery) {
return code;
}
+static int32_t serializeFlushVgroup(SVgroupInfo* pVg, SArray* pBufArray) {
+ int32_t len = sizeof(SMsgHead);
+ void* buf = taosMemoryMalloc(len);
+ if (NULL == buf) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ ((SMsgHead*)buf)->vgId = htonl(pVg->vgId);
+ ((SMsgHead*)buf)->contLen = htonl(len);
+
+ SVgDataBlocks* pVgData = taosMemoryCalloc(1, sizeof(SVgDataBlocks));
+ if (NULL == pVgData) {
+ taosMemoryFree(buf);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ pVgData->vg = *pVg;
+ pVgData->pData = buf;
+ pVgData->size = len;
+ taosArrayPush(pBufArray, &pVgData);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t serializeFlushDb(SArray* pVgs, SArray** pOutput) {
+ int32_t numOfVgs = taosArrayGetSize(pVgs);
+
+ SArray* pBufArray = taosArrayInit(numOfVgs, sizeof(void*));
+ if (NULL == pBufArray) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ for (int32_t i = 0; i < numOfVgs; ++i) {
+ int32_t code = serializeFlushVgroup((SVgroupInfo*)taosArrayGet(pVgs, i), pBufArray);
+ if (TSDB_CODE_SUCCESS != code) {
+ taosArrayDestroy(pBufArray);
+ return code;
+ }
+ }
+
+ *pOutput = pBufArray;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t rewriteFlushDatabase(STranslateContext* pCxt, SQuery* pQuery) {
+ SFlushDatabaseStmt* pStmt = (SFlushDatabaseStmt*)pQuery->pRoot;
+
+ SArray* pBufArray = NULL;
+ SArray* pVgs = NULL;
+ int32_t code = getDBVgInfo(pCxt, pStmt->dbName, &pVgs);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = serializeFlushDb(pVgs, &pBufArray);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = rewriteToVnodeModifyOpStmt(pQuery, pBufArray);
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ taosArrayDestroy(pBufArray);
+ }
+ taosArrayDestroy(pVgs);
+ return code;
+}
+
static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pQuery->pRoot)) {
@@ -5795,8 +6264,9 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
case QUERY_NODE_SHOW_CLUSTER_STMT:
case QUERY_NODE_SHOW_TOPICS_STMT:
case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
- case QUERY_NODE_SHOW_VARIABLES_STMT:
case QUERY_NODE_SHOW_APPS_STMT:
+ case QUERY_NODE_SHOW_CONSUMERS_STMT:
+ case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
code = rewriteShow(pCxt, pQuery);
break;
case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
@@ -5819,6 +6289,9 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
case QUERY_NODE_ALTER_TABLE_STMT:
code = rewriteAlterTable(pCxt, pQuery);
break;
+ case QUERY_NODE_FLUSH_DATABASE_STMT:
+ code = rewriteFlushDatabase(pCxt, pQuery);
+ break;
default:
break;
}
@@ -5869,16 +6342,25 @@ static int32_t setRefreshMate(STranslateContext* pCxt, SQuery* pQuery) {
static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
switch (nodeType(pQuery->pRoot)) {
case QUERY_NODE_SELECT_STMT:
+ if (NULL == ((SSelectStmt*)pQuery->pRoot)->pFromTable) {
+ pQuery->execMode = QUERY_EXEC_MODE_LOCAL;
+ pQuery->haveResultSet = true;
+ break;
+ }
case QUERY_NODE_SET_OPERATOR:
case QUERY_NODE_EXPLAIN_STMT:
pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
pQuery->haveResultSet = true;
- pQuery->msgType = TDMT_VND_QUERY;
+ pQuery->msgType = TDMT_SCH_QUERY;
break;
case QUERY_NODE_DELETE_STMT:
pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
pQuery->msgType = TDMT_VND_DELETE;
break;
+ case QUERY_NODE_INSERT_STMT:
+ pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
+ pQuery->msgType = TDMT_VND_SUBMIT;
+ break;
case QUERY_NODE_VNODE_MODIF_STMT:
pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
pQuery->msgType = toMsgType(((SVnodeModifOpStmt*)pQuery->pRoot)->sqlNodeType);
@@ -5887,14 +6369,22 @@ static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
case QUERY_NODE_SHOW_CREATE_DATABASE_STMT:
case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
+ case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
pQuery->execMode = QUERY_EXEC_MODE_LOCAL;
pQuery->haveResultSet = true;
break;
case QUERY_NODE_RESET_QUERY_CACHE_STMT:
case QUERY_NODE_ALTER_LOCAL_STMT:
- case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
pQuery->execMode = QUERY_EXEC_MODE_LOCAL;
break;
+ case QUERY_NODE_SHOW_VARIABLES_STMT:
+ pQuery->haveResultSet = true;
+ pQuery->execMode = QUERY_EXEC_MODE_RPC;
+ if (NULL != pCxt->pCmdMsg) {
+ TSWAP(pQuery->pCmdMsg, pCxt->pCmdMsg);
+ pQuery->msgType = pQuery->pCmdMsg->msgType;
+ }
+ break;
default:
pQuery->execMode = QUERY_EXEC_MODE_RPC;
if (NULL != pCxt->pCmdMsg) {
diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c
index 51e0dd58d88e6bec9337deff629858578d6a72b0..51f59c9362755702a804581c2981c7472b9f578d 100644
--- a/source/libs/parser/src/parUtil.c
+++ b/source/libs/parser/src/parUtil.c
@@ -60,7 +60,7 @@ static char* getSyntaxErrFormat(int32_t errCode) {
case TSDB_CODE_PAR_EXPRIE_STATEMENT:
return "This statement is no longer supported";
case TSDB_CODE_PAR_INTER_VALUE_TOO_SMALL:
- return "Interval cannot be less than %d us";
+ return "Interval cannot be less than %d %s";
case TSDB_CODE_PAR_DB_NOT_SPECIFIED:
return "Database not specified";
case TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME:
@@ -185,19 +185,21 @@ static char* getSyntaxErrFormat(int32_t errCode) {
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
- return "%s function does not supportted in fill query";
+ return "%s function is not supported in fill query";
case TSDB_CODE_PAR_INVALID_WINDOW_PC:
- return "_WSTARTTS, _WENDTS and _WDURATION can only be used in window query";
+ return "_WSTART, _WEND and _WDURATION can only be used in window query";
case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
- return "%s function does not supportted in time window query";
+ return "%s function is not supported in time window query";
case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
- return "%s function does not supportted in stream query";
+ return "%s function is not supported in stream query";
case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
- return "%s function does not supportted in group query";
+ return "%s function is not supported in group query";
case TSDB_CODE_PAR_INVALID_TABLE_OPTION:
return "Invalid option %s";
case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
return "Invalid usage of RANGE clause, EVERY clause or FILL clause";
+ case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN:
+ return "No valid function in window query";
case TSDB_CODE_OUT_OF_MEMORY:
return "Out of memory";
default:
@@ -213,19 +215,27 @@ int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...) {
return errCode;
}
+int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...) {
+ va_list vArgList;
+ va_start(vArgList, pFormat);
+ vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
+ va_end(vArgList);
+ return errCode;
+}
+
int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
strncpy(pBuf->buf, msg, pBuf->len);
return TSDB_CODE_TSC_INVALID_OPERATION;
}
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) {
+ if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
const char* msgFormat1 = "syntax error near \'%s\'";
const char* msgFormat2 = "syntax error near \'%s\' (%s)";
const char* msgFormat3 = "%s";
const char* prefix = "syntax error";
if (sourceStr == NULL) {
- assert(additionalInfo != NULL);
snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo);
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
}
@@ -243,40 +253,25 @@ int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char*
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
}
-SSchema* getTableColumnSchema(const STableMeta* pTableMeta) {
- assert(pTableMeta != NULL);
- return (SSchema*)pTableMeta->schema;
-}
+SSchema* getTableColumnSchema(const STableMeta* pTableMeta) { return (SSchema*)pTableMeta->schema; }
static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
- assert(pTableMeta != NULL && pTableMeta->schema != NULL && colIndex >= 0 &&
- colIndex < (getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta)));
-
SSchema* pSchema = (SSchema*)pTableMeta->schema;
return &pSchema[colIndex];
}
SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
- assert(pTableMeta != NULL &&
- (pTableMeta->tableType == TSDB_SUPER_TABLE || pTableMeta->tableType == TSDB_CHILD_TABLE));
return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
}
int32_t getNumOfColumns(const STableMeta* pTableMeta) {
- assert(pTableMeta != NULL);
// table created according to super table, use data from super table
return getTableInfo(pTableMeta).numOfColumns;
}
-int32_t getNumOfTags(const STableMeta* pTableMeta) {
- assert(pTableMeta != NULL);
- return getTableInfo(pTableMeta).numOfTags;
-}
+int32_t getNumOfTags(const STableMeta* pTableMeta) { return getTableInfo(pTableMeta).numOfTags; }
-STableComInfo getTableInfo(const STableMeta* pTableMeta) {
- assert(pTableMeta != NULL);
- return pTableMeta->tableInfo;
-}
+STableComInfo getTableInfo(const STableMeta* pTableMeta) { return pTableMeta->tableInfo; }
STableMeta* tableMetaDup(const STableMeta* pTableMeta) {
size_t size = TABLE_META_SIZE(pTableMeta);
@@ -337,12 +332,16 @@ int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen) {
static bool isValidateTag(char* input) {
if (!input) return false;
for (size_t i = 0; i < strlen(input); ++i) {
+#ifdef WINDOWS
+ if (input[i] < 0x20 || input[i] > 0x7E) return false;
+#else
if (isprint(input[i]) == 0) return false;
+#endif
}
return true;
}
-int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, SMsgBuf* pMsgBuf) {
+int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, void* pMsgBuf) {
int32_t retCode = TSDB_CODE_SUCCESS;
cJSON* root = NULL;
SHashObj* keyHash = NULL;
@@ -390,6 +389,7 @@ int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, SMs
continue;
}
STagVal val = {0};
+// strcpy(val.colName, colName);
val.pKey = jsonKey;
taosHashPut(keyHash, jsonKey, keyLen, &keyLen,
CHAR_BYTES); // add key to hash to remove dumplicate, value is useless
@@ -561,6 +561,9 @@ int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalog
if (TSDB_CODE_SUCCESS == code) {
code = buildTableReq(pMetaCache->pTableIndex, &pCatalogReq->pTableIndex);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = buildTableReq(pMetaCache->pTableCfg, &pCatalogReq->pTableCfg);
+ }
pCatalogReq->dNodeRequired = pMetaCache->dnodeRequired;
return code;
}
@@ -657,6 +660,9 @@ int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMet
if (TSDB_CODE_SUCCESS == code) {
code = putTableDataToCache(pCatalogReq->pTableIndex, pMetaData->pTableIndex, &pMetaCache->pTableIndex);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = putTableDataToCache(pCatalogReq->pTableCfg, pMetaData->pTableCfg, &pMetaCache->pTableCfg);
+ }
pMetaCache->pDnodes = pMetaData->pDnodeList;
return code;
}
@@ -863,6 +869,10 @@ int32_t reserveTableIndexInCache(int32_t acctId, const char* pDb, const char* pT
return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableIndex);
}
+int32_t reserveTableCfgInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
+ return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableCfg);
+}
+
int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes) {
char fullName[TSDB_TABLE_FNAME_LEN];
tNameExtractFullName(pName, fullName);
@@ -877,13 +887,53 @@ int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName,
return code;
}
+STableCfg* tableCfgDup(STableCfg* pCfg) {
+ STableCfg* pNew = taosMemoryMalloc(sizeof(*pNew));
+
+ memcpy(pNew, pCfg, sizeof(*pNew));
+ if (pNew->pComment) {
+ pNew->pComment = strdup(pNew->pComment);
+ }
+ if (pNew->pFuncs) {
+ pNew->pFuncs = taosArrayDup(pNew->pFuncs);
+ }
+
+ int32_t schemaSize = (pCfg->numOfColumns + pCfg->numOfTags) * sizeof(SSchema);
+
+ SSchema* pSchema = taosMemoryMalloc(schemaSize);
+ memcpy(pSchema, pCfg->pSchemas, schemaSize);
+
+ pNew->pSchemas = pSchema;
+
+ return pNew;
+}
+
+int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput) {
+ char fullName[TSDB_TABLE_FNAME_LEN];
+ tNameExtractFullName(pName, fullName);
+ STableCfg* pCfg = NULL;
+ int32_t code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableCfg, (void**)&pCfg);
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = tableCfgDup(pCfg);
+ if (NULL == *pOutput) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+ return code;
+}
+
int32_t reserveDnodeRequiredInCache(SParseMetaCache* pMetaCache) {
pMetaCache->dnodeRequired = true;
return TSDB_CODE_SUCCESS;
}
int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes) {
- *pDnodes = taosArrayDup(pMetaCache->pDnodes);
+ SMetaRes* pRes = taosArrayGet(pMetaCache->pDnodes, 0);
+ if (TSDB_CODE_SUCCESS != pRes->code) {
+ return pRes->code;
+ }
+
+ *pDnodes = taosArrayDup((SArray*)pRes->pRes);
if (NULL == *pDnodes) {
return TSDB_CODE_OUT_OF_MEMORY;
}
@@ -899,4 +949,5 @@ void destoryParseMetaCache(SParseMetaCache* pMetaCache) {
taosHashCleanup(pMetaCache->pUserAuth);
taosHashCleanup(pMetaCache->pUdf);
taosHashCleanup(pMetaCache->pTableIndex);
+ taosHashCleanup(pMetaCache->pTableCfg);
}
diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c
index 538404798d699b98ab5e91e5aa725fac147dc4c1..fdba0e2fccaf36413de248ccf671334f48b37aa9 100644
--- a/source/libs/parser/src/parser.c
+++ b/source/libs/parser/src/parser.c
@@ -19,19 +19,33 @@
#include "parInt.h"
#include "parToken.h"
-bool qIsInsertSql(const char* pStr, size_t length) {
+bool qIsInsertValuesSql(const char* pStr, size_t length) {
if (NULL == pStr) {
return false;
}
+ const char* pSql = pStr;
+
int32_t index = 0;
+ SToken t = tStrGetToken((char*)pStr, &index, false);
+ if (TK_INSERT != t.type && TK_IMPORT != t.type) {
+ return false;
+ }
do {
- SToken t0 = tStrGetToken((char*)pStr, &index, false);
- if (t0.type != TK_NK_LP) {
- return t0.type == TK_INSERT || t0.type == TK_IMPORT;
+ pStr += index;
+ index = 0;
+ t = tStrGetToken((char*)pStr, &index, false);
+ if (TK_USING == t.type || TK_VALUES == t.type) {
+ return true;
+ } else if (TK_SELECT == t.type) {
+ return false;
+ }
+ if (0 == t.type || 0 == t.n) {
+ break;
}
- } while (1);
+ } while (pStr - pSql < length);
+ return false;
}
static int32_t analyseSemantic(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
@@ -148,7 +162,7 @@ static void rewriteExprAlias(SNode* pRoot) {
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) {
int32_t code = TSDB_CODE_SUCCESS;
- if (qIsInsertSql(pCxt->pSql, pCxt->sqlLen)) {
+ if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
code = parseInsertSql(pCxt, pQuery, NULL);
} else {
code = parseSqlIntoAst(pCxt, pQuery);
@@ -160,7 +174,7 @@ int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) {
int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
SParseMetaCache metaCache = {0};
int32_t code = TSDB_CODE_SUCCESS;
- if (qIsInsertSql(pCxt->pSql, pCxt->sqlLen)) {
+ if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
code = parseInsertSyntax(pCxt, pQuery, &metaCache);
} else {
code = parseSqlSyntax(pCxt, pQuery, &metaCache);
diff --git a/source/libs/parser/src/sql.c b/source/libs/parser/src/sql.c
index c7651137b1d7f8d5dc219790797394978fada021..2200b43db1a0af14d2382311c7f2adb6ca40b7a4 100644
--- a/source/libs/parser/src/sql.c
+++ b/source/libs/parser/src/sql.c
@@ -104,25 +104,26 @@
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 364
+#define YYNOCODE 379
#define YYACTIONTYPE unsigned short int
#define ParseTOKENTYPE SToken
typedef union {
int yyinit;
ParseTOKENTYPE yy0;
- SToken yy57;
- EOrder yy162;
- EJoinType yy204;
- SAlterOption yy221;
- int32_t yy228;
- EFillMode yy270;
- EOperatorType yy324;
- int64_t yy389;
- SNode* yy392;
- SDataType yy448;
- bool yy481;
- ENullOrder yy529;
- SNodeList* yy600;
+ EOrder yy58;
+ bool yy151;
+ int8_t yy285;
+ SNodeList* yy356;
+ SToken yy361;
+ SAlterOption yy409;
+ int64_t yy457;
+ EFillMode yy494;
+ EJoinType yy504;
+ EOperatorType yy526;
+ SDataType yy600;
+ ENullOrder yy613;
+ SNode* yy616;
+ int32_t yy734;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -138,17 +139,17 @@ typedef union {
#define ParseCTX_FETCH
#define ParseCTX_STORE
#define YYFALLBACK 1
-#define YYNSTATE 641
-#define YYNRULE 466
-#define YYNTOKEN 242
-#define YY_MAX_SHIFT 640
-#define YY_MIN_SHIFTREDUCE 933
-#define YY_MAX_SHIFTREDUCE 1398
-#define YY_ERROR_ACTION 1399
-#define YY_ACCEPT_ACTION 1400
-#define YY_NO_ACTION 1401
-#define YY_MIN_REDUCE 1402
-#define YY_MAX_REDUCE 1867
+#define YYNSTATE 669
+#define YYNRULE 491
+#define YYNTOKEN 256
+#define YY_MAX_SHIFT 668
+#define YY_MIN_SHIFTREDUCE 974
+#define YY_MAX_SHIFTREDUCE 1464
+#define YY_ERROR_ACTION 1465
+#define YY_ACCEPT_ACTION 1466
+#define YY_NO_ACTION 1467
+#define YY_MIN_REDUCE 1468
+#define YY_MAX_REDUCE 1958
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -215,619 +216,694 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (2192)
+#define YY_ACTTAB_COUNT (2547)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 1697, 1845, 1522, 309, 412, 1697, 413, 1434, 326, 1400,
- /* 10 */ 137, 1694, 37, 35, 1490, 1844, 1694, 1710, 417, 1842,
- /* 20 */ 318, 556, 1208, 556, 1230, 38, 36, 34, 33, 32,
- /* 30 */ 325, 324, 109, 420, 109, 413, 1434, 1690, 1696, 451,
- /* 40 */ 1222, 456, 1690, 1696, 1726, 30, 240, 1206, 559, 1533,
- /* 50 */ 1793, 1533, 540, 559, 22, 556, 555, 1680, 14, 539,
- /* 60 */ 37, 35, 1335, 322, 1214, 1215, 157, 335, 318, 1710,
- /* 70 */ 1208, 134, 520, 365, 1790, 38, 36, 34, 33, 32,
- /* 80 */ 1535, 1, 1214, 1533, 1739, 67, 555, 85, 1711, 542,
- /* 90 */ 1713, 1714, 538, 58, 559, 1206, 1726, 1779, 113, 76,
- /* 100 */ 371, 292, 1775, 637, 519, 556, 14, 1528, 1845, 1680,
- /* 110 */ 1425, 539, 1214, 1845, 1845, 543, 369, 1277, 1278, 963,
- /* 120 */ 1526, 560, 152, 470, 555, 1631, 1842, 154, 152, 2,
- /* 130 */ 430, 1842, 1842, 1533, 206, 82, 1739, 290, 478, 86,
- /* 140 */ 1711, 542, 1713, 1714, 538, 1369, 559, 40, 118, 1779,
- /* 150 */ 1680, 637, 198, 311, 1775, 148, 1525, 967, 968, 1209,
- /* 160 */ 58, 1207, 70, 328, 473, 1277, 1278, 232, 56, 467,
- /* 170 */ 364, 134, 363, 1233, 197, 495, 1806, 1223, 330, 1218,
- /* 180 */ 1535, 1578, 1580, 1212, 1213, 41, 1259, 1260, 1262, 1263,
- /* 190 */ 1264, 1265, 1266, 535, 557, 1274, 1275, 1276, 1279, 53,
- /* 200 */ 1232, 1226, 52, 1579, 1580, 26, 59, 1209, 1845, 1207,
- /* 210 */ 510, 155, 557, 1274, 1275, 38, 36, 34, 33, 32,
- /* 220 */ 37, 35, 153, 155, 1424, 1710, 1842, 402, 318, 67,
- /* 230 */ 1208, 1212, 1213, 302, 1259, 1260, 1262, 1263, 1264, 1265,
- /* 240 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 516, 1726, 465,
- /* 250 */ 464, 1529, 1726, 489, 463, 1206, 509, 114, 460, 1668,
- /* 260 */ 540, 459, 458, 457, 1680, 1680, 14, 539, 37, 35,
- /* 270 */ 1112, 1113, 1214, 166, 165, 117, 318, 155, 1208, 1299,
- /* 280 */ 520, 1511, 303, 58, 301, 300, 356, 453, 58, 2,
- /* 290 */ 155, 455, 1739, 508, 1845, 85, 1711, 542, 1713, 1714,
- /* 300 */ 538, 1304, 559, 1206, 344, 1779, 358, 354, 152, 292,
- /* 310 */ 1775, 637, 1842, 454, 115, 38, 36, 34, 33, 32,
- /* 320 */ 1214, 1845, 136, 1524, 1414, 1277, 1278, 1509, 518, 149,
- /* 330 */ 1786, 1787, 1233, 1791, 1694, 152, 27, 8, 430, 1842,
- /* 340 */ 1070, 582, 581, 580, 1074, 579, 1076, 1077, 578, 1079,
- /* 350 */ 575, 1403, 1085, 572, 1087, 1088, 569, 566, 81, 637,
- /* 360 */ 1690, 1696, 38, 36, 34, 33, 32, 1209, 78, 1207,
- /* 370 */ 1359, 559, 99, 1277, 1278, 98, 97, 96, 95, 94,
- /* 380 */ 93, 92, 91, 90, 593, 1349, 38, 36, 34, 33,
- /* 390 */ 32, 1212, 1213, 522, 1259, 1260, 1262, 1263, 1264, 1265,
- /* 400 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 502, 1357, 1358,
- /* 410 */ 1360, 1361, 980, 155, 979, 1209, 99, 1207, 155, 98,
- /* 420 */ 97, 96, 95, 94, 93, 92, 91, 90, 37, 35,
- /* 430 */ 1280, 11, 10, 1710, 462, 461, 318, 162, 1208, 1212,
- /* 440 */ 1213, 981, 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535,
- /* 450 */ 557, 1274, 1275, 1276, 1279, 38, 36, 34, 33, 32,
- /* 460 */ 1726, 479, 65, 1206, 1845, 64, 593, 155, 540, 980,
- /* 470 */ 147, 979, 1585, 1680, 1231, 539, 37, 35, 1843, 308,
- /* 480 */ 1214, 1461, 1842, 1572, 318, 1793, 1208, 1423, 1583, 1214,
- /* 490 */ 38, 36, 34, 33, 32, 1422, 449, 9, 981, 1234,
- /* 500 */ 1739, 1395, 1845, 87, 1711, 542, 1713, 1714, 538, 1789,
- /* 510 */ 559, 1206, 1311, 1779, 199, 134, 152, 1778, 1775, 637,
- /* 520 */ 1842, 543, 133, 1585, 1536, 1246, 1342, 1680, 1214, 321,
- /* 530 */ 323, 1630, 1232, 1277, 1278, 1680, 293, 609, 607, 1583,
- /* 540 */ 1421, 615, 614, 613, 333, 9, 612, 611, 610, 119,
- /* 550 */ 605, 604, 603, 602, 601, 600, 599, 598, 127, 594,
- /* 560 */ 1246, 1402, 38, 36, 34, 33, 32, 637, 1297, 505,
- /* 570 */ 69, 291, 1285, 967, 968, 1209, 1420, 1207, 1232, 1419,
- /* 580 */ 1680, 1277, 1278, 1394, 28, 108, 107, 106, 105, 104,
- /* 590 */ 103, 102, 101, 100, 38, 36, 34, 33, 32, 1212,
- /* 600 */ 1213, 1510, 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535,
- /* 610 */ 557, 1274, 1275, 1276, 1279, 556, 1680, 1585, 1585, 1680,
- /* 620 */ 1298, 331, 585, 1209, 329, 1207, 370, 231, 1518, 134,
- /* 630 */ 34, 33, 32, 1583, 1584, 1418, 37, 35, 1535, 511,
- /* 640 */ 506, 200, 1303, 1533, 318, 591, 1208, 1212, 1213, 1417,
- /* 650 */ 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, 557, 1274,
- /* 660 */ 1275, 1276, 1279, 556, 125, 124, 588, 587, 586, 411,
- /* 670 */ 419, 1206, 415, 415, 372, 1680, 556, 29, 316, 1292,
- /* 680 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 387, 1214, 1680,
- /* 690 */ 185, 1533, 556, 263, 591, 597, 1563, 1505, 1416, 1261,
- /* 700 */ 1190, 1191, 140, 388, 1533, 2, 1413, 556, 447, 443,
- /* 710 */ 439, 435, 184, 125, 124, 588, 587, 586, 429, 1793,
- /* 720 */ 1533, 1698, 1710, 1334, 289, 1232, 1230, 637, 1412, 1700,
- /* 730 */ 1411, 455, 1694, 395, 7, 1533, 407, 68, 1680, 556,
- /* 740 */ 182, 1277, 1278, 1788, 556, 1261, 1680, 1410, 1409, 1726,
- /* 750 */ 1530, 380, 1235, 454, 408, 1657, 382, 540, 1690, 1696,
- /* 760 */ 135, 524, 1680, 556, 539, 269, 1702, 1533, 1680, 559,
- /* 770 */ 1680, 1621, 1533, 556, 487, 496, 589, 267, 55, 1576,
- /* 780 */ 527, 54, 164, 1209, 553, 1207, 373, 1680, 1680, 1739,
- /* 790 */ 596, 1533, 287, 1711, 542, 1713, 1714, 538, 167, 559,
- /* 800 */ 181, 1533, 173, 1464, 178, 1520, 425, 1212, 1213, 1408,
- /* 810 */ 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, 557, 1274,
- /* 820 */ 1275, 1276, 1279, 58, 590, 171, 406, 1576, 1516, 401,
- /* 830 */ 400, 399, 398, 397, 394, 393, 392, 391, 390, 386,
- /* 840 */ 385, 384, 383, 377, 376, 375, 374, 203, 1032, 1680,
- /* 850 */ 38, 36, 34, 33, 32, 556, 556, 1208, 556, 516,
- /* 860 */ 1407, 84, 1406, 465, 464, 1034, 554, 253, 463, 332,
- /* 870 */ 1405, 114, 460, 1798, 1330, 459, 458, 457, 608, 1451,
- /* 880 */ 212, 534, 1206, 1533, 1533, 190, 1533, 117, 188, 486,
- /* 890 */ 1710, 1508, 1261, 62, 61, 368, 293, 1217, 161, 1214,
- /* 900 */ 1680, 466, 1680, 192, 362, 516, 191, 1330, 194, 196,
- /* 910 */ 1680, 193, 195, 1446, 1444, 288, 584, 1726, 352, 359,
- /* 920 */ 350, 346, 342, 158, 337, 519, 115, 477, 1297, 1415,
- /* 930 */ 1680, 1333, 539, 117, 1216, 468, 471, 123, 637, 1004,
- /* 940 */ 475, 150, 1786, 1787, 532, 1791, 235, 11, 10, 48,
- /* 950 */ 525, 216, 1491, 155, 448, 503, 1005, 1739, 1710, 480,
- /* 960 */ 86, 1711, 542, 1713, 1714, 538, 1440, 559, 1397, 1398,
- /* 970 */ 1779, 528, 115, 39, 311, 1775, 148, 223, 491, 39,
- /* 980 */ 1298, 1727, 1710, 334, 591, 1726, 39, 151, 1786, 1787,
- /* 990 */ 1356, 1791, 218, 540, 1209, 242, 1207, 1807, 1680, 1435,
- /* 1000 */ 539, 1573, 1303, 125, 124, 588, 587, 586, 1809, 1726,
- /* 1010 */ 121, 1220, 633, 517, 1305, 234, 237, 540, 1212, 1213,
- /* 1020 */ 1267, 239, 1680, 1710, 539, 1739, 3, 1163, 272, 1711,
- /* 1030 */ 542, 1713, 1714, 538, 122, 559, 244, 29, 316, 1292,
- /* 1040 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 123, 1219, 1739,
- /* 1050 */ 1726, 548, 86, 1711, 542, 1713, 1714, 538, 540, 559,
- /* 1060 */ 48, 564, 1779, 1680, 1710, 539, 311, 1775, 1858, 1289,
- /* 1070 */ 122, 123, 110, 122, 5, 250, 336, 1813, 1230, 339,
- /* 1080 */ 343, 298, 1174, 1032, 299, 259, 389, 163, 1063, 396,
- /* 1090 */ 1739, 1726, 1623, 86, 1711, 542, 1713, 1714, 538, 540,
- /* 1100 */ 559, 262, 1091, 1779, 1680, 404, 539, 311, 1775, 1858,
- /* 1110 */ 403, 1095, 1102, 1100, 126, 405, 409, 1236, 1836, 410,
- /* 1120 */ 418, 1239, 421, 170, 172, 1238, 422, 423, 1240, 426,
- /* 1130 */ 424, 1739, 175, 177, 86, 1711, 542, 1713, 1714, 538,
- /* 1140 */ 1710, 559, 427, 1237, 1779, 428, 180, 450, 311, 1775,
- /* 1150 */ 1858, 431, 452, 66, 183, 1523, 187, 1519, 481, 1797,
- /* 1160 */ 189, 128, 307, 89, 260, 129, 1521, 1726, 482, 485,
- /* 1170 */ 201, 204, 488, 1517, 130, 540, 131, 490, 207, 1235,
- /* 1180 */ 1680, 210, 539, 1810, 504, 546, 6, 492, 1662, 1820,
- /* 1190 */ 1661, 1819, 513, 1800, 222, 520, 142, 499, 500, 224,
- /* 1200 */ 498, 225, 493, 1710, 501, 1330, 310, 1739, 497, 226,
- /* 1210 */ 278, 1711, 542, 1713, 1714, 538, 507, 559, 214, 217,
- /* 1220 */ 1710, 116, 1234, 42, 1841, 18, 526, 529, 227, 523,
- /* 1230 */ 1726, 233, 312, 1861, 544, 545, 1845, 320, 540, 1794,
- /* 1240 */ 1629, 549, 246, 1680, 1628, 539, 551, 1726, 261, 550,
- /* 1250 */ 154, 77, 1534, 248, 1842, 540, 75, 562, 520, 264,
- /* 1260 */ 1680, 228, 539, 1760, 1577, 1506, 256, 49, 636, 266,
- /* 1270 */ 1739, 270, 1674, 278, 1711, 542, 1713, 1714, 538, 279,
- /* 1280 */ 559, 271, 268, 1710, 141, 236, 1673, 1739, 530, 60,
- /* 1290 */ 87, 1711, 542, 1713, 1714, 538, 238, 559, 1672, 1845,
- /* 1300 */ 1779, 1710, 338, 1669, 531, 1775, 340, 341, 1201, 1202,
- /* 1310 */ 1726, 159, 345, 152, 1667, 347, 348, 1842, 537, 349,
- /* 1320 */ 1666, 1665, 351, 1680, 353, 539, 1664, 355, 1726, 1663,
- /* 1330 */ 357, 1647, 160, 360, 361, 1177, 540, 1176, 1641, 1640,
- /* 1340 */ 366, 1680, 367, 539, 1639, 1638, 1149, 1616, 63, 1615,
- /* 1350 */ 1739, 378, 1710, 286, 1711, 542, 1713, 1714, 538, 536,
- /* 1360 */ 559, 533, 1751, 1614, 1613, 1612, 1611, 1610, 1739, 379,
- /* 1370 */ 640, 138, 1711, 542, 1713, 1714, 538, 381, 559, 1726,
- /* 1380 */ 1609, 1608, 1607, 1606, 258, 1605, 1604, 540, 1603, 1602,
- /* 1390 */ 1601, 1600, 1680, 516, 539, 1599, 145, 1598, 1597, 1596,
- /* 1400 */ 120, 1595, 631, 627, 623, 619, 257, 1594, 1593, 1592,
- /* 1410 */ 1591, 1590, 1589, 1710, 1151, 1588, 521, 1859, 1587, 1739,
- /* 1420 */ 1586, 117, 87, 1711, 542, 1713, 1714, 538, 1463, 559,
- /* 1430 */ 1431, 83, 1779, 168, 251, 146, 970, 1776, 969, 111,
- /* 1440 */ 1726, 520, 1430, 169, 414, 1655, 1649, 416, 540, 1637,
- /* 1450 */ 112, 174, 1636, 1680, 176, 539, 1626, 1512, 179, 1462,
- /* 1460 */ 115, 1460, 434, 998, 433, 1458, 1710, 552, 438, 1456,
- /* 1470 */ 432, 1454, 437, 436, 441, 229, 1786, 515, 442, 514,
- /* 1480 */ 1739, 440, 1845, 282, 1711, 542, 1713, 1714, 538, 1710,
- /* 1490 */ 559, 444, 445, 1726, 1443, 494, 154, 446, 208, 1442,
- /* 1500 */ 1842, 540, 1429, 1514, 186, 1106, 1680, 516, 539, 1105,
- /* 1510 */ 1513, 1031, 1452, 1030, 1029, 1028, 1726, 1182, 606, 202,
- /* 1520 */ 608, 1025, 512, 47, 540, 1024, 304, 1023, 1447, 1680,
- /* 1530 */ 305, 539, 469, 1739, 1445, 117, 138, 1711, 542, 1713,
- /* 1540 */ 1714, 538, 315, 559, 306, 1710, 1428, 472, 474, 1427,
- /* 1550 */ 88, 476, 1654, 1184, 51, 520, 1739, 1648, 483, 287,
- /* 1560 */ 1711, 542, 1713, 1714, 538, 1635, 559, 1634, 1633, 1625,
- /* 1570 */ 71, 15, 1726, 4, 115, 209, 39, 1371, 23, 213,
- /* 1580 */ 537, 205, 1860, 484, 45, 1680, 211, 539, 50, 229,
- /* 1590 */ 1786, 515, 139, 514, 220, 215, 1845, 132, 1710, 1355,
- /* 1600 */ 219, 24, 221, 1348, 1700, 72, 230, 1710, 143, 1327,
- /* 1610 */ 152, 25, 1739, 1326, 1842, 286, 1711, 542, 1713, 1714,
- /* 1620 */ 538, 1710, 559, 44, 1752, 1726, 1388, 17, 1383, 1377,
- /* 1630 */ 10, 1382, 313, 540, 1726, 1387, 1386, 314, 1680, 19,
- /* 1640 */ 539, 1269, 540, 1268, 31, 1290, 144, 1680, 1726, 539,
- /* 1650 */ 156, 317, 16, 12, 13, 20, 540, 43, 1254, 21,
- /* 1660 */ 319, 1680, 1710, 539, 1624, 1739, 541, 247, 287, 1711,
- /* 1670 */ 542, 1713, 1714, 538, 1739, 559, 241, 287, 1711, 542,
- /* 1680 */ 1713, 1714, 538, 1710, 559, 1353, 243, 547, 1739, 1726,
- /* 1690 */ 245, 273, 1711, 542, 1713, 1714, 538, 540, 559, 73,
- /* 1700 */ 74, 78, 1680, 1699, 539, 252, 1742, 1224, 1271, 249,
- /* 1710 */ 1726, 1092, 558, 46, 561, 563, 327, 1089, 540, 565,
- /* 1720 */ 567, 568, 570, 1680, 1086, 539, 571, 573, 1080, 1739,
- /* 1730 */ 574, 576, 274, 1711, 542, 1713, 1714, 538, 1078, 559,
- /* 1740 */ 1069, 1710, 1084, 583, 577, 1101, 1083, 79, 1082, 1081,
- /* 1750 */ 1739, 80, 1710, 281, 1711, 542, 1713, 1714, 538, 57,
- /* 1760 */ 559, 254, 1097, 1710, 996, 592, 1020, 595, 1726, 255,
- /* 1770 */ 1038, 1013, 1018, 1017, 1016, 1035, 540, 1015, 1014, 1726,
- /* 1780 */ 1012, 1680, 1011, 539, 1033, 1008, 1007, 540, 1006, 1003,
- /* 1790 */ 1726, 1002, 1680, 1001, 539, 1459, 617, 616, 540, 618,
- /* 1800 */ 1457, 620, 621, 1680, 622, 539, 1455, 624, 1739, 625,
- /* 1810 */ 626, 283, 1711, 542, 1713, 1714, 538, 1453, 559, 1739,
- /* 1820 */ 629, 628, 275, 1711, 542, 1713, 1714, 538, 1710, 559,
- /* 1830 */ 1739, 630, 1441, 284, 1711, 542, 1713, 1714, 538, 632,
- /* 1840 */ 559, 1426, 634, 635, 1710, 1210, 265, 638, 639, 1401,
- /* 1850 */ 1401, 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401, 1401,
- /* 1860 */ 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, 1401,
- /* 1870 */ 539, 1726, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 540,
- /* 1880 */ 1401, 1401, 1401, 1401, 1680, 1401, 539, 1401, 1401, 1401,
- /* 1890 */ 1401, 1401, 1401, 1710, 1401, 1739, 1401, 1401, 276, 1711,
- /* 1900 */ 542, 1713, 1714, 538, 1401, 559, 1401, 1710, 1401, 1401,
- /* 1910 */ 1401, 1739, 1401, 1401, 285, 1711, 542, 1713, 1714, 538,
- /* 1920 */ 1726, 559, 1401, 1401, 1401, 1401, 1401, 1401, 540, 1401,
- /* 1930 */ 1401, 1401, 1401, 1680, 1726, 539, 1401, 1401, 1401, 1401,
- /* 1940 */ 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, 1710, 539,
- /* 1950 */ 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401,
- /* 1960 */ 1739, 1401, 1401, 277, 1711, 542, 1713, 1714, 538, 1710,
- /* 1970 */ 559, 1401, 1401, 1401, 1739, 1726, 1401, 1722, 1711, 542,
- /* 1980 */ 1713, 1714, 538, 540, 559, 1401, 1401, 1401, 1680, 1401,
- /* 1990 */ 539, 1401, 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401,
- /* 2000 */ 1401, 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680,
- /* 2010 */ 1401, 539, 1401, 1401, 1401, 1739, 1401, 1401, 1721, 1711,
- /* 2020 */ 542, 1713, 1714, 538, 1401, 559, 1401, 1710, 1401, 1401,
- /* 2030 */ 1401, 1401, 1401, 1401, 1401, 1401, 1739, 1401, 1710, 1720,
- /* 2040 */ 1711, 542, 1713, 1714, 538, 1401, 559, 1401, 1401, 1710,
- /* 2050 */ 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401, 1401, 1401,
- /* 2060 */ 1401, 1401, 540, 1401, 1401, 1726, 1401, 1680, 1401, 539,
- /* 2070 */ 1401, 1401, 1401, 540, 1401, 1401, 1726, 1401, 1680, 1401,
- /* 2080 */ 539, 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680,
- /* 2090 */ 1710, 539, 1401, 1401, 1739, 1401, 1401, 296, 1711, 542,
- /* 2100 */ 1713, 1714, 538, 1401, 559, 1739, 1401, 1401, 295, 1711,
- /* 2110 */ 542, 1713, 1714, 538, 1710, 559, 1739, 1726, 1401, 297,
- /* 2120 */ 1711, 542, 1713, 1714, 538, 540, 559, 1401, 1401, 1401,
- /* 2130 */ 1680, 1401, 539, 1401, 1401, 1401, 1401, 1401, 1401, 1401,
- /* 2140 */ 1401, 1726, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 540,
- /* 2150 */ 1401, 1401, 1401, 1401, 1680, 1401, 539, 1739, 1401, 1401,
- /* 2160 */ 294, 1711, 542, 1713, 1714, 538, 1401, 559, 1401, 1401,
- /* 2170 */ 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401,
- /* 2180 */ 1401, 1739, 1401, 1401, 280, 1711, 542, 1713, 1714, 538,
- /* 2190 */ 1401, 559,
+ /* 0 */ 532, 73, 1466, 436, 555, 437, 1503, 327, 520, 73,
+ /* 10 */ 1658, 115, 39, 37, 119, 142, 326, 312, 474, 1703,
+ /* 20 */ 340, 1469, 1264, 1601, 1608, 145, 1656, 555, 1606, 1562,
+ /* 30 */ 1810, 1602, 124, 1341, 444, 1262, 437, 1503, 548, 558,
+ /* 40 */ 345, 389, 105, 1651, 1653, 104, 103, 102, 101, 100,
+ /* 50 */ 99, 98, 97, 96, 81, 124, 1336, 1491, 1792, 33,
+ /* 60 */ 32, 14, 353, 40, 38, 36, 35, 34, 1270, 39,
+ /* 70 */ 37, 1404, 122, 558, 558, 1599, 547, 340, 303, 1264,
+ /* 80 */ 1936, 1290, 144, 1936, 1480, 1, 1810, 158, 1878, 1879,
+ /* 90 */ 1341, 1883, 1262, 162, 584, 122, 1935, 1933, 1761, 1761,
+ /* 100 */ 1933, 583, 435, 1936, 64, 439, 1289, 665, 532, 557,
+ /* 110 */ 157, 1878, 1879, 1336, 1883, 560, 161, 1290, 14, 55,
+ /* 120 */ 1933, 1343, 1344, 30, 261, 1270, 1824, 131, 155, 221,
+ /* 130 */ 91, 1793, 586, 1795, 1796, 582, 1606, 577, 43, 42,
+ /* 140 */ 1870, 1645, 2, 105, 306, 1866, 104, 103, 102, 101,
+ /* 150 */ 100, 99, 98, 97, 96, 343, 1936, 40, 38, 36,
+ /* 160 */ 35, 34, 1080, 142, 665, 63, 1265, 195, 1263, 163,
+ /* 170 */ 54, 63, 1608, 1933, 383, 519, 351, 443, 1343, 1344,
+ /* 180 */ 439, 148, 1160, 1161, 1401, 63, 470, 466, 462, 458,
+ /* 190 */ 194, 1243, 1244, 1268, 1269, 1082, 1318, 1319, 1321, 1322,
+ /* 200 */ 1323, 1324, 1325, 1326, 579, 575, 1334, 1335, 1337, 1338,
+ /* 210 */ 1339, 1340, 1342, 1345, 1936, 1936, 1936, 1936, 74, 1652,
+ /* 220 */ 1653, 192, 1024, 1265, 1023, 1263, 164, 162, 161, 161,
+ /* 230 */ 161, 1933, 1933, 1933, 1933, 33, 32, 350, 63, 40,
+ /* 240 */ 38, 36, 35, 34, 1490, 382, 171, 381, 555, 564,
+ /* 250 */ 1268, 1269, 1025, 1318, 1319, 1321, 1322, 1323, 1324, 1325,
+ /* 260 */ 1326, 579, 575, 1334, 1335, 1337, 1338, 1339, 1340, 1342,
+ /* 270 */ 1345, 39, 37, 1468, 71, 1289, 124, 70, 1936, 340,
+ /* 280 */ 164, 1264, 1792, 191, 184, 1761, 189, 1584, 307, 49,
+ /* 290 */ 449, 161, 1341, 453, 1262, 1933, 532, 114, 113, 112,
+ /* 300 */ 111, 110, 109, 108, 107, 106, 164, 115, 1289, 182,
+ /* 310 */ 1810, 1489, 164, 1303, 479, 1336, 122, 1936, 559, 505,
+ /* 320 */ 14, 1363, 1488, 1761, 1606, 583, 164, 1270, 39, 37,
+ /* 330 */ 1934, 159, 1878, 1879, 1933, 1883, 340, 532, 1264, 1530,
+ /* 340 */ 317, 485, 484, 1425, 2, 478, 1658, 453, 166, 1341,
+ /* 350 */ 1824, 1262, 1761, 328, 92, 1793, 586, 1795, 1796, 582,
+ /* 360 */ 1936, 577, 1656, 1761, 1870, 1606, 665, 477, 331, 1866,
+ /* 370 */ 156, 1582, 1336, 161, 549, 1364, 1658, 1933, 1291, 164,
+ /* 380 */ 1343, 1344, 160, 344, 1270, 541, 1423, 1424, 1426, 1427,
+ /* 390 */ 1896, 318, 1656, 316, 315, 1702, 476, 300, 1369, 1706,
+ /* 400 */ 478, 8, 642, 641, 640, 639, 348, 1400, 638, 637,
+ /* 410 */ 636, 125, 631, 630, 629, 628, 627, 626, 625, 624,
+ /* 420 */ 135, 620, 477, 665, 1024, 1265, 1023, 1263, 33, 32,
+ /* 430 */ 164, 619, 40, 38, 36, 35, 34, 1343, 1344, 472,
+ /* 440 */ 1007, 29, 338, 1358, 1359, 1360, 1361, 1362, 1366, 1367,
+ /* 450 */ 1368, 565, 1268, 1269, 1025, 1318, 1319, 1321, 1322, 1323,
+ /* 460 */ 1324, 1325, 1326, 579, 575, 1334, 1335, 1337, 1338, 1339,
+ /* 470 */ 1340, 1342, 1345, 1583, 216, 222, 223, 489, 488, 487,
+ /* 480 */ 1011, 1012, 1265, 486, 1263, 1320, 120, 483, 635, 633,
+ /* 490 */ 482, 481, 480, 33, 32, 1533, 1779, 40, 38, 36,
+ /* 500 */ 35, 34, 209, 63, 619, 77, 1487, 1775, 422, 1268,
+ /* 510 */ 1269, 253, 1318, 1319, 1321, 1322, 1323, 1324, 1325, 1326,
+ /* 520 */ 579, 575, 1334, 1335, 1337, 1338, 1339, 1340, 1342, 1345,
+ /* 530 */ 39, 37, 1346, 1771, 1777, 329, 305, 441, 340, 522,
+ /* 540 */ 1264, 1792, 164, 1287, 215, 577, 307, 1761, 1701, 346,
+ /* 550 */ 300, 1341, 532, 1262, 175, 174, 1509, 142, 489, 488,
+ /* 560 */ 487, 75, 305, 387, 486, 522, 1608, 120, 483, 1810,
+ /* 570 */ 617, 482, 481, 480, 1336, 76, 1365, 559, 1461, 1363,
+ /* 580 */ 1606, 544, 1761, 494, 583, 1658, 1270, 39, 37, 133,
+ /* 590 */ 132, 614, 613, 612, 532, 340, 532, 1264, 504, 1370,
+ /* 600 */ 1696, 1657, 567, 9, 660, 388, 503, 392, 1341, 1824,
+ /* 610 */ 1262, 173, 208, 92, 1793, 586, 1795, 1796, 582, 501,
+ /* 620 */ 577, 499, 1606, 1870, 1606, 665, 497, 331, 1866, 156,
+ /* 630 */ 491, 1336, 374, 1364, 1597, 207, 532, 532, 1288, 1343,
+ /* 640 */ 1344, 1779, 27, 1270, 164, 1775, 88, 407, 408, 1897,
+ /* 650 */ 1595, 1408, 1775, 1486, 376, 372, 1369, 1289, 1270, 121,
+ /* 660 */ 9, 550, 545, 58, 1606, 1606, 57, 1598, 1460, 33,
+ /* 670 */ 32, 1771, 1777, 40, 38, 36, 35, 34, 1771, 1777,
+ /* 680 */ 335, 520, 665, 577, 1265, 1351, 1263, 36, 35, 34,
+ /* 690 */ 577, 1289, 1704, 1485, 1761, 611, 1343, 1344, 1581, 29,
+ /* 700 */ 338, 1358, 1359, 1360, 1361, 1362, 1366, 1367, 1368, 11,
+ /* 710 */ 10, 1268, 1269, 61, 1318, 1319, 1321, 1322, 1323, 1324,
+ /* 720 */ 1325, 1326, 579, 575, 1334, 1335, 1337, 1338, 1339, 1340,
+ /* 730 */ 1342, 1345, 33, 32, 1761, 1885, 40, 38, 36, 35,
+ /* 740 */ 34, 1265, 615, 1263, 623, 1649, 1578, 1435, 1118, 608,
+ /* 750 */ 607, 606, 1122, 605, 1124, 1125, 604, 1127, 601, 1882,
+ /* 760 */ 1133, 598, 1135, 1136, 595, 592, 1484, 22, 1268, 1269,
+ /* 770 */ 1483, 1318, 1319, 1321, 1322, 1323, 1324, 1325, 1326, 579,
+ /* 780 */ 575, 1334, 1335, 1337, 1338, 1339, 1340, 1342, 1345, 39,
+ /* 790 */ 37, 302, 1051, 1287, 1377, 617, 142, 340, 532, 1264,
+ /* 800 */ 415, 1792, 532, 427, 622, 1609, 568, 1761, 532, 452,
+ /* 810 */ 1341, 1761, 1262, 1603, 133, 132, 614, 613, 612, 1735,
+ /* 820 */ 400, 532, 428, 1747, 402, 1052, 1606, 532, 532, 1810,
+ /* 830 */ 1606, 1292, 513, 1336, 1320, 7, 1606, 584, 517, 530,
+ /* 840 */ 1482, 1479, 1761, 634, 583, 1270, 33, 32, 87, 1606,
+ /* 850 */ 40, 38, 36, 35, 34, 1606, 1606, 393, 84, 33,
+ /* 860 */ 32, 532, 2, 40, 38, 36, 35, 34, 1320, 1824,
+ /* 870 */ 362, 617, 531, 93, 1793, 586, 1795, 1796, 582, 1591,
+ /* 880 */ 577, 1761, 1761, 1870, 665, 1478, 377, 1869, 1866, 1606,
+ /* 890 */ 133, 132, 614, 613, 612, 44, 4, 426, 1343, 1344,
+ /* 900 */ 421, 420, 419, 418, 417, 414, 413, 412, 411, 410,
+ /* 910 */ 406, 405, 404, 403, 397, 396, 395, 394, 1885, 391,
+ /* 920 */ 390, 1593, 1477, 26, 1415, 1885, 1761, 143, 1589, 33,
+ /* 930 */ 32, 1476, 279, 40, 38, 36, 35, 34, 1011, 1012,
+ /* 940 */ 1273, 532, 1881, 1265, 212, 1263, 277, 60, 28, 1880,
+ /* 950 */ 59, 512, 262, 562, 33, 32, 1475, 41, 40, 38,
+ /* 960 */ 36, 35, 34, 1761, 233, 1792, 178, 432, 430, 1606,
+ /* 970 */ 1268, 1269, 1761, 1318, 1319, 1321, 1322, 1323, 1324, 1325,
+ /* 980 */ 1326, 579, 575, 1334, 1335, 1337, 1338, 1339, 1340, 1342,
+ /* 990 */ 1345, 668, 532, 1810, 63, 273, 616, 1761, 1636, 1649,
+ /* 1000 */ 1211, 584, 578, 347, 141, 268, 1761, 1474, 583, 1473,
+ /* 1010 */ 33, 32, 1472, 1471, 40, 38, 36, 35, 34, 153,
+ /* 1020 */ 1606, 1397, 560, 1520, 658, 654, 650, 646, 266, 1272,
+ /* 1030 */ 1890, 1397, 90, 1824, 53, 516, 1782, 91, 1793, 586,
+ /* 1040 */ 1795, 1796, 582, 220, 577, 490, 1792, 1870, 1761, 1515,
+ /* 1050 */ 1761, 306, 1866, 1761, 1761, 200, 89, 1513, 198, 231,
+ /* 1060 */ 337, 336, 202, 1936, 127, 201, 573, 68, 67, 386,
+ /* 1070 */ 1278, 492, 170, 1276, 1810, 1784, 161, 610, 380, 495,
+ /* 1080 */ 1933, 1341, 584, 1271, 130, 1481, 224, 1761, 1303, 583,
+ /* 1090 */ 1563, 301, 529, 256, 370, 131, 368, 364, 360, 167,
+ /* 1100 */ 355, 352, 1780, 204, 1336, 206, 203, 525, 205, 51,
+ /* 1110 */ 41, 237, 542, 1775, 1824, 51, 1270, 41, 92, 1793,
+ /* 1120 */ 586, 1795, 1796, 582, 218, 577, 590, 230, 1870, 11,
+ /* 1130 */ 10, 471, 331, 1866, 1949, 164, 1792, 1811, 1111, 1771,
+ /* 1140 */ 1777, 1463, 1464, 1904, 130, 1235, 131, 211, 116, 506,
+ /* 1150 */ 130, 577, 1422, 1327, 240, 572, 245, 349, 1371, 1504,
+ /* 1160 */ 272, 1646, 1275, 1900, 1810, 556, 250, 3, 255, 1139,
+ /* 1170 */ 258, 5, 584, 260, 354, 1287, 361, 1761, 357, 583,
+ /* 1180 */ 313, 1080, 1227, 314, 269, 409, 1698, 1143, 424, 1150,
+ /* 1190 */ 172, 1148, 1792, 134, 416, 423, 425, 429, 1355, 431,
+ /* 1200 */ 434, 433, 1293, 442, 1824, 1296, 445, 181, 93, 1793,
+ /* 1210 */ 586, 1795, 1796, 582, 1279, 577, 1274, 446, 1870, 183,
+ /* 1220 */ 1810, 1295, 571, 1866, 1297, 448, 186, 447, 584, 188,
+ /* 1230 */ 1294, 450, 451, 1761, 1792, 583, 190, 454, 72, 193,
+ /* 1240 */ 473, 1282, 1284, 475, 1596, 95, 197, 1592, 199, 136,
+ /* 1250 */ 137, 1594, 304, 575, 1334, 1335, 1337, 1338, 1339, 1340,
+ /* 1260 */ 1824, 1590, 1810, 138, 92, 1793, 586, 1795, 1796, 582,
+ /* 1270 */ 584, 577, 139, 270, 1870, 1761, 210, 583, 331, 1866,
+ /* 1280 */ 1949, 1740, 507, 540, 511, 526, 213, 1792, 217, 1927,
+ /* 1290 */ 508, 514, 518, 521, 128, 323, 1739, 1792, 1708, 523,
+ /* 1300 */ 129, 325, 1824, 226, 527, 528, 92, 1793, 586, 1795,
+ /* 1310 */ 1796, 582, 228, 577, 271, 1810, 1870, 1607, 1292, 543,
+ /* 1320 */ 331, 1866, 1949, 584, 80, 1810, 536, 538, 1761, 539,
+ /* 1330 */ 583, 1889, 1264, 584, 1901, 330, 546, 6, 1761, 534,
+ /* 1340 */ 583, 235, 244, 239, 552, 1262, 537, 1792, 1397, 1911,
+ /* 1350 */ 1910, 150, 535, 123, 560, 1824, 1291, 1792, 1892, 280,
+ /* 1360 */ 1793, 586, 1795, 1796, 582, 1824, 577, 249, 246, 286,
+ /* 1370 */ 1793, 586, 1795, 1796, 582, 1810, 577, 569, 1270, 332,
+ /* 1380 */ 1886, 566, 1932, 584, 254, 1810, 563, 257, 1761, 1952,
+ /* 1390 */ 583, 48, 82, 581, 247, 1936, 1650, 248, 1761, 1579,
+ /* 1400 */ 583, 274, 265, 1851, 560, 588, 661, 570, 163, 662,
+ /* 1410 */ 664, 259, 1933, 52, 149, 1824, 278, 665, 1755, 286,
+ /* 1420 */ 1793, 586, 1795, 1796, 582, 1824, 577, 276, 1754, 294,
+ /* 1430 */ 1793, 586, 1795, 1796, 582, 580, 577, 574, 1842, 1792,
+ /* 1440 */ 555, 287, 297, 296, 65, 1936, 1753, 1752, 66, 1751,
+ /* 1450 */ 356, 1748, 358, 359, 1255, 1256, 168, 363, 161, 1746,
+ /* 1460 */ 365, 366, 1933, 367, 1745, 369, 1744, 1810, 124, 1743,
+ /* 1470 */ 371, 1742, 373, 375, 1725, 584, 1265, 169, 1263, 378,
+ /* 1480 */ 1761, 379, 583, 1230, 1229, 1719, 1718, 384, 385, 560,
+ /* 1490 */ 1717, 1716, 1691, 1792, 1199, 1690, 1689, 69, 1688, 1687,
+ /* 1500 */ 1686, 1685, 1684, 1268, 1269, 398, 1683, 1824, 122, 401,
+ /* 1510 */ 399, 146, 1793, 586, 1795, 1796, 582, 1792, 577, 1682,
+ /* 1520 */ 1681, 1810, 126, 251, 1878, 554, 1680, 553, 1679, 584,
+ /* 1530 */ 1936, 1678, 1677, 1676, 1761, 1675, 583, 1674, 1673, 1672,
+ /* 1540 */ 1671, 1670, 1669, 163, 1668, 1810, 1667, 1933, 1666, 1665,
+ /* 1550 */ 324, 1664, 1663, 584, 117, 561, 1950, 1662, 1761, 1661,
+ /* 1560 */ 583, 1824, 1660, 1659, 1535, 93, 1793, 586, 1795, 1796,
+ /* 1570 */ 582, 1792, 577, 176, 1534, 1870, 1201, 177, 1532, 1500,
+ /* 1580 */ 1867, 1792, 1014, 1013, 1499, 1824, 154, 179, 1733, 295,
+ /* 1590 */ 1793, 586, 1795, 1796, 582, 1727, 577, 1715, 180, 1810,
+ /* 1600 */ 118, 438, 440, 1714, 533, 185, 1700, 584, 1585, 1810,
+ /* 1610 */ 187, 1531, 1761, 1529, 583, 1044, 455, 584, 456, 457,
+ /* 1620 */ 1527, 459, 1761, 460, 583, 1525, 461, 1523, 463, 465,
+ /* 1630 */ 464, 1792, 468, 467, 1512, 469, 1511, 1496, 1587, 1824,
+ /* 1640 */ 1154, 50, 196, 295, 1793, 586, 1795, 1796, 582, 1824,
+ /* 1650 */ 577, 1153, 1586, 290, 1793, 586, 1795, 1796, 582, 1810,
+ /* 1660 */ 577, 1079, 632, 1078, 634, 1077, 1076, 584, 1073, 1521,
+ /* 1670 */ 1072, 319, 1761, 320, 583, 1071, 1070, 1516, 1514, 321,
+ /* 1680 */ 496, 1792, 1495, 498, 1494, 500, 1493, 502, 493, 1732,
+ /* 1690 */ 94, 551, 15, 1792, 1237, 1726, 140, 509, 1713, 1824,
+ /* 1700 */ 1711, 1712, 1710, 146, 1793, 586, 1795, 1796, 582, 1810,
+ /* 1710 */ 577, 1709, 1707, 56, 1699, 1247, 229, 581, 510, 227,
+ /* 1720 */ 214, 1810, 1761, 16, 583, 232, 339, 225, 322, 584,
+ /* 1730 */ 219, 78, 515, 41, 1761, 17, 583, 47, 79, 23,
+ /* 1740 */ 524, 1437, 84, 234, 13, 243, 236, 1419, 1951, 1824,
+ /* 1750 */ 1421, 238, 147, 294, 1793, 586, 1795, 1796, 582, 241,
+ /* 1760 */ 577, 1824, 1843, 242, 1782, 295, 1793, 586, 1795, 1796,
+ /* 1770 */ 582, 1792, 577, 24, 25, 252, 46, 1414, 83, 18,
+ /* 1780 */ 1781, 1792, 1394, 1393, 151, 1449, 1448, 333, 1453, 1454,
+ /* 1790 */ 1443, 1452, 334, 10, 1280, 1356, 1331, 45, 19, 1810,
+ /* 1800 */ 1827, 576, 1311, 1329, 341, 1328, 31, 584, 152, 1810,
+ /* 1810 */ 12, 20, 1761, 165, 583, 21, 589, 584, 585, 587,
+ /* 1820 */ 342, 1140, 1761, 1137, 583, 591, 594, 593, 1134, 596,
+ /* 1830 */ 597, 1792, 1128, 599, 600, 602, 1132, 1131, 1117, 1824,
+ /* 1840 */ 609, 1792, 1149, 295, 1793, 586, 1795, 1796, 582, 1824,
+ /* 1850 */ 577, 1792, 1126, 281, 1793, 586, 1795, 1796, 582, 1810,
+ /* 1860 */ 577, 603, 85, 86, 62, 263, 1145, 584, 1130, 1810,
+ /* 1870 */ 1129, 1042, 1761, 618, 583, 264, 1067, 584, 1086, 1810,
+ /* 1880 */ 621, 1065, 1761, 1064, 583, 1063, 1062, 584, 1061, 1060,
+ /* 1890 */ 1059, 1058, 1761, 1083, 583, 1081, 1055, 1054, 1053, 1824,
+ /* 1900 */ 1050, 1049, 1528, 282, 1793, 586, 1795, 1796, 582, 1824,
+ /* 1910 */ 577, 1048, 1047, 289, 1793, 586, 1795, 1796, 582, 1824,
+ /* 1920 */ 577, 643, 644, 291, 1793, 586, 1795, 1796, 582, 645,
+ /* 1930 */ 577, 1526, 1792, 647, 648, 649, 1524, 1522, 651, 652,
+ /* 1940 */ 653, 655, 656, 657, 1510, 659, 1004, 1492, 267, 663,
+ /* 1950 */ 666, 1792, 1266, 667, 275, 1467, 1467, 1467, 1467, 1467,
+ /* 1960 */ 1810, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467,
+ /* 1970 */ 1467, 1467, 1467, 1761, 1467, 583, 1467, 1467, 1467, 1810,
+ /* 1980 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467,
+ /* 1990 */ 1467, 1467, 1761, 1467, 583, 1467, 1467, 1467, 1467, 1467,
+ /* 2000 */ 1824, 1467, 1467, 1467, 283, 1793, 586, 1795, 1796, 582,
+ /* 2010 */ 1467, 577, 1467, 1792, 1467, 1467, 1467, 1467, 1467, 1824,
+ /* 2020 */ 1467, 1467, 1467, 292, 1793, 586, 1795, 1796, 582, 1792,
+ /* 2030 */ 577, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2040 */ 1467, 1810, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584,
+ /* 2050 */ 1467, 1467, 1467, 1467, 1761, 1467, 583, 1810, 1467, 1467,
+ /* 2060 */ 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467, 1467, 1467,
+ /* 2070 */ 1761, 1467, 583, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2080 */ 1467, 1824, 1792, 1467, 1467, 284, 1793, 586, 1795, 1796,
+ /* 2090 */ 582, 1467, 577, 1467, 1467, 1467, 1467, 1824, 1467, 1792,
+ /* 2100 */ 1467, 293, 1793, 586, 1795, 1796, 582, 1467, 577, 1467,
+ /* 2110 */ 1810, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467,
+ /* 2120 */ 1467, 1467, 1467, 1761, 1467, 583, 1467, 1810, 1467, 1467,
+ /* 2130 */ 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467, 1467, 1467,
+ /* 2140 */ 1761, 1467, 583, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2150 */ 1824, 1467, 1792, 1467, 285, 1793, 586, 1795, 1796, 582,
+ /* 2160 */ 1467, 577, 1467, 1467, 1792, 1467, 1467, 1824, 1467, 1467,
+ /* 2170 */ 1467, 298, 1793, 586, 1795, 1796, 582, 1467, 577, 1467,
+ /* 2180 */ 1810, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467,
+ /* 2190 */ 1467, 1467, 1810, 1761, 1467, 583, 1467, 1467, 1467, 1467,
+ /* 2200 */ 584, 1467, 1467, 1467, 1467, 1761, 1467, 583, 1467, 1467,
+ /* 2210 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2220 */ 1824, 1467, 1467, 1467, 299, 1793, 586, 1795, 1796, 582,
+ /* 2230 */ 1467, 577, 1824, 1792, 1467, 1467, 1804, 1793, 586, 1795,
+ /* 2240 */ 1796, 582, 1467, 577, 1467, 1467, 1467, 1792, 1467, 1467,
+ /* 2250 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2260 */ 1467, 1810, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584,
+ /* 2270 */ 1467, 1467, 1467, 1467, 1761, 1810, 583, 1467, 1467, 1467,
+ /* 2280 */ 1467, 1467, 1467, 584, 1467, 1467, 1467, 1467, 1761, 1792,
+ /* 2290 */ 583, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2300 */ 1467, 1824, 1467, 1467, 1467, 1803, 1793, 586, 1795, 1796,
+ /* 2310 */ 582, 1467, 577, 1467, 1467, 1824, 1467, 1810, 1467, 1802,
+ /* 2320 */ 1793, 586, 1795, 1796, 582, 584, 577, 1467, 1467, 1467,
+ /* 2330 */ 1761, 1467, 583, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2340 */ 1467, 1792, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2350 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1824, 1467, 1792,
+ /* 2360 */ 1467, 310, 1793, 586, 1795, 1796, 582, 1467, 577, 1810,
+ /* 2370 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467,
+ /* 2380 */ 1467, 1467, 1761, 1792, 583, 1467, 1467, 1810, 1467, 1467,
+ /* 2390 */ 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467, 1467, 1467,
+ /* 2400 */ 1761, 1467, 583, 1467, 1467, 1467, 1467, 1467, 1467, 1824,
+ /* 2410 */ 1467, 1810, 1467, 309, 1793, 586, 1795, 1796, 582, 584,
+ /* 2420 */ 577, 1467, 1467, 1467, 1761, 1467, 583, 1824, 1467, 1467,
+ /* 2430 */ 1467, 311, 1793, 586, 1795, 1796, 582, 1467, 577, 555,
+ /* 2440 */ 1792, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2450 */ 1467, 1824, 1467, 1467, 1467, 308, 1793, 586, 1795, 1796,
+ /* 2460 */ 582, 1467, 577, 1467, 1467, 1467, 1467, 124, 1810, 1467,
+ /* 2470 */ 1467, 1467, 1467, 1467, 1467, 1467, 584, 1467, 1467, 1467,
+ /* 2480 */ 1467, 1761, 1467, 583, 1467, 1467, 1467, 1467, 560, 1467,
+ /* 2490 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2500 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 122, 1824, 1467,
+ /* 2510 */ 1467, 1467, 288, 1793, 586, 1795, 1796, 582, 1467, 577,
+ /* 2520 */ 1467, 1467, 251, 1878, 554, 1467, 553, 1467, 1467, 1936,
+ /* 2530 */ 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+ /* 2540 */ 1467, 1467, 161, 1467, 1467, 1467, 1933,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 274, 341, 273, 277, 248, 274, 250, 251, 277, 242,
- /* 10 */ 257, 285, 12, 13, 261, 355, 285, 245, 14, 359,
- /* 20 */ 20, 252, 22, 252, 20, 12, 13, 14, 15, 16,
- /* 30 */ 12, 13, 263, 248, 263, 250, 251, 311, 312, 270,
- /* 40 */ 22, 270, 311, 312, 272, 326, 327, 47, 322, 280,
- /* 50 */ 313, 280, 280, 322, 41, 252, 20, 285, 58, 287,
- /* 60 */ 12, 13, 14, 264, 64, 47, 263, 300, 20, 245,
- /* 70 */ 22, 272, 300, 300, 337, 12, 13, 14, 15, 16,
- /* 80 */ 281, 81, 64, 280, 312, 256, 20, 315, 316, 317,
- /* 90 */ 318, 319, 320, 81, 322, 47, 272, 325, 269, 254,
- /* 100 */ 252, 329, 330, 103, 280, 252, 58, 278, 341, 285,
- /* 110 */ 245, 287, 64, 341, 341, 287, 263, 117, 118, 4,
- /* 120 */ 275, 103, 355, 4, 20, 297, 359, 355, 355, 81,
- /* 130 */ 57, 359, 359, 280, 55, 254, 312, 289, 19, 315,
- /* 140 */ 316, 317, 318, 319, 320, 82, 322, 81, 267, 325,
- /* 150 */ 285, 103, 33, 329, 330, 331, 275, 42, 43, 159,
- /* 160 */ 81, 161, 83, 264, 45, 117, 118, 343, 3, 50,
- /* 170 */ 158, 272, 160, 20, 55, 351, 352, 159, 283, 161,
- /* 180 */ 281, 286, 287, 183, 184, 81, 186, 187, 188, 189,
- /* 190 */ 190, 191, 192, 193, 194, 195, 196, 197, 198, 80,
- /* 200 */ 20, 183, 83, 286, 287, 2, 4, 159, 341, 161,
- /* 210 */ 20, 211, 194, 195, 196, 12, 13, 14, 15, 16,
- /* 220 */ 12, 13, 355, 211, 245, 245, 359, 75, 20, 256,
- /* 230 */ 22, 183, 184, 35, 186, 187, 188, 189, 190, 191,
- /* 240 */ 192, 193, 194, 195, 196, 197, 198, 252, 272, 60,
- /* 250 */ 61, 278, 272, 300, 65, 47, 280, 68, 69, 0,
- /* 260 */ 280, 72, 73, 74, 285, 285, 58, 287, 12, 13,
- /* 270 */ 117, 118, 64, 121, 122, 280, 20, 211, 22, 142,
- /* 280 */ 300, 0, 84, 81, 86, 87, 154, 89, 81, 81,
- /* 290 */ 211, 93, 312, 317, 341, 315, 316, 317, 318, 319,
- /* 300 */ 320, 164, 322, 47, 45, 325, 174, 175, 355, 329,
- /* 310 */ 330, 103, 359, 115, 319, 12, 13, 14, 15, 16,
- /* 320 */ 64, 341, 244, 274, 246, 117, 118, 0, 333, 334,
- /* 330 */ 335, 336, 20, 338, 285, 355, 199, 81, 57, 359,
- /* 340 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
- /* 350 */ 104, 0, 106, 107, 108, 109, 110, 111, 81, 103,
- /* 360 */ 311, 312, 12, 13, 14, 15, 16, 159, 91, 161,
- /* 370 */ 183, 322, 21, 117, 118, 24, 25, 26, 27, 28,
- /* 380 */ 29, 30, 31, 32, 57, 82, 12, 13, 14, 15,
- /* 390 */ 16, 183, 184, 228, 186, 187, 188, 189, 190, 191,
- /* 400 */ 192, 193, 194, 195, 196, 197, 198, 220, 221, 222,
- /* 410 */ 223, 224, 20, 211, 22, 159, 21, 161, 211, 24,
- /* 420 */ 25, 26, 27, 28, 29, 30, 31, 32, 12, 13,
- /* 430 */ 14, 1, 2, 245, 258, 259, 20, 55, 22, 183,
- /* 440 */ 184, 49, 186, 187, 188, 189, 190, 191, 192, 193,
- /* 450 */ 194, 195, 196, 197, 198, 12, 13, 14, 15, 16,
- /* 460 */ 272, 300, 80, 47, 341, 83, 57, 211, 280, 20,
- /* 470 */ 271, 22, 272, 285, 20, 287, 12, 13, 355, 279,
- /* 480 */ 64, 0, 359, 284, 20, 313, 22, 245, 288, 64,
- /* 490 */ 12, 13, 14, 15, 16, 245, 47, 81, 49, 20,
- /* 500 */ 312, 151, 341, 315, 316, 317, 318, 319, 320, 337,
- /* 510 */ 322, 47, 82, 325, 113, 272, 355, 329, 330, 103,
- /* 520 */ 359, 287, 148, 272, 281, 82, 14, 285, 64, 295,
- /* 530 */ 279, 297, 20, 117, 118, 285, 58, 258, 259, 288,
- /* 540 */ 245, 60, 61, 62, 63, 81, 65, 66, 67, 68,
- /* 550 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 560 */ 82, 0, 12, 13, 14, 15, 16, 103, 90, 146,
- /* 570 */ 169, 170, 14, 42, 43, 159, 245, 161, 20, 245,
- /* 580 */ 285, 117, 118, 233, 2, 24, 25, 26, 27, 28,
- /* 590 */ 29, 30, 31, 32, 12, 13, 14, 15, 16, 183,
- /* 600 */ 184, 0, 186, 187, 188, 189, 190, 191, 192, 193,
- /* 610 */ 194, 195, 196, 197, 198, 252, 285, 272, 272, 285,
- /* 620 */ 142, 264, 92, 159, 279, 161, 263, 148, 273, 272,
- /* 630 */ 14, 15, 16, 288, 288, 245, 12, 13, 281, 216,
- /* 640 */ 217, 112, 164, 280, 20, 93, 22, 183, 184, 245,
- /* 650 */ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
- /* 660 */ 196, 197, 198, 252, 112, 113, 114, 115, 116, 249,
- /* 670 */ 249, 47, 252, 252, 263, 285, 252, 199, 200, 201,
- /* 680 */ 202, 203, 204, 205, 206, 207, 208, 263, 64, 285,
- /* 690 */ 33, 280, 252, 265, 93, 260, 268, 262, 245, 187,
- /* 700 */ 171, 172, 45, 263, 280, 81, 245, 252, 51, 52,
- /* 710 */ 53, 54, 55, 112, 113, 114, 115, 116, 263, 313,
- /* 720 */ 280, 274, 245, 4, 18, 20, 20, 103, 245, 44,
- /* 730 */ 245, 93, 285, 27, 37, 280, 30, 80, 285, 252,
- /* 740 */ 83, 117, 118, 337, 252, 187, 285, 245, 245, 272,
- /* 750 */ 263, 45, 20, 115, 48, 263, 50, 280, 311, 312,
- /* 760 */ 18, 41, 285, 252, 287, 23, 81, 280, 285, 322,
- /* 770 */ 285, 280, 280, 252, 263, 298, 282, 35, 36, 285,
- /* 780 */ 41, 39, 291, 159, 263, 161, 80, 285, 285, 312,
- /* 790 */ 64, 280, 315, 316, 317, 318, 319, 320, 56, 322,
- /* 800 */ 143, 280, 145, 0, 147, 273, 149, 183, 184, 245,
- /* 810 */ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
- /* 820 */ 196, 197, 198, 81, 282, 168, 120, 285, 273, 123,
- /* 830 */ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
- /* 840 */ 134, 135, 136, 137, 138, 139, 140, 273, 47, 285,
- /* 850 */ 12, 13, 14, 15, 16, 252, 252, 22, 252, 252,
- /* 860 */ 245, 119, 245, 60, 61, 64, 263, 263, 65, 263,
- /* 870 */ 245, 68, 69, 209, 210, 72, 73, 74, 41, 0,
- /* 880 */ 148, 273, 47, 280, 280, 85, 280, 280, 88, 304,
- /* 890 */ 245, 0, 187, 151, 152, 153, 58, 47, 156, 64,
- /* 900 */ 285, 22, 285, 85, 162, 252, 88, 210, 85, 85,
- /* 910 */ 285, 88, 88, 0, 0, 173, 273, 272, 176, 82,
- /* 920 */ 178, 179, 180, 181, 182, 280, 319, 21, 90, 246,
- /* 930 */ 285, 212, 287, 280, 47, 22, 22, 41, 103, 47,
- /* 940 */ 34, 334, 335, 336, 58, 338, 362, 1, 2, 41,
- /* 950 */ 230, 41, 261, 211, 253, 353, 64, 312, 245, 308,
- /* 960 */ 315, 316, 317, 318, 319, 320, 0, 322, 117, 118,
- /* 970 */ 325, 232, 319, 41, 329, 330, 331, 348, 82, 41,
- /* 980 */ 142, 272, 245, 253, 93, 272, 41, 334, 335, 336,
- /* 990 */ 82, 338, 82, 280, 159, 41, 161, 352, 285, 251,
- /* 1000 */ 287, 284, 164, 112, 113, 114, 115, 116, 314, 272,
- /* 1010 */ 41, 161, 46, 339, 82, 356, 356, 280, 183, 184,
- /* 1020 */ 82, 356, 285, 245, 287, 312, 342, 82, 315, 316,
- /* 1030 */ 317, 318, 319, 320, 41, 322, 82, 199, 200, 201,
- /* 1040 */ 202, 203, 204, 205, 206, 207, 208, 41, 161, 312,
- /* 1050 */ 272, 82, 315, 316, 317, 318, 319, 320, 280, 322,
- /* 1060 */ 41, 41, 325, 285, 245, 287, 329, 330, 331, 183,
- /* 1070 */ 41, 41, 41, 41, 213, 82, 310, 340, 20, 252,
- /* 1080 */ 45, 309, 157, 47, 258, 302, 252, 40, 82, 292,
- /* 1090 */ 312, 272, 252, 315, 316, 317, 318, 319, 320, 280,
- /* 1100 */ 322, 82, 82, 325, 285, 142, 287, 329, 330, 331,
- /* 1110 */ 290, 82, 82, 82, 82, 290, 252, 20, 340, 247,
- /* 1120 */ 247, 20, 306, 256, 256, 20, 287, 299, 20, 299,
- /* 1130 */ 301, 312, 256, 256, 315, 316, 317, 318, 319, 320,
- /* 1140 */ 245, 322, 280, 20, 325, 293, 256, 247, 329, 330,
- /* 1150 */ 331, 252, 272, 256, 256, 272, 272, 272, 167, 340,
- /* 1160 */ 272, 272, 247, 252, 306, 272, 272, 272, 305, 287,
- /* 1170 */ 254, 254, 252, 272, 272, 280, 272, 299, 254, 20,
- /* 1180 */ 285, 254, 287, 314, 219, 218, 225, 280, 285, 347,
- /* 1190 */ 285, 347, 150, 350, 349, 300, 347, 285, 227, 346,
- /* 1200 */ 226, 345, 293, 245, 285, 210, 285, 312, 214, 344,
- /* 1210 */ 315, 316, 317, 318, 319, 320, 285, 322, 296, 296,
- /* 1220 */ 245, 280, 20, 40, 358, 81, 229, 231, 310, 358,
- /* 1230 */ 272, 357, 234, 363, 285, 285, 341, 285, 280, 313,
- /* 1240 */ 296, 145, 280, 285, 296, 287, 293, 272, 268, 294,
- /* 1250 */ 355, 81, 280, 254, 359, 280, 254, 276, 300, 252,
- /* 1260 */ 285, 332, 287, 328, 285, 262, 254, 303, 247, 255,
- /* 1270 */ 312, 266, 0, 315, 316, 317, 318, 319, 320, 266,
- /* 1280 */ 322, 266, 243, 245, 307, 357, 0, 312, 358, 40,
- /* 1290 */ 315, 316, 317, 318, 319, 320, 357, 322, 0, 341,
- /* 1300 */ 325, 245, 72, 0, 329, 330, 47, 177, 47, 47,
- /* 1310 */ 272, 47, 177, 355, 0, 47, 47, 359, 280, 177,
- /* 1320 */ 0, 0, 177, 285, 47, 287, 0, 22, 272, 0,
- /* 1330 */ 47, 0, 81, 164, 163, 161, 280, 159, 0, 0,
- /* 1340 */ 155, 285, 154, 287, 0, 0, 44, 0, 141, 0,
- /* 1350 */ 312, 136, 245, 315, 316, 317, 318, 319, 320, 321,
- /* 1360 */ 322, 323, 324, 0, 0, 0, 0, 0, 312, 47,
- /* 1370 */ 19, 315, 316, 317, 318, 319, 320, 136, 322, 272,
- /* 1380 */ 0, 0, 0, 0, 33, 0, 0, 280, 0, 0,
- /* 1390 */ 0, 0, 285, 252, 287, 0, 45, 0, 0, 0,
- /* 1400 */ 40, 0, 51, 52, 53, 54, 55, 0, 0, 0,
- /* 1410 */ 0, 0, 0, 245, 22, 0, 360, 361, 0, 312,
- /* 1420 */ 0, 280, 315, 316, 317, 318, 319, 320, 0, 322,
- /* 1430 */ 0, 80, 325, 40, 83, 41, 14, 330, 14, 37,
- /* 1440 */ 272, 300, 0, 38, 44, 0, 0, 44, 280, 0,
- /* 1450 */ 37, 37, 0, 285, 150, 287, 0, 0, 37, 0,
- /* 1460 */ 319, 0, 37, 59, 45, 0, 245, 116, 37, 0,
- /* 1470 */ 47, 0, 45, 47, 45, 334, 335, 336, 37, 338,
- /* 1480 */ 312, 47, 341, 315, 316, 317, 318, 319, 320, 245,
- /* 1490 */ 322, 47, 45, 272, 0, 144, 355, 37, 147, 0,
- /* 1500 */ 359, 280, 0, 0, 88, 47, 285, 252, 287, 22,
- /* 1510 */ 0, 47, 0, 47, 47, 47, 272, 166, 41, 168,
- /* 1520 */ 41, 47, 354, 90, 280, 47, 22, 47, 0, 285,
- /* 1530 */ 22, 287, 48, 312, 0, 280, 315, 316, 317, 318,
- /* 1540 */ 319, 320, 298, 322, 22, 245, 0, 47, 22, 0,
- /* 1550 */ 20, 22, 0, 47, 148, 300, 312, 0, 22, 315,
- /* 1560 */ 316, 317, 318, 319, 320, 0, 322, 0, 0, 0,
- /* 1570 */ 81, 215, 272, 41, 319, 37, 41, 82, 81, 81,
- /* 1580 */ 280, 145, 361, 148, 41, 285, 143, 287, 148, 334,
- /* 1590 */ 335, 336, 81, 338, 41, 82, 341, 165, 245, 82,
- /* 1600 */ 81, 81, 44, 82, 44, 81, 44, 245, 44, 82,
- /* 1610 */ 355, 41, 312, 82, 359, 315, 316, 317, 318, 319,
- /* 1620 */ 320, 245, 322, 41, 324, 272, 82, 41, 47, 82,
- /* 1630 */ 2, 47, 47, 280, 272, 47, 47, 47, 285, 41,
- /* 1640 */ 287, 82, 280, 82, 81, 183, 44, 285, 272, 287,
- /* 1650 */ 44, 298, 215, 81, 215, 81, 280, 209, 22, 81,
- /* 1660 */ 298, 285, 245, 287, 0, 312, 185, 37, 315, 316,
- /* 1670 */ 317, 318, 319, 320, 312, 322, 82, 315, 316, 317,
- /* 1680 */ 318, 319, 320, 245, 322, 82, 81, 146, 312, 272,
- /* 1690 */ 81, 315, 316, 317, 318, 319, 320, 280, 322, 81,
- /* 1700 */ 81, 91, 285, 44, 287, 44, 81, 22, 82, 143,
- /* 1710 */ 272, 82, 81, 81, 92, 47, 47, 82, 280, 81,
- /* 1720 */ 47, 81, 47, 285, 82, 287, 81, 47, 82, 312,
- /* 1730 */ 81, 47, 315, 316, 317, 318, 319, 320, 82, 322,
- /* 1740 */ 22, 245, 105, 93, 81, 47, 105, 81, 105, 105,
- /* 1750 */ 312, 81, 245, 315, 316, 317, 318, 319, 320, 81,
- /* 1760 */ 322, 41, 22, 245, 59, 58, 47, 79, 272, 41,
- /* 1770 */ 64, 22, 47, 47, 47, 64, 280, 47, 47, 272,
- /* 1780 */ 47, 285, 47, 287, 47, 47, 47, 280, 47, 47,
- /* 1790 */ 272, 47, 285, 47, 287, 0, 45, 47, 280, 37,
- /* 1800 */ 0, 47, 45, 285, 37, 287, 0, 47, 312, 45,
- /* 1810 */ 37, 315, 316, 317, 318, 319, 320, 0, 322, 312,
- /* 1820 */ 45, 47, 315, 316, 317, 318, 319, 320, 245, 322,
- /* 1830 */ 312, 37, 0, 315, 316, 317, 318, 319, 320, 47,
- /* 1840 */ 322, 0, 22, 21, 245, 22, 22, 21, 20, 364,
- /* 1850 */ 364, 364, 364, 364, 364, 272, 364, 364, 364, 364,
- /* 1860 */ 364, 364, 364, 280, 364, 364, 364, 364, 285, 364,
- /* 1870 */ 287, 272, 364, 364, 364, 364, 364, 364, 364, 280,
- /* 1880 */ 364, 364, 364, 364, 285, 364, 287, 364, 364, 364,
- /* 1890 */ 364, 364, 364, 245, 364, 312, 364, 364, 315, 316,
- /* 1900 */ 317, 318, 319, 320, 364, 322, 364, 245, 364, 364,
- /* 1910 */ 364, 312, 364, 364, 315, 316, 317, 318, 319, 320,
- /* 1920 */ 272, 322, 364, 364, 364, 364, 364, 364, 280, 364,
- /* 1930 */ 364, 364, 364, 285, 272, 287, 364, 364, 364, 364,
- /* 1940 */ 364, 364, 280, 364, 364, 364, 364, 285, 245, 287,
- /* 1950 */ 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
- /* 1960 */ 312, 364, 364, 315, 316, 317, 318, 319, 320, 245,
- /* 1970 */ 322, 364, 364, 364, 312, 272, 364, 315, 316, 317,
- /* 1980 */ 318, 319, 320, 280, 322, 364, 364, 364, 285, 364,
- /* 1990 */ 287, 364, 364, 364, 364, 364, 272, 364, 364, 364,
- /* 2000 */ 364, 364, 364, 364, 280, 364, 364, 364, 364, 285,
- /* 2010 */ 364, 287, 364, 364, 364, 312, 364, 364, 315, 316,
- /* 2020 */ 317, 318, 319, 320, 364, 322, 364, 245, 364, 364,
- /* 2030 */ 364, 364, 364, 364, 364, 364, 312, 364, 245, 315,
- /* 2040 */ 316, 317, 318, 319, 320, 364, 322, 364, 364, 245,
- /* 2050 */ 364, 364, 364, 364, 272, 364, 364, 364, 364, 364,
- /* 2060 */ 364, 364, 280, 364, 364, 272, 364, 285, 364, 287,
- /* 2070 */ 364, 364, 364, 280, 364, 364, 272, 364, 285, 364,
- /* 2080 */ 287, 364, 364, 364, 280, 364, 364, 364, 364, 285,
- /* 2090 */ 245, 287, 364, 364, 312, 364, 364, 315, 316, 317,
- /* 2100 */ 318, 319, 320, 364, 322, 312, 364, 364, 315, 316,
- /* 2110 */ 317, 318, 319, 320, 245, 322, 312, 272, 364, 315,
- /* 2120 */ 316, 317, 318, 319, 320, 280, 322, 364, 364, 364,
- /* 2130 */ 285, 364, 287, 364, 364, 364, 364, 364, 364, 364,
- /* 2140 */ 364, 272, 364, 364, 364, 364, 364, 364, 364, 280,
- /* 2150 */ 364, 364, 364, 364, 285, 364, 287, 312, 364, 364,
- /* 2160 */ 315, 316, 317, 318, 319, 320, 364, 322, 364, 364,
- /* 2170 */ 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
- /* 2180 */ 364, 312, 364, 364, 315, 316, 317, 318, 319, 320,
- /* 2190 */ 364, 322,
+ /* 0 */ 267, 271, 256, 263, 267, 265, 266, 279, 302, 271,
+ /* 10 */ 287, 278, 12, 13, 284, 287, 310, 294, 285, 313,
+ /* 20 */ 20, 0, 22, 293, 296, 272, 303, 267, 295, 276,
+ /* 30 */ 287, 293, 295, 33, 263, 35, 265, 266, 295, 20,
+ /* 40 */ 298, 267, 21, 301, 302, 24, 25, 26, 27, 28,
+ /* 50 */ 29, 30, 31, 32, 269, 295, 56, 259, 259, 8,
+ /* 60 */ 9, 61, 316, 12, 13, 14, 15, 16, 68, 12,
+ /* 70 */ 13, 14, 335, 20, 20, 290, 333, 20, 304, 22,
+ /* 80 */ 357, 20, 258, 357, 260, 85, 287, 350, 351, 352,
+ /* 90 */ 33, 354, 35, 370, 295, 335, 370, 374, 300, 300,
+ /* 100 */ 374, 302, 264, 357, 4, 267, 20, 107, 267, 349,
+ /* 110 */ 350, 351, 352, 56, 354, 316, 370, 20, 61, 278,
+ /* 120 */ 374, 121, 122, 342, 343, 68, 327, 43, 286, 116,
+ /* 130 */ 331, 332, 333, 334, 335, 336, 295, 338, 85, 85,
+ /* 140 */ 341, 299, 85, 21, 345, 346, 24, 25, 26, 27,
+ /* 150 */ 28, 29, 30, 31, 32, 279, 357, 12, 13, 14,
+ /* 160 */ 15, 16, 35, 287, 107, 85, 166, 33, 168, 370,
+ /* 170 */ 86, 85, 296, 374, 316, 316, 316, 264, 121, 122,
+ /* 180 */ 267, 47, 121, 122, 4, 85, 52, 53, 54, 55,
+ /* 190 */ 56, 178, 179, 193, 194, 68, 196, 197, 198, 199,
+ /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ /* 210 */ 210, 211, 212, 213, 357, 357, 357, 357, 84, 301,
+ /* 220 */ 302, 87, 20, 166, 22, 168, 226, 370, 370, 370,
+ /* 230 */ 370, 374, 374, 374, 374, 8, 9, 316, 85, 12,
+ /* 240 */ 13, 14, 15, 16, 259, 165, 56, 167, 267, 43,
+ /* 250 */ 193, 194, 50, 196, 197, 198, 199, 200, 201, 202,
+ /* 260 */ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+ /* 270 */ 213, 12, 13, 0, 84, 20, 295, 87, 357, 20,
+ /* 280 */ 226, 22, 259, 149, 150, 300, 152, 0, 61, 85,
+ /* 290 */ 156, 370, 33, 60, 35, 374, 267, 24, 25, 26,
+ /* 300 */ 27, 28, 29, 30, 31, 32, 226, 278, 20, 175,
+ /* 310 */ 287, 259, 226, 86, 285, 56, 335, 357, 295, 316,
+ /* 320 */ 61, 94, 259, 300, 295, 302, 226, 68, 12, 13,
+ /* 330 */ 370, 350, 351, 352, 374, 354, 20, 267, 22, 0,
+ /* 340 */ 37, 273, 274, 193, 85, 97, 287, 60, 278, 33,
+ /* 350 */ 327, 35, 300, 294, 331, 332, 333, 334, 335, 336,
+ /* 360 */ 357, 338, 303, 300, 341, 295, 107, 119, 345, 346,
+ /* 370 */ 347, 0, 56, 370, 20, 148, 287, 374, 20, 226,
+ /* 380 */ 121, 122, 359, 294, 68, 235, 236, 237, 238, 239,
+ /* 390 */ 367, 88, 303, 90, 91, 312, 93, 314, 171, 0,
+ /* 400 */ 97, 85, 63, 64, 65, 66, 67, 227, 69, 70,
+ /* 410 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 420 */ 81, 82, 119, 107, 20, 166, 22, 168, 8, 9,
+ /* 430 */ 226, 60, 12, 13, 14, 15, 16, 121, 122, 35,
+ /* 440 */ 4, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+ /* 450 */ 223, 245, 193, 194, 50, 196, 197, 198, 199, 200,
+ /* 460 */ 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
+ /* 470 */ 211, 212, 213, 0, 56, 116, 117, 63, 64, 65,
+ /* 480 */ 44, 45, 166, 69, 168, 197, 72, 73, 273, 274,
+ /* 490 */ 76, 77, 78, 8, 9, 0, 289, 12, 13, 14,
+ /* 500 */ 15, 16, 117, 85, 60, 87, 259, 300, 79, 193,
+ /* 510 */ 194, 153, 196, 197, 198, 199, 200, 201, 202, 203,
+ /* 520 */ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ /* 530 */ 12, 13, 14, 326, 327, 328, 177, 14, 20, 180,
+ /* 540 */ 22, 259, 226, 20, 56, 338, 61, 300, 312, 279,
+ /* 550 */ 314, 33, 267, 35, 125, 126, 0, 287, 63, 64,
+ /* 560 */ 65, 176, 177, 278, 69, 180, 296, 72, 73, 287,
+ /* 570 */ 97, 76, 77, 78, 56, 87, 148, 295, 158, 94,
+ /* 580 */ 295, 151, 300, 4, 302, 287, 68, 12, 13, 116,
+ /* 590 */ 117, 118, 119, 120, 267, 20, 267, 22, 19, 171,
+ /* 600 */ 295, 303, 43, 85, 48, 278, 21, 278, 33, 327,
+ /* 610 */ 35, 306, 33, 331, 332, 333, 334, 335, 336, 34,
+ /* 620 */ 338, 36, 295, 341, 295, 107, 47, 345, 346, 347,
+ /* 630 */ 51, 56, 161, 148, 289, 56, 267, 267, 20, 121,
+ /* 640 */ 122, 289, 214, 68, 226, 300, 269, 278, 278, 367,
+ /* 650 */ 288, 14, 300, 259, 183, 184, 171, 20, 68, 282,
+ /* 660 */ 85, 231, 232, 84, 295, 295, 87, 290, 248, 8,
+ /* 670 */ 9, 326, 327, 12, 13, 14, 15, 16, 326, 327,
+ /* 680 */ 328, 302, 107, 338, 166, 14, 168, 14, 15, 16,
+ /* 690 */ 338, 20, 313, 259, 300, 96, 121, 122, 0, 214,
+ /* 700 */ 215, 216, 217, 218, 219, 220, 221, 222, 223, 1,
+ /* 710 */ 2, 193, 194, 3, 196, 197, 198, 199, 200, 201,
+ /* 720 */ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ /* 730 */ 212, 213, 8, 9, 300, 329, 12, 13, 14, 15,
+ /* 740 */ 16, 166, 297, 168, 275, 300, 277, 86, 98, 99,
+ /* 750 */ 100, 101, 102, 103, 104, 105, 106, 107, 108, 353,
+ /* 760 */ 110, 111, 112, 113, 114, 115, 259, 43, 193, 194,
+ /* 770 */ 259, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ /* 780 */ 205, 206, 207, 208, 209, 210, 211, 212, 213, 12,
+ /* 790 */ 13, 18, 35, 20, 86, 97, 287, 20, 267, 22,
+ /* 800 */ 27, 259, 267, 30, 68, 296, 247, 300, 267, 278,
+ /* 810 */ 33, 300, 35, 278, 116, 117, 118, 119, 120, 278,
+ /* 820 */ 47, 267, 49, 0, 51, 68, 295, 267, 267, 287,
+ /* 830 */ 295, 20, 278, 56, 197, 39, 295, 295, 278, 278,
+ /* 840 */ 259, 259, 300, 43, 302, 68, 8, 9, 85, 295,
+ /* 850 */ 12, 13, 14, 15, 16, 295, 295, 84, 95, 8,
+ /* 860 */ 9, 267, 85, 12, 13, 14, 15, 16, 197, 327,
+ /* 870 */ 47, 97, 278, 331, 332, 333, 334, 335, 336, 288,
+ /* 880 */ 338, 300, 300, 341, 107, 259, 86, 345, 346, 295,
+ /* 890 */ 116, 117, 118, 119, 120, 42, 43, 124, 121, 122,
+ /* 900 */ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ /* 910 */ 137, 138, 139, 140, 141, 142, 143, 144, 329, 146,
+ /* 920 */ 147, 288, 259, 2, 86, 329, 300, 18, 288, 8,
+ /* 930 */ 9, 259, 23, 12, 13, 14, 15, 16, 44, 45,
+ /* 940 */ 35, 267, 353, 166, 288, 168, 37, 38, 2, 353,
+ /* 950 */ 41, 320, 278, 243, 8, 9, 259, 43, 12, 13,
+ /* 960 */ 14, 15, 16, 300, 153, 259, 57, 58, 59, 295,
+ /* 970 */ 193, 194, 300, 196, 197, 198, 199, 200, 201, 202,
+ /* 980 */ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+ /* 990 */ 213, 19, 267, 287, 85, 280, 297, 300, 283, 300,
+ /* 1000 */ 86, 295, 288, 278, 153, 33, 300, 259, 302, 259,
+ /* 1010 */ 8, 9, 259, 259, 12, 13, 14, 15, 16, 47,
+ /* 1020 */ 295, 225, 316, 0, 52, 53, 54, 55, 56, 35,
+ /* 1030 */ 224, 225, 123, 327, 153, 154, 46, 331, 332, 333,
+ /* 1040 */ 334, 335, 336, 43, 338, 22, 259, 341, 300, 0,
+ /* 1050 */ 300, 345, 346, 300, 300, 89, 84, 0, 92, 87,
+ /* 1060 */ 12, 13, 89, 357, 43, 92, 61, 158, 159, 160,
+ /* 1070 */ 22, 22, 163, 168, 287, 85, 370, 288, 169, 22,
+ /* 1080 */ 374, 33, 295, 35, 43, 260, 86, 300, 86, 302,
+ /* 1090 */ 276, 182, 120, 377, 185, 43, 187, 188, 189, 190,
+ /* 1100 */ 191, 192, 289, 89, 56, 89, 92, 86, 92, 43,
+ /* 1110 */ 43, 43, 368, 300, 327, 43, 68, 43, 331, 332,
+ /* 1120 */ 333, 334, 335, 336, 152, 338, 43, 86, 341, 1,
+ /* 1130 */ 2, 268, 345, 346, 347, 226, 259, 287, 86, 326,
+ /* 1140 */ 327, 121, 122, 356, 43, 173, 43, 175, 43, 323,
+ /* 1150 */ 43, 338, 86, 86, 86, 107, 364, 268, 86, 266,
+ /* 1160 */ 86, 299, 168, 330, 287, 355, 348, 358, 371, 86,
+ /* 1170 */ 371, 228, 295, 371, 325, 20, 47, 300, 267, 302,
+ /* 1180 */ 324, 35, 164, 273, 318, 267, 267, 86, 148, 86,
+ /* 1190 */ 42, 86, 259, 86, 307, 305, 305, 267, 193, 267,
+ /* 1200 */ 261, 267, 20, 261, 327, 20, 322, 271, 331, 332,
+ /* 1210 */ 333, 334, 335, 336, 166, 338, 168, 302, 341, 271,
+ /* 1220 */ 287, 20, 345, 346, 20, 317, 271, 315, 295, 271,
+ /* 1230 */ 20, 315, 308, 300, 259, 302, 271, 267, 271, 271,
+ /* 1240 */ 261, 193, 194, 287, 287, 267, 287, 287, 287, 287,
+ /* 1250 */ 287, 287, 261, 205, 206, 207, 208, 209, 210, 211,
+ /* 1260 */ 327, 287, 287, 287, 331, 332, 333, 334, 335, 336,
+ /* 1270 */ 295, 338, 287, 322, 341, 300, 269, 302, 345, 346,
+ /* 1280 */ 347, 300, 174, 233, 302, 150, 269, 259, 269, 356,
+ /* 1290 */ 321, 267, 267, 300, 311, 315, 300, 259, 300, 300,
+ /* 1300 */ 311, 300, 327, 295, 309, 308, 331, 332, 333, 334,
+ /* 1310 */ 335, 336, 269, 338, 283, 287, 341, 295, 20, 234,
+ /* 1320 */ 345, 346, 347, 295, 269, 287, 300, 300, 300, 300,
+ /* 1330 */ 302, 356, 22, 295, 330, 300, 300, 240, 300, 229,
+ /* 1340 */ 302, 311, 365, 311, 157, 35, 242, 259, 225, 363,
+ /* 1350 */ 363, 363, 241, 295, 316, 327, 20, 259, 366, 331,
+ /* 1360 */ 332, 333, 334, 335, 336, 327, 338, 325, 362, 331,
+ /* 1370 */ 332, 333, 334, 335, 336, 287, 338, 246, 68, 249,
+ /* 1380 */ 329, 244, 373, 295, 372, 287, 373, 372, 300, 378,
+ /* 1390 */ 302, 85, 85, 295, 361, 357, 300, 360, 300, 277,
+ /* 1400 */ 302, 267, 269, 344, 316, 291, 36, 373, 370, 262,
+ /* 1410 */ 261, 372, 374, 319, 314, 327, 257, 107, 0, 331,
+ /* 1420 */ 332, 333, 334, 335, 336, 327, 338, 270, 0, 331,
+ /* 1430 */ 332, 333, 334, 335, 336, 337, 338, 339, 340, 259,
+ /* 1440 */ 267, 281, 281, 281, 176, 357, 0, 0, 42, 0,
+ /* 1450 */ 76, 0, 35, 186, 35, 35, 35, 186, 370, 0,
+ /* 1460 */ 35, 35, 374, 186, 0, 186, 0, 287, 295, 0,
+ /* 1470 */ 35, 0, 22, 35, 0, 295, 166, 85, 168, 171,
+ /* 1480 */ 300, 170, 302, 168, 166, 0, 0, 162, 161, 316,
+ /* 1490 */ 0, 0, 0, 259, 46, 0, 0, 145, 0, 0,
+ /* 1500 */ 0, 0, 0, 193, 194, 140, 0, 327, 335, 140,
+ /* 1510 */ 35, 331, 332, 333, 334, 335, 336, 259, 338, 0,
+ /* 1520 */ 0, 287, 42, 350, 351, 352, 0, 354, 0, 295,
+ /* 1530 */ 357, 0, 0, 0, 300, 0, 302, 0, 0, 0,
+ /* 1540 */ 0, 0, 0, 370, 0, 287, 0, 374, 0, 0,
+ /* 1550 */ 292, 0, 0, 295, 39, 375, 376, 0, 300, 0,
+ /* 1560 */ 302, 327, 0, 0, 0, 331, 332, 333, 334, 335,
+ /* 1570 */ 336, 259, 338, 56, 0, 341, 22, 56, 0, 0,
+ /* 1580 */ 346, 259, 14, 14, 0, 327, 43, 42, 0, 331,
+ /* 1590 */ 332, 333, 334, 335, 336, 0, 338, 0, 40, 287,
+ /* 1600 */ 39, 46, 46, 0, 292, 39, 0, 295, 0, 287,
+ /* 1610 */ 157, 0, 300, 0, 302, 62, 35, 295, 47, 39,
+ /* 1620 */ 0, 35, 300, 47, 302, 0, 39, 0, 35, 39,
+ /* 1630 */ 47, 259, 47, 35, 0, 39, 0, 0, 0, 327,
+ /* 1640 */ 35, 94, 92, 331, 332, 333, 334, 335, 336, 327,
+ /* 1650 */ 338, 22, 0, 331, 332, 333, 334, 335, 336, 287,
+ /* 1660 */ 338, 35, 43, 35, 43, 35, 35, 295, 35, 0,
+ /* 1670 */ 35, 22, 300, 22, 302, 35, 35, 0, 0, 22,
+ /* 1680 */ 35, 259, 0, 35, 0, 35, 0, 22, 49, 0,
+ /* 1690 */ 20, 369, 85, 259, 35, 0, 172, 22, 0, 327,
+ /* 1700 */ 0, 0, 0, 331, 332, 333, 334, 335, 336, 287,
+ /* 1710 */ 338, 0, 0, 153, 0, 181, 149, 295, 153, 39,
+ /* 1720 */ 150, 287, 300, 230, 302, 46, 292, 85, 153, 295,
+ /* 1730 */ 86, 85, 155, 43, 300, 230, 302, 43, 85, 85,
+ /* 1740 */ 151, 86, 95, 85, 230, 46, 86, 86, 376, 327,
+ /* 1750 */ 86, 85, 85, 331, 332, 333, 334, 335, 336, 85,
+ /* 1760 */ 338, 327, 340, 43, 46, 331, 332, 333, 334, 335,
+ /* 1770 */ 336, 259, 338, 85, 43, 46, 43, 86, 85, 43,
+ /* 1780 */ 46, 259, 86, 86, 46, 35, 35, 35, 35, 86,
+ /* 1790 */ 86, 35, 35, 2, 22, 193, 86, 224, 43, 287,
+ /* 1800 */ 85, 85, 22, 86, 292, 86, 85, 295, 46, 287,
+ /* 1810 */ 85, 85, 300, 46, 302, 85, 35, 295, 195, 96,
+ /* 1820 */ 35, 86, 300, 86, 302, 85, 85, 35, 86, 35,
+ /* 1830 */ 85, 259, 86, 35, 85, 35, 109, 109, 22, 327,
+ /* 1840 */ 97, 259, 35, 331, 332, 333, 334, 335, 336, 327,
+ /* 1850 */ 338, 259, 86, 331, 332, 333, 334, 335, 336, 287,
+ /* 1860 */ 338, 85, 85, 85, 85, 43, 22, 295, 109, 287,
+ /* 1870 */ 109, 62, 300, 61, 302, 43, 35, 295, 68, 287,
+ /* 1880 */ 83, 35, 300, 35, 302, 35, 35, 295, 35, 22,
+ /* 1890 */ 35, 35, 300, 68, 302, 35, 35, 35, 35, 327,
+ /* 1900 */ 35, 35, 0, 331, 332, 333, 334, 335, 336, 327,
+ /* 1910 */ 338, 35, 35, 331, 332, 333, 334, 335, 336, 327,
+ /* 1920 */ 338, 35, 47, 331, 332, 333, 334, 335, 336, 39,
+ /* 1930 */ 338, 0, 259, 35, 47, 39, 0, 0, 35, 47,
+ /* 1940 */ 39, 35, 47, 39, 0, 35, 35, 0, 22, 21,
+ /* 1950 */ 21, 259, 22, 20, 22, 379, 379, 379, 379, 379,
+ /* 1960 */ 287, 379, 379, 379, 379, 379, 379, 379, 295, 379,
+ /* 1970 */ 379, 379, 379, 300, 379, 302, 379, 379, 379, 287,
+ /* 1980 */ 379, 379, 379, 379, 379, 379, 379, 295, 379, 379,
+ /* 1990 */ 379, 379, 300, 379, 302, 379, 379, 379, 379, 379,
+ /* 2000 */ 327, 379, 379, 379, 331, 332, 333, 334, 335, 336,
+ /* 2010 */ 379, 338, 379, 259, 379, 379, 379, 379, 379, 327,
+ /* 2020 */ 379, 379, 379, 331, 332, 333, 334, 335, 336, 259,
+ /* 2030 */ 338, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2040 */ 379, 287, 379, 379, 379, 379, 379, 379, 379, 295,
+ /* 2050 */ 379, 379, 379, 379, 300, 379, 302, 287, 379, 379,
+ /* 2060 */ 379, 379, 379, 379, 379, 295, 379, 379, 379, 379,
+ /* 2070 */ 300, 379, 302, 379, 379, 379, 379, 379, 379, 379,
+ /* 2080 */ 379, 327, 259, 379, 379, 331, 332, 333, 334, 335,
+ /* 2090 */ 336, 379, 338, 379, 379, 379, 379, 327, 379, 259,
+ /* 2100 */ 379, 331, 332, 333, 334, 335, 336, 379, 338, 379,
+ /* 2110 */ 287, 379, 379, 379, 379, 379, 379, 379, 295, 379,
+ /* 2120 */ 379, 379, 379, 300, 379, 302, 379, 287, 379, 379,
+ /* 2130 */ 379, 379, 379, 379, 379, 295, 379, 379, 379, 379,
+ /* 2140 */ 300, 379, 302, 379, 379, 379, 379, 379, 379, 379,
+ /* 2150 */ 327, 379, 259, 379, 331, 332, 333, 334, 335, 336,
+ /* 2160 */ 379, 338, 379, 379, 259, 379, 379, 327, 379, 379,
+ /* 2170 */ 379, 331, 332, 333, 334, 335, 336, 379, 338, 379,
+ /* 2180 */ 287, 379, 379, 379, 379, 379, 379, 379, 295, 379,
+ /* 2190 */ 379, 379, 287, 300, 379, 302, 379, 379, 379, 379,
+ /* 2200 */ 295, 379, 379, 379, 379, 300, 379, 302, 379, 379,
+ /* 2210 */ 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2220 */ 327, 379, 379, 379, 331, 332, 333, 334, 335, 336,
+ /* 2230 */ 379, 338, 327, 259, 379, 379, 331, 332, 333, 334,
+ /* 2240 */ 335, 336, 379, 338, 379, 379, 379, 259, 379, 379,
+ /* 2250 */ 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2260 */ 379, 287, 379, 379, 379, 379, 379, 379, 379, 295,
+ /* 2270 */ 379, 379, 379, 379, 300, 287, 302, 379, 379, 379,
+ /* 2280 */ 379, 379, 379, 295, 379, 379, 379, 379, 300, 259,
+ /* 2290 */ 302, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2300 */ 379, 327, 379, 379, 379, 331, 332, 333, 334, 335,
+ /* 2310 */ 336, 379, 338, 379, 379, 327, 379, 287, 379, 331,
+ /* 2320 */ 332, 333, 334, 335, 336, 295, 338, 379, 379, 379,
+ /* 2330 */ 300, 379, 302, 379, 379, 379, 379, 379, 379, 379,
+ /* 2340 */ 379, 259, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2350 */ 379, 379, 379, 379, 379, 379, 379, 327, 379, 259,
+ /* 2360 */ 379, 331, 332, 333, 334, 335, 336, 379, 338, 287,
+ /* 2370 */ 379, 379, 379, 379, 379, 379, 379, 295, 379, 379,
+ /* 2380 */ 379, 379, 300, 259, 302, 379, 379, 287, 379, 379,
+ /* 2390 */ 379, 379, 379, 379, 379, 295, 379, 379, 379, 379,
+ /* 2400 */ 300, 379, 302, 379, 379, 379, 379, 379, 379, 327,
+ /* 2410 */ 379, 287, 379, 331, 332, 333, 334, 335, 336, 295,
+ /* 2420 */ 338, 379, 379, 379, 300, 379, 302, 327, 379, 379,
+ /* 2430 */ 379, 331, 332, 333, 334, 335, 336, 379, 338, 267,
+ /* 2440 */ 259, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2450 */ 379, 327, 379, 379, 379, 331, 332, 333, 334, 335,
+ /* 2460 */ 336, 379, 338, 379, 379, 379, 379, 295, 287, 379,
+ /* 2470 */ 379, 379, 379, 379, 379, 379, 295, 379, 379, 379,
+ /* 2480 */ 379, 300, 379, 302, 379, 379, 379, 379, 316, 379,
+ /* 2490 */ 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2500 */ 379, 379, 379, 379, 379, 379, 379, 335, 327, 379,
+ /* 2510 */ 379, 379, 331, 332, 333, 334, 335, 336, 379, 338,
+ /* 2520 */ 379, 379, 350, 351, 352, 379, 354, 379, 379, 357,
+ /* 2530 */ 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
+ /* 2540 */ 379, 379, 370, 379, 379, 379, 374,
};
-#define YY_SHIFT_COUNT (640)
+#define YY_SHIFT_COUNT (668)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1841)
+#define YY_SHIFT_MAX (1947)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 742, 0, 0, 48, 208, 208, 208, 208, 256, 256,
- /* 10 */ 208, 208, 416, 464, 624, 464, 464, 464, 464, 464,
- /* 20 */ 464, 464, 464, 464, 464, 464, 464, 464, 464, 464,
- /* 30 */ 464, 464, 464, 464, 464, 464, 464, 464, 464, 464,
- /* 40 */ 66, 66, 104, 104, 104, 18, 18, 18, 18, 12,
- /* 50 */ 79, 207, 36, 36, 115, 115, 202, 153, 207, 207,
- /* 60 */ 36, 36, 36, 36, 36, 36, 36, 36, 73, 36,
- /* 70 */ 36, 180, 190, 312, 180, 36, 36, 180, 36, 180,
- /* 80 */ 180, 180, 36, 409, 706, 478, 838, 838, 395, 189,
- /* 90 */ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- /* 100 */ 835, 835, 835, 835, 835, 835, 835, 835, 835, 198,
- /* 110 */ 153, 4, 4, 281, 801, 479, 479, 479, 327, 801,
- /* 120 */ 454, 312, 180, 180, 425, 425, 530, 726, 246, 246,
- /* 130 */ 246, 246, 246, 246, 246, 1351, 351, 803, 350, 187,
- /* 140 */ 449, 401, 423, 512, 558, 392, 531, 638, 732, 664,
- /* 150 */ 697, 664, 165, 165, 165, 719, 705, 861, 1058, 1035,
- /* 160 */ 1036, 925, 1058, 1058, 1047, 963, 963, 1058, 1097, 1097,
- /* 170 */ 1101, 73, 312, 73, 1105, 1108, 73, 1105, 73, 454,
- /* 180 */ 1123, 73, 73, 1058, 73, 1097, 180, 180, 180, 180,
- /* 190 */ 180, 180, 180, 180, 180, 180, 180, 1058, 1097, 425,
- /* 200 */ 425, 1101, 409, 991, 312, 409, 1058, 1105, 409, 454,
- /* 210 */ 1123, 409, 1159, 425, 965, 967, 425, 965, 967, 425,
- /* 220 */ 425, 180, 961, 1042, 965, 971, 974, 994, 861, 995,
- /* 230 */ 454, 1202, 1183, 996, 997, 998, 996, 997, 996, 997,
- /* 240 */ 1144, 967, 425, 425, 967, 425, 1096, 454, 1123, 409,
- /* 250 */ 530, 409, 454, 1170, 425, 726, 1058, 409, 1097, 2192,
- /* 260 */ 2192, 2192, 2192, 2192, 2192, 2192, 481, 657, 561, 119,
- /* 270 */ 601, 891, 63, 13, 303, 203, 582, 374, 443, 552,
- /* 280 */ 550, 550, 550, 550, 550, 550, 550, 550, 132, 382,
- /* 290 */ 152, 529, 430, 137, 616, 616, 616, 616, 259, 837,
- /* 300 */ 800, 818, 823, 824, 879, 913, 914, 906, 896, 908,
- /* 310 */ 910, 946, 851, 720, 739, 932, 886, 938, 685, 945,
- /* 320 */ 954, 969, 993, 1006, 850, 887, 1019, 1020, 1029, 1030,
- /* 330 */ 1031, 1032, 277, 892, 966, 1272, 1286, 1249, 1298, 1230,
- /* 340 */ 1303, 1259, 1130, 1261, 1262, 1264, 1135, 1314, 1268, 1269,
- /* 350 */ 1142, 1320, 1145, 1321, 1277, 1326, 1305, 1329, 1283, 1331,
- /* 360 */ 1251, 1169, 1171, 1174, 1178, 1338, 1339, 1185, 1188, 1344,
- /* 370 */ 1345, 1302, 1347, 1207, 1349, 1363, 1364, 1365, 1366, 1215,
- /* 380 */ 1322, 1367, 1241, 1380, 1381, 1382, 1383, 1385, 1386, 1388,
- /* 390 */ 1389, 1390, 1391, 1395, 1397, 1398, 1399, 1360, 1401, 1407,
- /* 400 */ 1408, 1409, 1410, 1411, 1392, 1412, 1415, 1418, 1420, 1428,
- /* 410 */ 1430, 1393, 1402, 1394, 1422, 1400, 1424, 1403, 1442, 1405,
- /* 420 */ 1413, 1445, 1446, 1449, 1414, 1304, 1452, 1456, 1421, 1457,
- /* 430 */ 1404, 1459, 1461, 1423, 1419, 1425, 1465, 1426, 1427, 1431,
- /* 440 */ 1469, 1434, 1429, 1441, 1471, 1444, 1447, 1460, 1494, 1499,
- /* 450 */ 1502, 1503, 1433, 1416, 1458, 1487, 1510, 1464, 1466, 1467,
- /* 460 */ 1468, 1477, 1479, 1474, 1478, 1480, 1512, 1504, 1528, 1508,
- /* 470 */ 1484, 1534, 1522, 1500, 1546, 1526, 1549, 1529, 1530, 1552,
- /* 480 */ 1406, 1506, 1557, 1432, 1536, 1435, 1436, 1565, 1567, 1568,
- /* 490 */ 1440, 1569, 1489, 1538, 1443, 1532, 1535, 1356, 1497, 1495,
- /* 500 */ 1498, 1513, 1543, 1517, 1511, 1519, 1520, 1521, 1553, 1558,
- /* 510 */ 1560, 1524, 1570, 1437, 1527, 1531, 1562, 1448, 1582, 1564,
- /* 520 */ 1544, 1586, 1439, 1547, 1581, 1584, 1585, 1588, 1589, 1590,
- /* 530 */ 1547, 1628, 1462, 1598, 1559, 1563, 1561, 1602, 1572, 1574,
- /* 540 */ 1606, 1636, 1481, 1578, 1594, 1603, 1605, 1609, 1541, 1618,
- /* 550 */ 1664, 1630, 1566, 1619, 1610, 1659, 1661, 1625, 1626, 1631,
- /* 560 */ 1685, 1632, 1622, 1629, 1668, 1669, 1638, 1635, 1673, 1640,
- /* 570 */ 1642, 1675, 1645, 1646, 1680, 1649, 1656, 1684, 1663, 1637,
- /* 580 */ 1641, 1643, 1644, 1718, 1650, 1666, 1670, 1698, 1678, 1720,
- /* 590 */ 1720, 1740, 1705, 1707, 1719, 1706, 1688, 1728, 1725, 1726,
- /* 600 */ 1727, 1730, 1731, 1749, 1733, 1735, 1711, 1477, 1737, 1479,
- /* 610 */ 1738, 1739, 1741, 1742, 1744, 1746, 1795, 1750, 1751, 1762,
- /* 620 */ 1800, 1754, 1757, 1767, 1806, 1760, 1764, 1773, 1817, 1774,
- /* 630 */ 1775, 1794, 1832, 1792, 1841, 1820, 1822, 1823, 1824, 1826,
- /* 640 */ 1828,
+ /* 0 */ 909, 0, 0, 57, 57, 259, 259, 259, 316, 316,
+ /* 10 */ 259, 259, 518, 575, 777, 575, 575, 575, 575, 575,
+ /* 20 */ 575, 575, 575, 575, 575, 575, 575, 575, 575, 575,
+ /* 30 */ 575, 575, 575, 575, 575, 575, 575, 575, 575, 575,
+ /* 40 */ 575, 575, 54, 54, 53, 53, 53, 1048, 1048, 86,
+ /* 50 */ 1048, 1048, 80, 418, 153, 204, 153, 19, 19, 436,
+ /* 60 */ 436, 100, 61, 153, 153, 19, 19, 19, 19, 19,
+ /* 70 */ 19, 19, 19, 19, 233, 19, 19, 19, 97, 255,
+ /* 80 */ 19, 19, 255, 354, 19, 255, 255, 255, 19, 444,
+ /* 90 */ 773, 227, 485, 485, 122, 414, 1310, 1310, 1310, 1310,
+ /* 100 */ 1310, 1310, 1310, 1310, 1310, 1310, 1310, 1310, 1310, 1310,
+ /* 110 */ 1310, 1310, 1310, 1310, 1310, 303, 61, 523, 523, 287,
+ /* 120 */ 127, 371, 358, 358, 358, 127, 618, 97, 399, 399,
+ /* 130 */ 255, 255, 590, 590, 599, 736, 650, 650, 650, 650,
+ /* 140 */ 650, 650, 650, 972, 21, 495, 420, 150, 404, 385,
+ /* 150 */ 430, 637, 671, 202, 894, 248, 811, 806, 796, 806,
+ /* 160 */ 853, 710, 710, 710, 180, 288, 943, 1155, 1129, 1146,
+ /* 170 */ 1018, 1155, 1155, 1148, 1040, 1040, 1155, 1155, 1155, 1182,
+ /* 180 */ 1182, 1185, 233, 97, 233, 1201, 1204, 233, 1201, 233,
+ /* 190 */ 1210, 233, 233, 1155, 233, 1182, 255, 255, 255, 255,
+ /* 200 */ 255, 255, 255, 255, 255, 255, 255, 1155, 1182, 590,
+ /* 210 */ 1185, 444, 1108, 97, 444, 1155, 1155, 1201, 444, 1050,
+ /* 220 */ 590, 590, 590, 590, 1050, 590, 1135, 618, 1210, 444,
+ /* 230 */ 599, 444, 618, 1298, 590, 1085, 1050, 590, 590, 1085,
+ /* 240 */ 1050, 590, 590, 255, 1097, 1187, 1085, 1104, 1111, 1110,
+ /* 250 */ 943, 1123, 618, 1336, 1131, 1137, 1130, 1131, 1137, 1131,
+ /* 260 */ 1137, 1306, 1307, 590, 736, 1155, 444, 1370, 1182, 2547,
+ /* 270 */ 2547, 2547, 2547, 2547, 2547, 2547, 339, 134, 273, 579,
+ /* 280 */ 661, 724, 838, 921, 946, 851, 1002, 473, 51, 51,
+ /* 290 */ 51, 51, 51, 51, 51, 51, 698, 774, 145, 145,
+ /* 300 */ 359, 471, 190, 429, 585, 13, 708, 428, 673, 673,
+ /* 310 */ 673, 673, 84, 823, 800, 966, 973, 1014, 1016, 1023,
+ /* 320 */ 1049, 1057, 488, 881, 914, 1000, 1021, 1041, 1052, 1066,
+ /* 330 */ 1068, 1128, 1020, 206, 559, 1072, 905, 994, 1005, 1067,
+ /* 340 */ 990, 1074, 1083, 1101, 1103, 1105, 1107, 763, 757, 556,
+ /* 350 */ 1418, 1428, 1268, 1446, 1447, 1406, 1449, 1374, 1451, 1417,
+ /* 360 */ 1267, 1419, 1420, 1421, 1271, 1459, 1425, 1426, 1277, 1464,
+ /* 370 */ 1279, 1466, 1435, 1469, 1450, 1471, 1438, 1474, 1392, 1308,
+ /* 380 */ 1311, 1315, 1318, 1485, 1486, 1325, 1327, 1490, 1491, 1448,
+ /* 390 */ 1492, 1495, 1496, 1352, 1498, 1499, 1500, 1501, 1502, 1365,
+ /* 400 */ 1475, 1506, 1369, 1519, 1520, 1526, 1528, 1531, 1532, 1533,
+ /* 410 */ 1535, 1537, 1538, 1539, 1540, 1541, 1542, 1480, 1544, 1546,
+ /* 420 */ 1548, 1549, 1551, 1552, 1554, 1557, 1559, 1562, 1563, 1564,
+ /* 430 */ 1517, 1574, 1521, 1578, 1579, 1545, 1515, 1543, 1568, 1555,
+ /* 440 */ 1569, 1556, 1584, 1558, 1561, 1588, 1595, 1597, 1566, 1453,
+ /* 450 */ 1603, 1606, 1608, 1553, 1611, 1613, 1581, 1571, 1580, 1620,
+ /* 460 */ 1586, 1576, 1587, 1625, 1593, 1583, 1590, 1627, 1598, 1585,
+ /* 470 */ 1596, 1634, 1636, 1637, 1638, 1547, 1550, 1605, 1629, 1652,
+ /* 480 */ 1626, 1628, 1630, 1631, 1619, 1621, 1633, 1635, 1640, 1641,
+ /* 490 */ 1669, 1649, 1677, 1651, 1639, 1678, 1657, 1645, 1682, 1648,
+ /* 500 */ 1684, 1650, 1686, 1665, 1670, 1689, 1560, 1659, 1695, 1524,
+ /* 510 */ 1675, 1565, 1570, 1698, 1700, 1575, 1577, 1701, 1702, 1711,
+ /* 520 */ 1607, 1644, 1534, 1712, 1642, 1589, 1646, 1714, 1680, 1567,
+ /* 530 */ 1653, 1647, 1679, 1690, 1493, 1654, 1655, 1658, 1660, 1661,
+ /* 540 */ 1666, 1694, 1664, 1667, 1674, 1688, 1691, 1720, 1699, 1718,
+ /* 550 */ 1693, 1731, 1505, 1696, 1697, 1729, 1573, 1733, 1734, 1738,
+ /* 560 */ 1703, 1736, 1514, 1704, 1750, 1751, 1752, 1753, 1756, 1757,
+ /* 570 */ 1704, 1791, 1772, 1602, 1755, 1715, 1710, 1716, 1717, 1721,
+ /* 580 */ 1719, 1762, 1725, 1726, 1767, 1780, 1623, 1730, 1723, 1735,
+ /* 590 */ 1781, 1785, 1740, 1737, 1792, 1741, 1742, 1794, 1745, 1746,
+ /* 600 */ 1798, 1749, 1766, 1800, 1776, 1727, 1728, 1759, 1761, 1816,
+ /* 610 */ 1743, 1777, 1778, 1807, 1779, 1822, 1822, 1844, 1809, 1812,
+ /* 620 */ 1841, 1810, 1797, 1832, 1846, 1848, 1850, 1851, 1853, 1867,
+ /* 630 */ 1855, 1856, 1825, 1619, 1860, 1621, 1861, 1862, 1863, 1865,
+ /* 640 */ 1866, 1876, 1877, 1902, 1886, 1875, 1890, 1931, 1898, 1887,
+ /* 650 */ 1896, 1936, 1903, 1892, 1901, 1937, 1906, 1895, 1904, 1944,
+ /* 660 */ 1910, 1911, 1947, 1926, 1928, 1930, 1932, 1929, 1933,
};
-#define YY_REDUCE_COUNT (265)
-#define YY_REDUCE_MIN (-340)
-#define YY_REDUCE_MAX (1869)
+#define YY_REDUCE_COUNT (275)
+#define YY_REDUCE_MIN (-294)
+#define YY_REDUCE_MAX (2181)
static const short yy_reduce_ofst[] = {
- /* 0 */ -233, -228, -20, -176, 645, 737, 778, 819, 895, 958,
- /* 10 */ 188, 975, 1038, 1056, 1107, 477, 1168, 1221, 1244, 1300,
- /* 20 */ 1353, 1362, 713, 1376, 1417, 1438, 1496, 1507, 1518, 1583,
- /* 30 */ 1599, 1648, 1662, 1703, 1724, 1782, 1793, 1804, 1845, 1869,
- /* 40 */ 1141, 1255, -5, 607, 653, -274, -269, 49, 447, -227,
- /* 50 */ -47, 161, -231, -229, -244, -215, -340, -105, -133, 123,
- /* 60 */ -197, -147, 363, 411, 424, 440, 455, 487, -171, 492,
- /* 70 */ 511, 200, -24, 234, -201, 521, 603, 251, 604, -101,
- /* 80 */ 345, 357, 606, -119, -152, -281, -281, -281, 78, -247,
- /* 90 */ -135, -21, 242, 250, 295, 331, 334, 390, 404, 453,
- /* 100 */ 461, 483, 485, 502, 503, 564, 615, 617, 625, 199,
- /* 110 */ -83, 420, 421, -27, 176, -263, 172, 406, -155, 279,
- /* 120 */ 491, -172, 243, 346, 494, 542, 428, 435, -271, 355,
- /* 130 */ 532, 555, 574, 608, 643, 585, 683, 691, 584, 602,
- /* 140 */ 701, 651, 629, 709, 709, 730, 748, 717, 694, 674,
- /* 150 */ 674, 674, 659, 660, 665, 684, 709, 766, 827, 772,
- /* 160 */ 826, 783, 834, 840, 797, 820, 825, 864, 872, 873,
- /* 170 */ 816, 867, 839, 868, 828, 829, 876, 830, 877, 862,
- /* 180 */ 852, 890, 897, 899, 898, 900, 880, 883, 884, 885,
- /* 190 */ 888, 889, 893, 894, 901, 902, 904, 911, 915, 903,
- /* 200 */ 905, 858, 916, 863, 882, 917, 920, 878, 924, 907,
- /* 210 */ 909, 927, 869, 912, 842, 922, 919, 844, 923, 921,
- /* 220 */ 931, 709, 843, 845, 849, 853, 856, 865, 918, 674,
- /* 230 */ 941, 926, 929, 866, 874, 870, 871, 928, 930, 939,
- /* 240 */ 935, 944, 949, 950, 948, 952, 955, 962, 953, 999,
- /* 250 */ 980, 1002, 972, 981, 979, 1003, 1007, 1012, 1021, 964,
- /* 260 */ 977, 1005, 1013, 1015, 1014, 1039,
+ /* 0 */ -254, -201, 706, 23, 282, 787, 933, 975, 1038, 1088,
+ /* 10 */ 542, 877, 1098, 1180, 1234, 1258, 1312, 1322, 1372, 1422,
+ /* 20 */ 1434, 1512, 1028, 1522, 1572, 1582, 1592, 1673, 1692, 1754,
+ /* 30 */ 1770, 1823, 1840, 1893, 1905, 1974, 1988, 2030, 2082, 2100,
+ /* 40 */ 2124, 2181, 1173, 2172, -240, -263, -19, 207, 352, -277,
+ /* 50 */ 345, 813, -142, -141, -140, -79, 3, -267, 29, -260,
+ /* 60 */ -229, -274, -258, -143, -40, -159, 70, 285, 327, 329,
+ /* 70 */ 369, 370, 531, 535, -270, 541, 554, 560, -294, -272,
+ /* 80 */ 561, 594, 59, -257, 674, -124, 89, 270, 725, 377,
+ /* 90 */ -226, -219, -219, -219, -176, -247, -202, -15, 52, 63,
+ /* 100 */ 247, 394, 434, 507, 511, 581, 582, 626, 663, 672,
+ /* 110 */ 697, 748, 750, 753, 754, -158, -82, -162, -87, -262,
+ /* 120 */ 68, -215, 406, 589, 596, 215, 305, 379, 83, 236,
+ /* 130 */ 509, 298, 445, 699, 715, 469, 362, 591, 633, 640,
+ /* 140 */ 656, 714, 789, 631, 825, 814, 716, 744, 863, 826,
+ /* 150 */ 792, 850, 850, 889, 893, 862, 833, 810, 810, 810,
+ /* 160 */ 818, 797, 799, 802, 809, 850, 849, 911, 856, 910,
+ /* 170 */ 866, 918, 919, 887, 890, 891, 930, 932, 934, 939,
+ /* 180 */ 942, 884, 936, 915, 948, 912, 908, 955, 916, 958,
+ /* 190 */ 924, 965, 967, 970, 968, 979, 956, 957, 959, 960,
+ /* 200 */ 961, 962, 963, 964, 974, 976, 985, 978, 991, 981,
+ /* 210 */ 951, 1007, 969, 982, 1017, 1024, 1025, 980, 1019, 983,
+ /* 220 */ 993, 996, 998, 999, 989, 1001, 995, 1008, 997, 1043,
+ /* 230 */ 1031, 1055, 1022, 1004, 1026, 986, 1030, 1027, 1029, 987,
+ /* 240 */ 1032, 1035, 1036, 850, 992, 977, 988, 1006, 1033, 1037,
+ /* 250 */ 1042, 810, 1058, 1051, 1009, 1012, 1011, 1013, 1015, 1034,
+ /* 260 */ 1039, 1059, 1114, 1096, 1122, 1134, 1133, 1147, 1149, 1094,
+ /* 270 */ 1100, 1160, 1161, 1162, 1157, 1159,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 10 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 20 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 30 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 40 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 50 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 60 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1468, 1399,
- /* 70 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 80 */ 1399, 1399, 1399, 1466, 1617, 1399, 1781, 1399, 1399, 1399,
- /* 90 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 100 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 110 */ 1399, 1399, 1399, 1468, 1399, 1792, 1792, 1792, 1466, 1399,
- /* 120 */ 1399, 1399, 1399, 1399, 1399, 1399, 1562, 1399, 1399, 1399,
- /* 130 */ 1399, 1399, 1399, 1399, 1399, 1650, 1399, 1399, 1862, 1399,
- /* 140 */ 1399, 1656, 1816, 1399, 1399, 1399, 1399, 1515, 1808, 1784,
- /* 150 */ 1798, 1785, 1847, 1847, 1847, 1801, 1399, 1812, 1399, 1399,
- /* 160 */ 1399, 1642, 1399, 1399, 1622, 1619, 1619, 1399, 1399, 1399,
- /* 170 */ 1399, 1468, 1399, 1468, 1399, 1399, 1468, 1399, 1468, 1399,
- /* 180 */ 1399, 1468, 1468, 1399, 1468, 1399, 1399, 1399, 1399, 1399,
- /* 190 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 200 */ 1399, 1399, 1466, 1652, 1399, 1466, 1399, 1399, 1466, 1399,
- /* 210 */ 1399, 1466, 1399, 1399, 1823, 1821, 1399, 1823, 1821, 1399,
- /* 220 */ 1399, 1399, 1835, 1831, 1823, 1839, 1837, 1814, 1812, 1798,
- /* 230 */ 1399, 1399, 1399, 1853, 1849, 1865, 1853, 1849, 1853, 1849,
- /* 240 */ 1399, 1821, 1399, 1399, 1821, 1399, 1627, 1399, 1399, 1466,
- /* 250 */ 1399, 1466, 1399, 1531, 1399, 1399, 1399, 1466, 1399, 1644,
- /* 260 */ 1658, 1565, 1565, 1565, 1469, 1404, 1399, 1399, 1399, 1399,
- /* 270 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1527,
- /* 280 */ 1725, 1834, 1833, 1757, 1756, 1755, 1753, 1724, 1399, 1399,
- /* 290 */ 1399, 1399, 1399, 1399, 1718, 1719, 1717, 1716, 1399, 1399,
- /* 300 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 310 */ 1399, 1782, 1399, 1850, 1854, 1399, 1399, 1399, 1701, 1399,
- /* 320 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 330 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 340 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 350 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 360 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 370 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 380 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 390 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 400 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 410 */ 1399, 1399, 1399, 1433, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 420 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 430 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 440 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 450 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 460 */ 1399, 1496, 1495, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 470 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 480 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 490 */ 1399, 1399, 1399, 1399, 1399, 1805, 1815, 1399, 1399, 1399,
- /* 500 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 510 */ 1701, 1399, 1832, 1399, 1791, 1787, 1399, 1399, 1783, 1399,
- /* 520 */ 1399, 1848, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 530 */ 1399, 1777, 1399, 1750, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 540 */ 1399, 1399, 1712, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 550 */ 1399, 1399, 1399, 1399, 1399, 1700, 1399, 1741, 1399, 1399,
- /* 560 */ 1399, 1399, 1399, 1399, 1399, 1399, 1559, 1399, 1399, 1399,
- /* 570 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1544,
- /* 580 */ 1542, 1541, 1540, 1399, 1537, 1399, 1399, 1399, 1399, 1568,
- /* 590 */ 1567, 1399, 1399, 1399, 1399, 1399, 1399, 1488, 1399, 1399,
- /* 600 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1479, 1399, 1478,
- /* 610 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 620 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 630 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
- /* 640 */ 1399,
+ /* 0 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 10 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 20 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 30 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 40 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 50 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 60 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 70 */ 1465, 1465, 1465, 1465, 1539, 1465, 1465, 1465, 1465, 1465,
+ /* 80 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1537,
+ /* 90 */ 1692, 1465, 1872, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 100 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 110 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1539,
+ /* 120 */ 1465, 1537, 1884, 1884, 1884, 1465, 1465, 1465, 1736, 1736,
+ /* 130 */ 1465, 1465, 1465, 1465, 1635, 1465, 1465, 1465, 1465, 1465,
+ /* 140 */ 1465, 1465, 1465, 1728, 1465, 1465, 1953, 1465, 1465, 1734,
+ /* 150 */ 1907, 1465, 1465, 1465, 1465, 1588, 1899, 1876, 1890, 1877,
+ /* 160 */ 1874, 1938, 1938, 1938, 1893, 1465, 1903, 1465, 1465, 1465,
+ /* 170 */ 1720, 1465, 1465, 1697, 1694, 1694, 1465, 1465, 1465, 1465,
+ /* 180 */ 1465, 1465, 1539, 1465, 1539, 1465, 1465, 1539, 1465, 1539,
+ /* 190 */ 1465, 1539, 1539, 1465, 1539, 1465, 1465, 1465, 1465, 1465,
+ /* 200 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 210 */ 1465, 1537, 1730, 1465, 1537, 1465, 1465, 1465, 1537, 1912,
+ /* 220 */ 1465, 1465, 1465, 1465, 1912, 1465, 1465, 1465, 1465, 1537,
+ /* 230 */ 1465, 1537, 1465, 1465, 1465, 1914, 1912, 1465, 1465, 1914,
+ /* 240 */ 1912, 1465, 1465, 1465, 1926, 1922, 1914, 1930, 1928, 1905,
+ /* 250 */ 1903, 1890, 1465, 1465, 1944, 1940, 1956, 1944, 1940, 1944,
+ /* 260 */ 1940, 1465, 1604, 1465, 1465, 1465, 1537, 1497, 1465, 1722,
+ /* 270 */ 1736, 1638, 1638, 1638, 1540, 1470, 1465, 1465, 1465, 1465,
+ /* 280 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1809, 1925,
+ /* 290 */ 1924, 1848, 1847, 1846, 1844, 1808, 1465, 1600, 1807, 1806,
+ /* 300 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1800, 1801,
+ /* 310 */ 1799, 1798, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 320 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 330 */ 1465, 1873, 1465, 1941, 1945, 1465, 1465, 1465, 1465, 1465,
+ /* 340 */ 1783, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 350 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 360 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 370 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 380 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 390 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 400 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 410 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 420 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 430 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1502, 1465, 1465,
+ /* 440 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 450 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 460 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 470 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 480 */ 1465, 1465, 1465, 1465, 1569, 1568, 1465, 1465, 1465, 1465,
+ /* 490 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 500 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 510 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 520 */ 1465, 1465, 1465, 1740, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 530 */ 1465, 1465, 1465, 1906, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 540 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1783,
+ /* 550 */ 1465, 1923, 1465, 1883, 1879, 1465, 1465, 1875, 1782, 1465,
+ /* 560 */ 1465, 1939, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 570 */ 1465, 1868, 1465, 1465, 1841, 1826, 1465, 1465, 1465, 1465,
+ /* 580 */ 1465, 1465, 1465, 1465, 1465, 1465, 1794, 1465, 1465, 1465,
+ /* 590 */ 1465, 1465, 1632, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 600 */ 1465, 1465, 1465, 1465, 1465, 1617, 1615, 1614, 1613, 1465,
+ /* 610 */ 1610, 1465, 1465, 1465, 1465, 1641, 1640, 1465, 1465, 1465,
+ /* 620 */ 1465, 1465, 1465, 1560, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 630 */ 1465, 1465, 1465, 1551, 1465, 1550, 1465, 1465, 1465, 1465,
+ /* 640 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 650 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
+ /* 660 */ 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -881,7 +957,9 @@ static const YYCODETYPE yyFallback[] = {
0, /* CONNS => nothing */
0, /* STATE => nothing */
0, /* USER => nothing */
- 0, /* PRIVILEGE => nothing */
+ 0, /* ENABLE => nothing */
+ 0, /* NK_INTEGER => nothing */
+ 0, /* SYSINFO => nothing */
0, /* DROP => nothing */
0, /* GRANT => nothing */
0, /* ON => nothing */
@@ -894,7 +972,6 @@ static const YYCODETYPE yyFallback[] = {
0, /* NK_DOT => nothing */
0, /* DNODE => nothing */
0, /* PORT => nothing */
- 0, /* NK_INTEGER => nothing */
0, /* DNODES => nothing */
0, /* NK_IPTOKEN => nothing */
0, /* LOCAL => nothing */
@@ -904,11 +981,14 @@ static const YYCODETYPE yyFallback[] = {
0, /* MNODE => nothing */
0, /* DATABASE => nothing */
0, /* USE => nothing */
+ 0, /* FLUSH => nothing */
+ 0, /* TRIM => nothing */
0, /* IF => nothing */
0, /* NOT => nothing */
0, /* EXISTS => nothing */
0, /* BUFFER => nothing */
0, /* CACHELAST => nothing */
+ 0, /* CACHELASTSIZE => nothing */
0, /* COMP => nothing */
0, /* DURATION => nothing */
0, /* NK_VARIABLE => nothing */
@@ -989,13 +1069,16 @@ static const YYCODETYPE yyFallback[] = {
0, /* CLUSTER => nothing */
0, /* TRANSACTIONS => nothing */
0, /* DISTRIBUTED => nothing */
+ 0, /* CONSUMERS => nothing */
+ 0, /* SUBSCRIPTIONS => nothing */
0, /* LIKE => nothing */
0, /* INDEX => nothing */
- 0, /* FULLTEXT => nothing */
0, /* FUNCTION => nothing */
0, /* INTERVAL => nothing */
0, /* TOPIC => nothing */
0, /* AS => nothing */
+ 0, /* WITH => nothing */
+ 0, /* META => nothing */
0, /* CONSUMER => nothing */
0, /* GROUP => nothing */
0, /* DESC => nothing */
@@ -1020,6 +1103,8 @@ static const YYCODETYPE yyFallback[] = {
0, /* TRIGGER => nothing */
0, /* AT_ONCE => nothing */
0, /* WINDOW_CLOSE => nothing */
+ 0, /* IGNORE => nothing */
+ 0, /* EXPIRED => nothing */
0, /* KILL => nothing */
0, /* CONNECTION => nothing */
0, /* TRANSACTION => nothing */
@@ -1030,20 +1115,26 @@ static const YYCODETYPE yyFallback[] = {
0, /* SPLIT => nothing */
0, /* SYNCDB => nothing */
0, /* DELETE => nothing */
+ 0, /* INSERT => nothing */
0, /* NULL => nothing */
0, /* NK_QUESTION => nothing */
0, /* NK_ARROW => nothing */
0, /* ROWTS => nothing */
0, /* TBNAME => nothing */
- 0, /* QSTARTTS => nothing */
- 0, /* QENDTS => nothing */
- 0, /* WSTARTTS => nothing */
- 0, /* WENDTS => nothing */
+ 0, /* QSTART => nothing */
+ 0, /* QEND => nothing */
+ 0, /* QDURATION => nothing */
+ 0, /* WSTART => nothing */
+ 0, /* WEND => nothing */
0, /* WDURATION => nothing */
0, /* CAST => nothing */
0, /* NOW => nothing */
0, /* TODAY => nothing */
0, /* TIMEZONE => nothing */
+ 0, /* CLIENT_VERSION => nothing */
+ 0, /* SERVER_VERSION => nothing */
+ 0, /* SERVER_STATUS => nothing */
+ 0, /* CURRENT_USER => nothing */
0, /* COUNT => nothing */
0, /* LAST_ROW => nothing */
0, /* BETWEEN => nothing */
@@ -1083,12 +1174,11 @@ static const YYCODETYPE yyFallback[] = {
0, /* ASC => nothing */
0, /* NULLS => nothing */
0, /* ID => nothing */
- 235, /* NK_BITNOT => ID */
- 235, /* INSERT => ID */
- 235, /* VALUES => ID */
- 235, /* IMPORT => ID */
- 235, /* NK_SEMI => ID */
- 235, /* FILE => ID */
+ 250, /* NK_BITNOT => ID */
+ 250, /* VALUES => ID */
+ 250, /* IMPORT => ID */
+ 250, /* NK_SEMI => ID */
+ 250, /* FILE => ID */
};
#endif /* YYFALLBACK */
@@ -1210,336 +1300,351 @@ static const char *const yyTokenName[] = {
/* 31 */ "CONNS",
/* 32 */ "STATE",
/* 33 */ "USER",
- /* 34 */ "PRIVILEGE",
- /* 35 */ "DROP",
- /* 36 */ "GRANT",
- /* 37 */ "ON",
- /* 38 */ "TO",
- /* 39 */ "REVOKE",
- /* 40 */ "FROM",
- /* 41 */ "NK_COMMA",
- /* 42 */ "READ",
- /* 43 */ "WRITE",
- /* 44 */ "NK_DOT",
- /* 45 */ "DNODE",
- /* 46 */ "PORT",
- /* 47 */ "NK_INTEGER",
- /* 48 */ "DNODES",
- /* 49 */ "NK_IPTOKEN",
- /* 50 */ "LOCAL",
- /* 51 */ "QNODE",
- /* 52 */ "BNODE",
- /* 53 */ "SNODE",
- /* 54 */ "MNODE",
- /* 55 */ "DATABASE",
- /* 56 */ "USE",
- /* 57 */ "IF",
- /* 58 */ "NOT",
- /* 59 */ "EXISTS",
- /* 60 */ "BUFFER",
- /* 61 */ "CACHELAST",
- /* 62 */ "COMP",
- /* 63 */ "DURATION",
- /* 64 */ "NK_VARIABLE",
- /* 65 */ "FSYNC",
- /* 66 */ "MAXROWS",
- /* 67 */ "MINROWS",
- /* 68 */ "KEEP",
- /* 69 */ "PAGES",
- /* 70 */ "PAGESIZE",
- /* 71 */ "PRECISION",
- /* 72 */ "REPLICA",
- /* 73 */ "STRICT",
- /* 74 */ "WAL",
- /* 75 */ "VGROUPS",
- /* 76 */ "SINGLE_STABLE",
- /* 77 */ "RETENTIONS",
- /* 78 */ "SCHEMALESS",
- /* 79 */ "NK_COLON",
- /* 80 */ "TABLE",
- /* 81 */ "NK_LP",
- /* 82 */ "NK_RP",
- /* 83 */ "STABLE",
- /* 84 */ "ADD",
- /* 85 */ "COLUMN",
- /* 86 */ "MODIFY",
- /* 87 */ "RENAME",
- /* 88 */ "TAG",
- /* 89 */ "SET",
- /* 90 */ "NK_EQ",
- /* 91 */ "USING",
- /* 92 */ "TAGS",
- /* 93 */ "COMMENT",
- /* 94 */ "BOOL",
- /* 95 */ "TINYINT",
- /* 96 */ "SMALLINT",
- /* 97 */ "INT",
- /* 98 */ "INTEGER",
- /* 99 */ "BIGINT",
- /* 100 */ "FLOAT",
- /* 101 */ "DOUBLE",
- /* 102 */ "BINARY",
- /* 103 */ "TIMESTAMP",
- /* 104 */ "NCHAR",
- /* 105 */ "UNSIGNED",
- /* 106 */ "JSON",
- /* 107 */ "VARCHAR",
- /* 108 */ "MEDIUMBLOB",
- /* 109 */ "BLOB",
- /* 110 */ "VARBINARY",
- /* 111 */ "DECIMAL",
- /* 112 */ "MAX_DELAY",
- /* 113 */ "WATERMARK",
- /* 114 */ "ROLLUP",
- /* 115 */ "TTL",
- /* 116 */ "SMA",
- /* 117 */ "FIRST",
- /* 118 */ "LAST",
- /* 119 */ "SHOW",
- /* 120 */ "DATABASES",
- /* 121 */ "TABLES",
- /* 122 */ "STABLES",
- /* 123 */ "MNODES",
- /* 124 */ "MODULES",
- /* 125 */ "QNODES",
- /* 126 */ "FUNCTIONS",
- /* 127 */ "INDEXES",
- /* 128 */ "ACCOUNTS",
- /* 129 */ "APPS",
- /* 130 */ "CONNECTIONS",
- /* 131 */ "LICENCE",
- /* 132 */ "GRANTS",
- /* 133 */ "QUERIES",
- /* 134 */ "SCORES",
- /* 135 */ "TOPICS",
- /* 136 */ "VARIABLES",
- /* 137 */ "BNODES",
- /* 138 */ "SNODES",
- /* 139 */ "CLUSTER",
- /* 140 */ "TRANSACTIONS",
- /* 141 */ "DISTRIBUTED",
- /* 142 */ "LIKE",
- /* 143 */ "INDEX",
- /* 144 */ "FULLTEXT",
- /* 145 */ "FUNCTION",
- /* 146 */ "INTERVAL",
- /* 147 */ "TOPIC",
- /* 148 */ "AS",
- /* 149 */ "CONSUMER",
- /* 150 */ "GROUP",
- /* 151 */ "DESC",
- /* 152 */ "DESCRIBE",
- /* 153 */ "RESET",
- /* 154 */ "QUERY",
- /* 155 */ "CACHE",
- /* 156 */ "EXPLAIN",
- /* 157 */ "ANALYZE",
- /* 158 */ "VERBOSE",
- /* 159 */ "NK_BOOL",
- /* 160 */ "RATIO",
- /* 161 */ "NK_FLOAT",
- /* 162 */ "COMPACT",
- /* 163 */ "VNODES",
- /* 164 */ "IN",
- /* 165 */ "OUTPUTTYPE",
- /* 166 */ "AGGREGATE",
- /* 167 */ "BUFSIZE",
- /* 168 */ "STREAM",
- /* 169 */ "INTO",
- /* 170 */ "TRIGGER",
- /* 171 */ "AT_ONCE",
- /* 172 */ "WINDOW_CLOSE",
- /* 173 */ "KILL",
- /* 174 */ "CONNECTION",
- /* 175 */ "TRANSACTION",
- /* 176 */ "BALANCE",
- /* 177 */ "VGROUP",
- /* 178 */ "MERGE",
- /* 179 */ "REDISTRIBUTE",
- /* 180 */ "SPLIT",
- /* 181 */ "SYNCDB",
- /* 182 */ "DELETE",
- /* 183 */ "NULL",
- /* 184 */ "NK_QUESTION",
- /* 185 */ "NK_ARROW",
- /* 186 */ "ROWTS",
- /* 187 */ "TBNAME",
- /* 188 */ "QSTARTTS",
- /* 189 */ "QENDTS",
- /* 190 */ "WSTARTTS",
- /* 191 */ "WENDTS",
- /* 192 */ "WDURATION",
- /* 193 */ "CAST",
- /* 194 */ "NOW",
- /* 195 */ "TODAY",
- /* 196 */ "TIMEZONE",
- /* 197 */ "COUNT",
- /* 198 */ "LAST_ROW",
- /* 199 */ "BETWEEN",
- /* 200 */ "IS",
- /* 201 */ "NK_LT",
- /* 202 */ "NK_GT",
- /* 203 */ "NK_LE",
- /* 204 */ "NK_GE",
- /* 205 */ "NK_NE",
- /* 206 */ "MATCH",
- /* 207 */ "NMATCH",
- /* 208 */ "CONTAINS",
- /* 209 */ "JOIN",
- /* 210 */ "INNER",
- /* 211 */ "SELECT",
- /* 212 */ "DISTINCT",
- /* 213 */ "WHERE",
- /* 214 */ "PARTITION",
- /* 215 */ "BY",
- /* 216 */ "SESSION",
- /* 217 */ "STATE_WINDOW",
- /* 218 */ "SLIDING",
- /* 219 */ "FILL",
- /* 220 */ "VALUE",
- /* 221 */ "NONE",
- /* 222 */ "PREV",
- /* 223 */ "LINEAR",
- /* 224 */ "NEXT",
- /* 225 */ "HAVING",
- /* 226 */ "RANGE",
- /* 227 */ "EVERY",
- /* 228 */ "ORDER",
- /* 229 */ "SLIMIT",
- /* 230 */ "SOFFSET",
- /* 231 */ "LIMIT",
- /* 232 */ "OFFSET",
- /* 233 */ "ASC",
- /* 234 */ "NULLS",
- /* 235 */ "ID",
- /* 236 */ "NK_BITNOT",
- /* 237 */ "INSERT",
- /* 238 */ "VALUES",
- /* 239 */ "IMPORT",
- /* 240 */ "NK_SEMI",
- /* 241 */ "FILE",
- /* 242 */ "cmd",
- /* 243 */ "account_options",
- /* 244 */ "alter_account_options",
- /* 245 */ "literal",
- /* 246 */ "alter_account_option",
- /* 247 */ "user_name",
- /* 248 */ "privileges",
- /* 249 */ "priv_level",
- /* 250 */ "priv_type_list",
- /* 251 */ "priv_type",
- /* 252 */ "db_name",
- /* 253 */ "dnode_endpoint",
- /* 254 */ "not_exists_opt",
- /* 255 */ "db_options",
- /* 256 */ "exists_opt",
- /* 257 */ "alter_db_options",
- /* 258 */ "integer_list",
- /* 259 */ "variable_list",
- /* 260 */ "retention_list",
- /* 261 */ "alter_db_option",
- /* 262 */ "retention",
- /* 263 */ "full_table_name",
- /* 264 */ "column_def_list",
- /* 265 */ "tags_def_opt",
- /* 266 */ "table_options",
- /* 267 */ "multi_create_clause",
- /* 268 */ "tags_def",
- /* 269 */ "multi_drop_clause",
- /* 270 */ "alter_table_clause",
- /* 271 */ "alter_table_options",
- /* 272 */ "column_name",
- /* 273 */ "type_name",
- /* 274 */ "signed_literal",
- /* 275 */ "create_subtable_clause",
- /* 276 */ "specific_tags_opt",
- /* 277 */ "literal_list",
- /* 278 */ "drop_table_clause",
- /* 279 */ "col_name_list",
- /* 280 */ "table_name",
- /* 281 */ "column_def",
- /* 282 */ "duration_list",
- /* 283 */ "rollup_func_list",
- /* 284 */ "alter_table_option",
- /* 285 */ "duration_literal",
- /* 286 */ "rollup_func_name",
- /* 287 */ "function_name",
- /* 288 */ "col_name",
- /* 289 */ "db_name_cond_opt",
- /* 290 */ "like_pattern_opt",
- /* 291 */ "table_name_cond",
- /* 292 */ "from_db_opt",
- /* 293 */ "index_name",
- /* 294 */ "index_options",
- /* 295 */ "func_list",
- /* 296 */ "sliding_opt",
- /* 297 */ "func",
- /* 298 */ "expression_list",
- /* 299 */ "topic_name",
- /* 300 */ "query_expression",
- /* 301 */ "cgroup_name",
- /* 302 */ "analyze_opt",
- /* 303 */ "explain_options",
- /* 304 */ "agg_func_opt",
- /* 305 */ "bufsize_opt",
- /* 306 */ "stream_name",
- /* 307 */ "stream_options",
- /* 308 */ "into_opt",
- /* 309 */ "dnode_list",
- /* 310 */ "where_clause_opt",
- /* 311 */ "signed",
- /* 312 */ "literal_func",
- /* 313 */ "table_alias",
- /* 314 */ "column_alias",
- /* 315 */ "expression",
- /* 316 */ "pseudo_column",
- /* 317 */ "column_reference",
- /* 318 */ "function_expression",
- /* 319 */ "subquery",
- /* 320 */ "star_func",
- /* 321 */ "star_func_para_list",
- /* 322 */ "noarg_func",
- /* 323 */ "other_para_list",
- /* 324 */ "star_func_para",
- /* 325 */ "predicate",
- /* 326 */ "compare_op",
- /* 327 */ "in_op",
- /* 328 */ "in_predicate_value",
- /* 329 */ "boolean_value_expression",
- /* 330 */ "boolean_primary",
- /* 331 */ "common_expression",
- /* 332 */ "from_clause",
- /* 333 */ "table_reference_list",
- /* 334 */ "table_reference",
- /* 335 */ "table_primary",
- /* 336 */ "joined_table",
- /* 337 */ "alias_opt",
- /* 338 */ "parenthesized_joined_table",
- /* 339 */ "join_type",
- /* 340 */ "search_condition",
- /* 341 */ "query_specification",
- /* 342 */ "set_quantifier_opt",
- /* 343 */ "select_list",
- /* 344 */ "partition_by_clause_opt",
- /* 345 */ "range_opt",
- /* 346 */ "every_opt",
- /* 347 */ "fill_opt",
- /* 348 */ "twindow_clause_opt",
- /* 349 */ "group_by_clause_opt",
- /* 350 */ "having_clause_opt",
- /* 351 */ "select_sublist",
- /* 352 */ "select_item",
- /* 353 */ "fill_mode",
- /* 354 */ "group_by_list",
- /* 355 */ "query_expression_body",
- /* 356 */ "order_by_clause_opt",
- /* 357 */ "slimit_clause_opt",
- /* 358 */ "limit_clause_opt",
- /* 359 */ "query_primary",
- /* 360 */ "sort_specification_list",
- /* 361 */ "sort_specification",
- /* 362 */ "ordering_specification_opt",
- /* 363 */ "null_ordering_opt",
+ /* 34 */ "ENABLE",
+ /* 35 */ "NK_INTEGER",
+ /* 36 */ "SYSINFO",
+ /* 37 */ "DROP",
+ /* 38 */ "GRANT",
+ /* 39 */ "ON",
+ /* 40 */ "TO",
+ /* 41 */ "REVOKE",
+ /* 42 */ "FROM",
+ /* 43 */ "NK_COMMA",
+ /* 44 */ "READ",
+ /* 45 */ "WRITE",
+ /* 46 */ "NK_DOT",
+ /* 47 */ "DNODE",
+ /* 48 */ "PORT",
+ /* 49 */ "DNODES",
+ /* 50 */ "NK_IPTOKEN",
+ /* 51 */ "LOCAL",
+ /* 52 */ "QNODE",
+ /* 53 */ "BNODE",
+ /* 54 */ "SNODE",
+ /* 55 */ "MNODE",
+ /* 56 */ "DATABASE",
+ /* 57 */ "USE",
+ /* 58 */ "FLUSH",
+ /* 59 */ "TRIM",
+ /* 60 */ "IF",
+ /* 61 */ "NOT",
+ /* 62 */ "EXISTS",
+ /* 63 */ "BUFFER",
+ /* 64 */ "CACHELAST",
+ /* 65 */ "CACHELASTSIZE",
+ /* 66 */ "COMP",
+ /* 67 */ "DURATION",
+ /* 68 */ "NK_VARIABLE",
+ /* 69 */ "FSYNC",
+ /* 70 */ "MAXROWS",
+ /* 71 */ "MINROWS",
+ /* 72 */ "KEEP",
+ /* 73 */ "PAGES",
+ /* 74 */ "PAGESIZE",
+ /* 75 */ "PRECISION",
+ /* 76 */ "REPLICA",
+ /* 77 */ "STRICT",
+ /* 78 */ "WAL",
+ /* 79 */ "VGROUPS",
+ /* 80 */ "SINGLE_STABLE",
+ /* 81 */ "RETENTIONS",
+ /* 82 */ "SCHEMALESS",
+ /* 83 */ "NK_COLON",
+ /* 84 */ "TABLE",
+ /* 85 */ "NK_LP",
+ /* 86 */ "NK_RP",
+ /* 87 */ "STABLE",
+ /* 88 */ "ADD",
+ /* 89 */ "COLUMN",
+ /* 90 */ "MODIFY",
+ /* 91 */ "RENAME",
+ /* 92 */ "TAG",
+ /* 93 */ "SET",
+ /* 94 */ "NK_EQ",
+ /* 95 */ "USING",
+ /* 96 */ "TAGS",
+ /* 97 */ "COMMENT",
+ /* 98 */ "BOOL",
+ /* 99 */ "TINYINT",
+ /* 100 */ "SMALLINT",
+ /* 101 */ "INT",
+ /* 102 */ "INTEGER",
+ /* 103 */ "BIGINT",
+ /* 104 */ "FLOAT",
+ /* 105 */ "DOUBLE",
+ /* 106 */ "BINARY",
+ /* 107 */ "TIMESTAMP",
+ /* 108 */ "NCHAR",
+ /* 109 */ "UNSIGNED",
+ /* 110 */ "JSON",
+ /* 111 */ "VARCHAR",
+ /* 112 */ "MEDIUMBLOB",
+ /* 113 */ "BLOB",
+ /* 114 */ "VARBINARY",
+ /* 115 */ "DECIMAL",
+ /* 116 */ "MAX_DELAY",
+ /* 117 */ "WATERMARK",
+ /* 118 */ "ROLLUP",
+ /* 119 */ "TTL",
+ /* 120 */ "SMA",
+ /* 121 */ "FIRST",
+ /* 122 */ "LAST",
+ /* 123 */ "SHOW",
+ /* 124 */ "DATABASES",
+ /* 125 */ "TABLES",
+ /* 126 */ "STABLES",
+ /* 127 */ "MNODES",
+ /* 128 */ "MODULES",
+ /* 129 */ "QNODES",
+ /* 130 */ "FUNCTIONS",
+ /* 131 */ "INDEXES",
+ /* 132 */ "ACCOUNTS",
+ /* 133 */ "APPS",
+ /* 134 */ "CONNECTIONS",
+ /* 135 */ "LICENCE",
+ /* 136 */ "GRANTS",
+ /* 137 */ "QUERIES",
+ /* 138 */ "SCORES",
+ /* 139 */ "TOPICS",
+ /* 140 */ "VARIABLES",
+ /* 141 */ "BNODES",
+ /* 142 */ "SNODES",
+ /* 143 */ "CLUSTER",
+ /* 144 */ "TRANSACTIONS",
+ /* 145 */ "DISTRIBUTED",
+ /* 146 */ "CONSUMERS",
+ /* 147 */ "SUBSCRIPTIONS",
+ /* 148 */ "LIKE",
+ /* 149 */ "INDEX",
+ /* 150 */ "FUNCTION",
+ /* 151 */ "INTERVAL",
+ /* 152 */ "TOPIC",
+ /* 153 */ "AS",
+ /* 154 */ "WITH",
+ /* 155 */ "META",
+ /* 156 */ "CONSUMER",
+ /* 157 */ "GROUP",
+ /* 158 */ "DESC",
+ /* 159 */ "DESCRIBE",
+ /* 160 */ "RESET",
+ /* 161 */ "QUERY",
+ /* 162 */ "CACHE",
+ /* 163 */ "EXPLAIN",
+ /* 164 */ "ANALYZE",
+ /* 165 */ "VERBOSE",
+ /* 166 */ "NK_BOOL",
+ /* 167 */ "RATIO",
+ /* 168 */ "NK_FLOAT",
+ /* 169 */ "COMPACT",
+ /* 170 */ "VNODES",
+ /* 171 */ "IN",
+ /* 172 */ "OUTPUTTYPE",
+ /* 173 */ "AGGREGATE",
+ /* 174 */ "BUFSIZE",
+ /* 175 */ "STREAM",
+ /* 176 */ "INTO",
+ /* 177 */ "TRIGGER",
+ /* 178 */ "AT_ONCE",
+ /* 179 */ "WINDOW_CLOSE",
+ /* 180 */ "IGNORE",
+ /* 181 */ "EXPIRED",
+ /* 182 */ "KILL",
+ /* 183 */ "CONNECTION",
+ /* 184 */ "TRANSACTION",
+ /* 185 */ "BALANCE",
+ /* 186 */ "VGROUP",
+ /* 187 */ "MERGE",
+ /* 188 */ "REDISTRIBUTE",
+ /* 189 */ "SPLIT",
+ /* 190 */ "SYNCDB",
+ /* 191 */ "DELETE",
+ /* 192 */ "INSERT",
+ /* 193 */ "NULL",
+ /* 194 */ "NK_QUESTION",
+ /* 195 */ "NK_ARROW",
+ /* 196 */ "ROWTS",
+ /* 197 */ "TBNAME",
+ /* 198 */ "QSTART",
+ /* 199 */ "QEND",
+ /* 200 */ "QDURATION",
+ /* 201 */ "WSTART",
+ /* 202 */ "WEND",
+ /* 203 */ "WDURATION",
+ /* 204 */ "CAST",
+ /* 205 */ "NOW",
+ /* 206 */ "TODAY",
+ /* 207 */ "TIMEZONE",
+ /* 208 */ "CLIENT_VERSION",
+ /* 209 */ "SERVER_VERSION",
+ /* 210 */ "SERVER_STATUS",
+ /* 211 */ "CURRENT_USER",
+ /* 212 */ "COUNT",
+ /* 213 */ "LAST_ROW",
+ /* 214 */ "BETWEEN",
+ /* 215 */ "IS",
+ /* 216 */ "NK_LT",
+ /* 217 */ "NK_GT",
+ /* 218 */ "NK_LE",
+ /* 219 */ "NK_GE",
+ /* 220 */ "NK_NE",
+ /* 221 */ "MATCH",
+ /* 222 */ "NMATCH",
+ /* 223 */ "CONTAINS",
+ /* 224 */ "JOIN",
+ /* 225 */ "INNER",
+ /* 226 */ "SELECT",
+ /* 227 */ "DISTINCT",
+ /* 228 */ "WHERE",
+ /* 229 */ "PARTITION",
+ /* 230 */ "BY",
+ /* 231 */ "SESSION",
+ /* 232 */ "STATE_WINDOW",
+ /* 233 */ "SLIDING",
+ /* 234 */ "FILL",
+ /* 235 */ "VALUE",
+ /* 236 */ "NONE",
+ /* 237 */ "PREV",
+ /* 238 */ "LINEAR",
+ /* 239 */ "NEXT",
+ /* 240 */ "HAVING",
+ /* 241 */ "RANGE",
+ /* 242 */ "EVERY",
+ /* 243 */ "ORDER",
+ /* 244 */ "SLIMIT",
+ /* 245 */ "SOFFSET",
+ /* 246 */ "LIMIT",
+ /* 247 */ "OFFSET",
+ /* 248 */ "ASC",
+ /* 249 */ "NULLS",
+ /* 250 */ "ID",
+ /* 251 */ "NK_BITNOT",
+ /* 252 */ "VALUES",
+ /* 253 */ "IMPORT",
+ /* 254 */ "NK_SEMI",
+ /* 255 */ "FILE",
+ /* 256 */ "cmd",
+ /* 257 */ "account_options",
+ /* 258 */ "alter_account_options",
+ /* 259 */ "literal",
+ /* 260 */ "alter_account_option",
+ /* 261 */ "user_name",
+ /* 262 */ "sysinfo_opt",
+ /* 263 */ "privileges",
+ /* 264 */ "priv_level",
+ /* 265 */ "priv_type_list",
+ /* 266 */ "priv_type",
+ /* 267 */ "db_name",
+ /* 268 */ "dnode_endpoint",
+ /* 269 */ "not_exists_opt",
+ /* 270 */ "db_options",
+ /* 271 */ "exists_opt",
+ /* 272 */ "alter_db_options",
+ /* 273 */ "integer_list",
+ /* 274 */ "variable_list",
+ /* 275 */ "retention_list",
+ /* 276 */ "alter_db_option",
+ /* 277 */ "retention",
+ /* 278 */ "full_table_name",
+ /* 279 */ "column_def_list",
+ /* 280 */ "tags_def_opt",
+ /* 281 */ "table_options",
+ /* 282 */ "multi_create_clause",
+ /* 283 */ "tags_def",
+ /* 284 */ "multi_drop_clause",
+ /* 285 */ "alter_table_clause",
+ /* 286 */ "alter_table_options",
+ /* 287 */ "column_name",
+ /* 288 */ "type_name",
+ /* 289 */ "signed_literal",
+ /* 290 */ "create_subtable_clause",
+ /* 291 */ "specific_cols_opt",
+ /* 292 */ "expression_list",
+ /* 293 */ "drop_table_clause",
+ /* 294 */ "col_name_list",
+ /* 295 */ "table_name",
+ /* 296 */ "column_def",
+ /* 297 */ "duration_list",
+ /* 298 */ "rollup_func_list",
+ /* 299 */ "alter_table_option",
+ /* 300 */ "duration_literal",
+ /* 301 */ "rollup_func_name",
+ /* 302 */ "function_name",
+ /* 303 */ "col_name",
+ /* 304 */ "db_name_cond_opt",
+ /* 305 */ "like_pattern_opt",
+ /* 306 */ "table_name_cond",
+ /* 307 */ "from_db_opt",
+ /* 308 */ "index_name",
+ /* 309 */ "index_options",
+ /* 310 */ "func_list",
+ /* 311 */ "sliding_opt",
+ /* 312 */ "sma_stream_opt",
+ /* 313 */ "func",
+ /* 314 */ "stream_options",
+ /* 315 */ "topic_name",
+ /* 316 */ "query_expression",
+ /* 317 */ "cgroup_name",
+ /* 318 */ "analyze_opt",
+ /* 319 */ "explain_options",
+ /* 320 */ "agg_func_opt",
+ /* 321 */ "bufsize_opt",
+ /* 322 */ "stream_name",
+ /* 323 */ "into_opt",
+ /* 324 */ "dnode_list",
+ /* 325 */ "where_clause_opt",
+ /* 326 */ "signed",
+ /* 327 */ "literal_func",
+ /* 328 */ "literal_list",
+ /* 329 */ "table_alias",
+ /* 330 */ "column_alias",
+ /* 331 */ "expression",
+ /* 332 */ "pseudo_column",
+ /* 333 */ "column_reference",
+ /* 334 */ "function_expression",
+ /* 335 */ "subquery",
+ /* 336 */ "star_func",
+ /* 337 */ "star_func_para_list",
+ /* 338 */ "noarg_func",
+ /* 339 */ "other_para_list",
+ /* 340 */ "star_func_para",
+ /* 341 */ "predicate",
+ /* 342 */ "compare_op",
+ /* 343 */ "in_op",
+ /* 344 */ "in_predicate_value",
+ /* 345 */ "boolean_value_expression",
+ /* 346 */ "boolean_primary",
+ /* 347 */ "common_expression",
+ /* 348 */ "from_clause_opt",
+ /* 349 */ "table_reference_list",
+ /* 350 */ "table_reference",
+ /* 351 */ "table_primary",
+ /* 352 */ "joined_table",
+ /* 353 */ "alias_opt",
+ /* 354 */ "parenthesized_joined_table",
+ /* 355 */ "join_type",
+ /* 356 */ "search_condition",
+ /* 357 */ "query_specification",
+ /* 358 */ "set_quantifier_opt",
+ /* 359 */ "select_list",
+ /* 360 */ "partition_by_clause_opt",
+ /* 361 */ "range_opt",
+ /* 362 */ "every_opt",
+ /* 363 */ "fill_opt",
+ /* 364 */ "twindow_clause_opt",
+ /* 365 */ "group_by_clause_opt",
+ /* 366 */ "having_clause_opt",
+ /* 367 */ "select_item",
+ /* 368 */ "fill_mode",
+ /* 369 */ "group_by_list",
+ /* 370 */ "query_expression_body",
+ /* 371 */ "order_by_clause_opt",
+ /* 372 */ "slimit_clause_opt",
+ /* 373 */ "limit_clause_opt",
+ /* 374 */ "query_primary",
+ /* 375 */ "sort_specification_list",
+ /* 376 */ "sort_specification",
+ /* 377 */ "ordering_specification_opt",
+ /* 378 */ "null_ordering_opt",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -1571,448 +1676,473 @@ static const char *const yyRuleName[] = {
/* 21 */ "alter_account_option ::= USERS literal",
/* 22 */ "alter_account_option ::= CONNS literal",
/* 23 */ "alter_account_option ::= STATE literal",
- /* 24 */ "cmd ::= CREATE USER user_name PASS NK_STRING",
+ /* 24 */ "cmd ::= CREATE USER user_name PASS NK_STRING sysinfo_opt",
/* 25 */ "cmd ::= ALTER USER user_name PASS NK_STRING",
- /* 26 */ "cmd ::= ALTER USER user_name PRIVILEGE NK_STRING",
- /* 27 */ "cmd ::= DROP USER user_name",
- /* 28 */ "cmd ::= GRANT privileges ON priv_level TO user_name",
- /* 29 */ "cmd ::= REVOKE privileges ON priv_level FROM user_name",
- /* 30 */ "privileges ::= ALL",
- /* 31 */ "privileges ::= priv_type_list",
- /* 32 */ "priv_type_list ::= priv_type",
- /* 33 */ "priv_type_list ::= priv_type_list NK_COMMA priv_type",
- /* 34 */ "priv_type ::= READ",
- /* 35 */ "priv_type ::= WRITE",
- /* 36 */ "priv_level ::= NK_STAR NK_DOT NK_STAR",
- /* 37 */ "priv_level ::= db_name NK_DOT NK_STAR",
- /* 38 */ "cmd ::= CREATE DNODE dnode_endpoint",
- /* 39 */ "cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER",
- /* 40 */ "cmd ::= DROP DNODE NK_INTEGER",
- /* 41 */ "cmd ::= DROP DNODE dnode_endpoint",
- /* 42 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING",
- /* 43 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING",
- /* 44 */ "cmd ::= ALTER ALL DNODES NK_STRING",
- /* 45 */ "cmd ::= ALTER ALL DNODES NK_STRING NK_STRING",
- /* 46 */ "dnode_endpoint ::= NK_STRING",
- /* 47 */ "dnode_endpoint ::= NK_ID",
- /* 48 */ "dnode_endpoint ::= NK_IPTOKEN",
- /* 49 */ "cmd ::= ALTER LOCAL NK_STRING",
- /* 50 */ "cmd ::= ALTER LOCAL NK_STRING NK_STRING",
- /* 51 */ "cmd ::= CREATE QNODE ON DNODE NK_INTEGER",
- /* 52 */ "cmd ::= DROP QNODE ON DNODE NK_INTEGER",
- /* 53 */ "cmd ::= CREATE BNODE ON DNODE NK_INTEGER",
- /* 54 */ "cmd ::= DROP BNODE ON DNODE NK_INTEGER",
- /* 55 */ "cmd ::= CREATE SNODE ON DNODE NK_INTEGER",
- /* 56 */ "cmd ::= DROP SNODE ON DNODE NK_INTEGER",
- /* 57 */ "cmd ::= CREATE MNODE ON DNODE NK_INTEGER",
- /* 58 */ "cmd ::= DROP MNODE ON DNODE NK_INTEGER",
- /* 59 */ "cmd ::= CREATE DATABASE not_exists_opt db_name db_options",
- /* 60 */ "cmd ::= DROP DATABASE exists_opt db_name",
- /* 61 */ "cmd ::= USE db_name",
- /* 62 */ "cmd ::= ALTER DATABASE db_name alter_db_options",
- /* 63 */ "not_exists_opt ::= IF NOT EXISTS",
- /* 64 */ "not_exists_opt ::=",
- /* 65 */ "exists_opt ::= IF EXISTS",
- /* 66 */ "exists_opt ::=",
- /* 67 */ "db_options ::=",
- /* 68 */ "db_options ::= db_options BUFFER NK_INTEGER",
- /* 69 */ "db_options ::= db_options CACHELAST NK_INTEGER",
- /* 70 */ "db_options ::= db_options COMP NK_INTEGER",
- /* 71 */ "db_options ::= db_options DURATION NK_INTEGER",
- /* 72 */ "db_options ::= db_options DURATION NK_VARIABLE",
- /* 73 */ "db_options ::= db_options FSYNC NK_INTEGER",
- /* 74 */ "db_options ::= db_options MAXROWS NK_INTEGER",
- /* 75 */ "db_options ::= db_options MINROWS NK_INTEGER",
- /* 76 */ "db_options ::= db_options KEEP integer_list",
- /* 77 */ "db_options ::= db_options KEEP variable_list",
- /* 78 */ "db_options ::= db_options PAGES NK_INTEGER",
- /* 79 */ "db_options ::= db_options PAGESIZE NK_INTEGER",
- /* 80 */ "db_options ::= db_options PRECISION NK_STRING",
- /* 81 */ "db_options ::= db_options REPLICA NK_INTEGER",
- /* 82 */ "db_options ::= db_options STRICT NK_INTEGER",
- /* 83 */ "db_options ::= db_options WAL NK_INTEGER",
- /* 84 */ "db_options ::= db_options VGROUPS NK_INTEGER",
- /* 85 */ "db_options ::= db_options SINGLE_STABLE NK_INTEGER",
- /* 86 */ "db_options ::= db_options RETENTIONS retention_list",
- /* 87 */ "db_options ::= db_options SCHEMALESS NK_INTEGER",
- /* 88 */ "alter_db_options ::= alter_db_option",
- /* 89 */ "alter_db_options ::= alter_db_options alter_db_option",
- /* 90 */ "alter_db_option ::= BUFFER NK_INTEGER",
- /* 91 */ "alter_db_option ::= CACHELAST NK_INTEGER",
- /* 92 */ "alter_db_option ::= FSYNC NK_INTEGER",
- /* 93 */ "alter_db_option ::= KEEP integer_list",
- /* 94 */ "alter_db_option ::= KEEP variable_list",
- /* 95 */ "alter_db_option ::= PAGES NK_INTEGER",
- /* 96 */ "alter_db_option ::= REPLICA NK_INTEGER",
- /* 97 */ "alter_db_option ::= STRICT NK_INTEGER",
- /* 98 */ "alter_db_option ::= WAL NK_INTEGER",
- /* 99 */ "integer_list ::= NK_INTEGER",
- /* 100 */ "integer_list ::= integer_list NK_COMMA NK_INTEGER",
- /* 101 */ "variable_list ::= NK_VARIABLE",
- /* 102 */ "variable_list ::= variable_list NK_COMMA NK_VARIABLE",
- /* 103 */ "retention_list ::= retention",
- /* 104 */ "retention_list ::= retention_list NK_COMMA retention",
- /* 105 */ "retention ::= NK_VARIABLE NK_COLON NK_VARIABLE",
- /* 106 */ "cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options",
- /* 107 */ "cmd ::= CREATE TABLE multi_create_clause",
- /* 108 */ "cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options",
- /* 109 */ "cmd ::= DROP TABLE multi_drop_clause",
- /* 110 */ "cmd ::= DROP STABLE exists_opt full_table_name",
- /* 111 */ "cmd ::= ALTER TABLE alter_table_clause",
- /* 112 */ "cmd ::= ALTER STABLE alter_table_clause",
- /* 113 */ "alter_table_clause ::= full_table_name alter_table_options",
- /* 114 */ "alter_table_clause ::= full_table_name ADD COLUMN column_name type_name",
- /* 115 */ "alter_table_clause ::= full_table_name DROP COLUMN column_name",
- /* 116 */ "alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name",
- /* 117 */ "alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name",
- /* 118 */ "alter_table_clause ::= full_table_name ADD TAG column_name type_name",
- /* 119 */ "alter_table_clause ::= full_table_name DROP TAG column_name",
- /* 120 */ "alter_table_clause ::= full_table_name MODIFY TAG column_name type_name",
- /* 121 */ "alter_table_clause ::= full_table_name RENAME TAG column_name column_name",
- /* 122 */ "alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal",
- /* 123 */ "multi_create_clause ::= create_subtable_clause",
- /* 124 */ "multi_create_clause ::= multi_create_clause create_subtable_clause",
- /* 125 */ "create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP table_options",
- /* 126 */ "multi_drop_clause ::= drop_table_clause",
- /* 127 */ "multi_drop_clause ::= multi_drop_clause drop_table_clause",
- /* 128 */ "drop_table_clause ::= exists_opt full_table_name",
- /* 129 */ "specific_tags_opt ::=",
- /* 130 */ "specific_tags_opt ::= NK_LP col_name_list NK_RP",
- /* 131 */ "full_table_name ::= table_name",
- /* 132 */ "full_table_name ::= db_name NK_DOT table_name",
- /* 133 */ "column_def_list ::= column_def",
- /* 134 */ "column_def_list ::= column_def_list NK_COMMA column_def",
- /* 135 */ "column_def ::= column_name type_name",
- /* 136 */ "column_def ::= column_name type_name COMMENT NK_STRING",
- /* 137 */ "type_name ::= BOOL",
- /* 138 */ "type_name ::= TINYINT",
- /* 139 */ "type_name ::= SMALLINT",
- /* 140 */ "type_name ::= INT",
- /* 141 */ "type_name ::= INTEGER",
- /* 142 */ "type_name ::= BIGINT",
- /* 143 */ "type_name ::= FLOAT",
- /* 144 */ "type_name ::= DOUBLE",
- /* 145 */ "type_name ::= BINARY NK_LP NK_INTEGER NK_RP",
- /* 146 */ "type_name ::= TIMESTAMP",
- /* 147 */ "type_name ::= NCHAR NK_LP NK_INTEGER NK_RP",
- /* 148 */ "type_name ::= TINYINT UNSIGNED",
- /* 149 */ "type_name ::= SMALLINT UNSIGNED",
- /* 150 */ "type_name ::= INT UNSIGNED",
- /* 151 */ "type_name ::= BIGINT UNSIGNED",
- /* 152 */ "type_name ::= JSON",
- /* 153 */ "type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP",
- /* 154 */ "type_name ::= MEDIUMBLOB",
- /* 155 */ "type_name ::= BLOB",
- /* 156 */ "type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP",
- /* 157 */ "type_name ::= DECIMAL",
- /* 158 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP",
- /* 159 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP",
- /* 160 */ "tags_def_opt ::=",
- /* 161 */ "tags_def_opt ::= tags_def",
- /* 162 */ "tags_def ::= TAGS NK_LP column_def_list NK_RP",
- /* 163 */ "table_options ::=",
- /* 164 */ "table_options ::= table_options COMMENT NK_STRING",
- /* 165 */ "table_options ::= table_options MAX_DELAY duration_list",
- /* 166 */ "table_options ::= table_options WATERMARK duration_list",
- /* 167 */ "table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP",
- /* 168 */ "table_options ::= table_options TTL NK_INTEGER",
- /* 169 */ "table_options ::= table_options SMA NK_LP col_name_list NK_RP",
- /* 170 */ "alter_table_options ::= alter_table_option",
- /* 171 */ "alter_table_options ::= alter_table_options alter_table_option",
- /* 172 */ "alter_table_option ::= COMMENT NK_STRING",
- /* 173 */ "alter_table_option ::= TTL NK_INTEGER",
- /* 174 */ "duration_list ::= duration_literal",
- /* 175 */ "duration_list ::= duration_list NK_COMMA duration_literal",
- /* 176 */ "rollup_func_list ::= rollup_func_name",
- /* 177 */ "rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name",
- /* 178 */ "rollup_func_name ::= function_name",
- /* 179 */ "rollup_func_name ::= FIRST",
- /* 180 */ "rollup_func_name ::= LAST",
- /* 181 */ "col_name_list ::= col_name",
- /* 182 */ "col_name_list ::= col_name_list NK_COMMA col_name",
- /* 183 */ "col_name ::= column_name",
- /* 184 */ "cmd ::= SHOW DNODES",
- /* 185 */ "cmd ::= SHOW USERS",
- /* 186 */ "cmd ::= SHOW DATABASES",
- /* 187 */ "cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt",
- /* 188 */ "cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt",
- /* 189 */ "cmd ::= SHOW db_name_cond_opt VGROUPS",
- /* 190 */ "cmd ::= SHOW MNODES",
- /* 191 */ "cmd ::= SHOW MODULES",
- /* 192 */ "cmd ::= SHOW QNODES",
- /* 193 */ "cmd ::= SHOW FUNCTIONS",
- /* 194 */ "cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt",
- /* 195 */ "cmd ::= SHOW STREAMS",
- /* 196 */ "cmd ::= SHOW ACCOUNTS",
- /* 197 */ "cmd ::= SHOW APPS",
- /* 198 */ "cmd ::= SHOW CONNECTIONS",
- /* 199 */ "cmd ::= SHOW LICENCE",
- /* 200 */ "cmd ::= SHOW GRANTS",
- /* 201 */ "cmd ::= SHOW CREATE DATABASE db_name",
- /* 202 */ "cmd ::= SHOW CREATE TABLE full_table_name",
- /* 203 */ "cmd ::= SHOW CREATE STABLE full_table_name",
- /* 204 */ "cmd ::= SHOW QUERIES",
- /* 205 */ "cmd ::= SHOW SCORES",
- /* 206 */ "cmd ::= SHOW TOPICS",
- /* 207 */ "cmd ::= SHOW VARIABLES",
- /* 208 */ "cmd ::= SHOW LOCAL VARIABLES",
- /* 209 */ "cmd ::= SHOW DNODE NK_INTEGER VARIABLES",
- /* 210 */ "cmd ::= SHOW BNODES",
- /* 211 */ "cmd ::= SHOW SNODES",
- /* 212 */ "cmd ::= SHOW CLUSTER",
- /* 213 */ "cmd ::= SHOW TRANSACTIONS",
- /* 214 */ "cmd ::= SHOW TABLE DISTRIBUTED full_table_name",
- /* 215 */ "db_name_cond_opt ::=",
- /* 216 */ "db_name_cond_opt ::= db_name NK_DOT",
- /* 217 */ "like_pattern_opt ::=",
- /* 218 */ "like_pattern_opt ::= LIKE NK_STRING",
- /* 219 */ "table_name_cond ::= table_name",
- /* 220 */ "from_db_opt ::=",
- /* 221 */ "from_db_opt ::= FROM db_name",
- /* 222 */ "cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options",
- /* 223 */ "cmd ::= CREATE FULLTEXT INDEX not_exists_opt index_name ON table_name NK_LP col_name_list NK_RP",
- /* 224 */ "cmd ::= DROP INDEX exists_opt index_name ON table_name",
- /* 225 */ "index_options ::=",
- /* 226 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt",
- /* 227 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt",
- /* 228 */ "func_list ::= func",
- /* 229 */ "func_list ::= func_list NK_COMMA func",
- /* 230 */ "func ::= function_name NK_LP expression_list NK_RP",
- /* 231 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression",
- /* 232 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name",
- /* 233 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name",
- /* 234 */ "cmd ::= DROP TOPIC exists_opt topic_name",
- /* 235 */ "cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name",
- /* 236 */ "cmd ::= DESC full_table_name",
- /* 237 */ "cmd ::= DESCRIBE full_table_name",
- /* 238 */ "cmd ::= RESET QUERY CACHE",
- /* 239 */ "cmd ::= EXPLAIN analyze_opt explain_options query_expression",
- /* 240 */ "analyze_opt ::=",
- /* 241 */ "analyze_opt ::= ANALYZE",
- /* 242 */ "explain_options ::=",
- /* 243 */ "explain_options ::= explain_options VERBOSE NK_BOOL",
- /* 244 */ "explain_options ::= explain_options RATIO NK_FLOAT",
- /* 245 */ "cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP",
- /* 246 */ "cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt",
- /* 247 */ "cmd ::= DROP FUNCTION exists_opt function_name",
- /* 248 */ "agg_func_opt ::=",
- /* 249 */ "agg_func_opt ::= AGGREGATE",
- /* 250 */ "bufsize_opt ::=",
- /* 251 */ "bufsize_opt ::= BUFSIZE NK_INTEGER",
- /* 252 */ "cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression",
- /* 253 */ "cmd ::= DROP STREAM exists_opt stream_name",
- /* 254 */ "into_opt ::=",
- /* 255 */ "into_opt ::= INTO full_table_name",
- /* 256 */ "stream_options ::=",
- /* 257 */ "stream_options ::= stream_options TRIGGER AT_ONCE",
- /* 258 */ "stream_options ::= stream_options TRIGGER WINDOW_CLOSE",
- /* 259 */ "stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal",
- /* 260 */ "stream_options ::= stream_options WATERMARK duration_literal",
- /* 261 */ "cmd ::= KILL CONNECTION NK_INTEGER",
- /* 262 */ "cmd ::= KILL QUERY NK_STRING",
- /* 263 */ "cmd ::= KILL TRANSACTION NK_INTEGER",
- /* 264 */ "cmd ::= BALANCE VGROUP",
- /* 265 */ "cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER",
- /* 266 */ "cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list",
- /* 267 */ "cmd ::= SPLIT VGROUP NK_INTEGER",
- /* 268 */ "dnode_list ::= DNODE NK_INTEGER",
- /* 269 */ "dnode_list ::= dnode_list DNODE NK_INTEGER",
- /* 270 */ "cmd ::= SYNCDB db_name REPLICA",
- /* 271 */ "cmd ::= DELETE FROM full_table_name where_clause_opt",
- /* 272 */ "cmd ::= query_expression",
- /* 273 */ "literal ::= NK_INTEGER",
- /* 274 */ "literal ::= NK_FLOAT",
- /* 275 */ "literal ::= NK_STRING",
- /* 276 */ "literal ::= NK_BOOL",
- /* 277 */ "literal ::= TIMESTAMP NK_STRING",
- /* 278 */ "literal ::= duration_literal",
- /* 279 */ "literal ::= NULL",
- /* 280 */ "literal ::= NK_QUESTION",
- /* 281 */ "duration_literal ::= NK_VARIABLE",
- /* 282 */ "signed ::= NK_INTEGER",
- /* 283 */ "signed ::= NK_PLUS NK_INTEGER",
- /* 284 */ "signed ::= NK_MINUS NK_INTEGER",
- /* 285 */ "signed ::= NK_FLOAT",
- /* 286 */ "signed ::= NK_PLUS NK_FLOAT",
- /* 287 */ "signed ::= NK_MINUS NK_FLOAT",
- /* 288 */ "signed_literal ::= signed",
- /* 289 */ "signed_literal ::= NK_STRING",
- /* 290 */ "signed_literal ::= NK_BOOL",
- /* 291 */ "signed_literal ::= TIMESTAMP NK_STRING",
- /* 292 */ "signed_literal ::= duration_literal",
- /* 293 */ "signed_literal ::= NULL",
- /* 294 */ "signed_literal ::= literal_func",
- /* 295 */ "literal_list ::= signed_literal",
- /* 296 */ "literal_list ::= literal_list NK_COMMA signed_literal",
- /* 297 */ "db_name ::= NK_ID",
- /* 298 */ "table_name ::= NK_ID",
- /* 299 */ "column_name ::= NK_ID",
- /* 300 */ "function_name ::= NK_ID",
- /* 301 */ "table_alias ::= NK_ID",
- /* 302 */ "column_alias ::= NK_ID",
- /* 303 */ "user_name ::= NK_ID",
- /* 304 */ "index_name ::= NK_ID",
- /* 305 */ "topic_name ::= NK_ID",
- /* 306 */ "stream_name ::= NK_ID",
- /* 307 */ "cgroup_name ::= NK_ID",
- /* 308 */ "expression ::= literal",
- /* 309 */ "expression ::= pseudo_column",
- /* 310 */ "expression ::= column_reference",
- /* 311 */ "expression ::= function_expression",
- /* 312 */ "expression ::= subquery",
- /* 313 */ "expression ::= NK_LP expression NK_RP",
- /* 314 */ "expression ::= NK_PLUS expression",
- /* 315 */ "expression ::= NK_MINUS expression",
- /* 316 */ "expression ::= expression NK_PLUS expression",
- /* 317 */ "expression ::= expression NK_MINUS expression",
- /* 318 */ "expression ::= expression NK_STAR expression",
- /* 319 */ "expression ::= expression NK_SLASH expression",
- /* 320 */ "expression ::= expression NK_REM expression",
- /* 321 */ "expression ::= column_reference NK_ARROW NK_STRING",
- /* 322 */ "expression_list ::= expression",
- /* 323 */ "expression_list ::= expression_list NK_COMMA expression",
- /* 324 */ "column_reference ::= column_name",
- /* 325 */ "column_reference ::= table_name NK_DOT column_name",
- /* 326 */ "pseudo_column ::= ROWTS",
- /* 327 */ "pseudo_column ::= TBNAME",
- /* 328 */ "pseudo_column ::= table_name NK_DOT TBNAME",
- /* 329 */ "pseudo_column ::= QSTARTTS",
- /* 330 */ "pseudo_column ::= QENDTS",
- /* 331 */ "pseudo_column ::= WSTARTTS",
- /* 332 */ "pseudo_column ::= WENDTS",
- /* 333 */ "pseudo_column ::= WDURATION",
- /* 334 */ "function_expression ::= function_name NK_LP expression_list NK_RP",
- /* 335 */ "function_expression ::= star_func NK_LP star_func_para_list NK_RP",
- /* 336 */ "function_expression ::= CAST NK_LP expression AS type_name NK_RP",
- /* 337 */ "function_expression ::= literal_func",
- /* 338 */ "literal_func ::= noarg_func NK_LP NK_RP",
- /* 339 */ "literal_func ::= NOW",
- /* 340 */ "noarg_func ::= NOW",
- /* 341 */ "noarg_func ::= TODAY",
- /* 342 */ "noarg_func ::= TIMEZONE",
- /* 343 */ "star_func ::= COUNT",
- /* 344 */ "star_func ::= FIRST",
- /* 345 */ "star_func ::= LAST",
- /* 346 */ "star_func ::= LAST_ROW",
- /* 347 */ "star_func_para_list ::= NK_STAR",
- /* 348 */ "star_func_para_list ::= other_para_list",
- /* 349 */ "other_para_list ::= star_func_para",
- /* 350 */ "other_para_list ::= other_para_list NK_COMMA star_func_para",
- /* 351 */ "star_func_para ::= expression",
- /* 352 */ "star_func_para ::= table_name NK_DOT NK_STAR",
- /* 353 */ "predicate ::= expression compare_op expression",
- /* 354 */ "predicate ::= expression BETWEEN expression AND expression",
- /* 355 */ "predicate ::= expression NOT BETWEEN expression AND expression",
- /* 356 */ "predicate ::= expression IS NULL",
- /* 357 */ "predicate ::= expression IS NOT NULL",
- /* 358 */ "predicate ::= expression in_op in_predicate_value",
- /* 359 */ "compare_op ::= NK_LT",
- /* 360 */ "compare_op ::= NK_GT",
- /* 361 */ "compare_op ::= NK_LE",
- /* 362 */ "compare_op ::= NK_GE",
- /* 363 */ "compare_op ::= NK_NE",
- /* 364 */ "compare_op ::= NK_EQ",
- /* 365 */ "compare_op ::= LIKE",
- /* 366 */ "compare_op ::= NOT LIKE",
- /* 367 */ "compare_op ::= MATCH",
- /* 368 */ "compare_op ::= NMATCH",
- /* 369 */ "compare_op ::= CONTAINS",
- /* 370 */ "in_op ::= IN",
- /* 371 */ "in_op ::= NOT IN",
- /* 372 */ "in_predicate_value ::= NK_LP expression_list NK_RP",
- /* 373 */ "boolean_value_expression ::= boolean_primary",
- /* 374 */ "boolean_value_expression ::= NOT boolean_primary",
- /* 375 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression",
- /* 376 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression",
- /* 377 */ "boolean_primary ::= predicate",
- /* 378 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP",
- /* 379 */ "common_expression ::= expression",
- /* 380 */ "common_expression ::= boolean_value_expression",
- /* 381 */ "from_clause ::= FROM table_reference_list",
- /* 382 */ "table_reference_list ::= table_reference",
- /* 383 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference",
- /* 384 */ "table_reference ::= table_primary",
- /* 385 */ "table_reference ::= joined_table",
- /* 386 */ "table_primary ::= table_name alias_opt",
- /* 387 */ "table_primary ::= db_name NK_DOT table_name alias_opt",
- /* 388 */ "table_primary ::= subquery alias_opt",
- /* 389 */ "table_primary ::= parenthesized_joined_table",
- /* 390 */ "alias_opt ::=",
- /* 391 */ "alias_opt ::= table_alias",
- /* 392 */ "alias_opt ::= AS table_alias",
- /* 393 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP",
- /* 394 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP",
- /* 395 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition",
- /* 396 */ "join_type ::=",
- /* 397 */ "join_type ::= INNER",
- /* 398 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt",
- /* 399 */ "set_quantifier_opt ::=",
- /* 400 */ "set_quantifier_opt ::= DISTINCT",
- /* 401 */ "set_quantifier_opt ::= ALL",
- /* 402 */ "select_list ::= NK_STAR",
- /* 403 */ "select_list ::= select_sublist",
- /* 404 */ "select_sublist ::= select_item",
- /* 405 */ "select_sublist ::= select_sublist NK_COMMA select_item",
- /* 406 */ "select_item ::= common_expression",
- /* 407 */ "select_item ::= common_expression column_alias",
- /* 408 */ "select_item ::= common_expression AS column_alias",
- /* 409 */ "select_item ::= table_name NK_DOT NK_STAR",
- /* 410 */ "where_clause_opt ::=",
- /* 411 */ "where_clause_opt ::= WHERE search_condition",
- /* 412 */ "partition_by_clause_opt ::=",
- /* 413 */ "partition_by_clause_opt ::= PARTITION BY expression_list",
- /* 414 */ "twindow_clause_opt ::=",
- /* 415 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP",
- /* 416 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP",
- /* 417 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt",
- /* 418 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt",
- /* 419 */ "sliding_opt ::=",
- /* 420 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP",
- /* 421 */ "fill_opt ::=",
- /* 422 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP",
- /* 423 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP",
- /* 424 */ "fill_mode ::= NONE",
- /* 425 */ "fill_mode ::= PREV",
- /* 426 */ "fill_mode ::= NULL",
- /* 427 */ "fill_mode ::= LINEAR",
- /* 428 */ "fill_mode ::= NEXT",
- /* 429 */ "group_by_clause_opt ::=",
- /* 430 */ "group_by_clause_opt ::= GROUP BY group_by_list",
- /* 431 */ "group_by_list ::= expression",
- /* 432 */ "group_by_list ::= group_by_list NK_COMMA expression",
- /* 433 */ "having_clause_opt ::=",
- /* 434 */ "having_clause_opt ::= HAVING search_condition",
- /* 435 */ "range_opt ::=",
- /* 436 */ "range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP",
- /* 437 */ "every_opt ::=",
- /* 438 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP",
- /* 439 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt",
- /* 440 */ "query_expression_body ::= query_primary",
- /* 441 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body",
- /* 442 */ "query_expression_body ::= query_expression_body UNION query_expression_body",
- /* 443 */ "query_primary ::= query_specification",
- /* 444 */ "query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP",
- /* 445 */ "order_by_clause_opt ::=",
- /* 446 */ "order_by_clause_opt ::= ORDER BY sort_specification_list",
- /* 447 */ "slimit_clause_opt ::=",
- /* 448 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER",
- /* 449 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER",
- /* 450 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER",
- /* 451 */ "limit_clause_opt ::=",
- /* 452 */ "limit_clause_opt ::= LIMIT NK_INTEGER",
- /* 453 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER",
- /* 454 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER",
- /* 455 */ "subquery ::= NK_LP query_expression NK_RP",
- /* 456 */ "search_condition ::= common_expression",
- /* 457 */ "sort_specification_list ::= sort_specification",
- /* 458 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification",
- /* 459 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt",
- /* 460 */ "ordering_specification_opt ::=",
- /* 461 */ "ordering_specification_opt ::= ASC",
- /* 462 */ "ordering_specification_opt ::= DESC",
- /* 463 */ "null_ordering_opt ::=",
- /* 464 */ "null_ordering_opt ::= NULLS FIRST",
- /* 465 */ "null_ordering_opt ::= NULLS LAST",
+ /* 26 */ "cmd ::= ALTER USER user_name ENABLE NK_INTEGER",
+ /* 27 */ "cmd ::= ALTER USER user_name SYSINFO NK_INTEGER",
+ /* 28 */ "cmd ::= DROP USER user_name",
+ /* 29 */ "sysinfo_opt ::=",
+ /* 30 */ "sysinfo_opt ::= SYSINFO NK_INTEGER",
+ /* 31 */ "cmd ::= GRANT privileges ON priv_level TO user_name",
+ /* 32 */ "cmd ::= REVOKE privileges ON priv_level FROM user_name",
+ /* 33 */ "privileges ::= ALL",
+ /* 34 */ "privileges ::= priv_type_list",
+ /* 35 */ "priv_type_list ::= priv_type",
+ /* 36 */ "priv_type_list ::= priv_type_list NK_COMMA priv_type",
+ /* 37 */ "priv_type ::= READ",
+ /* 38 */ "priv_type ::= WRITE",
+ /* 39 */ "priv_level ::= NK_STAR NK_DOT NK_STAR",
+ /* 40 */ "priv_level ::= db_name NK_DOT NK_STAR",
+ /* 41 */ "cmd ::= CREATE DNODE dnode_endpoint",
+ /* 42 */ "cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER",
+ /* 43 */ "cmd ::= DROP DNODE NK_INTEGER",
+ /* 44 */ "cmd ::= DROP DNODE dnode_endpoint",
+ /* 45 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING",
+ /* 46 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING",
+ /* 47 */ "cmd ::= ALTER ALL DNODES NK_STRING",
+ /* 48 */ "cmd ::= ALTER ALL DNODES NK_STRING NK_STRING",
+ /* 49 */ "dnode_endpoint ::= NK_STRING",
+ /* 50 */ "dnode_endpoint ::= NK_ID",
+ /* 51 */ "dnode_endpoint ::= NK_IPTOKEN",
+ /* 52 */ "cmd ::= ALTER LOCAL NK_STRING",
+ /* 53 */ "cmd ::= ALTER LOCAL NK_STRING NK_STRING",
+ /* 54 */ "cmd ::= CREATE QNODE ON DNODE NK_INTEGER",
+ /* 55 */ "cmd ::= DROP QNODE ON DNODE NK_INTEGER",
+ /* 56 */ "cmd ::= CREATE BNODE ON DNODE NK_INTEGER",
+ /* 57 */ "cmd ::= DROP BNODE ON DNODE NK_INTEGER",
+ /* 58 */ "cmd ::= CREATE SNODE ON DNODE NK_INTEGER",
+ /* 59 */ "cmd ::= DROP SNODE ON DNODE NK_INTEGER",
+ /* 60 */ "cmd ::= CREATE MNODE ON DNODE NK_INTEGER",
+ /* 61 */ "cmd ::= DROP MNODE ON DNODE NK_INTEGER",
+ /* 62 */ "cmd ::= CREATE DATABASE not_exists_opt db_name db_options",
+ /* 63 */ "cmd ::= DROP DATABASE exists_opt db_name",
+ /* 64 */ "cmd ::= USE db_name",
+ /* 65 */ "cmd ::= ALTER DATABASE db_name alter_db_options",
+ /* 66 */ "cmd ::= FLUSH DATABASE db_name",
+ /* 67 */ "cmd ::= TRIM DATABASE db_name",
+ /* 68 */ "not_exists_opt ::= IF NOT EXISTS",
+ /* 69 */ "not_exists_opt ::=",
+ /* 70 */ "exists_opt ::= IF EXISTS",
+ /* 71 */ "exists_opt ::=",
+ /* 72 */ "db_options ::=",
+ /* 73 */ "db_options ::= db_options BUFFER NK_INTEGER",
+ /* 74 */ "db_options ::= db_options CACHELAST NK_INTEGER",
+ /* 75 */ "db_options ::= db_options CACHELASTSIZE NK_INTEGER",
+ /* 76 */ "db_options ::= db_options COMP NK_INTEGER",
+ /* 77 */ "db_options ::= db_options DURATION NK_INTEGER",
+ /* 78 */ "db_options ::= db_options DURATION NK_VARIABLE",
+ /* 79 */ "db_options ::= db_options FSYNC NK_INTEGER",
+ /* 80 */ "db_options ::= db_options MAXROWS NK_INTEGER",
+ /* 81 */ "db_options ::= db_options MINROWS NK_INTEGER",
+ /* 82 */ "db_options ::= db_options KEEP integer_list",
+ /* 83 */ "db_options ::= db_options KEEP variable_list",
+ /* 84 */ "db_options ::= db_options PAGES NK_INTEGER",
+ /* 85 */ "db_options ::= db_options PAGESIZE NK_INTEGER",
+ /* 86 */ "db_options ::= db_options PRECISION NK_STRING",
+ /* 87 */ "db_options ::= db_options REPLICA NK_INTEGER",
+ /* 88 */ "db_options ::= db_options STRICT NK_INTEGER",
+ /* 89 */ "db_options ::= db_options WAL NK_INTEGER",
+ /* 90 */ "db_options ::= db_options VGROUPS NK_INTEGER",
+ /* 91 */ "db_options ::= db_options SINGLE_STABLE NK_INTEGER",
+ /* 92 */ "db_options ::= db_options RETENTIONS retention_list",
+ /* 93 */ "db_options ::= db_options SCHEMALESS NK_INTEGER",
+ /* 94 */ "alter_db_options ::= alter_db_option",
+ /* 95 */ "alter_db_options ::= alter_db_options alter_db_option",
+ /* 96 */ "alter_db_option ::= BUFFER NK_INTEGER",
+ /* 97 */ "alter_db_option ::= CACHELAST NK_INTEGER",
+ /* 98 */ "alter_db_option ::= CACHELASTSIZE NK_INTEGER",
+ /* 99 */ "alter_db_option ::= FSYNC NK_INTEGER",
+ /* 100 */ "alter_db_option ::= KEEP integer_list",
+ /* 101 */ "alter_db_option ::= KEEP variable_list",
+ /* 102 */ "alter_db_option ::= PAGES NK_INTEGER",
+ /* 103 */ "alter_db_option ::= REPLICA NK_INTEGER",
+ /* 104 */ "alter_db_option ::= STRICT NK_INTEGER",
+ /* 105 */ "alter_db_option ::= WAL NK_INTEGER",
+ /* 106 */ "integer_list ::= NK_INTEGER",
+ /* 107 */ "integer_list ::= integer_list NK_COMMA NK_INTEGER",
+ /* 108 */ "variable_list ::= NK_VARIABLE",
+ /* 109 */ "variable_list ::= variable_list NK_COMMA NK_VARIABLE",
+ /* 110 */ "retention_list ::= retention",
+ /* 111 */ "retention_list ::= retention_list NK_COMMA retention",
+ /* 112 */ "retention ::= NK_VARIABLE NK_COLON NK_VARIABLE",
+ /* 113 */ "cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options",
+ /* 114 */ "cmd ::= CREATE TABLE multi_create_clause",
+ /* 115 */ "cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options",
+ /* 116 */ "cmd ::= DROP TABLE multi_drop_clause",
+ /* 117 */ "cmd ::= DROP STABLE exists_opt full_table_name",
+ /* 118 */ "cmd ::= ALTER TABLE alter_table_clause",
+ /* 119 */ "cmd ::= ALTER STABLE alter_table_clause",
+ /* 120 */ "alter_table_clause ::= full_table_name alter_table_options",
+ /* 121 */ "alter_table_clause ::= full_table_name ADD COLUMN column_name type_name",
+ /* 122 */ "alter_table_clause ::= full_table_name DROP COLUMN column_name",
+ /* 123 */ "alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name",
+ /* 124 */ "alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name",
+ /* 125 */ "alter_table_clause ::= full_table_name ADD TAG column_name type_name",
+ /* 126 */ "alter_table_clause ::= full_table_name DROP TAG column_name",
+ /* 127 */ "alter_table_clause ::= full_table_name MODIFY TAG column_name type_name",
+ /* 128 */ "alter_table_clause ::= full_table_name RENAME TAG column_name column_name",
+ /* 129 */ "alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal",
+ /* 130 */ "multi_create_clause ::= create_subtable_clause",
+ /* 131 */ "multi_create_clause ::= multi_create_clause create_subtable_clause",
+ /* 132 */ "create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options",
+ /* 133 */ "multi_drop_clause ::= drop_table_clause",
+ /* 134 */ "multi_drop_clause ::= multi_drop_clause drop_table_clause",
+ /* 135 */ "drop_table_clause ::= exists_opt full_table_name",
+ /* 136 */ "specific_cols_opt ::=",
+ /* 137 */ "specific_cols_opt ::= NK_LP col_name_list NK_RP",
+ /* 138 */ "full_table_name ::= table_name",
+ /* 139 */ "full_table_name ::= db_name NK_DOT table_name",
+ /* 140 */ "column_def_list ::= column_def",
+ /* 141 */ "column_def_list ::= column_def_list NK_COMMA column_def",
+ /* 142 */ "column_def ::= column_name type_name",
+ /* 143 */ "column_def ::= column_name type_name COMMENT NK_STRING",
+ /* 144 */ "type_name ::= BOOL",
+ /* 145 */ "type_name ::= TINYINT",
+ /* 146 */ "type_name ::= SMALLINT",
+ /* 147 */ "type_name ::= INT",
+ /* 148 */ "type_name ::= INTEGER",
+ /* 149 */ "type_name ::= BIGINT",
+ /* 150 */ "type_name ::= FLOAT",
+ /* 151 */ "type_name ::= DOUBLE",
+ /* 152 */ "type_name ::= BINARY NK_LP NK_INTEGER NK_RP",
+ /* 153 */ "type_name ::= TIMESTAMP",
+ /* 154 */ "type_name ::= NCHAR NK_LP NK_INTEGER NK_RP",
+ /* 155 */ "type_name ::= TINYINT UNSIGNED",
+ /* 156 */ "type_name ::= SMALLINT UNSIGNED",
+ /* 157 */ "type_name ::= INT UNSIGNED",
+ /* 158 */ "type_name ::= BIGINT UNSIGNED",
+ /* 159 */ "type_name ::= JSON",
+ /* 160 */ "type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP",
+ /* 161 */ "type_name ::= MEDIUMBLOB",
+ /* 162 */ "type_name ::= BLOB",
+ /* 163 */ "type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP",
+ /* 164 */ "type_name ::= DECIMAL",
+ /* 165 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP",
+ /* 166 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP",
+ /* 167 */ "tags_def_opt ::=",
+ /* 168 */ "tags_def_opt ::= tags_def",
+ /* 169 */ "tags_def ::= TAGS NK_LP column_def_list NK_RP",
+ /* 170 */ "table_options ::=",
+ /* 171 */ "table_options ::= table_options COMMENT NK_STRING",
+ /* 172 */ "table_options ::= table_options MAX_DELAY duration_list",
+ /* 173 */ "table_options ::= table_options WATERMARK duration_list",
+ /* 174 */ "table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP",
+ /* 175 */ "table_options ::= table_options TTL NK_INTEGER",
+ /* 176 */ "table_options ::= table_options SMA NK_LP col_name_list NK_RP",
+ /* 177 */ "alter_table_options ::= alter_table_option",
+ /* 178 */ "alter_table_options ::= alter_table_options alter_table_option",
+ /* 179 */ "alter_table_option ::= COMMENT NK_STRING",
+ /* 180 */ "alter_table_option ::= TTL NK_INTEGER",
+ /* 181 */ "duration_list ::= duration_literal",
+ /* 182 */ "duration_list ::= duration_list NK_COMMA duration_literal",
+ /* 183 */ "rollup_func_list ::= rollup_func_name",
+ /* 184 */ "rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name",
+ /* 185 */ "rollup_func_name ::= function_name",
+ /* 186 */ "rollup_func_name ::= FIRST",
+ /* 187 */ "rollup_func_name ::= LAST",
+ /* 188 */ "col_name_list ::= col_name",
+ /* 189 */ "col_name_list ::= col_name_list NK_COMMA col_name",
+ /* 190 */ "col_name ::= column_name",
+ /* 191 */ "cmd ::= SHOW DNODES",
+ /* 192 */ "cmd ::= SHOW USERS",
+ /* 193 */ "cmd ::= SHOW DATABASES",
+ /* 194 */ "cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt",
+ /* 195 */ "cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt",
+ /* 196 */ "cmd ::= SHOW db_name_cond_opt VGROUPS",
+ /* 197 */ "cmd ::= SHOW MNODES",
+ /* 198 */ "cmd ::= SHOW MODULES",
+ /* 199 */ "cmd ::= SHOW QNODES",
+ /* 200 */ "cmd ::= SHOW FUNCTIONS",
+ /* 201 */ "cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt",
+ /* 202 */ "cmd ::= SHOW STREAMS",
+ /* 203 */ "cmd ::= SHOW ACCOUNTS",
+ /* 204 */ "cmd ::= SHOW APPS",
+ /* 205 */ "cmd ::= SHOW CONNECTIONS",
+ /* 206 */ "cmd ::= SHOW LICENCE",
+ /* 207 */ "cmd ::= SHOW GRANTS",
+ /* 208 */ "cmd ::= SHOW CREATE DATABASE db_name",
+ /* 209 */ "cmd ::= SHOW CREATE TABLE full_table_name",
+ /* 210 */ "cmd ::= SHOW CREATE STABLE full_table_name",
+ /* 211 */ "cmd ::= SHOW QUERIES",
+ /* 212 */ "cmd ::= SHOW SCORES",
+ /* 213 */ "cmd ::= SHOW TOPICS",
+ /* 214 */ "cmd ::= SHOW VARIABLES",
+ /* 215 */ "cmd ::= SHOW LOCAL VARIABLES",
+ /* 216 */ "cmd ::= SHOW DNODE NK_INTEGER VARIABLES",
+ /* 217 */ "cmd ::= SHOW BNODES",
+ /* 218 */ "cmd ::= SHOW SNODES",
+ /* 219 */ "cmd ::= SHOW CLUSTER",
+ /* 220 */ "cmd ::= SHOW TRANSACTIONS",
+ /* 221 */ "cmd ::= SHOW TABLE DISTRIBUTED full_table_name",
+ /* 222 */ "cmd ::= SHOW CONSUMERS",
+ /* 223 */ "cmd ::= SHOW SUBSCRIPTIONS",
+ /* 224 */ "db_name_cond_opt ::=",
+ /* 225 */ "db_name_cond_opt ::= db_name NK_DOT",
+ /* 226 */ "like_pattern_opt ::=",
+ /* 227 */ "like_pattern_opt ::= LIKE NK_STRING",
+ /* 228 */ "table_name_cond ::= table_name",
+ /* 229 */ "from_db_opt ::=",
+ /* 230 */ "from_db_opt ::= FROM db_name",
+ /* 231 */ "cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options",
+ /* 232 */ "cmd ::= DROP INDEX exists_opt index_name",
+ /* 233 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt",
+ /* 234 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt",
+ /* 235 */ "func_list ::= func",
+ /* 236 */ "func_list ::= func_list NK_COMMA func",
+ /* 237 */ "func ::= function_name NK_LP expression_list NK_RP",
+ /* 238 */ "sma_stream_opt ::=",
+ /* 239 */ "sma_stream_opt ::= stream_options WATERMARK duration_literal",
+ /* 240 */ "sma_stream_opt ::= stream_options MAX_DELAY duration_literal",
+ /* 241 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression",
+ /* 242 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name",
+ /* 243 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name",
+ /* 244 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name",
+ /* 245 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name",
+ /* 246 */ "cmd ::= DROP TOPIC exists_opt topic_name",
+ /* 247 */ "cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name",
+ /* 248 */ "cmd ::= DESC full_table_name",
+ /* 249 */ "cmd ::= DESCRIBE full_table_name",
+ /* 250 */ "cmd ::= RESET QUERY CACHE",
+ /* 251 */ "cmd ::= EXPLAIN analyze_opt explain_options query_expression",
+ /* 252 */ "analyze_opt ::=",
+ /* 253 */ "analyze_opt ::= ANALYZE",
+ /* 254 */ "explain_options ::=",
+ /* 255 */ "explain_options ::= explain_options VERBOSE NK_BOOL",
+ /* 256 */ "explain_options ::= explain_options RATIO NK_FLOAT",
+ /* 257 */ "cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP",
+ /* 258 */ "cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt",
+ /* 259 */ "cmd ::= DROP FUNCTION exists_opt function_name",
+ /* 260 */ "agg_func_opt ::=",
+ /* 261 */ "agg_func_opt ::= AGGREGATE",
+ /* 262 */ "bufsize_opt ::=",
+ /* 263 */ "bufsize_opt ::= BUFSIZE NK_INTEGER",
+ /* 264 */ "cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression",
+ /* 265 */ "cmd ::= DROP STREAM exists_opt stream_name",
+ /* 266 */ "into_opt ::=",
+ /* 267 */ "into_opt ::= INTO full_table_name",
+ /* 268 */ "stream_options ::=",
+ /* 269 */ "stream_options ::= stream_options TRIGGER AT_ONCE",
+ /* 270 */ "stream_options ::= stream_options TRIGGER WINDOW_CLOSE",
+ /* 271 */ "stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal",
+ /* 272 */ "stream_options ::= stream_options WATERMARK duration_literal",
+ /* 273 */ "stream_options ::= stream_options IGNORE EXPIRED",
+ /* 274 */ "cmd ::= KILL CONNECTION NK_INTEGER",
+ /* 275 */ "cmd ::= KILL QUERY NK_STRING",
+ /* 276 */ "cmd ::= KILL TRANSACTION NK_INTEGER",
+ /* 277 */ "cmd ::= BALANCE VGROUP",
+ /* 278 */ "cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER",
+ /* 279 */ "cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list",
+ /* 280 */ "cmd ::= SPLIT VGROUP NK_INTEGER",
+ /* 281 */ "dnode_list ::= DNODE NK_INTEGER",
+ /* 282 */ "dnode_list ::= dnode_list DNODE NK_INTEGER",
+ /* 283 */ "cmd ::= SYNCDB db_name REPLICA",
+ /* 284 */ "cmd ::= DELETE FROM full_table_name where_clause_opt",
+ /* 285 */ "cmd ::= query_expression",
+ /* 286 */ "cmd ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_expression",
+ /* 287 */ "cmd ::= INSERT INTO full_table_name query_expression",
+ /* 288 */ "literal ::= NK_INTEGER",
+ /* 289 */ "literal ::= NK_FLOAT",
+ /* 290 */ "literal ::= NK_STRING",
+ /* 291 */ "literal ::= NK_BOOL",
+ /* 292 */ "literal ::= TIMESTAMP NK_STRING",
+ /* 293 */ "literal ::= duration_literal",
+ /* 294 */ "literal ::= NULL",
+ /* 295 */ "literal ::= NK_QUESTION",
+ /* 296 */ "duration_literal ::= NK_VARIABLE",
+ /* 297 */ "signed ::= NK_INTEGER",
+ /* 298 */ "signed ::= NK_PLUS NK_INTEGER",
+ /* 299 */ "signed ::= NK_MINUS NK_INTEGER",
+ /* 300 */ "signed ::= NK_FLOAT",
+ /* 301 */ "signed ::= NK_PLUS NK_FLOAT",
+ /* 302 */ "signed ::= NK_MINUS NK_FLOAT",
+ /* 303 */ "signed_literal ::= signed",
+ /* 304 */ "signed_literal ::= NK_STRING",
+ /* 305 */ "signed_literal ::= NK_BOOL",
+ /* 306 */ "signed_literal ::= TIMESTAMP NK_STRING",
+ /* 307 */ "signed_literal ::= duration_literal",
+ /* 308 */ "signed_literal ::= NULL",
+ /* 309 */ "signed_literal ::= literal_func",
+ /* 310 */ "signed_literal ::= NK_QUESTION",
+ /* 311 */ "literal_list ::= signed_literal",
+ /* 312 */ "literal_list ::= literal_list NK_COMMA signed_literal",
+ /* 313 */ "db_name ::= NK_ID",
+ /* 314 */ "table_name ::= NK_ID",
+ /* 315 */ "column_name ::= NK_ID",
+ /* 316 */ "function_name ::= NK_ID",
+ /* 317 */ "table_alias ::= NK_ID",
+ /* 318 */ "column_alias ::= NK_ID",
+ /* 319 */ "user_name ::= NK_ID",
+ /* 320 */ "index_name ::= NK_ID",
+ /* 321 */ "topic_name ::= NK_ID",
+ /* 322 */ "stream_name ::= NK_ID",
+ /* 323 */ "cgroup_name ::= NK_ID",
+ /* 324 */ "expression ::= literal",
+ /* 325 */ "expression ::= pseudo_column",
+ /* 326 */ "expression ::= column_reference",
+ /* 327 */ "expression ::= function_expression",
+ /* 328 */ "expression ::= subquery",
+ /* 329 */ "expression ::= NK_LP expression NK_RP",
+ /* 330 */ "expression ::= NK_PLUS expression",
+ /* 331 */ "expression ::= NK_MINUS expression",
+ /* 332 */ "expression ::= expression NK_PLUS expression",
+ /* 333 */ "expression ::= expression NK_MINUS expression",
+ /* 334 */ "expression ::= expression NK_STAR expression",
+ /* 335 */ "expression ::= expression NK_SLASH expression",
+ /* 336 */ "expression ::= expression NK_REM expression",
+ /* 337 */ "expression ::= column_reference NK_ARROW NK_STRING",
+ /* 338 */ "expression ::= expression NK_BITAND expression",
+ /* 339 */ "expression ::= expression NK_BITOR expression",
+ /* 340 */ "expression_list ::= expression",
+ /* 341 */ "expression_list ::= expression_list NK_COMMA expression",
+ /* 342 */ "column_reference ::= column_name",
+ /* 343 */ "column_reference ::= table_name NK_DOT column_name",
+ /* 344 */ "pseudo_column ::= ROWTS",
+ /* 345 */ "pseudo_column ::= TBNAME",
+ /* 346 */ "pseudo_column ::= table_name NK_DOT TBNAME",
+ /* 347 */ "pseudo_column ::= QSTART",
+ /* 348 */ "pseudo_column ::= QEND",
+ /* 349 */ "pseudo_column ::= QDURATION",
+ /* 350 */ "pseudo_column ::= WSTART",
+ /* 351 */ "pseudo_column ::= WEND",
+ /* 352 */ "pseudo_column ::= WDURATION",
+ /* 353 */ "function_expression ::= function_name NK_LP expression_list NK_RP",
+ /* 354 */ "function_expression ::= star_func NK_LP star_func_para_list NK_RP",
+ /* 355 */ "function_expression ::= CAST NK_LP expression AS type_name NK_RP",
+ /* 356 */ "function_expression ::= literal_func",
+ /* 357 */ "literal_func ::= noarg_func NK_LP NK_RP",
+ /* 358 */ "literal_func ::= NOW",
+ /* 359 */ "noarg_func ::= NOW",
+ /* 360 */ "noarg_func ::= TODAY",
+ /* 361 */ "noarg_func ::= TIMEZONE",
+ /* 362 */ "noarg_func ::= DATABASE",
+ /* 363 */ "noarg_func ::= CLIENT_VERSION",
+ /* 364 */ "noarg_func ::= SERVER_VERSION",
+ /* 365 */ "noarg_func ::= SERVER_STATUS",
+ /* 366 */ "noarg_func ::= CURRENT_USER",
+ /* 367 */ "noarg_func ::= USER",
+ /* 368 */ "star_func ::= COUNT",
+ /* 369 */ "star_func ::= FIRST",
+ /* 370 */ "star_func ::= LAST",
+ /* 371 */ "star_func ::= LAST_ROW",
+ /* 372 */ "star_func_para_list ::= NK_STAR",
+ /* 373 */ "star_func_para_list ::= other_para_list",
+ /* 374 */ "other_para_list ::= star_func_para",
+ /* 375 */ "other_para_list ::= other_para_list NK_COMMA star_func_para",
+ /* 376 */ "star_func_para ::= expression",
+ /* 377 */ "star_func_para ::= table_name NK_DOT NK_STAR",
+ /* 378 */ "predicate ::= expression compare_op expression",
+ /* 379 */ "predicate ::= expression BETWEEN expression AND expression",
+ /* 380 */ "predicate ::= expression NOT BETWEEN expression AND expression",
+ /* 381 */ "predicate ::= expression IS NULL",
+ /* 382 */ "predicate ::= expression IS NOT NULL",
+ /* 383 */ "predicate ::= expression in_op in_predicate_value",
+ /* 384 */ "compare_op ::= NK_LT",
+ /* 385 */ "compare_op ::= NK_GT",
+ /* 386 */ "compare_op ::= NK_LE",
+ /* 387 */ "compare_op ::= NK_GE",
+ /* 388 */ "compare_op ::= NK_NE",
+ /* 389 */ "compare_op ::= NK_EQ",
+ /* 390 */ "compare_op ::= LIKE",
+ /* 391 */ "compare_op ::= NOT LIKE",
+ /* 392 */ "compare_op ::= MATCH",
+ /* 393 */ "compare_op ::= NMATCH",
+ /* 394 */ "compare_op ::= CONTAINS",
+ /* 395 */ "in_op ::= IN",
+ /* 396 */ "in_op ::= NOT IN",
+ /* 397 */ "in_predicate_value ::= NK_LP literal_list NK_RP",
+ /* 398 */ "boolean_value_expression ::= boolean_primary",
+ /* 399 */ "boolean_value_expression ::= NOT boolean_primary",
+ /* 400 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression",
+ /* 401 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression",
+ /* 402 */ "boolean_primary ::= predicate",
+ /* 403 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP",
+ /* 404 */ "common_expression ::= expression",
+ /* 405 */ "common_expression ::= boolean_value_expression",
+ /* 406 */ "from_clause_opt ::=",
+ /* 407 */ "from_clause_opt ::= FROM table_reference_list",
+ /* 408 */ "table_reference_list ::= table_reference",
+ /* 409 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference",
+ /* 410 */ "table_reference ::= table_primary",
+ /* 411 */ "table_reference ::= joined_table",
+ /* 412 */ "table_primary ::= table_name alias_opt",
+ /* 413 */ "table_primary ::= db_name NK_DOT table_name alias_opt",
+ /* 414 */ "table_primary ::= subquery alias_opt",
+ /* 415 */ "table_primary ::= parenthesized_joined_table",
+ /* 416 */ "alias_opt ::=",
+ /* 417 */ "alias_opt ::= table_alias",
+ /* 418 */ "alias_opt ::= AS table_alias",
+ /* 419 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP",
+ /* 420 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP",
+ /* 421 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition",
+ /* 422 */ "join_type ::=",
+ /* 423 */ "join_type ::= INNER",
+ /* 424 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt",
+ /* 425 */ "set_quantifier_opt ::=",
+ /* 426 */ "set_quantifier_opt ::= DISTINCT",
+ /* 427 */ "set_quantifier_opt ::= ALL",
+ /* 428 */ "select_list ::= select_item",
+ /* 429 */ "select_list ::= select_list NK_COMMA select_item",
+ /* 430 */ "select_item ::= NK_STAR",
+ /* 431 */ "select_item ::= common_expression",
+ /* 432 */ "select_item ::= common_expression column_alias",
+ /* 433 */ "select_item ::= common_expression AS column_alias",
+ /* 434 */ "select_item ::= table_name NK_DOT NK_STAR",
+ /* 435 */ "where_clause_opt ::=",
+ /* 436 */ "where_clause_opt ::= WHERE search_condition",
+ /* 437 */ "partition_by_clause_opt ::=",
+ /* 438 */ "partition_by_clause_opt ::= PARTITION BY expression_list",
+ /* 439 */ "twindow_clause_opt ::=",
+ /* 440 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP",
+ /* 441 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP",
+ /* 442 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt",
+ /* 443 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt",
+ /* 444 */ "sliding_opt ::=",
+ /* 445 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP",
+ /* 446 */ "fill_opt ::=",
+ /* 447 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP",
+ /* 448 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP",
+ /* 449 */ "fill_mode ::= NONE",
+ /* 450 */ "fill_mode ::= PREV",
+ /* 451 */ "fill_mode ::= NULL",
+ /* 452 */ "fill_mode ::= LINEAR",
+ /* 453 */ "fill_mode ::= NEXT",
+ /* 454 */ "group_by_clause_opt ::=",
+ /* 455 */ "group_by_clause_opt ::= GROUP BY group_by_list",
+ /* 456 */ "group_by_list ::= expression",
+ /* 457 */ "group_by_list ::= group_by_list NK_COMMA expression",
+ /* 458 */ "having_clause_opt ::=",
+ /* 459 */ "having_clause_opt ::= HAVING search_condition",
+ /* 460 */ "range_opt ::=",
+ /* 461 */ "range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP",
+ /* 462 */ "every_opt ::=",
+ /* 463 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP",
+ /* 464 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt",
+ /* 465 */ "query_expression_body ::= query_primary",
+ /* 466 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body",
+ /* 467 */ "query_expression_body ::= query_expression_body UNION query_expression_body",
+ /* 468 */ "query_primary ::= query_specification",
+ /* 469 */ "query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP",
+ /* 470 */ "order_by_clause_opt ::=",
+ /* 471 */ "order_by_clause_opt ::= ORDER BY sort_specification_list",
+ /* 472 */ "slimit_clause_opt ::=",
+ /* 473 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER",
+ /* 474 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER",
+ /* 475 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER",
+ /* 476 */ "limit_clause_opt ::=",
+ /* 477 */ "limit_clause_opt ::= LIMIT NK_INTEGER",
+ /* 478 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER",
+ /* 479 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER",
+ /* 480 */ "subquery ::= NK_LP query_expression NK_RP",
+ /* 481 */ "search_condition ::= common_expression",
+ /* 482 */ "sort_specification_list ::= sort_specification",
+ /* 483 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification",
+ /* 484 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt",
+ /* 485 */ "ordering_specification_opt ::=",
+ /* 486 */ "ordering_specification_opt ::= ASC",
+ /* 487 */ "ordering_specification_opt ::= DESC",
+ /* 488 */ "null_ordering_opt ::=",
+ /* 489 */ "null_ordering_opt ::= NULLS FIRST",
+ /* 490 */ "null_ordering_opt ::= NULLS LAST",
};
#endif /* NDEBUG */
@@ -2139,176 +2269,181 @@ static void yy_destructor(
*/
/********* Begin destructor definitions ***************************************/
/* Default NON-TERMINAL Destructor */
- case 242: /* cmd */
- case 245: /* literal */
- case 255: /* db_options */
- case 257: /* alter_db_options */
- case 262: /* retention */
- case 263: /* full_table_name */
- case 266: /* table_options */
- case 270: /* alter_table_clause */
- case 271: /* alter_table_options */
- case 274: /* signed_literal */
- case 275: /* create_subtable_clause */
- case 278: /* drop_table_clause */
- case 281: /* column_def */
- case 285: /* duration_literal */
- case 286: /* rollup_func_name */
- case 288: /* col_name */
- case 289: /* db_name_cond_opt */
- case 290: /* like_pattern_opt */
- case 291: /* table_name_cond */
- case 292: /* from_db_opt */
- case 294: /* index_options */
- case 296: /* sliding_opt */
- case 297: /* func */
- case 300: /* query_expression */
- case 303: /* explain_options */
- case 307: /* stream_options */
- case 308: /* into_opt */
- case 310: /* where_clause_opt */
- case 311: /* signed */
- case 312: /* literal_func */
- case 315: /* expression */
- case 316: /* pseudo_column */
- case 317: /* column_reference */
- case 318: /* function_expression */
- case 319: /* subquery */
- case 324: /* star_func_para */
- case 325: /* predicate */
- case 328: /* in_predicate_value */
- case 329: /* boolean_value_expression */
- case 330: /* boolean_primary */
- case 331: /* common_expression */
- case 332: /* from_clause */
- case 333: /* table_reference_list */
- case 334: /* table_reference */
- case 335: /* table_primary */
- case 336: /* joined_table */
- case 338: /* parenthesized_joined_table */
- case 340: /* search_condition */
- case 341: /* query_specification */
- case 345: /* range_opt */
- case 346: /* every_opt */
- case 347: /* fill_opt */
- case 348: /* twindow_clause_opt */
- case 350: /* having_clause_opt */
- case 352: /* select_item */
- case 355: /* query_expression_body */
- case 357: /* slimit_clause_opt */
- case 358: /* limit_clause_opt */
- case 359: /* query_primary */
- case 361: /* sort_specification */
+ case 256: /* cmd */
+ case 259: /* literal */
+ case 270: /* db_options */
+ case 272: /* alter_db_options */
+ case 277: /* retention */
+ case 278: /* full_table_name */
+ case 281: /* table_options */
+ case 285: /* alter_table_clause */
+ case 286: /* alter_table_options */
+ case 289: /* signed_literal */
+ case 290: /* create_subtable_clause */
+ case 293: /* drop_table_clause */
+ case 296: /* column_def */
+ case 300: /* duration_literal */
+ case 301: /* rollup_func_name */
+ case 303: /* col_name */
+ case 304: /* db_name_cond_opt */
+ case 305: /* like_pattern_opt */
+ case 306: /* table_name_cond */
+ case 307: /* from_db_opt */
+ case 309: /* index_options */
+ case 311: /* sliding_opt */
+ case 312: /* sma_stream_opt */
+ case 313: /* func */
+ case 314: /* stream_options */
+ case 316: /* query_expression */
+ case 319: /* explain_options */
+ case 323: /* into_opt */
+ case 325: /* where_clause_opt */
+ case 326: /* signed */
+ case 327: /* literal_func */
+ case 331: /* expression */
+ case 332: /* pseudo_column */
+ case 333: /* column_reference */
+ case 334: /* function_expression */
+ case 335: /* subquery */
+ case 340: /* star_func_para */
+ case 341: /* predicate */
+ case 344: /* in_predicate_value */
+ case 345: /* boolean_value_expression */
+ case 346: /* boolean_primary */
+ case 347: /* common_expression */
+ case 348: /* from_clause_opt */
+ case 349: /* table_reference_list */
+ case 350: /* table_reference */
+ case 351: /* table_primary */
+ case 352: /* joined_table */
+ case 354: /* parenthesized_joined_table */
+ case 356: /* search_condition */
+ case 357: /* query_specification */
+ case 361: /* range_opt */
+ case 362: /* every_opt */
+ case 363: /* fill_opt */
+ case 364: /* twindow_clause_opt */
+ case 366: /* having_clause_opt */
+ case 367: /* select_item */
+ case 370: /* query_expression_body */
+ case 372: /* slimit_clause_opt */
+ case 373: /* limit_clause_opt */
+ case 374: /* query_primary */
+ case 376: /* sort_specification */
{
- nodesDestroyNode((yypminor->yy392));
+ nodesDestroyNode((yypminor->yy616));
}
break;
- case 243: /* account_options */
- case 244: /* alter_account_options */
- case 246: /* alter_account_option */
- case 305: /* bufsize_opt */
+ case 257: /* account_options */
+ case 258: /* alter_account_options */
+ case 260: /* alter_account_option */
+ case 321: /* bufsize_opt */
{
}
break;
- case 247: /* user_name */
- case 249: /* priv_level */
- case 252: /* db_name */
- case 253: /* dnode_endpoint */
- case 272: /* column_name */
- case 280: /* table_name */
- case 287: /* function_name */
- case 293: /* index_name */
- case 299: /* topic_name */
- case 301: /* cgroup_name */
- case 306: /* stream_name */
- case 313: /* table_alias */
- case 314: /* column_alias */
- case 320: /* star_func */
- case 322: /* noarg_func */
- case 337: /* alias_opt */
+ case 261: /* user_name */
+ case 264: /* priv_level */
+ case 267: /* db_name */
+ case 268: /* dnode_endpoint */
+ case 287: /* column_name */
+ case 295: /* table_name */
+ case 302: /* function_name */
+ case 308: /* index_name */
+ case 315: /* topic_name */
+ case 317: /* cgroup_name */
+ case 322: /* stream_name */
+ case 329: /* table_alias */
+ case 330: /* column_alias */
+ case 336: /* star_func */
+ case 338: /* noarg_func */
+ case 353: /* alias_opt */
{
}
break;
- case 248: /* privileges */
- case 250: /* priv_type_list */
- case 251: /* priv_type */
+ case 262: /* sysinfo_opt */
{
}
break;
- case 254: /* not_exists_opt */
- case 256: /* exists_opt */
- case 302: /* analyze_opt */
- case 304: /* agg_func_opt */
- case 342: /* set_quantifier_opt */
+ case 263: /* privileges */
+ case 265: /* priv_type_list */
+ case 266: /* priv_type */
{
}
break;
- case 258: /* integer_list */
- case 259: /* variable_list */
- case 260: /* retention_list */
- case 264: /* column_def_list */
- case 265: /* tags_def_opt */
- case 267: /* multi_create_clause */
- case 268: /* tags_def */
- case 269: /* multi_drop_clause */
- case 276: /* specific_tags_opt */
- case 277: /* literal_list */
- case 279: /* col_name_list */
- case 282: /* duration_list */
- case 283: /* rollup_func_list */
- case 295: /* func_list */
- case 298: /* expression_list */
- case 309: /* dnode_list */
- case 321: /* star_func_para_list */
- case 323: /* other_para_list */
- case 343: /* select_list */
- case 344: /* partition_by_clause_opt */
- case 349: /* group_by_clause_opt */
- case 351: /* select_sublist */
- case 354: /* group_by_list */
- case 356: /* order_by_clause_opt */
- case 360: /* sort_specification_list */
+ case 269: /* not_exists_opt */
+ case 271: /* exists_opt */
+ case 318: /* analyze_opt */
+ case 320: /* agg_func_opt */
+ case 358: /* set_quantifier_opt */
{
- nodesDestroyList((yypminor->yy600));
+
}
break;
- case 261: /* alter_db_option */
- case 284: /* alter_table_option */
+ case 273: /* integer_list */
+ case 274: /* variable_list */
+ case 275: /* retention_list */
+ case 279: /* column_def_list */
+ case 280: /* tags_def_opt */
+ case 282: /* multi_create_clause */
+ case 283: /* tags_def */
+ case 284: /* multi_drop_clause */
+ case 291: /* specific_cols_opt */
+ case 292: /* expression_list */
+ case 294: /* col_name_list */
+ case 297: /* duration_list */
+ case 298: /* rollup_func_list */
+ case 310: /* func_list */
+ case 324: /* dnode_list */
+ case 328: /* literal_list */
+ case 337: /* star_func_para_list */
+ case 339: /* other_para_list */
+ case 359: /* select_list */
+ case 360: /* partition_by_clause_opt */
+ case 365: /* group_by_clause_opt */
+ case 369: /* group_by_list */
+ case 371: /* order_by_clause_opt */
+ case 375: /* sort_specification_list */
+{
+ nodesDestroyList((yypminor->yy356));
+}
+ break;
+ case 276: /* alter_db_option */
+ case 299: /* alter_table_option */
{
}
break;
- case 273: /* type_name */
+ case 288: /* type_name */
{
}
break;
- case 326: /* compare_op */
- case 327: /* in_op */
+ case 342: /* compare_op */
+ case 343: /* in_op */
{
}
break;
- case 339: /* join_type */
+ case 355: /* join_type */
{
}
break;
- case 353: /* fill_mode */
+ case 368: /* fill_mode */
{
}
break;
- case 362: /* ordering_specification_opt */
+ case 377: /* ordering_specification_opt */
{
}
break;
- case 363: /* null_ordering_opt */
+ case 378: /* null_ordering_opt */
{
}
@@ -2607,472 +2742,497 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
- { 242, -6 }, /* (0) cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */
- { 242, -4 }, /* (1) cmd ::= ALTER ACCOUNT NK_ID alter_account_options */
- { 243, 0 }, /* (2) account_options ::= */
- { 243, -3 }, /* (3) account_options ::= account_options PPS literal */
- { 243, -3 }, /* (4) account_options ::= account_options TSERIES literal */
- { 243, -3 }, /* (5) account_options ::= account_options STORAGE literal */
- { 243, -3 }, /* (6) account_options ::= account_options STREAMS literal */
- { 243, -3 }, /* (7) account_options ::= account_options QTIME literal */
- { 243, -3 }, /* (8) account_options ::= account_options DBS literal */
- { 243, -3 }, /* (9) account_options ::= account_options USERS literal */
- { 243, -3 }, /* (10) account_options ::= account_options CONNS literal */
- { 243, -3 }, /* (11) account_options ::= account_options STATE literal */
- { 244, -1 }, /* (12) alter_account_options ::= alter_account_option */
- { 244, -2 }, /* (13) alter_account_options ::= alter_account_options alter_account_option */
- { 246, -2 }, /* (14) alter_account_option ::= PASS literal */
- { 246, -2 }, /* (15) alter_account_option ::= PPS literal */
- { 246, -2 }, /* (16) alter_account_option ::= TSERIES literal */
- { 246, -2 }, /* (17) alter_account_option ::= STORAGE literal */
- { 246, -2 }, /* (18) alter_account_option ::= STREAMS literal */
- { 246, -2 }, /* (19) alter_account_option ::= QTIME literal */
- { 246, -2 }, /* (20) alter_account_option ::= DBS literal */
- { 246, -2 }, /* (21) alter_account_option ::= USERS literal */
- { 246, -2 }, /* (22) alter_account_option ::= CONNS literal */
- { 246, -2 }, /* (23) alter_account_option ::= STATE literal */
- { 242, -5 }, /* (24) cmd ::= CREATE USER user_name PASS NK_STRING */
- { 242, -5 }, /* (25) cmd ::= ALTER USER user_name PASS NK_STRING */
- { 242, -5 }, /* (26) cmd ::= ALTER USER user_name PRIVILEGE NK_STRING */
- { 242, -3 }, /* (27) cmd ::= DROP USER user_name */
- { 242, -6 }, /* (28) cmd ::= GRANT privileges ON priv_level TO user_name */
- { 242, -6 }, /* (29) cmd ::= REVOKE privileges ON priv_level FROM user_name */
- { 248, -1 }, /* (30) privileges ::= ALL */
- { 248, -1 }, /* (31) privileges ::= priv_type_list */
- { 250, -1 }, /* (32) priv_type_list ::= priv_type */
- { 250, -3 }, /* (33) priv_type_list ::= priv_type_list NK_COMMA priv_type */
- { 251, -1 }, /* (34) priv_type ::= READ */
- { 251, -1 }, /* (35) priv_type ::= WRITE */
- { 249, -3 }, /* (36) priv_level ::= NK_STAR NK_DOT NK_STAR */
- { 249, -3 }, /* (37) priv_level ::= db_name NK_DOT NK_STAR */
- { 242, -3 }, /* (38) cmd ::= CREATE DNODE dnode_endpoint */
- { 242, -5 }, /* (39) cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */
- { 242, -3 }, /* (40) cmd ::= DROP DNODE NK_INTEGER */
- { 242, -3 }, /* (41) cmd ::= DROP DNODE dnode_endpoint */
- { 242, -4 }, /* (42) cmd ::= ALTER DNODE NK_INTEGER NK_STRING */
- { 242, -5 }, /* (43) cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */
- { 242, -4 }, /* (44) cmd ::= ALTER ALL DNODES NK_STRING */
- { 242, -5 }, /* (45) cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */
- { 253, -1 }, /* (46) dnode_endpoint ::= NK_STRING */
- { 253, -1 }, /* (47) dnode_endpoint ::= NK_ID */
- { 253, -1 }, /* (48) dnode_endpoint ::= NK_IPTOKEN */
- { 242, -3 }, /* (49) cmd ::= ALTER LOCAL NK_STRING */
- { 242, -4 }, /* (50) cmd ::= ALTER LOCAL NK_STRING NK_STRING */
- { 242, -5 }, /* (51) cmd ::= CREATE QNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (52) cmd ::= DROP QNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (53) cmd ::= CREATE BNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (54) cmd ::= DROP BNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (55) cmd ::= CREATE SNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (56) cmd ::= DROP SNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (57) cmd ::= CREATE MNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (58) cmd ::= DROP MNODE ON DNODE NK_INTEGER */
- { 242, -5 }, /* (59) cmd ::= CREATE DATABASE not_exists_opt db_name db_options */
- { 242, -4 }, /* (60) cmd ::= DROP DATABASE exists_opt db_name */
- { 242, -2 }, /* (61) cmd ::= USE db_name */
- { 242, -4 }, /* (62) cmd ::= ALTER DATABASE db_name alter_db_options */
- { 254, -3 }, /* (63) not_exists_opt ::= IF NOT EXISTS */
- { 254, 0 }, /* (64) not_exists_opt ::= */
- { 256, -2 }, /* (65) exists_opt ::= IF EXISTS */
- { 256, 0 }, /* (66) exists_opt ::= */
- { 255, 0 }, /* (67) db_options ::= */
- { 255, -3 }, /* (68) db_options ::= db_options BUFFER NK_INTEGER */
- { 255, -3 }, /* (69) db_options ::= db_options CACHELAST NK_INTEGER */
- { 255, -3 }, /* (70) db_options ::= db_options COMP NK_INTEGER */
- { 255, -3 }, /* (71) db_options ::= db_options DURATION NK_INTEGER */
- { 255, -3 }, /* (72) db_options ::= db_options DURATION NK_VARIABLE */
- { 255, -3 }, /* (73) db_options ::= db_options FSYNC NK_INTEGER */
- { 255, -3 }, /* (74) db_options ::= db_options MAXROWS NK_INTEGER */
- { 255, -3 }, /* (75) db_options ::= db_options MINROWS NK_INTEGER */
- { 255, -3 }, /* (76) db_options ::= db_options KEEP integer_list */
- { 255, -3 }, /* (77) db_options ::= db_options KEEP variable_list */
- { 255, -3 }, /* (78) db_options ::= db_options PAGES NK_INTEGER */
- { 255, -3 }, /* (79) db_options ::= db_options PAGESIZE NK_INTEGER */
- { 255, -3 }, /* (80) db_options ::= db_options PRECISION NK_STRING */
- { 255, -3 }, /* (81) db_options ::= db_options REPLICA NK_INTEGER */
- { 255, -3 }, /* (82) db_options ::= db_options STRICT NK_INTEGER */
- { 255, -3 }, /* (83) db_options ::= db_options WAL NK_INTEGER */
- { 255, -3 }, /* (84) db_options ::= db_options VGROUPS NK_INTEGER */
- { 255, -3 }, /* (85) db_options ::= db_options SINGLE_STABLE NK_INTEGER */
- { 255, -3 }, /* (86) db_options ::= db_options RETENTIONS retention_list */
- { 255, -3 }, /* (87) db_options ::= db_options SCHEMALESS NK_INTEGER */
- { 257, -1 }, /* (88) alter_db_options ::= alter_db_option */
- { 257, -2 }, /* (89) alter_db_options ::= alter_db_options alter_db_option */
- { 261, -2 }, /* (90) alter_db_option ::= BUFFER NK_INTEGER */
- { 261, -2 }, /* (91) alter_db_option ::= CACHELAST NK_INTEGER */
- { 261, -2 }, /* (92) alter_db_option ::= FSYNC NK_INTEGER */
- { 261, -2 }, /* (93) alter_db_option ::= KEEP integer_list */
- { 261, -2 }, /* (94) alter_db_option ::= KEEP variable_list */
- { 261, -2 }, /* (95) alter_db_option ::= PAGES NK_INTEGER */
- { 261, -2 }, /* (96) alter_db_option ::= REPLICA NK_INTEGER */
- { 261, -2 }, /* (97) alter_db_option ::= STRICT NK_INTEGER */
- { 261, -2 }, /* (98) alter_db_option ::= WAL NK_INTEGER */
- { 258, -1 }, /* (99) integer_list ::= NK_INTEGER */
- { 258, -3 }, /* (100) integer_list ::= integer_list NK_COMMA NK_INTEGER */
- { 259, -1 }, /* (101) variable_list ::= NK_VARIABLE */
- { 259, -3 }, /* (102) variable_list ::= variable_list NK_COMMA NK_VARIABLE */
- { 260, -1 }, /* (103) retention_list ::= retention */
- { 260, -3 }, /* (104) retention_list ::= retention_list NK_COMMA retention */
- { 262, -3 }, /* (105) retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */
- { 242, -9 }, /* (106) cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */
- { 242, -3 }, /* (107) cmd ::= CREATE TABLE multi_create_clause */
- { 242, -9 }, /* (108) cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */
- { 242, -3 }, /* (109) cmd ::= DROP TABLE multi_drop_clause */
- { 242, -4 }, /* (110) cmd ::= DROP STABLE exists_opt full_table_name */
- { 242, -3 }, /* (111) cmd ::= ALTER TABLE alter_table_clause */
- { 242, -3 }, /* (112) cmd ::= ALTER STABLE alter_table_clause */
- { 270, -2 }, /* (113) alter_table_clause ::= full_table_name alter_table_options */
- { 270, -5 }, /* (114) alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */
- { 270, -4 }, /* (115) alter_table_clause ::= full_table_name DROP COLUMN column_name */
- { 270, -5 }, /* (116) alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */
- { 270, -5 }, /* (117) alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */
- { 270, -5 }, /* (118) alter_table_clause ::= full_table_name ADD TAG column_name type_name */
- { 270, -4 }, /* (119) alter_table_clause ::= full_table_name DROP TAG column_name */
- { 270, -5 }, /* (120) alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */
- { 270, -5 }, /* (121) alter_table_clause ::= full_table_name RENAME TAG column_name column_name */
- { 270, -6 }, /* (122) alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */
- { 267, -1 }, /* (123) multi_create_clause ::= create_subtable_clause */
- { 267, -2 }, /* (124) multi_create_clause ::= multi_create_clause create_subtable_clause */
- { 275, -10 }, /* (125) create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP table_options */
- { 269, -1 }, /* (126) multi_drop_clause ::= drop_table_clause */
- { 269, -2 }, /* (127) multi_drop_clause ::= multi_drop_clause drop_table_clause */
- { 278, -2 }, /* (128) drop_table_clause ::= exists_opt full_table_name */
- { 276, 0 }, /* (129) specific_tags_opt ::= */
- { 276, -3 }, /* (130) specific_tags_opt ::= NK_LP col_name_list NK_RP */
- { 263, -1 }, /* (131) full_table_name ::= table_name */
- { 263, -3 }, /* (132) full_table_name ::= db_name NK_DOT table_name */
- { 264, -1 }, /* (133) column_def_list ::= column_def */
- { 264, -3 }, /* (134) column_def_list ::= column_def_list NK_COMMA column_def */
- { 281, -2 }, /* (135) column_def ::= column_name type_name */
- { 281, -4 }, /* (136) column_def ::= column_name type_name COMMENT NK_STRING */
- { 273, -1 }, /* (137) type_name ::= BOOL */
- { 273, -1 }, /* (138) type_name ::= TINYINT */
- { 273, -1 }, /* (139) type_name ::= SMALLINT */
- { 273, -1 }, /* (140) type_name ::= INT */
- { 273, -1 }, /* (141) type_name ::= INTEGER */
- { 273, -1 }, /* (142) type_name ::= BIGINT */
- { 273, -1 }, /* (143) type_name ::= FLOAT */
- { 273, -1 }, /* (144) type_name ::= DOUBLE */
- { 273, -4 }, /* (145) type_name ::= BINARY NK_LP NK_INTEGER NK_RP */
- { 273, -1 }, /* (146) type_name ::= TIMESTAMP */
- { 273, -4 }, /* (147) type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */
- { 273, -2 }, /* (148) type_name ::= TINYINT UNSIGNED */
- { 273, -2 }, /* (149) type_name ::= SMALLINT UNSIGNED */
- { 273, -2 }, /* (150) type_name ::= INT UNSIGNED */
- { 273, -2 }, /* (151) type_name ::= BIGINT UNSIGNED */
- { 273, -1 }, /* (152) type_name ::= JSON */
- { 273, -4 }, /* (153) type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */
- { 273, -1 }, /* (154) type_name ::= MEDIUMBLOB */
- { 273, -1 }, /* (155) type_name ::= BLOB */
- { 273, -4 }, /* (156) type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */
- { 273, -1 }, /* (157) type_name ::= DECIMAL */
- { 273, -4 }, /* (158) type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */
- { 273, -6 }, /* (159) type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */
- { 265, 0 }, /* (160) tags_def_opt ::= */
- { 265, -1 }, /* (161) tags_def_opt ::= tags_def */
- { 268, -4 }, /* (162) tags_def ::= TAGS NK_LP column_def_list NK_RP */
- { 266, 0 }, /* (163) table_options ::= */
- { 266, -3 }, /* (164) table_options ::= table_options COMMENT NK_STRING */
- { 266, -3 }, /* (165) table_options ::= table_options MAX_DELAY duration_list */
- { 266, -3 }, /* (166) table_options ::= table_options WATERMARK duration_list */
- { 266, -5 }, /* (167) table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */
- { 266, -3 }, /* (168) table_options ::= table_options TTL NK_INTEGER */
- { 266, -5 }, /* (169) table_options ::= table_options SMA NK_LP col_name_list NK_RP */
- { 271, -1 }, /* (170) alter_table_options ::= alter_table_option */
- { 271, -2 }, /* (171) alter_table_options ::= alter_table_options alter_table_option */
- { 284, -2 }, /* (172) alter_table_option ::= COMMENT NK_STRING */
- { 284, -2 }, /* (173) alter_table_option ::= TTL NK_INTEGER */
- { 282, -1 }, /* (174) duration_list ::= duration_literal */
- { 282, -3 }, /* (175) duration_list ::= duration_list NK_COMMA duration_literal */
- { 283, -1 }, /* (176) rollup_func_list ::= rollup_func_name */
- { 283, -3 }, /* (177) rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */
- { 286, -1 }, /* (178) rollup_func_name ::= function_name */
- { 286, -1 }, /* (179) rollup_func_name ::= FIRST */
- { 286, -1 }, /* (180) rollup_func_name ::= LAST */
- { 279, -1 }, /* (181) col_name_list ::= col_name */
- { 279, -3 }, /* (182) col_name_list ::= col_name_list NK_COMMA col_name */
- { 288, -1 }, /* (183) col_name ::= column_name */
- { 242, -2 }, /* (184) cmd ::= SHOW DNODES */
- { 242, -2 }, /* (185) cmd ::= SHOW USERS */
- { 242, -2 }, /* (186) cmd ::= SHOW DATABASES */
- { 242, -4 }, /* (187) cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */
- { 242, -4 }, /* (188) cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */
- { 242, -3 }, /* (189) cmd ::= SHOW db_name_cond_opt VGROUPS */
- { 242, -2 }, /* (190) cmd ::= SHOW MNODES */
- { 242, -2 }, /* (191) cmd ::= SHOW MODULES */
- { 242, -2 }, /* (192) cmd ::= SHOW QNODES */
- { 242, -2 }, /* (193) cmd ::= SHOW FUNCTIONS */
- { 242, -5 }, /* (194) cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */
- { 242, -2 }, /* (195) cmd ::= SHOW STREAMS */
- { 242, -2 }, /* (196) cmd ::= SHOW ACCOUNTS */
- { 242, -2 }, /* (197) cmd ::= SHOW APPS */
- { 242, -2 }, /* (198) cmd ::= SHOW CONNECTIONS */
- { 242, -2 }, /* (199) cmd ::= SHOW LICENCE */
- { 242, -2 }, /* (200) cmd ::= SHOW GRANTS */
- { 242, -4 }, /* (201) cmd ::= SHOW CREATE DATABASE db_name */
- { 242, -4 }, /* (202) cmd ::= SHOW CREATE TABLE full_table_name */
- { 242, -4 }, /* (203) cmd ::= SHOW CREATE STABLE full_table_name */
- { 242, -2 }, /* (204) cmd ::= SHOW QUERIES */
- { 242, -2 }, /* (205) cmd ::= SHOW SCORES */
- { 242, -2 }, /* (206) cmd ::= SHOW TOPICS */
- { 242, -2 }, /* (207) cmd ::= SHOW VARIABLES */
- { 242, -3 }, /* (208) cmd ::= SHOW LOCAL VARIABLES */
- { 242, -4 }, /* (209) cmd ::= SHOW DNODE NK_INTEGER VARIABLES */
- { 242, -2 }, /* (210) cmd ::= SHOW BNODES */
- { 242, -2 }, /* (211) cmd ::= SHOW SNODES */
- { 242, -2 }, /* (212) cmd ::= SHOW CLUSTER */
- { 242, -2 }, /* (213) cmd ::= SHOW TRANSACTIONS */
- { 242, -4 }, /* (214) cmd ::= SHOW TABLE DISTRIBUTED full_table_name */
- { 289, 0 }, /* (215) db_name_cond_opt ::= */
- { 289, -2 }, /* (216) db_name_cond_opt ::= db_name NK_DOT */
- { 290, 0 }, /* (217) like_pattern_opt ::= */
- { 290, -2 }, /* (218) like_pattern_opt ::= LIKE NK_STRING */
- { 291, -1 }, /* (219) table_name_cond ::= table_name */
- { 292, 0 }, /* (220) from_db_opt ::= */
- { 292, -2 }, /* (221) from_db_opt ::= FROM db_name */
- { 242, -8 }, /* (222) cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options */
- { 242, -10 }, /* (223) cmd ::= CREATE FULLTEXT INDEX not_exists_opt index_name ON table_name NK_LP col_name_list NK_RP */
- { 242, -6 }, /* (224) cmd ::= DROP INDEX exists_opt index_name ON table_name */
- { 294, 0 }, /* (225) index_options ::= */
- { 294, -9 }, /* (226) index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt */
- { 294, -11 }, /* (227) index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt */
- { 295, -1 }, /* (228) func_list ::= func */
- { 295, -3 }, /* (229) func_list ::= func_list NK_COMMA func */
- { 297, -4 }, /* (230) func ::= function_name NK_LP expression_list NK_RP */
- { 242, -6 }, /* (231) cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression */
- { 242, -7 }, /* (232) cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */
- { 242, -7 }, /* (233) cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */
- { 242, -4 }, /* (234) cmd ::= DROP TOPIC exists_opt topic_name */
- { 242, -7 }, /* (235) cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */
- { 242, -2 }, /* (236) cmd ::= DESC full_table_name */
- { 242, -2 }, /* (237) cmd ::= DESCRIBE full_table_name */
- { 242, -3 }, /* (238) cmd ::= RESET QUERY CACHE */
- { 242, -4 }, /* (239) cmd ::= EXPLAIN analyze_opt explain_options query_expression */
- { 302, 0 }, /* (240) analyze_opt ::= */
- { 302, -1 }, /* (241) analyze_opt ::= ANALYZE */
- { 303, 0 }, /* (242) explain_options ::= */
- { 303, -3 }, /* (243) explain_options ::= explain_options VERBOSE NK_BOOL */
- { 303, -3 }, /* (244) explain_options ::= explain_options RATIO NK_FLOAT */
- { 242, -6 }, /* (245) cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP */
- { 242, -10 }, /* (246) cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt */
- { 242, -4 }, /* (247) cmd ::= DROP FUNCTION exists_opt function_name */
- { 304, 0 }, /* (248) agg_func_opt ::= */
- { 304, -1 }, /* (249) agg_func_opt ::= AGGREGATE */
- { 305, 0 }, /* (250) bufsize_opt ::= */
- { 305, -2 }, /* (251) bufsize_opt ::= BUFSIZE NK_INTEGER */
- { 242, -8 }, /* (252) cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression */
- { 242, -4 }, /* (253) cmd ::= DROP STREAM exists_opt stream_name */
- { 308, 0 }, /* (254) into_opt ::= */
- { 308, -2 }, /* (255) into_opt ::= INTO full_table_name */
- { 307, 0 }, /* (256) stream_options ::= */
- { 307, -3 }, /* (257) stream_options ::= stream_options TRIGGER AT_ONCE */
- { 307, -3 }, /* (258) stream_options ::= stream_options TRIGGER WINDOW_CLOSE */
- { 307, -4 }, /* (259) stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */
- { 307, -3 }, /* (260) stream_options ::= stream_options WATERMARK duration_literal */
- { 242, -3 }, /* (261) cmd ::= KILL CONNECTION NK_INTEGER */
- { 242, -3 }, /* (262) cmd ::= KILL QUERY NK_STRING */
- { 242, -3 }, /* (263) cmd ::= KILL TRANSACTION NK_INTEGER */
- { 242, -2 }, /* (264) cmd ::= BALANCE VGROUP */
- { 242, -4 }, /* (265) cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */
- { 242, -4 }, /* (266) cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */
- { 242, -3 }, /* (267) cmd ::= SPLIT VGROUP NK_INTEGER */
- { 309, -2 }, /* (268) dnode_list ::= DNODE NK_INTEGER */
- { 309, -3 }, /* (269) dnode_list ::= dnode_list DNODE NK_INTEGER */
- { 242, -3 }, /* (270) cmd ::= SYNCDB db_name REPLICA */
- { 242, -4 }, /* (271) cmd ::= DELETE FROM full_table_name where_clause_opt */
- { 242, -1 }, /* (272) cmd ::= query_expression */
- { 245, -1 }, /* (273) literal ::= NK_INTEGER */
- { 245, -1 }, /* (274) literal ::= NK_FLOAT */
- { 245, -1 }, /* (275) literal ::= NK_STRING */
- { 245, -1 }, /* (276) literal ::= NK_BOOL */
- { 245, -2 }, /* (277) literal ::= TIMESTAMP NK_STRING */
- { 245, -1 }, /* (278) literal ::= duration_literal */
- { 245, -1 }, /* (279) literal ::= NULL */
- { 245, -1 }, /* (280) literal ::= NK_QUESTION */
- { 285, -1 }, /* (281) duration_literal ::= NK_VARIABLE */
- { 311, -1 }, /* (282) signed ::= NK_INTEGER */
- { 311, -2 }, /* (283) signed ::= NK_PLUS NK_INTEGER */
- { 311, -2 }, /* (284) signed ::= NK_MINUS NK_INTEGER */
- { 311, -1 }, /* (285) signed ::= NK_FLOAT */
- { 311, -2 }, /* (286) signed ::= NK_PLUS NK_FLOAT */
- { 311, -2 }, /* (287) signed ::= NK_MINUS NK_FLOAT */
- { 274, -1 }, /* (288) signed_literal ::= signed */
- { 274, -1 }, /* (289) signed_literal ::= NK_STRING */
- { 274, -1 }, /* (290) signed_literal ::= NK_BOOL */
- { 274, -2 }, /* (291) signed_literal ::= TIMESTAMP NK_STRING */
- { 274, -1 }, /* (292) signed_literal ::= duration_literal */
- { 274, -1 }, /* (293) signed_literal ::= NULL */
- { 274, -1 }, /* (294) signed_literal ::= literal_func */
- { 277, -1 }, /* (295) literal_list ::= signed_literal */
- { 277, -3 }, /* (296) literal_list ::= literal_list NK_COMMA signed_literal */
- { 252, -1 }, /* (297) db_name ::= NK_ID */
- { 280, -1 }, /* (298) table_name ::= NK_ID */
- { 272, -1 }, /* (299) column_name ::= NK_ID */
- { 287, -1 }, /* (300) function_name ::= NK_ID */
- { 313, -1 }, /* (301) table_alias ::= NK_ID */
- { 314, -1 }, /* (302) column_alias ::= NK_ID */
- { 247, -1 }, /* (303) user_name ::= NK_ID */
- { 293, -1 }, /* (304) index_name ::= NK_ID */
- { 299, -1 }, /* (305) topic_name ::= NK_ID */
- { 306, -1 }, /* (306) stream_name ::= NK_ID */
- { 301, -1 }, /* (307) cgroup_name ::= NK_ID */
- { 315, -1 }, /* (308) expression ::= literal */
- { 315, -1 }, /* (309) expression ::= pseudo_column */
- { 315, -1 }, /* (310) expression ::= column_reference */
- { 315, -1 }, /* (311) expression ::= function_expression */
- { 315, -1 }, /* (312) expression ::= subquery */
- { 315, -3 }, /* (313) expression ::= NK_LP expression NK_RP */
- { 315, -2 }, /* (314) expression ::= NK_PLUS expression */
- { 315, -2 }, /* (315) expression ::= NK_MINUS expression */
- { 315, -3 }, /* (316) expression ::= expression NK_PLUS expression */
- { 315, -3 }, /* (317) expression ::= expression NK_MINUS expression */
- { 315, -3 }, /* (318) expression ::= expression NK_STAR expression */
- { 315, -3 }, /* (319) expression ::= expression NK_SLASH expression */
- { 315, -3 }, /* (320) expression ::= expression NK_REM expression */
- { 315, -3 }, /* (321) expression ::= column_reference NK_ARROW NK_STRING */
- { 298, -1 }, /* (322) expression_list ::= expression */
- { 298, -3 }, /* (323) expression_list ::= expression_list NK_COMMA expression */
- { 317, -1 }, /* (324) column_reference ::= column_name */
- { 317, -3 }, /* (325) column_reference ::= table_name NK_DOT column_name */
- { 316, -1 }, /* (326) pseudo_column ::= ROWTS */
- { 316, -1 }, /* (327) pseudo_column ::= TBNAME */
- { 316, -3 }, /* (328) pseudo_column ::= table_name NK_DOT TBNAME */
- { 316, -1 }, /* (329) pseudo_column ::= QSTARTTS */
- { 316, -1 }, /* (330) pseudo_column ::= QENDTS */
- { 316, -1 }, /* (331) pseudo_column ::= WSTARTTS */
- { 316, -1 }, /* (332) pseudo_column ::= WENDTS */
- { 316, -1 }, /* (333) pseudo_column ::= WDURATION */
- { 318, -4 }, /* (334) function_expression ::= function_name NK_LP expression_list NK_RP */
- { 318, -4 }, /* (335) function_expression ::= star_func NK_LP star_func_para_list NK_RP */
- { 318, -6 }, /* (336) function_expression ::= CAST NK_LP expression AS type_name NK_RP */
- { 318, -1 }, /* (337) function_expression ::= literal_func */
- { 312, -3 }, /* (338) literal_func ::= noarg_func NK_LP NK_RP */
- { 312, -1 }, /* (339) literal_func ::= NOW */
- { 322, -1 }, /* (340) noarg_func ::= NOW */
- { 322, -1 }, /* (341) noarg_func ::= TODAY */
- { 322, -1 }, /* (342) noarg_func ::= TIMEZONE */
- { 320, -1 }, /* (343) star_func ::= COUNT */
- { 320, -1 }, /* (344) star_func ::= FIRST */
- { 320, -1 }, /* (345) star_func ::= LAST */
- { 320, -1 }, /* (346) star_func ::= LAST_ROW */
- { 321, -1 }, /* (347) star_func_para_list ::= NK_STAR */
- { 321, -1 }, /* (348) star_func_para_list ::= other_para_list */
- { 323, -1 }, /* (349) other_para_list ::= star_func_para */
- { 323, -3 }, /* (350) other_para_list ::= other_para_list NK_COMMA star_func_para */
- { 324, -1 }, /* (351) star_func_para ::= expression */
- { 324, -3 }, /* (352) star_func_para ::= table_name NK_DOT NK_STAR */
- { 325, -3 }, /* (353) predicate ::= expression compare_op expression */
- { 325, -5 }, /* (354) predicate ::= expression BETWEEN expression AND expression */
- { 325, -6 }, /* (355) predicate ::= expression NOT BETWEEN expression AND expression */
- { 325, -3 }, /* (356) predicate ::= expression IS NULL */
- { 325, -4 }, /* (357) predicate ::= expression IS NOT NULL */
- { 325, -3 }, /* (358) predicate ::= expression in_op in_predicate_value */
- { 326, -1 }, /* (359) compare_op ::= NK_LT */
- { 326, -1 }, /* (360) compare_op ::= NK_GT */
- { 326, -1 }, /* (361) compare_op ::= NK_LE */
- { 326, -1 }, /* (362) compare_op ::= NK_GE */
- { 326, -1 }, /* (363) compare_op ::= NK_NE */
- { 326, -1 }, /* (364) compare_op ::= NK_EQ */
- { 326, -1 }, /* (365) compare_op ::= LIKE */
- { 326, -2 }, /* (366) compare_op ::= NOT LIKE */
- { 326, -1 }, /* (367) compare_op ::= MATCH */
- { 326, -1 }, /* (368) compare_op ::= NMATCH */
- { 326, -1 }, /* (369) compare_op ::= CONTAINS */
- { 327, -1 }, /* (370) in_op ::= IN */
- { 327, -2 }, /* (371) in_op ::= NOT IN */
- { 328, -3 }, /* (372) in_predicate_value ::= NK_LP expression_list NK_RP */
- { 329, -1 }, /* (373) boolean_value_expression ::= boolean_primary */
- { 329, -2 }, /* (374) boolean_value_expression ::= NOT boolean_primary */
- { 329, -3 }, /* (375) boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */
- { 329, -3 }, /* (376) boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */
- { 330, -1 }, /* (377) boolean_primary ::= predicate */
- { 330, -3 }, /* (378) boolean_primary ::= NK_LP boolean_value_expression NK_RP */
- { 331, -1 }, /* (379) common_expression ::= expression */
- { 331, -1 }, /* (380) common_expression ::= boolean_value_expression */
- { 332, -2 }, /* (381) from_clause ::= FROM table_reference_list */
- { 333, -1 }, /* (382) table_reference_list ::= table_reference */
- { 333, -3 }, /* (383) table_reference_list ::= table_reference_list NK_COMMA table_reference */
- { 334, -1 }, /* (384) table_reference ::= table_primary */
- { 334, -1 }, /* (385) table_reference ::= joined_table */
- { 335, -2 }, /* (386) table_primary ::= table_name alias_opt */
- { 335, -4 }, /* (387) table_primary ::= db_name NK_DOT table_name alias_opt */
- { 335, -2 }, /* (388) table_primary ::= subquery alias_opt */
- { 335, -1 }, /* (389) table_primary ::= parenthesized_joined_table */
- { 337, 0 }, /* (390) alias_opt ::= */
- { 337, -1 }, /* (391) alias_opt ::= table_alias */
- { 337, -2 }, /* (392) alias_opt ::= AS table_alias */
- { 338, -3 }, /* (393) parenthesized_joined_table ::= NK_LP joined_table NK_RP */
- { 338, -3 }, /* (394) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */
- { 336, -6 }, /* (395) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */
- { 339, 0 }, /* (396) join_type ::= */
- { 339, -1 }, /* (397) join_type ::= INNER */
- { 341, -12 }, /* (398) query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */
- { 342, 0 }, /* (399) set_quantifier_opt ::= */
- { 342, -1 }, /* (400) set_quantifier_opt ::= DISTINCT */
- { 342, -1 }, /* (401) set_quantifier_opt ::= ALL */
- { 343, -1 }, /* (402) select_list ::= NK_STAR */
- { 343, -1 }, /* (403) select_list ::= select_sublist */
- { 351, -1 }, /* (404) select_sublist ::= select_item */
- { 351, -3 }, /* (405) select_sublist ::= select_sublist NK_COMMA select_item */
- { 352, -1 }, /* (406) select_item ::= common_expression */
- { 352, -2 }, /* (407) select_item ::= common_expression column_alias */
- { 352, -3 }, /* (408) select_item ::= common_expression AS column_alias */
- { 352, -3 }, /* (409) select_item ::= table_name NK_DOT NK_STAR */
- { 310, 0 }, /* (410) where_clause_opt ::= */
- { 310, -2 }, /* (411) where_clause_opt ::= WHERE search_condition */
- { 344, 0 }, /* (412) partition_by_clause_opt ::= */
- { 344, -3 }, /* (413) partition_by_clause_opt ::= PARTITION BY expression_list */
- { 348, 0 }, /* (414) twindow_clause_opt ::= */
- { 348, -6 }, /* (415) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */
- { 348, -4 }, /* (416) twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */
- { 348, -6 }, /* (417) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */
- { 348, -8 }, /* (418) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */
- { 296, 0 }, /* (419) sliding_opt ::= */
- { 296, -4 }, /* (420) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */
- { 347, 0 }, /* (421) fill_opt ::= */
- { 347, -4 }, /* (422) fill_opt ::= FILL NK_LP fill_mode NK_RP */
- { 347, -6 }, /* (423) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */
- { 353, -1 }, /* (424) fill_mode ::= NONE */
- { 353, -1 }, /* (425) fill_mode ::= PREV */
- { 353, -1 }, /* (426) fill_mode ::= NULL */
- { 353, -1 }, /* (427) fill_mode ::= LINEAR */
- { 353, -1 }, /* (428) fill_mode ::= NEXT */
- { 349, 0 }, /* (429) group_by_clause_opt ::= */
- { 349, -3 }, /* (430) group_by_clause_opt ::= GROUP BY group_by_list */
- { 354, -1 }, /* (431) group_by_list ::= expression */
- { 354, -3 }, /* (432) group_by_list ::= group_by_list NK_COMMA expression */
- { 350, 0 }, /* (433) having_clause_opt ::= */
- { 350, -2 }, /* (434) having_clause_opt ::= HAVING search_condition */
- { 345, 0 }, /* (435) range_opt ::= */
- { 345, -6 }, /* (436) range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */
- { 346, 0 }, /* (437) every_opt ::= */
- { 346, -4 }, /* (438) every_opt ::= EVERY NK_LP duration_literal NK_RP */
- { 300, -4 }, /* (439) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
- { 355, -1 }, /* (440) query_expression_body ::= query_primary */
- { 355, -4 }, /* (441) query_expression_body ::= query_expression_body UNION ALL query_expression_body */
- { 355, -3 }, /* (442) query_expression_body ::= query_expression_body UNION query_expression_body */
- { 359, -1 }, /* (443) query_primary ::= query_specification */
- { 359, -6 }, /* (444) query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */
- { 356, 0 }, /* (445) order_by_clause_opt ::= */
- { 356, -3 }, /* (446) order_by_clause_opt ::= ORDER BY sort_specification_list */
- { 357, 0 }, /* (447) slimit_clause_opt ::= */
- { 357, -2 }, /* (448) slimit_clause_opt ::= SLIMIT NK_INTEGER */
- { 357, -4 }, /* (449) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
- { 357, -4 }, /* (450) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
- { 358, 0 }, /* (451) limit_clause_opt ::= */
- { 358, -2 }, /* (452) limit_clause_opt ::= LIMIT NK_INTEGER */
- { 358, -4 }, /* (453) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */
- { 358, -4 }, /* (454) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */
- { 319, -3 }, /* (455) subquery ::= NK_LP query_expression NK_RP */
- { 340, -1 }, /* (456) search_condition ::= common_expression */
- { 360, -1 }, /* (457) sort_specification_list ::= sort_specification */
- { 360, -3 }, /* (458) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */
- { 361, -3 }, /* (459) sort_specification ::= expression ordering_specification_opt null_ordering_opt */
- { 362, 0 }, /* (460) ordering_specification_opt ::= */
- { 362, -1 }, /* (461) ordering_specification_opt ::= ASC */
- { 362, -1 }, /* (462) ordering_specification_opt ::= DESC */
- { 363, 0 }, /* (463) null_ordering_opt ::= */
- { 363, -2 }, /* (464) null_ordering_opt ::= NULLS FIRST */
- { 363, -2 }, /* (465) null_ordering_opt ::= NULLS LAST */
+ { 256, -6 }, /* (0) cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */
+ { 256, -4 }, /* (1) cmd ::= ALTER ACCOUNT NK_ID alter_account_options */
+ { 257, 0 }, /* (2) account_options ::= */
+ { 257, -3 }, /* (3) account_options ::= account_options PPS literal */
+ { 257, -3 }, /* (4) account_options ::= account_options TSERIES literal */
+ { 257, -3 }, /* (5) account_options ::= account_options STORAGE literal */
+ { 257, -3 }, /* (6) account_options ::= account_options STREAMS literal */
+ { 257, -3 }, /* (7) account_options ::= account_options QTIME literal */
+ { 257, -3 }, /* (8) account_options ::= account_options DBS literal */
+ { 257, -3 }, /* (9) account_options ::= account_options USERS literal */
+ { 257, -3 }, /* (10) account_options ::= account_options CONNS literal */
+ { 257, -3 }, /* (11) account_options ::= account_options STATE literal */
+ { 258, -1 }, /* (12) alter_account_options ::= alter_account_option */
+ { 258, -2 }, /* (13) alter_account_options ::= alter_account_options alter_account_option */
+ { 260, -2 }, /* (14) alter_account_option ::= PASS literal */
+ { 260, -2 }, /* (15) alter_account_option ::= PPS literal */
+ { 260, -2 }, /* (16) alter_account_option ::= TSERIES literal */
+ { 260, -2 }, /* (17) alter_account_option ::= STORAGE literal */
+ { 260, -2 }, /* (18) alter_account_option ::= STREAMS literal */
+ { 260, -2 }, /* (19) alter_account_option ::= QTIME literal */
+ { 260, -2 }, /* (20) alter_account_option ::= DBS literal */
+ { 260, -2 }, /* (21) alter_account_option ::= USERS literal */
+ { 260, -2 }, /* (22) alter_account_option ::= CONNS literal */
+ { 260, -2 }, /* (23) alter_account_option ::= STATE literal */
+ { 256, -6 }, /* (24) cmd ::= CREATE USER user_name PASS NK_STRING sysinfo_opt */
+ { 256, -5 }, /* (25) cmd ::= ALTER USER user_name PASS NK_STRING */
+ { 256, -5 }, /* (26) cmd ::= ALTER USER user_name ENABLE NK_INTEGER */
+ { 256, -5 }, /* (27) cmd ::= ALTER USER user_name SYSINFO NK_INTEGER */
+ { 256, -3 }, /* (28) cmd ::= DROP USER user_name */
+ { 262, 0 }, /* (29) sysinfo_opt ::= */
+ { 262, -2 }, /* (30) sysinfo_opt ::= SYSINFO NK_INTEGER */
+ { 256, -6 }, /* (31) cmd ::= GRANT privileges ON priv_level TO user_name */
+ { 256, -6 }, /* (32) cmd ::= REVOKE privileges ON priv_level FROM user_name */
+ { 263, -1 }, /* (33) privileges ::= ALL */
+ { 263, -1 }, /* (34) privileges ::= priv_type_list */
+ { 265, -1 }, /* (35) priv_type_list ::= priv_type */
+ { 265, -3 }, /* (36) priv_type_list ::= priv_type_list NK_COMMA priv_type */
+ { 266, -1 }, /* (37) priv_type ::= READ */
+ { 266, -1 }, /* (38) priv_type ::= WRITE */
+ { 264, -3 }, /* (39) priv_level ::= NK_STAR NK_DOT NK_STAR */
+ { 264, -3 }, /* (40) priv_level ::= db_name NK_DOT NK_STAR */
+ { 256, -3 }, /* (41) cmd ::= CREATE DNODE dnode_endpoint */
+ { 256, -5 }, /* (42) cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */
+ { 256, -3 }, /* (43) cmd ::= DROP DNODE NK_INTEGER */
+ { 256, -3 }, /* (44) cmd ::= DROP DNODE dnode_endpoint */
+ { 256, -4 }, /* (45) cmd ::= ALTER DNODE NK_INTEGER NK_STRING */
+ { 256, -5 }, /* (46) cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */
+ { 256, -4 }, /* (47) cmd ::= ALTER ALL DNODES NK_STRING */
+ { 256, -5 }, /* (48) cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */
+ { 268, -1 }, /* (49) dnode_endpoint ::= NK_STRING */
+ { 268, -1 }, /* (50) dnode_endpoint ::= NK_ID */
+ { 268, -1 }, /* (51) dnode_endpoint ::= NK_IPTOKEN */
+ { 256, -3 }, /* (52) cmd ::= ALTER LOCAL NK_STRING */
+ { 256, -4 }, /* (53) cmd ::= ALTER LOCAL NK_STRING NK_STRING */
+ { 256, -5 }, /* (54) cmd ::= CREATE QNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (55) cmd ::= DROP QNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (56) cmd ::= CREATE BNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (57) cmd ::= DROP BNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (58) cmd ::= CREATE SNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (59) cmd ::= DROP SNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (60) cmd ::= CREATE MNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (61) cmd ::= DROP MNODE ON DNODE NK_INTEGER */
+ { 256, -5 }, /* (62) cmd ::= CREATE DATABASE not_exists_opt db_name db_options */
+ { 256, -4 }, /* (63) cmd ::= DROP DATABASE exists_opt db_name */
+ { 256, -2 }, /* (64) cmd ::= USE db_name */
+ { 256, -4 }, /* (65) cmd ::= ALTER DATABASE db_name alter_db_options */
+ { 256, -3 }, /* (66) cmd ::= FLUSH DATABASE db_name */
+ { 256, -3 }, /* (67) cmd ::= TRIM DATABASE db_name */
+ { 269, -3 }, /* (68) not_exists_opt ::= IF NOT EXISTS */
+ { 269, 0 }, /* (69) not_exists_opt ::= */
+ { 271, -2 }, /* (70) exists_opt ::= IF EXISTS */
+ { 271, 0 }, /* (71) exists_opt ::= */
+ { 270, 0 }, /* (72) db_options ::= */
+ { 270, -3 }, /* (73) db_options ::= db_options BUFFER NK_INTEGER */
+ { 270, -3 }, /* (74) db_options ::= db_options CACHELAST NK_INTEGER */
+ { 270, -3 }, /* (75) db_options ::= db_options CACHELASTSIZE NK_INTEGER */
+ { 270, -3 }, /* (76) db_options ::= db_options COMP NK_INTEGER */
+ { 270, -3 }, /* (77) db_options ::= db_options DURATION NK_INTEGER */
+ { 270, -3 }, /* (78) db_options ::= db_options DURATION NK_VARIABLE */
+ { 270, -3 }, /* (79) db_options ::= db_options FSYNC NK_INTEGER */
+ { 270, -3 }, /* (80) db_options ::= db_options MAXROWS NK_INTEGER */
+ { 270, -3 }, /* (81) db_options ::= db_options MINROWS NK_INTEGER */
+ { 270, -3 }, /* (82) db_options ::= db_options KEEP integer_list */
+ { 270, -3 }, /* (83) db_options ::= db_options KEEP variable_list */
+ { 270, -3 }, /* (84) db_options ::= db_options PAGES NK_INTEGER */
+ { 270, -3 }, /* (85) db_options ::= db_options PAGESIZE NK_INTEGER */
+ { 270, -3 }, /* (86) db_options ::= db_options PRECISION NK_STRING */
+ { 270, -3 }, /* (87) db_options ::= db_options REPLICA NK_INTEGER */
+ { 270, -3 }, /* (88) db_options ::= db_options STRICT NK_INTEGER */
+ { 270, -3 }, /* (89) db_options ::= db_options WAL NK_INTEGER */
+ { 270, -3 }, /* (90) db_options ::= db_options VGROUPS NK_INTEGER */
+ { 270, -3 }, /* (91) db_options ::= db_options SINGLE_STABLE NK_INTEGER */
+ { 270, -3 }, /* (92) db_options ::= db_options RETENTIONS retention_list */
+ { 270, -3 }, /* (93) db_options ::= db_options SCHEMALESS NK_INTEGER */
+ { 272, -1 }, /* (94) alter_db_options ::= alter_db_option */
+ { 272, -2 }, /* (95) alter_db_options ::= alter_db_options alter_db_option */
+ { 276, -2 }, /* (96) alter_db_option ::= BUFFER NK_INTEGER */
+ { 276, -2 }, /* (97) alter_db_option ::= CACHELAST NK_INTEGER */
+ { 276, -2 }, /* (98) alter_db_option ::= CACHELASTSIZE NK_INTEGER */
+ { 276, -2 }, /* (99) alter_db_option ::= FSYNC NK_INTEGER */
+ { 276, -2 }, /* (100) alter_db_option ::= KEEP integer_list */
+ { 276, -2 }, /* (101) alter_db_option ::= KEEP variable_list */
+ { 276, -2 }, /* (102) alter_db_option ::= PAGES NK_INTEGER */
+ { 276, -2 }, /* (103) alter_db_option ::= REPLICA NK_INTEGER */
+ { 276, -2 }, /* (104) alter_db_option ::= STRICT NK_INTEGER */
+ { 276, -2 }, /* (105) alter_db_option ::= WAL NK_INTEGER */
+ { 273, -1 }, /* (106) integer_list ::= NK_INTEGER */
+ { 273, -3 }, /* (107) integer_list ::= integer_list NK_COMMA NK_INTEGER */
+ { 274, -1 }, /* (108) variable_list ::= NK_VARIABLE */
+ { 274, -3 }, /* (109) variable_list ::= variable_list NK_COMMA NK_VARIABLE */
+ { 275, -1 }, /* (110) retention_list ::= retention */
+ { 275, -3 }, /* (111) retention_list ::= retention_list NK_COMMA retention */
+ { 277, -3 }, /* (112) retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */
+ { 256, -9 }, /* (113) cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */
+ { 256, -3 }, /* (114) cmd ::= CREATE TABLE multi_create_clause */
+ { 256, -9 }, /* (115) cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */
+ { 256, -3 }, /* (116) cmd ::= DROP TABLE multi_drop_clause */
+ { 256, -4 }, /* (117) cmd ::= DROP STABLE exists_opt full_table_name */
+ { 256, -3 }, /* (118) cmd ::= ALTER TABLE alter_table_clause */
+ { 256, -3 }, /* (119) cmd ::= ALTER STABLE alter_table_clause */
+ { 285, -2 }, /* (120) alter_table_clause ::= full_table_name alter_table_options */
+ { 285, -5 }, /* (121) alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */
+ { 285, -4 }, /* (122) alter_table_clause ::= full_table_name DROP COLUMN column_name */
+ { 285, -5 }, /* (123) alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */
+ { 285, -5 }, /* (124) alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */
+ { 285, -5 }, /* (125) alter_table_clause ::= full_table_name ADD TAG column_name type_name */
+ { 285, -4 }, /* (126) alter_table_clause ::= full_table_name DROP TAG column_name */
+ { 285, -5 }, /* (127) alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */
+ { 285, -5 }, /* (128) alter_table_clause ::= full_table_name RENAME TAG column_name column_name */
+ { 285, -6 }, /* (129) alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */
+ { 282, -1 }, /* (130) multi_create_clause ::= create_subtable_clause */
+ { 282, -2 }, /* (131) multi_create_clause ::= multi_create_clause create_subtable_clause */
+ { 290, -10 }, /* (132) create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options */
+ { 284, -1 }, /* (133) multi_drop_clause ::= drop_table_clause */
+ { 284, -2 }, /* (134) multi_drop_clause ::= multi_drop_clause drop_table_clause */
+ { 293, -2 }, /* (135) drop_table_clause ::= exists_opt full_table_name */
+ { 291, 0 }, /* (136) specific_cols_opt ::= */
+ { 291, -3 }, /* (137) specific_cols_opt ::= NK_LP col_name_list NK_RP */
+ { 278, -1 }, /* (138) full_table_name ::= table_name */
+ { 278, -3 }, /* (139) full_table_name ::= db_name NK_DOT table_name */
+ { 279, -1 }, /* (140) column_def_list ::= column_def */
+ { 279, -3 }, /* (141) column_def_list ::= column_def_list NK_COMMA column_def */
+ { 296, -2 }, /* (142) column_def ::= column_name type_name */
+ { 296, -4 }, /* (143) column_def ::= column_name type_name COMMENT NK_STRING */
+ { 288, -1 }, /* (144) type_name ::= BOOL */
+ { 288, -1 }, /* (145) type_name ::= TINYINT */
+ { 288, -1 }, /* (146) type_name ::= SMALLINT */
+ { 288, -1 }, /* (147) type_name ::= INT */
+ { 288, -1 }, /* (148) type_name ::= INTEGER */
+ { 288, -1 }, /* (149) type_name ::= BIGINT */
+ { 288, -1 }, /* (150) type_name ::= FLOAT */
+ { 288, -1 }, /* (151) type_name ::= DOUBLE */
+ { 288, -4 }, /* (152) type_name ::= BINARY NK_LP NK_INTEGER NK_RP */
+ { 288, -1 }, /* (153) type_name ::= TIMESTAMP */
+ { 288, -4 }, /* (154) type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */
+ { 288, -2 }, /* (155) type_name ::= TINYINT UNSIGNED */
+ { 288, -2 }, /* (156) type_name ::= SMALLINT UNSIGNED */
+ { 288, -2 }, /* (157) type_name ::= INT UNSIGNED */
+ { 288, -2 }, /* (158) type_name ::= BIGINT UNSIGNED */
+ { 288, -1 }, /* (159) type_name ::= JSON */
+ { 288, -4 }, /* (160) type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */
+ { 288, -1 }, /* (161) type_name ::= MEDIUMBLOB */
+ { 288, -1 }, /* (162) type_name ::= BLOB */
+ { 288, -4 }, /* (163) type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */
+ { 288, -1 }, /* (164) type_name ::= DECIMAL */
+ { 288, -4 }, /* (165) type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */
+ { 288, -6 }, /* (166) type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */
+ { 280, 0 }, /* (167) tags_def_opt ::= */
+ { 280, -1 }, /* (168) tags_def_opt ::= tags_def */
+ { 283, -4 }, /* (169) tags_def ::= TAGS NK_LP column_def_list NK_RP */
+ { 281, 0 }, /* (170) table_options ::= */
+ { 281, -3 }, /* (171) table_options ::= table_options COMMENT NK_STRING */
+ { 281, -3 }, /* (172) table_options ::= table_options MAX_DELAY duration_list */
+ { 281, -3 }, /* (173) table_options ::= table_options WATERMARK duration_list */
+ { 281, -5 }, /* (174) table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */
+ { 281, -3 }, /* (175) table_options ::= table_options TTL NK_INTEGER */
+ { 281, -5 }, /* (176) table_options ::= table_options SMA NK_LP col_name_list NK_RP */
+ { 286, -1 }, /* (177) alter_table_options ::= alter_table_option */
+ { 286, -2 }, /* (178) alter_table_options ::= alter_table_options alter_table_option */
+ { 299, -2 }, /* (179) alter_table_option ::= COMMENT NK_STRING */
+ { 299, -2 }, /* (180) alter_table_option ::= TTL NK_INTEGER */
+ { 297, -1 }, /* (181) duration_list ::= duration_literal */
+ { 297, -3 }, /* (182) duration_list ::= duration_list NK_COMMA duration_literal */
+ { 298, -1 }, /* (183) rollup_func_list ::= rollup_func_name */
+ { 298, -3 }, /* (184) rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */
+ { 301, -1 }, /* (185) rollup_func_name ::= function_name */
+ { 301, -1 }, /* (186) rollup_func_name ::= FIRST */
+ { 301, -1 }, /* (187) rollup_func_name ::= LAST */
+ { 294, -1 }, /* (188) col_name_list ::= col_name */
+ { 294, -3 }, /* (189) col_name_list ::= col_name_list NK_COMMA col_name */
+ { 303, -1 }, /* (190) col_name ::= column_name */
+ { 256, -2 }, /* (191) cmd ::= SHOW DNODES */
+ { 256, -2 }, /* (192) cmd ::= SHOW USERS */
+ { 256, -2 }, /* (193) cmd ::= SHOW DATABASES */
+ { 256, -4 }, /* (194) cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */
+ { 256, -4 }, /* (195) cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */
+ { 256, -3 }, /* (196) cmd ::= SHOW db_name_cond_opt VGROUPS */
+ { 256, -2 }, /* (197) cmd ::= SHOW MNODES */
+ { 256, -2 }, /* (198) cmd ::= SHOW MODULES */
+ { 256, -2 }, /* (199) cmd ::= SHOW QNODES */
+ { 256, -2 }, /* (200) cmd ::= SHOW FUNCTIONS */
+ { 256, -5 }, /* (201) cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */
+ { 256, -2 }, /* (202) cmd ::= SHOW STREAMS */
+ { 256, -2 }, /* (203) cmd ::= SHOW ACCOUNTS */
+ { 256, -2 }, /* (204) cmd ::= SHOW APPS */
+ { 256, -2 }, /* (205) cmd ::= SHOW CONNECTIONS */
+ { 256, -2 }, /* (206) cmd ::= SHOW LICENCE */
+ { 256, -2 }, /* (207) cmd ::= SHOW GRANTS */
+ { 256, -4 }, /* (208) cmd ::= SHOW CREATE DATABASE db_name */
+ { 256, -4 }, /* (209) cmd ::= SHOW CREATE TABLE full_table_name */
+ { 256, -4 }, /* (210) cmd ::= SHOW CREATE STABLE full_table_name */
+ { 256, -2 }, /* (211) cmd ::= SHOW QUERIES */
+ { 256, -2 }, /* (212) cmd ::= SHOW SCORES */
+ { 256, -2 }, /* (213) cmd ::= SHOW TOPICS */
+ { 256, -2 }, /* (214) cmd ::= SHOW VARIABLES */
+ { 256, -3 }, /* (215) cmd ::= SHOW LOCAL VARIABLES */
+ { 256, -4 }, /* (216) cmd ::= SHOW DNODE NK_INTEGER VARIABLES */
+ { 256, -2 }, /* (217) cmd ::= SHOW BNODES */
+ { 256, -2 }, /* (218) cmd ::= SHOW SNODES */
+ { 256, -2 }, /* (219) cmd ::= SHOW CLUSTER */
+ { 256, -2 }, /* (220) cmd ::= SHOW TRANSACTIONS */
+ { 256, -4 }, /* (221) cmd ::= SHOW TABLE DISTRIBUTED full_table_name */
+ { 256, -2 }, /* (222) cmd ::= SHOW CONSUMERS */
+ { 256, -2 }, /* (223) cmd ::= SHOW SUBSCRIPTIONS */
+ { 304, 0 }, /* (224) db_name_cond_opt ::= */
+ { 304, -2 }, /* (225) db_name_cond_opt ::= db_name NK_DOT */
+ { 305, 0 }, /* (226) like_pattern_opt ::= */
+ { 305, -2 }, /* (227) like_pattern_opt ::= LIKE NK_STRING */
+ { 306, -1 }, /* (228) table_name_cond ::= table_name */
+ { 307, 0 }, /* (229) from_db_opt ::= */
+ { 307, -2 }, /* (230) from_db_opt ::= FROM db_name */
+ { 256, -8 }, /* (231) cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options */
+ { 256, -4 }, /* (232) cmd ::= DROP INDEX exists_opt index_name */
+ { 309, -10 }, /* (233) index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt */
+ { 309, -12 }, /* (234) index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt */
+ { 310, -1 }, /* (235) func_list ::= func */
+ { 310, -3 }, /* (236) func_list ::= func_list NK_COMMA func */
+ { 313, -4 }, /* (237) func ::= function_name NK_LP expression_list NK_RP */
+ { 312, 0 }, /* (238) sma_stream_opt ::= */
+ { 312, -3 }, /* (239) sma_stream_opt ::= stream_options WATERMARK duration_literal */
+ { 312, -3 }, /* (240) sma_stream_opt ::= stream_options MAX_DELAY duration_literal */
+ { 256, -6 }, /* (241) cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression */
+ { 256, -7 }, /* (242) cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */
+ { 256, -9 }, /* (243) cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name */
+ { 256, -7 }, /* (244) cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */
+ { 256, -9 }, /* (245) cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name */
+ { 256, -4 }, /* (246) cmd ::= DROP TOPIC exists_opt topic_name */
+ { 256, -7 }, /* (247) cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */
+ { 256, -2 }, /* (248) cmd ::= DESC full_table_name */
+ { 256, -2 }, /* (249) cmd ::= DESCRIBE full_table_name */
+ { 256, -3 }, /* (250) cmd ::= RESET QUERY CACHE */
+ { 256, -4 }, /* (251) cmd ::= EXPLAIN analyze_opt explain_options query_expression */
+ { 318, 0 }, /* (252) analyze_opt ::= */
+ { 318, -1 }, /* (253) analyze_opt ::= ANALYZE */
+ { 319, 0 }, /* (254) explain_options ::= */
+ { 319, -3 }, /* (255) explain_options ::= explain_options VERBOSE NK_BOOL */
+ { 319, -3 }, /* (256) explain_options ::= explain_options RATIO NK_FLOAT */
+ { 256, -6 }, /* (257) cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP */
+ { 256, -10 }, /* (258) cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt */
+ { 256, -4 }, /* (259) cmd ::= DROP FUNCTION exists_opt function_name */
+ { 320, 0 }, /* (260) agg_func_opt ::= */
+ { 320, -1 }, /* (261) agg_func_opt ::= AGGREGATE */
+ { 321, 0 }, /* (262) bufsize_opt ::= */
+ { 321, -2 }, /* (263) bufsize_opt ::= BUFSIZE NK_INTEGER */
+ { 256, -8 }, /* (264) cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression */
+ { 256, -4 }, /* (265) cmd ::= DROP STREAM exists_opt stream_name */
+ { 323, 0 }, /* (266) into_opt ::= */
+ { 323, -2 }, /* (267) into_opt ::= INTO full_table_name */
+ { 314, 0 }, /* (268) stream_options ::= */
+ { 314, -3 }, /* (269) stream_options ::= stream_options TRIGGER AT_ONCE */
+ { 314, -3 }, /* (270) stream_options ::= stream_options TRIGGER WINDOW_CLOSE */
+ { 314, -4 }, /* (271) stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */
+ { 314, -3 }, /* (272) stream_options ::= stream_options WATERMARK duration_literal */
+ { 314, -3 }, /* (273) stream_options ::= stream_options IGNORE EXPIRED */
+ { 256, -3 }, /* (274) cmd ::= KILL CONNECTION NK_INTEGER */
+ { 256, -3 }, /* (275) cmd ::= KILL QUERY NK_STRING */
+ { 256, -3 }, /* (276) cmd ::= KILL TRANSACTION NK_INTEGER */
+ { 256, -2 }, /* (277) cmd ::= BALANCE VGROUP */
+ { 256, -4 }, /* (278) cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */
+ { 256, -4 }, /* (279) cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */
+ { 256, -3 }, /* (280) cmd ::= SPLIT VGROUP NK_INTEGER */
+ { 324, -2 }, /* (281) dnode_list ::= DNODE NK_INTEGER */
+ { 324, -3 }, /* (282) dnode_list ::= dnode_list DNODE NK_INTEGER */
+ { 256, -3 }, /* (283) cmd ::= SYNCDB db_name REPLICA */
+ { 256, -4 }, /* (284) cmd ::= DELETE FROM full_table_name where_clause_opt */
+ { 256, -1 }, /* (285) cmd ::= query_expression */
+ { 256, -7 }, /* (286) cmd ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_expression */
+ { 256, -4 }, /* (287) cmd ::= INSERT INTO full_table_name query_expression */
+ { 259, -1 }, /* (288) literal ::= NK_INTEGER */
+ { 259, -1 }, /* (289) literal ::= NK_FLOAT */
+ { 259, -1 }, /* (290) literal ::= NK_STRING */
+ { 259, -1 }, /* (291) literal ::= NK_BOOL */
+ { 259, -2 }, /* (292) literal ::= TIMESTAMP NK_STRING */
+ { 259, -1 }, /* (293) literal ::= duration_literal */
+ { 259, -1 }, /* (294) literal ::= NULL */
+ { 259, -1 }, /* (295) literal ::= NK_QUESTION */
+ { 300, -1 }, /* (296) duration_literal ::= NK_VARIABLE */
+ { 326, -1 }, /* (297) signed ::= NK_INTEGER */
+ { 326, -2 }, /* (298) signed ::= NK_PLUS NK_INTEGER */
+ { 326, -2 }, /* (299) signed ::= NK_MINUS NK_INTEGER */
+ { 326, -1 }, /* (300) signed ::= NK_FLOAT */
+ { 326, -2 }, /* (301) signed ::= NK_PLUS NK_FLOAT */
+ { 326, -2 }, /* (302) signed ::= NK_MINUS NK_FLOAT */
+ { 289, -1 }, /* (303) signed_literal ::= signed */
+ { 289, -1 }, /* (304) signed_literal ::= NK_STRING */
+ { 289, -1 }, /* (305) signed_literal ::= NK_BOOL */
+ { 289, -2 }, /* (306) signed_literal ::= TIMESTAMP NK_STRING */
+ { 289, -1 }, /* (307) signed_literal ::= duration_literal */
+ { 289, -1 }, /* (308) signed_literal ::= NULL */
+ { 289, -1 }, /* (309) signed_literal ::= literal_func */
+ { 289, -1 }, /* (310) signed_literal ::= NK_QUESTION */
+ { 328, -1 }, /* (311) literal_list ::= signed_literal */
+ { 328, -3 }, /* (312) literal_list ::= literal_list NK_COMMA signed_literal */
+ { 267, -1 }, /* (313) db_name ::= NK_ID */
+ { 295, -1 }, /* (314) table_name ::= NK_ID */
+ { 287, -1 }, /* (315) column_name ::= NK_ID */
+ { 302, -1 }, /* (316) function_name ::= NK_ID */
+ { 329, -1 }, /* (317) table_alias ::= NK_ID */
+ { 330, -1 }, /* (318) column_alias ::= NK_ID */
+ { 261, -1 }, /* (319) user_name ::= NK_ID */
+ { 308, -1 }, /* (320) index_name ::= NK_ID */
+ { 315, -1 }, /* (321) topic_name ::= NK_ID */
+ { 322, -1 }, /* (322) stream_name ::= NK_ID */
+ { 317, -1 }, /* (323) cgroup_name ::= NK_ID */
+ { 331, -1 }, /* (324) expression ::= literal */
+ { 331, -1 }, /* (325) expression ::= pseudo_column */
+ { 331, -1 }, /* (326) expression ::= column_reference */
+ { 331, -1 }, /* (327) expression ::= function_expression */
+ { 331, -1 }, /* (328) expression ::= subquery */
+ { 331, -3 }, /* (329) expression ::= NK_LP expression NK_RP */
+ { 331, -2 }, /* (330) expression ::= NK_PLUS expression */
+ { 331, -2 }, /* (331) expression ::= NK_MINUS expression */
+ { 331, -3 }, /* (332) expression ::= expression NK_PLUS expression */
+ { 331, -3 }, /* (333) expression ::= expression NK_MINUS expression */
+ { 331, -3 }, /* (334) expression ::= expression NK_STAR expression */
+ { 331, -3 }, /* (335) expression ::= expression NK_SLASH expression */
+ { 331, -3 }, /* (336) expression ::= expression NK_REM expression */
+ { 331, -3 }, /* (337) expression ::= column_reference NK_ARROW NK_STRING */
+ { 331, -3 }, /* (338) expression ::= expression NK_BITAND expression */
+ { 331, -3 }, /* (339) expression ::= expression NK_BITOR expression */
+ { 292, -1 }, /* (340) expression_list ::= expression */
+ { 292, -3 }, /* (341) expression_list ::= expression_list NK_COMMA expression */
+ { 333, -1 }, /* (342) column_reference ::= column_name */
+ { 333, -3 }, /* (343) column_reference ::= table_name NK_DOT column_name */
+ { 332, -1 }, /* (344) pseudo_column ::= ROWTS */
+ { 332, -1 }, /* (345) pseudo_column ::= TBNAME */
+ { 332, -3 }, /* (346) pseudo_column ::= table_name NK_DOT TBNAME */
+ { 332, -1 }, /* (347) pseudo_column ::= QSTART */
+ { 332, -1 }, /* (348) pseudo_column ::= QEND */
+ { 332, -1 }, /* (349) pseudo_column ::= QDURATION */
+ { 332, -1 }, /* (350) pseudo_column ::= WSTART */
+ { 332, -1 }, /* (351) pseudo_column ::= WEND */
+ { 332, -1 }, /* (352) pseudo_column ::= WDURATION */
+ { 334, -4 }, /* (353) function_expression ::= function_name NK_LP expression_list NK_RP */
+ { 334, -4 }, /* (354) function_expression ::= star_func NK_LP star_func_para_list NK_RP */
+ { 334, -6 }, /* (355) function_expression ::= CAST NK_LP expression AS type_name NK_RP */
+ { 334, -1 }, /* (356) function_expression ::= literal_func */
+ { 327, -3 }, /* (357) literal_func ::= noarg_func NK_LP NK_RP */
+ { 327, -1 }, /* (358) literal_func ::= NOW */
+ { 338, -1 }, /* (359) noarg_func ::= NOW */
+ { 338, -1 }, /* (360) noarg_func ::= TODAY */
+ { 338, -1 }, /* (361) noarg_func ::= TIMEZONE */
+ { 338, -1 }, /* (362) noarg_func ::= DATABASE */
+ { 338, -1 }, /* (363) noarg_func ::= CLIENT_VERSION */
+ { 338, -1 }, /* (364) noarg_func ::= SERVER_VERSION */
+ { 338, -1 }, /* (365) noarg_func ::= SERVER_STATUS */
+ { 338, -1 }, /* (366) noarg_func ::= CURRENT_USER */
+ { 338, -1 }, /* (367) noarg_func ::= USER */
+ { 336, -1 }, /* (368) star_func ::= COUNT */
+ { 336, -1 }, /* (369) star_func ::= FIRST */
+ { 336, -1 }, /* (370) star_func ::= LAST */
+ { 336, -1 }, /* (371) star_func ::= LAST_ROW */
+ { 337, -1 }, /* (372) star_func_para_list ::= NK_STAR */
+ { 337, -1 }, /* (373) star_func_para_list ::= other_para_list */
+ { 339, -1 }, /* (374) other_para_list ::= star_func_para */
+ { 339, -3 }, /* (375) other_para_list ::= other_para_list NK_COMMA star_func_para */
+ { 340, -1 }, /* (376) star_func_para ::= expression */
+ { 340, -3 }, /* (377) star_func_para ::= table_name NK_DOT NK_STAR */
+ { 341, -3 }, /* (378) predicate ::= expression compare_op expression */
+ { 341, -5 }, /* (379) predicate ::= expression BETWEEN expression AND expression */
+ { 341, -6 }, /* (380) predicate ::= expression NOT BETWEEN expression AND expression */
+ { 341, -3 }, /* (381) predicate ::= expression IS NULL */
+ { 341, -4 }, /* (382) predicate ::= expression IS NOT NULL */
+ { 341, -3 }, /* (383) predicate ::= expression in_op in_predicate_value */
+ { 342, -1 }, /* (384) compare_op ::= NK_LT */
+ { 342, -1 }, /* (385) compare_op ::= NK_GT */
+ { 342, -1 }, /* (386) compare_op ::= NK_LE */
+ { 342, -1 }, /* (387) compare_op ::= NK_GE */
+ { 342, -1 }, /* (388) compare_op ::= NK_NE */
+ { 342, -1 }, /* (389) compare_op ::= NK_EQ */
+ { 342, -1 }, /* (390) compare_op ::= LIKE */
+ { 342, -2 }, /* (391) compare_op ::= NOT LIKE */
+ { 342, -1 }, /* (392) compare_op ::= MATCH */
+ { 342, -1 }, /* (393) compare_op ::= NMATCH */
+ { 342, -1 }, /* (394) compare_op ::= CONTAINS */
+ { 343, -1 }, /* (395) in_op ::= IN */
+ { 343, -2 }, /* (396) in_op ::= NOT IN */
+ { 344, -3 }, /* (397) in_predicate_value ::= NK_LP literal_list NK_RP */
+ { 345, -1 }, /* (398) boolean_value_expression ::= boolean_primary */
+ { 345, -2 }, /* (399) boolean_value_expression ::= NOT boolean_primary */
+ { 345, -3 }, /* (400) boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */
+ { 345, -3 }, /* (401) boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */
+ { 346, -1 }, /* (402) boolean_primary ::= predicate */
+ { 346, -3 }, /* (403) boolean_primary ::= NK_LP boolean_value_expression NK_RP */
+ { 347, -1 }, /* (404) common_expression ::= expression */
+ { 347, -1 }, /* (405) common_expression ::= boolean_value_expression */
+ { 348, 0 }, /* (406) from_clause_opt ::= */
+ { 348, -2 }, /* (407) from_clause_opt ::= FROM table_reference_list */
+ { 349, -1 }, /* (408) table_reference_list ::= table_reference */
+ { 349, -3 }, /* (409) table_reference_list ::= table_reference_list NK_COMMA table_reference */
+ { 350, -1 }, /* (410) table_reference ::= table_primary */
+ { 350, -1 }, /* (411) table_reference ::= joined_table */
+ { 351, -2 }, /* (412) table_primary ::= table_name alias_opt */
+ { 351, -4 }, /* (413) table_primary ::= db_name NK_DOT table_name alias_opt */
+ { 351, -2 }, /* (414) table_primary ::= subquery alias_opt */
+ { 351, -1 }, /* (415) table_primary ::= parenthesized_joined_table */
+ { 353, 0 }, /* (416) alias_opt ::= */
+ { 353, -1 }, /* (417) alias_opt ::= table_alias */
+ { 353, -2 }, /* (418) alias_opt ::= AS table_alias */
+ { 354, -3 }, /* (419) parenthesized_joined_table ::= NK_LP joined_table NK_RP */
+ { 354, -3 }, /* (420) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */
+ { 352, -6 }, /* (421) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */
+ { 355, 0 }, /* (422) join_type ::= */
+ { 355, -1 }, /* (423) join_type ::= INNER */
+ { 357, -12 }, /* (424) query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */
+ { 358, 0 }, /* (425) set_quantifier_opt ::= */
+ { 358, -1 }, /* (426) set_quantifier_opt ::= DISTINCT */
+ { 358, -1 }, /* (427) set_quantifier_opt ::= ALL */
+ { 359, -1 }, /* (428) select_list ::= select_item */
+ { 359, -3 }, /* (429) select_list ::= select_list NK_COMMA select_item */
+ { 367, -1 }, /* (430) select_item ::= NK_STAR */
+ { 367, -1 }, /* (431) select_item ::= common_expression */
+ { 367, -2 }, /* (432) select_item ::= common_expression column_alias */
+ { 367, -3 }, /* (433) select_item ::= common_expression AS column_alias */
+ { 367, -3 }, /* (434) select_item ::= table_name NK_DOT NK_STAR */
+ { 325, 0 }, /* (435) where_clause_opt ::= */
+ { 325, -2 }, /* (436) where_clause_opt ::= WHERE search_condition */
+ { 360, 0 }, /* (437) partition_by_clause_opt ::= */
+ { 360, -3 }, /* (438) partition_by_clause_opt ::= PARTITION BY expression_list */
+ { 364, 0 }, /* (439) twindow_clause_opt ::= */
+ { 364, -6 }, /* (440) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */
+ { 364, -4 }, /* (441) twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */
+ { 364, -6 }, /* (442) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */
+ { 364, -8 }, /* (443) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */
+ { 311, 0 }, /* (444) sliding_opt ::= */
+ { 311, -4 }, /* (445) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */
+ { 363, 0 }, /* (446) fill_opt ::= */
+ { 363, -4 }, /* (447) fill_opt ::= FILL NK_LP fill_mode NK_RP */
+ { 363, -6 }, /* (448) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */
+ { 368, -1 }, /* (449) fill_mode ::= NONE */
+ { 368, -1 }, /* (450) fill_mode ::= PREV */
+ { 368, -1 }, /* (451) fill_mode ::= NULL */
+ { 368, -1 }, /* (452) fill_mode ::= LINEAR */
+ { 368, -1 }, /* (453) fill_mode ::= NEXT */
+ { 365, 0 }, /* (454) group_by_clause_opt ::= */
+ { 365, -3 }, /* (455) group_by_clause_opt ::= GROUP BY group_by_list */
+ { 369, -1 }, /* (456) group_by_list ::= expression */
+ { 369, -3 }, /* (457) group_by_list ::= group_by_list NK_COMMA expression */
+ { 366, 0 }, /* (458) having_clause_opt ::= */
+ { 366, -2 }, /* (459) having_clause_opt ::= HAVING search_condition */
+ { 361, 0 }, /* (460) range_opt ::= */
+ { 361, -6 }, /* (461) range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */
+ { 362, 0 }, /* (462) every_opt ::= */
+ { 362, -4 }, /* (463) every_opt ::= EVERY NK_LP duration_literal NK_RP */
+ { 316, -4 }, /* (464) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
+ { 370, -1 }, /* (465) query_expression_body ::= query_primary */
+ { 370, -4 }, /* (466) query_expression_body ::= query_expression_body UNION ALL query_expression_body */
+ { 370, -3 }, /* (467) query_expression_body ::= query_expression_body UNION query_expression_body */
+ { 374, -1 }, /* (468) query_primary ::= query_specification */
+ { 374, -6 }, /* (469) query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */
+ { 371, 0 }, /* (470) order_by_clause_opt ::= */
+ { 371, -3 }, /* (471) order_by_clause_opt ::= ORDER BY sort_specification_list */
+ { 372, 0 }, /* (472) slimit_clause_opt ::= */
+ { 372, -2 }, /* (473) slimit_clause_opt ::= SLIMIT NK_INTEGER */
+ { 372, -4 }, /* (474) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
+ { 372, -4 }, /* (475) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
+ { 373, 0 }, /* (476) limit_clause_opt ::= */
+ { 373, -2 }, /* (477) limit_clause_opt ::= LIMIT NK_INTEGER */
+ { 373, -4 }, /* (478) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */
+ { 373, -4 }, /* (479) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */
+ { 335, -3 }, /* (480) subquery ::= NK_LP query_expression NK_RP */
+ { 356, -1 }, /* (481) search_condition ::= common_expression */
+ { 375, -1 }, /* (482) sort_specification_list ::= sort_specification */
+ { 375, -3 }, /* (483) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */
+ { 376, -3 }, /* (484) sort_specification ::= expression ordering_specification_opt null_ordering_opt */
+ { 377, 0 }, /* (485) ordering_specification_opt ::= */
+ { 377, -1 }, /* (486) ordering_specification_opt ::= ASC */
+ { 377, -1 }, /* (487) ordering_specification_opt ::= DESC */
+ { 378, 0 }, /* (488) null_ordering_opt ::= */
+ { 378, -2 }, /* (489) null_ordering_opt ::= NULLS FIRST */
+ { 378, -2 }, /* (490) null_ordering_opt ::= NULLS LAST */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -3161,11 +3321,11 @@ static YYACTIONTYPE yy_reduce(
YYMINORTYPE yylhsminor;
case 0: /* cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */
{ pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
- yy_destructor(yypParser,243,&yymsp[0].minor);
+ yy_destructor(yypParser,257,&yymsp[0].minor);
break;
case 1: /* cmd ::= ALTER ACCOUNT NK_ID alter_account_options */
{ pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
- yy_destructor(yypParser,244,&yymsp[0].minor);
+ yy_destructor(yypParser,258,&yymsp[0].minor);
break;
case 2: /* account_options ::= */
{ }
@@ -3179,20 +3339,20 @@ static YYACTIONTYPE yy_reduce(
case 9: /* account_options ::= account_options USERS literal */ yytestcase(yyruleno==9);
case 10: /* account_options ::= account_options CONNS literal */ yytestcase(yyruleno==10);
case 11: /* account_options ::= account_options STATE literal */ yytestcase(yyruleno==11);
-{ yy_destructor(yypParser,243,&yymsp[-2].minor);
+{ yy_destructor(yypParser,257,&yymsp[-2].minor);
{ }
- yy_destructor(yypParser,245,&yymsp[0].minor);
+ yy_destructor(yypParser,259,&yymsp[0].minor);
}
break;
case 12: /* alter_account_options ::= alter_account_option */
-{ yy_destructor(yypParser,246,&yymsp[0].minor);
+{ yy_destructor(yypParser,260,&yymsp[0].minor);
{ }
}
break;
case 13: /* alter_account_options ::= alter_account_options alter_account_option */
-{ yy_destructor(yypParser,244,&yymsp[-1].minor);
+{ yy_destructor(yypParser,258,&yymsp[-1].minor);
{ }
- yy_destructor(yypParser,246,&yymsp[0].minor);
+ yy_destructor(yypParser,260,&yymsp[0].minor);
}
break;
case 14: /* alter_account_option ::= PASS literal */
@@ -3206,1309 +3366,1386 @@ static YYACTIONTYPE yy_reduce(
case 22: /* alter_account_option ::= CONNS literal */ yytestcase(yyruleno==22);
case 23: /* alter_account_option ::= STATE literal */ yytestcase(yyruleno==23);
{ }
- yy_destructor(yypParser,245,&yymsp[0].minor);
+ yy_destructor(yypParser,259,&yymsp[0].minor);
break;
- case 24: /* cmd ::= CREATE USER user_name PASS NK_STRING */
-{ pCxt->pRootNode = createCreateUserStmt(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0); }
+ case 24: /* cmd ::= CREATE USER user_name PASS NK_STRING sysinfo_opt */
+{ pCxt->pRootNode = createCreateUserStmt(pCxt, &yymsp[-3].minor.yy361, &yymsp[-1].minor.yy0, yymsp[0].minor.yy285); }
break;
case 25: /* cmd ::= ALTER USER user_name PASS NK_STRING */
-{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy57, TSDB_ALTER_USER_PASSWD, &yymsp[0].minor.yy0); }
+{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy361, TSDB_ALTER_USER_PASSWD, &yymsp[0].minor.yy0); }
+ break;
+ case 26: /* cmd ::= ALTER USER user_name ENABLE NK_INTEGER */
+{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy361, TSDB_ALTER_USER_ENABLE, &yymsp[0].minor.yy0); }
+ break;
+ case 27: /* cmd ::= ALTER USER user_name SYSINFO NK_INTEGER */
+{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy361, TSDB_ALTER_USER_SYSINFO, &yymsp[0].minor.yy0); }
+ break;
+ case 28: /* cmd ::= DROP USER user_name */
+{ pCxt->pRootNode = createDropUserStmt(pCxt, &yymsp[0].minor.yy361); }
break;
- case 26: /* cmd ::= ALTER USER user_name PRIVILEGE NK_STRING */
-{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy57, TSDB_ALTER_USER_PRIVILEGES, &yymsp[0].minor.yy0); }
+ case 29: /* sysinfo_opt ::= */
+{ yymsp[1].minor.yy285 = 1; }
break;
- case 27: /* cmd ::= DROP USER user_name */
-{ pCxt->pRootNode = createDropUserStmt(pCxt, &yymsp[0].minor.yy57); }
+ case 30: /* sysinfo_opt ::= SYSINFO NK_INTEGER */
+{ yymsp[-1].minor.yy285 = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); }
break;
- case 28: /* cmd ::= GRANT privileges ON priv_level TO user_name */
-{ pCxt->pRootNode = createGrantStmt(pCxt, yymsp[-4].minor.yy389, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57); }
+ case 31: /* cmd ::= GRANT privileges ON priv_level TO user_name */
+{ pCxt->pRootNode = createGrantStmt(pCxt, yymsp[-4].minor.yy457, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361); }
break;
- case 29: /* cmd ::= REVOKE privileges ON priv_level FROM user_name */
-{ pCxt->pRootNode = createRevokeStmt(pCxt, yymsp[-4].minor.yy389, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57); }
+ case 32: /* cmd ::= REVOKE privileges ON priv_level FROM user_name */
+{ pCxt->pRootNode = createRevokeStmt(pCxt, yymsp[-4].minor.yy457, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361); }
break;
- case 30: /* privileges ::= ALL */
-{ yymsp[0].minor.yy389 = PRIVILEGE_TYPE_ALL; }
+ case 33: /* privileges ::= ALL */
+{ yymsp[0].minor.yy457 = PRIVILEGE_TYPE_ALL; }
break;
- case 31: /* privileges ::= priv_type_list */
- case 32: /* priv_type_list ::= priv_type */ yytestcase(yyruleno==32);
-{ yylhsminor.yy389 = yymsp[0].minor.yy389; }
- yymsp[0].minor.yy389 = yylhsminor.yy389;
+ case 34: /* privileges ::= priv_type_list */
+ case 35: /* priv_type_list ::= priv_type */ yytestcase(yyruleno==35);
+{ yylhsminor.yy457 = yymsp[0].minor.yy457; }
+ yymsp[0].minor.yy457 = yylhsminor.yy457;
break;
- case 33: /* priv_type_list ::= priv_type_list NK_COMMA priv_type */
-{ yylhsminor.yy389 = yymsp[-2].minor.yy389 | yymsp[0].minor.yy389; }
- yymsp[-2].minor.yy389 = yylhsminor.yy389;
+ case 36: /* priv_type_list ::= priv_type_list NK_COMMA priv_type */
+{ yylhsminor.yy457 = yymsp[-2].minor.yy457 | yymsp[0].minor.yy457; }
+ yymsp[-2].minor.yy457 = yylhsminor.yy457;
break;
- case 34: /* priv_type ::= READ */
-{ yymsp[0].minor.yy389 = PRIVILEGE_TYPE_READ; }
+ case 37: /* priv_type ::= READ */
+{ yymsp[0].minor.yy457 = PRIVILEGE_TYPE_READ; }
break;
- case 35: /* priv_type ::= WRITE */
-{ yymsp[0].minor.yy389 = PRIVILEGE_TYPE_WRITE; }
+ case 38: /* priv_type ::= WRITE */
+{ yymsp[0].minor.yy457 = PRIVILEGE_TYPE_WRITE; }
break;
- case 36: /* priv_level ::= NK_STAR NK_DOT NK_STAR */
-{ yylhsminor.yy57 = yymsp[-2].minor.yy0; }
- yymsp[-2].minor.yy57 = yylhsminor.yy57;
+ case 39: /* priv_level ::= NK_STAR NK_DOT NK_STAR */
+{ yylhsminor.yy361 = yymsp[-2].minor.yy0; }
+ yymsp[-2].minor.yy361 = yylhsminor.yy361;
break;
- case 37: /* priv_level ::= db_name NK_DOT NK_STAR */
-{ yylhsminor.yy57 = yymsp[-2].minor.yy57; }
- yymsp[-2].minor.yy57 = yylhsminor.yy57;
+ case 40: /* priv_level ::= db_name NK_DOT NK_STAR */
+{ yylhsminor.yy361 = yymsp[-2].minor.yy361; }
+ yymsp[-2].minor.yy361 = yylhsminor.yy361;
break;
- case 38: /* cmd ::= CREATE DNODE dnode_endpoint */
-{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[0].minor.yy57, NULL); }
+ case 41: /* cmd ::= CREATE DNODE dnode_endpoint */
+{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[0].minor.yy361, NULL); }
break;
- case 39: /* cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */
-{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0); }
+ case 42: /* cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */
+{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy0); }
break;
- case 40: /* cmd ::= DROP DNODE NK_INTEGER */
+ case 43: /* cmd ::= DROP DNODE NK_INTEGER */
{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[0].minor.yy0); }
break;
- case 41: /* cmd ::= DROP DNODE dnode_endpoint */
-{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[0].minor.yy57); }
+ case 44: /* cmd ::= DROP DNODE dnode_endpoint */
+{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[0].minor.yy361); }
break;
- case 42: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING */
+ case 45: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING */
{ pCxt->pRootNode = createAlterDnodeStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, NULL); }
break;
- case 43: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */
+ case 46: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */
{ pCxt->pRootNode = createAlterDnodeStmt(pCxt, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); }
break;
- case 44: /* cmd ::= ALTER ALL DNODES NK_STRING */
+ case 47: /* cmd ::= ALTER ALL DNODES NK_STRING */
{ pCxt->pRootNode = createAlterDnodeStmt(pCxt, NULL, &yymsp[0].minor.yy0, NULL); }
break;
- case 45: /* cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */
+ case 48: /* cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */
{ pCxt->pRootNode = createAlterDnodeStmt(pCxt, NULL, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); }
break;
- case 46: /* dnode_endpoint ::= NK_STRING */
- case 47: /* dnode_endpoint ::= NK_ID */ yytestcase(yyruleno==47);
- case 48: /* dnode_endpoint ::= NK_IPTOKEN */ yytestcase(yyruleno==48);
- case 297: /* db_name ::= NK_ID */ yytestcase(yyruleno==297);
- case 298: /* table_name ::= NK_ID */ yytestcase(yyruleno==298);
- case 299: /* column_name ::= NK_ID */ yytestcase(yyruleno==299);
- case 300: /* function_name ::= NK_ID */ yytestcase(yyruleno==300);
- case 301: /* table_alias ::= NK_ID */ yytestcase(yyruleno==301);
- case 302: /* column_alias ::= NK_ID */ yytestcase(yyruleno==302);
- case 303: /* user_name ::= NK_ID */ yytestcase(yyruleno==303);
- case 304: /* index_name ::= NK_ID */ yytestcase(yyruleno==304);
- case 305: /* topic_name ::= NK_ID */ yytestcase(yyruleno==305);
- case 306: /* stream_name ::= NK_ID */ yytestcase(yyruleno==306);
- case 307: /* cgroup_name ::= NK_ID */ yytestcase(yyruleno==307);
- case 340: /* noarg_func ::= NOW */ yytestcase(yyruleno==340);
- case 341: /* noarg_func ::= TODAY */ yytestcase(yyruleno==341);
- case 342: /* noarg_func ::= TIMEZONE */ yytestcase(yyruleno==342);
- case 343: /* star_func ::= COUNT */ yytestcase(yyruleno==343);
- case 344: /* star_func ::= FIRST */ yytestcase(yyruleno==344);
- case 345: /* star_func ::= LAST */ yytestcase(yyruleno==345);
- case 346: /* star_func ::= LAST_ROW */ yytestcase(yyruleno==346);
-{ yylhsminor.yy57 = yymsp[0].minor.yy0; }
- yymsp[0].minor.yy57 = yylhsminor.yy57;
- break;
- case 49: /* cmd ::= ALTER LOCAL NK_STRING */
+ case 49: /* dnode_endpoint ::= NK_STRING */
+ case 50: /* dnode_endpoint ::= NK_ID */ yytestcase(yyruleno==50);
+ case 51: /* dnode_endpoint ::= NK_IPTOKEN */ yytestcase(yyruleno==51);
+ case 313: /* db_name ::= NK_ID */ yytestcase(yyruleno==313);
+ case 314: /* table_name ::= NK_ID */ yytestcase(yyruleno==314);
+ case 315: /* column_name ::= NK_ID */ yytestcase(yyruleno==315);
+ case 316: /* function_name ::= NK_ID */ yytestcase(yyruleno==316);
+ case 317: /* table_alias ::= NK_ID */ yytestcase(yyruleno==317);
+ case 318: /* column_alias ::= NK_ID */ yytestcase(yyruleno==318);
+ case 319: /* user_name ::= NK_ID */ yytestcase(yyruleno==319);
+ case 320: /* index_name ::= NK_ID */ yytestcase(yyruleno==320);
+ case 321: /* topic_name ::= NK_ID */ yytestcase(yyruleno==321);
+ case 322: /* stream_name ::= NK_ID */ yytestcase(yyruleno==322);
+ case 323: /* cgroup_name ::= NK_ID */ yytestcase(yyruleno==323);
+ case 359: /* noarg_func ::= NOW */ yytestcase(yyruleno==359);
+ case 360: /* noarg_func ::= TODAY */ yytestcase(yyruleno==360);
+ case 361: /* noarg_func ::= TIMEZONE */ yytestcase(yyruleno==361);
+ case 362: /* noarg_func ::= DATABASE */ yytestcase(yyruleno==362);
+ case 363: /* noarg_func ::= CLIENT_VERSION */ yytestcase(yyruleno==363);
+ case 364: /* noarg_func ::= SERVER_VERSION */ yytestcase(yyruleno==364);
+ case 365: /* noarg_func ::= SERVER_STATUS */ yytestcase(yyruleno==365);
+ case 366: /* noarg_func ::= CURRENT_USER */ yytestcase(yyruleno==366);
+ case 367: /* noarg_func ::= USER */ yytestcase(yyruleno==367);
+ case 368: /* star_func ::= COUNT */ yytestcase(yyruleno==368);
+ case 369: /* star_func ::= FIRST */ yytestcase(yyruleno==369);
+ case 370: /* star_func ::= LAST */ yytestcase(yyruleno==370);
+ case 371: /* star_func ::= LAST_ROW */ yytestcase(yyruleno==371);
+{ yylhsminor.yy361 = yymsp[0].minor.yy0; }
+ yymsp[0].minor.yy361 = yylhsminor.yy361;
+ break;
+ case 52: /* cmd ::= ALTER LOCAL NK_STRING */
{ pCxt->pRootNode = createAlterLocalStmt(pCxt, &yymsp[0].minor.yy0, NULL); }
break;
- case 50: /* cmd ::= ALTER LOCAL NK_STRING NK_STRING */
+ case 53: /* cmd ::= ALTER LOCAL NK_STRING NK_STRING */
{ pCxt->pRootNode = createAlterLocalStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); }
break;
- case 51: /* cmd ::= CREATE QNODE ON DNODE NK_INTEGER */
+ case 54: /* cmd ::= CREATE QNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_QNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 52: /* cmd ::= DROP QNODE ON DNODE NK_INTEGER */
+ case 55: /* cmd ::= DROP QNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_QNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 53: /* cmd ::= CREATE BNODE ON DNODE NK_INTEGER */
+ case 56: /* cmd ::= CREATE BNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_BNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 54: /* cmd ::= DROP BNODE ON DNODE NK_INTEGER */
+ case 57: /* cmd ::= DROP BNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_BNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 55: /* cmd ::= CREATE SNODE ON DNODE NK_INTEGER */
+ case 58: /* cmd ::= CREATE SNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_SNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 56: /* cmd ::= DROP SNODE ON DNODE NK_INTEGER */
+ case 59: /* cmd ::= DROP SNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_SNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 57: /* cmd ::= CREATE MNODE ON DNODE NK_INTEGER */
+ case 60: /* cmd ::= CREATE MNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_MNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 58: /* cmd ::= DROP MNODE ON DNODE NK_INTEGER */
+ case 61: /* cmd ::= DROP MNODE ON DNODE NK_INTEGER */
{ pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_MNODE_STMT, &yymsp[0].minor.yy0); }
break;
- case 59: /* cmd ::= CREATE DATABASE not_exists_opt db_name db_options */
-{ pCxt->pRootNode = createCreateDatabaseStmt(pCxt, yymsp[-2].minor.yy481, &yymsp[-1].minor.yy57, yymsp[0].minor.yy392); }
+ case 62: /* cmd ::= CREATE DATABASE not_exists_opt db_name db_options */
+{ pCxt->pRootNode = createCreateDatabaseStmt(pCxt, yymsp[-2].minor.yy151, &yymsp[-1].minor.yy361, yymsp[0].minor.yy616); }
+ break;
+ case 63: /* cmd ::= DROP DATABASE exists_opt db_name */
+{ pCxt->pRootNode = createDropDatabaseStmt(pCxt, yymsp[-1].minor.yy151, &yymsp[0].minor.yy361); }
+ break;
+ case 64: /* cmd ::= USE db_name */
+{ pCxt->pRootNode = createUseDatabaseStmt(pCxt, &yymsp[0].minor.yy361); }
+ break;
+ case 65: /* cmd ::= ALTER DATABASE db_name alter_db_options */
+{ pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &yymsp[-1].minor.yy361, yymsp[0].minor.yy616); }
+ break;
+ case 66: /* cmd ::= FLUSH DATABASE db_name */
+{ pCxt->pRootNode = createFlushDatabaseStmt(pCxt, &yymsp[0].minor.yy361); }
+ break;
+ case 67: /* cmd ::= TRIM DATABASE db_name */
+{ pCxt->pRootNode = createTrimDatabaseStmt(pCxt, &yymsp[0].minor.yy361); }
+ break;
+ case 68: /* not_exists_opt ::= IF NOT EXISTS */
+{ yymsp[-2].minor.yy151 = true; }
+ break;
+ case 69: /* not_exists_opt ::= */
+ case 71: /* exists_opt ::= */ yytestcase(yyruleno==71);
+ case 252: /* analyze_opt ::= */ yytestcase(yyruleno==252);
+ case 260: /* agg_func_opt ::= */ yytestcase(yyruleno==260);
+ case 425: /* set_quantifier_opt ::= */ yytestcase(yyruleno==425);
+{ yymsp[1].minor.yy151 = false; }
+ break;
+ case 70: /* exists_opt ::= IF EXISTS */
+{ yymsp[-1].minor.yy151 = true; }
break;
- case 60: /* cmd ::= DROP DATABASE exists_opt db_name */
-{ pCxt->pRootNode = createDropDatabaseStmt(pCxt, yymsp[-1].minor.yy481, &yymsp[0].minor.yy57); }
+ case 72: /* db_options ::= */
+{ yymsp[1].minor.yy616 = createDefaultDatabaseOptions(pCxt); }
break;
- case 61: /* cmd ::= USE db_name */
-{ pCxt->pRootNode = createUseDatabaseStmt(pCxt, &yymsp[0].minor.yy57); }
+ case 73: /* db_options ::= db_options BUFFER NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_BUFFER, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 62: /* cmd ::= ALTER DATABASE db_name alter_db_options */
-{ pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &yymsp[-1].minor.yy57, yymsp[0].minor.yy392); }
+ case 74: /* db_options ::= db_options CACHELAST NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_CACHELAST, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 63: /* not_exists_opt ::= IF NOT EXISTS */
-{ yymsp[-2].minor.yy481 = true; }
+ case 75: /* db_options ::= db_options CACHELASTSIZE NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_CACHELASTSIZE, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 64: /* not_exists_opt ::= */
- case 66: /* exists_opt ::= */ yytestcase(yyruleno==66);
- case 240: /* analyze_opt ::= */ yytestcase(yyruleno==240);
- case 248: /* agg_func_opt ::= */ yytestcase(yyruleno==248);
- case 399: /* set_quantifier_opt ::= */ yytestcase(yyruleno==399);
-{ yymsp[1].minor.yy481 = false; }
+ case 76: /* db_options ::= db_options COMP NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_COMP, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 65: /* exists_opt ::= IF EXISTS */
-{ yymsp[-1].minor.yy481 = true; }
+ case 77: /* db_options ::= db_options DURATION NK_INTEGER */
+ case 78: /* db_options ::= db_options DURATION NK_VARIABLE */ yytestcase(yyruleno==78);
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_DAYS, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 67: /* db_options ::= */
-{ yymsp[1].minor.yy392 = createDefaultDatabaseOptions(pCxt); }
+ case 79: /* db_options ::= db_options FSYNC NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_FSYNC, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 68: /* db_options ::= db_options BUFFER NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_BUFFER, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 80: /* db_options ::= db_options MAXROWS NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_MAXROWS, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 69: /* db_options ::= db_options CACHELAST NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_CACHELAST, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 81: /* db_options ::= db_options MINROWS NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_MINROWS, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 70: /* db_options ::= db_options COMP NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_COMP, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 82: /* db_options ::= db_options KEEP integer_list */
+ case 83: /* db_options ::= db_options KEEP variable_list */ yytestcase(yyruleno==83);
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_KEEP, yymsp[0].minor.yy356); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 71: /* db_options ::= db_options DURATION NK_INTEGER */
- case 72: /* db_options ::= db_options DURATION NK_VARIABLE */ yytestcase(yyruleno==72);
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_DAYS, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 84: /* db_options ::= db_options PAGES NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_PAGES, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 73: /* db_options ::= db_options FSYNC NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_FSYNC, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 85: /* db_options ::= db_options PAGESIZE NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_PAGESIZE, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 74: /* db_options ::= db_options MAXROWS NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_MAXROWS, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 86: /* db_options ::= db_options PRECISION NK_STRING */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_PRECISION, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 75: /* db_options ::= db_options MINROWS NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_MINROWS, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 87: /* db_options ::= db_options REPLICA NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_REPLICA, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 88: /* db_options ::= db_options STRICT NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_STRICT, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 89: /* db_options ::= db_options WAL NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_WAL, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 90: /* db_options ::= db_options VGROUPS NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_VGROUPS, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 91: /* db_options ::= db_options SINGLE_STABLE NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_SINGLE_STABLE, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 92: /* db_options ::= db_options RETENTIONS retention_list */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_RETENTIONS, yymsp[0].minor.yy356); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 93: /* db_options ::= db_options SCHEMALESS NK_INTEGER */
+{ yylhsminor.yy616 = setDatabaseOption(pCxt, yymsp[-2].minor.yy616, DB_OPTION_SCHEMALESS, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 94: /* alter_db_options ::= alter_db_option */
+{ yylhsminor.yy616 = createAlterDatabaseOptions(pCxt); yylhsminor.yy616 = setAlterDatabaseOption(pCxt, yylhsminor.yy616, &yymsp[0].minor.yy409); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 95: /* alter_db_options ::= alter_db_options alter_db_option */
+{ yylhsminor.yy616 = setAlterDatabaseOption(pCxt, yymsp[-1].minor.yy616, &yymsp[0].minor.yy409); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 96: /* alter_db_option ::= BUFFER NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_BUFFER; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 97: /* alter_db_option ::= CACHELAST NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_CACHELAST; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 98: /* alter_db_option ::= CACHELASTSIZE NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_CACHELASTSIZE; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 99: /* alter_db_option ::= FSYNC NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_FSYNC; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 100: /* alter_db_option ::= KEEP integer_list */
+ case 101: /* alter_db_option ::= KEEP variable_list */ yytestcase(yyruleno==101);
+{ yymsp[-1].minor.yy409.type = DB_OPTION_KEEP; yymsp[-1].minor.yy409.pList = yymsp[0].minor.yy356; }
+ break;
+ case 102: /* alter_db_option ::= PAGES NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_PAGES; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 103: /* alter_db_option ::= REPLICA NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_REPLICA; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 104: /* alter_db_option ::= STRICT NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_STRICT; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 105: /* alter_db_option ::= WAL NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = DB_OPTION_WAL; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
+ break;
+ case 106: /* integer_list ::= NK_INTEGER */
+{ yylhsminor.yy356 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 107: /* integer_list ::= integer_list NK_COMMA NK_INTEGER */
+ case 282: /* dnode_list ::= dnode_list DNODE NK_INTEGER */ yytestcase(yyruleno==282);
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-2].minor.yy356, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
+ yymsp[-2].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 108: /* variable_list ::= NK_VARIABLE */
+{ yylhsminor.yy356 = createNodeList(pCxt, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 109: /* variable_list ::= variable_list NK_COMMA NK_VARIABLE */
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-2].minor.yy356, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
+ yymsp[-2].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 110: /* retention_list ::= retention */
+ case 130: /* multi_create_clause ::= create_subtable_clause */ yytestcase(yyruleno==130);
+ case 133: /* multi_drop_clause ::= drop_table_clause */ yytestcase(yyruleno==133);
+ case 140: /* column_def_list ::= column_def */ yytestcase(yyruleno==140);
+ case 183: /* rollup_func_list ::= rollup_func_name */ yytestcase(yyruleno==183);
+ case 188: /* col_name_list ::= col_name */ yytestcase(yyruleno==188);
+ case 235: /* func_list ::= func */ yytestcase(yyruleno==235);
+ case 311: /* literal_list ::= signed_literal */ yytestcase(yyruleno==311);
+ case 374: /* other_para_list ::= star_func_para */ yytestcase(yyruleno==374);
+ case 428: /* select_list ::= select_item */ yytestcase(yyruleno==428);
+ case 482: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==482);
+{ yylhsminor.yy356 = createNodeList(pCxt, yymsp[0].minor.yy616); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 111: /* retention_list ::= retention_list NK_COMMA retention */
+ case 141: /* column_def_list ::= column_def_list NK_COMMA column_def */ yytestcase(yyruleno==141);
+ case 184: /* rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */ yytestcase(yyruleno==184);
+ case 189: /* col_name_list ::= col_name_list NK_COMMA col_name */ yytestcase(yyruleno==189);
+ case 236: /* func_list ::= func_list NK_COMMA func */ yytestcase(yyruleno==236);
+ case 312: /* literal_list ::= literal_list NK_COMMA signed_literal */ yytestcase(yyruleno==312);
+ case 375: /* other_para_list ::= other_para_list NK_COMMA star_func_para */ yytestcase(yyruleno==375);
+ case 429: /* select_list ::= select_list NK_COMMA select_item */ yytestcase(yyruleno==429);
+ case 483: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==483);
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-2].minor.yy356, yymsp[0].minor.yy616); }
+ yymsp[-2].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 112: /* retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */
+{ yylhsminor.yy616 = createNodeListNodeEx(pCxt, createDurationValueNode(pCxt, &yymsp[-2].minor.yy0), createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 113: /* cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */
+ case 115: /* cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ yytestcase(yyruleno==115);
+{ pCxt->pRootNode = createCreateTableStmt(pCxt, yymsp[-6].minor.yy151, yymsp[-5].minor.yy616, yymsp[-3].minor.yy356, yymsp[-1].minor.yy356, yymsp[0].minor.yy616); }
+ break;
+ case 114: /* cmd ::= CREATE TABLE multi_create_clause */
+{ pCxt->pRootNode = createCreateMultiTableStmt(pCxt, yymsp[0].minor.yy356); }
+ break;
+ case 116: /* cmd ::= DROP TABLE multi_drop_clause */
+{ pCxt->pRootNode = createDropTableStmt(pCxt, yymsp[0].minor.yy356); }
+ break;
+ case 117: /* cmd ::= DROP STABLE exists_opt full_table_name */
+{ pCxt->pRootNode = createDropSuperTableStmt(pCxt, yymsp[-1].minor.yy151, yymsp[0].minor.yy616); }
+ break;
+ case 118: /* cmd ::= ALTER TABLE alter_table_clause */
+ case 285: /* cmd ::= query_expression */ yytestcase(yyruleno==285);
+{ pCxt->pRootNode = yymsp[0].minor.yy616; }
+ break;
+ case 119: /* cmd ::= ALTER STABLE alter_table_clause */
+{ pCxt->pRootNode = setAlterSuperTableType(yymsp[0].minor.yy616); }
+ break;
+ case 120: /* alter_table_clause ::= full_table_name alter_table_options */
+{ yylhsminor.yy616 = createAlterTableModifyOptions(pCxt, yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 76: /* db_options ::= db_options KEEP integer_list */
- case 77: /* db_options ::= db_options KEEP variable_list */ yytestcase(yyruleno==77);
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_KEEP, yymsp[0].minor.yy600); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 121: /* alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */
+{ yylhsminor.yy616 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_ADD_COLUMN, &yymsp[-1].minor.yy361, yymsp[0].minor.yy600); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 78: /* db_options ::= db_options PAGES NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_PAGES, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 122: /* alter_table_clause ::= full_table_name DROP COLUMN column_name */
+{ yylhsminor.yy616 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy616, TSDB_ALTER_TABLE_DROP_COLUMN, &yymsp[0].minor.yy361); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 123: /* alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */
+{ yylhsminor.yy616 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, &yymsp[-1].minor.yy361, yymsp[0].minor.yy600); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 79: /* db_options ::= db_options PAGESIZE NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_PAGESIZE, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 124: /* alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */
+{ yylhsminor.yy616 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, &yymsp[-1].minor.yy361, &yymsp[0].minor.yy361); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 80: /* db_options ::= db_options PRECISION NK_STRING */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_PRECISION, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 81: /* db_options ::= db_options REPLICA NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_REPLICA, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 82: /* db_options ::= db_options STRICT NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_STRICT, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 83: /* db_options ::= db_options WAL NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_WAL, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 84: /* db_options ::= db_options VGROUPS NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_VGROUPS, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 85: /* db_options ::= db_options SINGLE_STABLE NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_SINGLE_STABLE, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 86: /* db_options ::= db_options RETENTIONS retention_list */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_RETENTIONS, yymsp[0].minor.yy600); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 87: /* db_options ::= db_options SCHEMALESS NK_INTEGER */
-{ yylhsminor.yy392 = setDatabaseOption(pCxt, yymsp[-2].minor.yy392, DB_OPTION_SCHEMALESS, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 88: /* alter_db_options ::= alter_db_option */
-{ yylhsminor.yy392 = createAlterDatabaseOptions(pCxt); yylhsminor.yy392 = setAlterDatabaseOption(pCxt, yylhsminor.yy392, &yymsp[0].minor.yy221); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 89: /* alter_db_options ::= alter_db_options alter_db_option */
-{ yylhsminor.yy392 = setAlterDatabaseOption(pCxt, yymsp[-1].minor.yy392, &yymsp[0].minor.yy221); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
- break;
- case 90: /* alter_db_option ::= BUFFER NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_BUFFER; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 91: /* alter_db_option ::= CACHELAST NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_CACHELAST; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 92: /* alter_db_option ::= FSYNC NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_FSYNC; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 93: /* alter_db_option ::= KEEP integer_list */
- case 94: /* alter_db_option ::= KEEP variable_list */ yytestcase(yyruleno==94);
-{ yymsp[-1].minor.yy221.type = DB_OPTION_KEEP; yymsp[-1].minor.yy221.pList = yymsp[0].minor.yy600; }
- break;
- case 95: /* alter_db_option ::= PAGES NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_PAGES; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 96: /* alter_db_option ::= REPLICA NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_REPLICA; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 97: /* alter_db_option ::= STRICT NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_STRICT; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 98: /* alter_db_option ::= WAL NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = DB_OPTION_WAL; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
- break;
- case 99: /* integer_list ::= NK_INTEGER */
-{ yylhsminor.yy600 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
- break;
- case 100: /* integer_list ::= integer_list NK_COMMA NK_INTEGER */
- case 269: /* dnode_list ::= dnode_list DNODE NK_INTEGER */ yytestcase(yyruleno==269);
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
- yymsp[-2].minor.yy600 = yylhsminor.yy600;
- break;
- case 101: /* variable_list ::= NK_VARIABLE */
-{ yylhsminor.yy600 = createNodeList(pCxt, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
- break;
- case 102: /* variable_list ::= variable_list NK_COMMA NK_VARIABLE */
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
- yymsp[-2].minor.yy600 = yylhsminor.yy600;
- break;
- case 103: /* retention_list ::= retention */
- case 123: /* multi_create_clause ::= create_subtable_clause */ yytestcase(yyruleno==123);
- case 126: /* multi_drop_clause ::= drop_table_clause */ yytestcase(yyruleno==126);
- case 133: /* column_def_list ::= column_def */ yytestcase(yyruleno==133);
- case 176: /* rollup_func_list ::= rollup_func_name */ yytestcase(yyruleno==176);
- case 181: /* col_name_list ::= col_name */ yytestcase(yyruleno==181);
- case 228: /* func_list ::= func */ yytestcase(yyruleno==228);
- case 295: /* literal_list ::= signed_literal */ yytestcase(yyruleno==295);
- case 349: /* other_para_list ::= star_func_para */ yytestcase(yyruleno==349);
- case 404: /* select_sublist ::= select_item */ yytestcase(yyruleno==404);
- case 457: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==457);
-{ yylhsminor.yy600 = createNodeList(pCxt, yymsp[0].minor.yy392); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
- break;
- case 104: /* retention_list ::= retention_list NK_COMMA retention */
- case 134: /* column_def_list ::= column_def_list NK_COMMA column_def */ yytestcase(yyruleno==134);
- case 177: /* rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */ yytestcase(yyruleno==177);
- case 182: /* col_name_list ::= col_name_list NK_COMMA col_name */ yytestcase(yyruleno==182);
- case 229: /* func_list ::= func_list NK_COMMA func */ yytestcase(yyruleno==229);
- case 296: /* literal_list ::= literal_list NK_COMMA signed_literal */ yytestcase(yyruleno==296);
- case 350: /* other_para_list ::= other_para_list NK_COMMA star_func_para */ yytestcase(yyruleno==350);
- case 405: /* select_sublist ::= select_sublist NK_COMMA select_item */ yytestcase(yyruleno==405);
- case 458: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==458);
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, yymsp[0].minor.yy392); }
- yymsp[-2].minor.yy600 = yylhsminor.yy600;
- break;
- case 105: /* retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */
-{ yylhsminor.yy392 = createNodeListNodeEx(pCxt, createDurationValueNode(pCxt, &yymsp[-2].minor.yy0), createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 106: /* cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */
- case 108: /* cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ yytestcase(yyruleno==108);
-{ pCxt->pRootNode = createCreateTableStmt(pCxt, yymsp[-6].minor.yy481, yymsp[-5].minor.yy392, yymsp[-3].minor.yy600, yymsp[-1].minor.yy600, yymsp[0].minor.yy392); }
- break;
- case 107: /* cmd ::= CREATE TABLE multi_create_clause */
-{ pCxt->pRootNode = createCreateMultiTableStmt(pCxt, yymsp[0].minor.yy600); }
- break;
- case 109: /* cmd ::= DROP TABLE multi_drop_clause */
-{ pCxt->pRootNode = createDropTableStmt(pCxt, yymsp[0].minor.yy600); }
- break;
- case 110: /* cmd ::= DROP STABLE exists_opt full_table_name */
-{ pCxt->pRootNode = createDropSuperTableStmt(pCxt, yymsp[-1].minor.yy481, yymsp[0].minor.yy392); }
- break;
- case 111: /* cmd ::= ALTER TABLE alter_table_clause */
- case 112: /* cmd ::= ALTER STABLE alter_table_clause */ yytestcase(yyruleno==112);
- case 272: /* cmd ::= query_expression */ yytestcase(yyruleno==272);
-{ pCxt->pRootNode = yymsp[0].minor.yy392; }
- break;
- case 113: /* alter_table_clause ::= full_table_name alter_table_options */
-{ yylhsminor.yy392 = createAlterTableModifyOptions(pCxt, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
- break;
- case 114: /* alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */
-{ yylhsminor.yy392 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_ADD_COLUMN, &yymsp[-1].minor.yy57, yymsp[0].minor.yy448); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
- break;
- case 115: /* alter_table_clause ::= full_table_name DROP COLUMN column_name */
-{ yylhsminor.yy392 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy392, TSDB_ALTER_TABLE_DROP_COLUMN, &yymsp[0].minor.yy57); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
- break;
- case 116: /* alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */
-{ yylhsminor.yy392 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, &yymsp[-1].minor.yy57, yymsp[0].minor.yy448); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
+ case 125: /* alter_table_clause ::= full_table_name ADD TAG column_name type_name */
+{ yylhsminor.yy616 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_ADD_TAG, &yymsp[-1].minor.yy361, yymsp[0].minor.yy600); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 117: /* alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */
-{ yylhsminor.yy392 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
- break;
- case 118: /* alter_table_clause ::= full_table_name ADD TAG column_name type_name */
-{ yylhsminor.yy392 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_ADD_TAG, &yymsp[-1].minor.yy57, yymsp[0].minor.yy448); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
- break;
- case 119: /* alter_table_clause ::= full_table_name DROP TAG column_name */
-{ yylhsminor.yy392 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy392, TSDB_ALTER_TABLE_DROP_TAG, &yymsp[0].minor.yy57); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 126: /* alter_table_clause ::= full_table_name DROP TAG column_name */
+{ yylhsminor.yy616 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy616, TSDB_ALTER_TABLE_DROP_TAG, &yymsp[0].minor.yy361); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 120: /* alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */
-{ yylhsminor.yy392 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, &yymsp[-1].minor.yy57, yymsp[0].minor.yy448); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
+ case 127: /* alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */
+{ yylhsminor.yy616 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, &yymsp[-1].minor.yy361, yymsp[0].minor.yy600); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 121: /* alter_table_clause ::= full_table_name RENAME TAG column_name column_name */
-{ yylhsminor.yy392 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy392, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
- break;
- case 122: /* alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */
-{ yylhsminor.yy392 = createAlterTableSetTag(pCxt, yymsp[-5].minor.yy392, &yymsp[-2].minor.yy57, yymsp[0].minor.yy392); }
- yymsp[-5].minor.yy392 = yylhsminor.yy392;
+ case 128: /* alter_table_clause ::= full_table_name RENAME TAG column_name column_name */
+{ yylhsminor.yy616 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy616, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &yymsp[-1].minor.yy361, &yymsp[0].minor.yy361); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 124: /* multi_create_clause ::= multi_create_clause create_subtable_clause */
- case 127: /* multi_drop_clause ::= multi_drop_clause drop_table_clause */ yytestcase(yyruleno==127);
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-1].minor.yy600, yymsp[0].minor.yy392); }
- yymsp[-1].minor.yy600 = yylhsminor.yy600;
+ case 129: /* alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */
+{ yylhsminor.yy616 = createAlterTableSetTag(pCxt, yymsp[-5].minor.yy616, &yymsp[-2].minor.yy361, yymsp[0].minor.yy616); }
+ yymsp[-5].minor.yy616 = yylhsminor.yy616;
break;
- case 125: /* create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP table_options */
-{ yylhsminor.yy392 = createCreateSubTableClause(pCxt, yymsp[-9].minor.yy481, yymsp[-8].minor.yy392, yymsp[-6].minor.yy392, yymsp[-5].minor.yy600, yymsp[-2].minor.yy600, yymsp[0].minor.yy392); }
- yymsp[-9].minor.yy392 = yylhsminor.yy392;
+ case 131: /* multi_create_clause ::= multi_create_clause create_subtable_clause */
+ case 134: /* multi_drop_clause ::= multi_drop_clause drop_table_clause */ yytestcase(yyruleno==134);
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-1].minor.yy356, yymsp[0].minor.yy616); }
+ yymsp[-1].minor.yy356 = yylhsminor.yy356;
break;
- case 128: /* drop_table_clause ::= exists_opt full_table_name */
-{ yylhsminor.yy392 = createDropTableClause(pCxt, yymsp[-1].minor.yy481, yymsp[0].minor.yy392); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 132: /* create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options */
+{ yylhsminor.yy616 = createCreateSubTableClause(pCxt, yymsp[-9].minor.yy151, yymsp[-8].minor.yy616, yymsp[-6].minor.yy616, yymsp[-5].minor.yy356, yymsp[-2].minor.yy356, yymsp[0].minor.yy616); }
+ yymsp[-9].minor.yy616 = yylhsminor.yy616;
break;
- case 129: /* specific_tags_opt ::= */
- case 160: /* tags_def_opt ::= */ yytestcase(yyruleno==160);
- case 412: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==412);
- case 429: /* group_by_clause_opt ::= */ yytestcase(yyruleno==429);
- case 445: /* order_by_clause_opt ::= */ yytestcase(yyruleno==445);
-{ yymsp[1].minor.yy600 = NULL; }
+ case 135: /* drop_table_clause ::= exists_opt full_table_name */
+{ yylhsminor.yy616 = createDropTableClause(pCxt, yymsp[-1].minor.yy151, yymsp[0].minor.yy616); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 130: /* specific_tags_opt ::= NK_LP col_name_list NK_RP */
-{ yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600; }
+ case 136: /* specific_cols_opt ::= */
+ case 167: /* tags_def_opt ::= */ yytestcase(yyruleno==167);
+ case 437: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==437);
+ case 454: /* group_by_clause_opt ::= */ yytestcase(yyruleno==454);
+ case 470: /* order_by_clause_opt ::= */ yytestcase(yyruleno==470);
+{ yymsp[1].minor.yy356 = NULL; }
break;
- case 131: /* full_table_name ::= table_name */
-{ yylhsminor.yy392 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy57, NULL); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 137: /* specific_cols_opt ::= NK_LP col_name_list NK_RP */
+{ yymsp[-2].minor.yy356 = yymsp[-1].minor.yy356; }
break;
- case 132: /* full_table_name ::= db_name NK_DOT table_name */
-{ yylhsminor.yy392 = createRealTableNode(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57, NULL); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 138: /* full_table_name ::= table_name */
+{ yylhsminor.yy616 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy361, NULL); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 135: /* column_def ::= column_name type_name */
-{ yylhsminor.yy392 = createColumnDefNode(pCxt, &yymsp[-1].minor.yy57, yymsp[0].minor.yy448, NULL); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 139: /* full_table_name ::= db_name NK_DOT table_name */
+{ yylhsminor.yy616 = createRealTableNode(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361, NULL); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 136: /* column_def ::= column_name type_name COMMENT NK_STRING */
-{ yylhsminor.yy392 = createColumnDefNode(pCxt, &yymsp[-3].minor.yy57, yymsp[-2].minor.yy448, &yymsp[0].minor.yy0); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 142: /* column_def ::= column_name type_name */
+{ yylhsminor.yy616 = createColumnDefNode(pCxt, &yymsp[-1].minor.yy361, yymsp[0].minor.yy600, NULL); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 137: /* type_name ::= BOOL */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_BOOL); }
+ case 143: /* column_def ::= column_name type_name COMMENT NK_STRING */
+{ yylhsminor.yy616 = createColumnDefNode(pCxt, &yymsp[-3].minor.yy361, yymsp[-2].minor.yy600, &yymsp[0].minor.yy0); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 138: /* type_name ::= TINYINT */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_TINYINT); }
+ case 144: /* type_name ::= BOOL */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_BOOL); }
break;
- case 139: /* type_name ::= SMALLINT */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_SMALLINT); }
+ case 145: /* type_name ::= TINYINT */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_TINYINT); }
break;
- case 140: /* type_name ::= INT */
- case 141: /* type_name ::= INTEGER */ yytestcase(yyruleno==141);
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_INT); }
+ case 146: /* type_name ::= SMALLINT */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_SMALLINT); }
break;
- case 142: /* type_name ::= BIGINT */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_BIGINT); }
+ case 147: /* type_name ::= INT */
+ case 148: /* type_name ::= INTEGER */ yytestcase(yyruleno==148);
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_INT); }
break;
- case 143: /* type_name ::= FLOAT */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_FLOAT); }
+ case 149: /* type_name ::= BIGINT */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_BIGINT); }
break;
- case 144: /* type_name ::= DOUBLE */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_DOUBLE); }
+ case 150: /* type_name ::= FLOAT */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_FLOAT); }
break;
- case 145: /* type_name ::= BINARY NK_LP NK_INTEGER NK_RP */
-{ yymsp[-3].minor.yy448 = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy0); }
+ case 151: /* type_name ::= DOUBLE */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_DOUBLE); }
break;
- case 146: /* type_name ::= TIMESTAMP */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_TIMESTAMP); }
+ case 152: /* type_name ::= BINARY NK_LP NK_INTEGER NK_RP */
+{ yymsp[-3].minor.yy600 = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy0); }
break;
- case 147: /* type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */
-{ yymsp[-3].minor.yy448 = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &yymsp[-1].minor.yy0); }
+ case 153: /* type_name ::= TIMESTAMP */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_TIMESTAMP); }
break;
- case 148: /* type_name ::= TINYINT UNSIGNED */
-{ yymsp[-1].minor.yy448 = createDataType(TSDB_DATA_TYPE_UTINYINT); }
+ case 154: /* type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */
+{ yymsp[-3].minor.yy600 = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &yymsp[-1].minor.yy0); }
break;
- case 149: /* type_name ::= SMALLINT UNSIGNED */
-{ yymsp[-1].minor.yy448 = createDataType(TSDB_DATA_TYPE_USMALLINT); }
+ case 155: /* type_name ::= TINYINT UNSIGNED */
+{ yymsp[-1].minor.yy600 = createDataType(TSDB_DATA_TYPE_UTINYINT); }
break;
- case 150: /* type_name ::= INT UNSIGNED */
-{ yymsp[-1].minor.yy448 = createDataType(TSDB_DATA_TYPE_UINT); }
+ case 156: /* type_name ::= SMALLINT UNSIGNED */
+{ yymsp[-1].minor.yy600 = createDataType(TSDB_DATA_TYPE_USMALLINT); }
break;
- case 151: /* type_name ::= BIGINT UNSIGNED */
-{ yymsp[-1].minor.yy448 = createDataType(TSDB_DATA_TYPE_UBIGINT); }
+ case 157: /* type_name ::= INT UNSIGNED */
+{ yymsp[-1].minor.yy600 = createDataType(TSDB_DATA_TYPE_UINT); }
break;
- case 152: /* type_name ::= JSON */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_JSON); }
+ case 158: /* type_name ::= BIGINT UNSIGNED */
+{ yymsp[-1].minor.yy600 = createDataType(TSDB_DATA_TYPE_UBIGINT); }
break;
- case 153: /* type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */
-{ yymsp[-3].minor.yy448 = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &yymsp[-1].minor.yy0); }
+ case 159: /* type_name ::= JSON */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_JSON); }
break;
- case 154: /* type_name ::= MEDIUMBLOB */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); }
+ case 160: /* type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */
+{ yymsp[-3].minor.yy600 = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &yymsp[-1].minor.yy0); }
break;
- case 155: /* type_name ::= BLOB */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_BLOB); }
+ case 161: /* type_name ::= MEDIUMBLOB */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); }
break;
- case 156: /* type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */
-{ yymsp[-3].minor.yy448 = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &yymsp[-1].minor.yy0); }
+ case 162: /* type_name ::= BLOB */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_BLOB); }
break;
- case 157: /* type_name ::= DECIMAL */
-{ yymsp[0].minor.yy448 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
+ case 163: /* type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */
+{ yymsp[-3].minor.yy600 = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &yymsp[-1].minor.yy0); }
break;
- case 158: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */
-{ yymsp[-3].minor.yy448 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
+ case 164: /* type_name ::= DECIMAL */
+{ yymsp[0].minor.yy600 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
break;
- case 159: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */
-{ yymsp[-5].minor.yy448 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
+ case 165: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */
+{ yymsp[-3].minor.yy600 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
break;
- case 161: /* tags_def_opt ::= tags_def */
- case 348: /* star_func_para_list ::= other_para_list */ yytestcase(yyruleno==348);
- case 403: /* select_list ::= select_sublist */ yytestcase(yyruleno==403);
-{ yylhsminor.yy600 = yymsp[0].minor.yy600; }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
+ case 166: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */
+{ yymsp[-5].minor.yy600 = createDataType(TSDB_DATA_TYPE_DECIMAL); }
break;
- case 162: /* tags_def ::= TAGS NK_LP column_def_list NK_RP */
-{ yymsp[-3].minor.yy600 = yymsp[-1].minor.yy600; }
+ case 168: /* tags_def_opt ::= tags_def */
+ case 373: /* star_func_para_list ::= other_para_list */ yytestcase(yyruleno==373);
+{ yylhsminor.yy356 = yymsp[0].minor.yy356; }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
break;
- case 163: /* table_options ::= */
-{ yymsp[1].minor.yy392 = createDefaultTableOptions(pCxt); }
+ case 169: /* tags_def ::= TAGS NK_LP column_def_list NK_RP */
+{ yymsp[-3].minor.yy356 = yymsp[-1].minor.yy356; }
break;
- case 164: /* table_options ::= table_options COMMENT NK_STRING */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-2].minor.yy392, TABLE_OPTION_COMMENT, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 170: /* table_options ::= */
+{ yymsp[1].minor.yy616 = createDefaultTableOptions(pCxt); }
break;
- case 165: /* table_options ::= table_options MAX_DELAY duration_list */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-2].minor.yy392, TABLE_OPTION_MAXDELAY, yymsp[0].minor.yy600); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 171: /* table_options ::= table_options COMMENT NK_STRING */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-2].minor.yy616, TABLE_OPTION_COMMENT, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 166: /* table_options ::= table_options WATERMARK duration_list */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-2].minor.yy392, TABLE_OPTION_WATERMARK, yymsp[0].minor.yy600); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 172: /* table_options ::= table_options MAX_DELAY duration_list */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-2].minor.yy616, TABLE_OPTION_MAXDELAY, yymsp[0].minor.yy356); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 167: /* table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-4].minor.yy392, TABLE_OPTION_ROLLUP, yymsp[-1].minor.yy600); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
+ case 173: /* table_options ::= table_options WATERMARK duration_list */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-2].minor.yy616, TABLE_OPTION_WATERMARK, yymsp[0].minor.yy356); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 168: /* table_options ::= table_options TTL NK_INTEGER */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-2].minor.yy392, TABLE_OPTION_TTL, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 174: /* table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-4].minor.yy616, TABLE_OPTION_ROLLUP, yymsp[-1].minor.yy356); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 169: /* table_options ::= table_options SMA NK_LP col_name_list NK_RP */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-4].minor.yy392, TABLE_OPTION_SMA, yymsp[-1].minor.yy600); }
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
+ case 175: /* table_options ::= table_options TTL NK_INTEGER */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-2].minor.yy616, TABLE_OPTION_TTL, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 170: /* alter_table_options ::= alter_table_option */
-{ yylhsminor.yy392 = createAlterTableOptions(pCxt); yylhsminor.yy392 = setTableOption(pCxt, yylhsminor.yy392, yymsp[0].minor.yy221.type, &yymsp[0].minor.yy221.val); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 176: /* table_options ::= table_options SMA NK_LP col_name_list NK_RP */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-4].minor.yy616, TABLE_OPTION_SMA, yymsp[-1].minor.yy356); }
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 171: /* alter_table_options ::= alter_table_options alter_table_option */
-{ yylhsminor.yy392 = setTableOption(pCxt, yymsp[-1].minor.yy392, yymsp[0].minor.yy221.type, &yymsp[0].minor.yy221.val); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 177: /* alter_table_options ::= alter_table_option */
+{ yylhsminor.yy616 = createAlterTableOptions(pCxt); yylhsminor.yy616 = setTableOption(pCxt, yylhsminor.yy616, yymsp[0].minor.yy409.type, &yymsp[0].minor.yy409.val); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 172: /* alter_table_option ::= COMMENT NK_STRING */
-{ yymsp[-1].minor.yy221.type = TABLE_OPTION_COMMENT; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
+ case 178: /* alter_table_options ::= alter_table_options alter_table_option */
+{ yylhsminor.yy616 = setTableOption(pCxt, yymsp[-1].minor.yy616, yymsp[0].minor.yy409.type, &yymsp[0].minor.yy409.val); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 173: /* alter_table_option ::= TTL NK_INTEGER */
-{ yymsp[-1].minor.yy221.type = TABLE_OPTION_TTL; yymsp[-1].minor.yy221.val = yymsp[0].minor.yy0; }
+ case 179: /* alter_table_option ::= COMMENT NK_STRING */
+{ yymsp[-1].minor.yy409.type = TABLE_OPTION_COMMENT; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
break;
- case 174: /* duration_list ::= duration_literal */
- case 322: /* expression_list ::= expression */ yytestcase(yyruleno==322);
-{ yylhsminor.yy600 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy392)); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
+ case 180: /* alter_table_option ::= TTL NK_INTEGER */
+{ yymsp[-1].minor.yy409.type = TABLE_OPTION_TTL; yymsp[-1].minor.yy409.val = yymsp[0].minor.yy0; }
break;
- case 175: /* duration_list ::= duration_list NK_COMMA duration_literal */
- case 323: /* expression_list ::= expression_list NK_COMMA expression */ yytestcase(yyruleno==323);
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, releaseRawExprNode(pCxt, yymsp[0].minor.yy392)); }
- yymsp[-2].minor.yy600 = yylhsminor.yy600;
+ case 181: /* duration_list ::= duration_literal */
+ case 340: /* expression_list ::= expression */ yytestcase(yyruleno==340);
+{ yylhsminor.yy356 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy616)); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
break;
- case 178: /* rollup_func_name ::= function_name */
-{ yylhsminor.yy392 = createFunctionNode(pCxt, &yymsp[0].minor.yy57, NULL); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 182: /* duration_list ::= duration_list NK_COMMA duration_literal */
+ case 341: /* expression_list ::= expression_list NK_COMMA expression */ yytestcase(yyruleno==341);
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-2].minor.yy356, releaseRawExprNode(pCxt, yymsp[0].minor.yy616)); }
+ yymsp[-2].minor.yy356 = yylhsminor.yy356;
break;
- case 179: /* rollup_func_name ::= FIRST */
- case 180: /* rollup_func_name ::= LAST */ yytestcase(yyruleno==180);
-{ yylhsminor.yy392 = createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 185: /* rollup_func_name ::= function_name */
+{ yylhsminor.yy616 = createFunctionNode(pCxt, &yymsp[0].minor.yy361, NULL); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 183: /* col_name ::= column_name */
-{ yylhsminor.yy392 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy57); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 186: /* rollup_func_name ::= FIRST */
+ case 187: /* rollup_func_name ::= LAST */ yytestcase(yyruleno==187);
+{ yylhsminor.yy616 = createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 184: /* cmd ::= SHOW DNODES */
+ case 190: /* col_name ::= column_name */
+{ yylhsminor.yy616 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy361); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 191: /* cmd ::= SHOW DNODES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DNODES_STMT); }
break;
- case 185: /* cmd ::= SHOW USERS */
+ case 192: /* cmd ::= SHOW USERS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_USERS_STMT); }
break;
- case 186: /* cmd ::= SHOW DATABASES */
+ case 193: /* cmd ::= SHOW DATABASES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DATABASES_STMT); }
break;
- case 187: /* cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */
-{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLES_STMT, yymsp[-2].minor.yy392, yymsp[0].minor.yy392, OP_TYPE_LIKE); }
+ case 194: /* cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */
+{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLES_STMT, yymsp[-2].minor.yy616, yymsp[0].minor.yy616, OP_TYPE_LIKE); }
break;
- case 188: /* cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */
-{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_STABLES_STMT, yymsp[-2].minor.yy392, yymsp[0].minor.yy392, OP_TYPE_LIKE); }
+ case 195: /* cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */
+{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_STABLES_STMT, yymsp[-2].minor.yy616, yymsp[0].minor.yy616, OP_TYPE_LIKE); }
break;
- case 189: /* cmd ::= SHOW db_name_cond_opt VGROUPS */
-{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, yymsp[-1].minor.yy392, NULL, OP_TYPE_LIKE); }
+ case 196: /* cmd ::= SHOW db_name_cond_opt VGROUPS */
+{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, yymsp[-1].minor.yy616, NULL, OP_TYPE_LIKE); }
break;
- case 190: /* cmd ::= SHOW MNODES */
+ case 197: /* cmd ::= SHOW MNODES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MNODES_STMT); }
break;
- case 191: /* cmd ::= SHOW MODULES */
+ case 198: /* cmd ::= SHOW MODULES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MODULES_STMT); }
break;
- case 192: /* cmd ::= SHOW QNODES */
+ case 199: /* cmd ::= SHOW QNODES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_QNODES_STMT); }
break;
- case 193: /* cmd ::= SHOW FUNCTIONS */
+ case 200: /* cmd ::= SHOW FUNCTIONS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_FUNCTIONS_STMT); }
break;
- case 194: /* cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */
-{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, yymsp[0].minor.yy392, yymsp[-1].minor.yy392, OP_TYPE_EQUAL); }
+ case 201: /* cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */
+{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, yymsp[0].minor.yy616, yymsp[-1].minor.yy616, OP_TYPE_EQUAL); }
break;
- case 195: /* cmd ::= SHOW STREAMS */
+ case 202: /* cmd ::= SHOW STREAMS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT); }
break;
- case 196: /* cmd ::= SHOW ACCOUNTS */
+ case 203: /* cmd ::= SHOW ACCOUNTS */
{ pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
break;
- case 197: /* cmd ::= SHOW APPS */
+ case 204: /* cmd ::= SHOW APPS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT); }
break;
- case 198: /* cmd ::= SHOW CONNECTIONS */
+ case 205: /* cmd ::= SHOW CONNECTIONS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONNECTIONS_STMT); }
break;
- case 199: /* cmd ::= SHOW LICENCE */
- case 200: /* cmd ::= SHOW GRANTS */ yytestcase(yyruleno==200);
+ case 206: /* cmd ::= SHOW LICENCE */
+ case 207: /* cmd ::= SHOW GRANTS */ yytestcase(yyruleno==207);
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LICENCE_STMT); }
break;
- case 201: /* cmd ::= SHOW CREATE DATABASE db_name */
-{ pCxt->pRootNode = createShowCreateDatabaseStmt(pCxt, &yymsp[0].minor.yy57); }
+ case 208: /* cmd ::= SHOW CREATE DATABASE db_name */
+{ pCxt->pRootNode = createShowCreateDatabaseStmt(pCxt, &yymsp[0].minor.yy361); }
break;
- case 202: /* cmd ::= SHOW CREATE TABLE full_table_name */
-{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_TABLE_STMT, yymsp[0].minor.yy392); }
+ case 209: /* cmd ::= SHOW CREATE TABLE full_table_name */
+{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_TABLE_STMT, yymsp[0].minor.yy616); }
break;
- case 203: /* cmd ::= SHOW CREATE STABLE full_table_name */
-{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_STABLE_STMT, yymsp[0].minor.yy392); }
+ case 210: /* cmd ::= SHOW CREATE STABLE full_table_name */
+{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_STABLE_STMT, yymsp[0].minor.yy616); }
break;
- case 204: /* cmd ::= SHOW QUERIES */
+ case 211: /* cmd ::= SHOW QUERIES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_QUERIES_STMT); }
break;
- case 205: /* cmd ::= SHOW SCORES */
+ case 212: /* cmd ::= SHOW SCORES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SCORES_STMT); }
break;
- case 206: /* cmd ::= SHOW TOPICS */
+ case 213: /* cmd ::= SHOW TOPICS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TOPICS_STMT); }
break;
- case 207: /* cmd ::= SHOW VARIABLES */
+ case 214: /* cmd ::= SHOW VARIABLES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VARIABLES_STMT); }
break;
- case 208: /* cmd ::= SHOW LOCAL VARIABLES */
+ case 215: /* cmd ::= SHOW LOCAL VARIABLES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT); }
break;
- case 209: /* cmd ::= SHOW DNODE NK_INTEGER VARIABLES */
+ case 216: /* cmd ::= SHOW DNODE NK_INTEGER VARIABLES */
{ pCxt->pRootNode = createShowDnodeVariablesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[-1].minor.yy0)); }
break;
- case 210: /* cmd ::= SHOW BNODES */
+ case 217: /* cmd ::= SHOW BNODES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_BNODES_STMT); }
break;
- case 211: /* cmd ::= SHOW SNODES */
+ case 218: /* cmd ::= SHOW SNODES */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SNODES_STMT); }
break;
- case 212: /* cmd ::= SHOW CLUSTER */
+ case 219: /* cmd ::= SHOW CLUSTER */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CLUSTER_STMT); }
break;
- case 213: /* cmd ::= SHOW TRANSACTIONS */
+ case 220: /* cmd ::= SHOW TRANSACTIONS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TRANSACTIONS_STMT); }
break;
- case 214: /* cmd ::= SHOW TABLE DISTRIBUTED full_table_name */
-{ pCxt->pRootNode = createShowTableDistributedStmt(pCxt, yymsp[0].minor.yy392); }
+ case 221: /* cmd ::= SHOW TABLE DISTRIBUTED full_table_name */
+{ pCxt->pRootNode = createShowTableDistributedStmt(pCxt, yymsp[0].minor.yy616); }
break;
- case 215: /* db_name_cond_opt ::= */
- case 220: /* from_db_opt ::= */ yytestcase(yyruleno==220);
-{ yymsp[1].minor.yy392 = createDefaultDatabaseCondValue(pCxt); }
+ case 222: /* cmd ::= SHOW CONSUMERS */
+{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONSUMERS_STMT); }
break;
- case 216: /* db_name_cond_opt ::= db_name NK_DOT */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy57); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 223: /* cmd ::= SHOW SUBSCRIPTIONS */
+{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT); }
break;
- case 217: /* like_pattern_opt ::= */
- case 225: /* index_options ::= */ yytestcase(yyruleno==225);
- case 254: /* into_opt ::= */ yytestcase(yyruleno==254);
- case 410: /* where_clause_opt ::= */ yytestcase(yyruleno==410);
- case 414: /* twindow_clause_opt ::= */ yytestcase(yyruleno==414);
- case 419: /* sliding_opt ::= */ yytestcase(yyruleno==419);
- case 421: /* fill_opt ::= */ yytestcase(yyruleno==421);
- case 433: /* having_clause_opt ::= */ yytestcase(yyruleno==433);
- case 435: /* range_opt ::= */ yytestcase(yyruleno==435);
- case 437: /* every_opt ::= */ yytestcase(yyruleno==437);
- case 447: /* slimit_clause_opt ::= */ yytestcase(yyruleno==447);
- case 451: /* limit_clause_opt ::= */ yytestcase(yyruleno==451);
-{ yymsp[1].minor.yy392 = NULL; }
+ case 224: /* db_name_cond_opt ::= */
+ case 229: /* from_db_opt ::= */ yytestcase(yyruleno==229);
+{ yymsp[1].minor.yy616 = createDefaultDatabaseCondValue(pCxt); }
break;
- case 218: /* like_pattern_opt ::= LIKE NK_STRING */
-{ yymsp[-1].minor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); }
+ case 225: /* db_name_cond_opt ::= db_name NK_DOT */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy361); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 219: /* table_name_cond ::= table_name */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy57); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 226: /* like_pattern_opt ::= */
+ case 266: /* into_opt ::= */ yytestcase(yyruleno==266);
+ case 406: /* from_clause_opt ::= */ yytestcase(yyruleno==406);
+ case 435: /* where_clause_opt ::= */ yytestcase(yyruleno==435);
+ case 439: /* twindow_clause_opt ::= */ yytestcase(yyruleno==439);
+ case 444: /* sliding_opt ::= */ yytestcase(yyruleno==444);
+ case 446: /* fill_opt ::= */ yytestcase(yyruleno==446);
+ case 458: /* having_clause_opt ::= */ yytestcase(yyruleno==458);
+ case 460: /* range_opt ::= */ yytestcase(yyruleno==460);
+ case 462: /* every_opt ::= */ yytestcase(yyruleno==462);
+ case 472: /* slimit_clause_opt ::= */ yytestcase(yyruleno==472);
+ case 476: /* limit_clause_opt ::= */ yytestcase(yyruleno==476);
+{ yymsp[1].minor.yy616 = NULL; }
break;
- case 221: /* from_db_opt ::= FROM db_name */
-{ yymsp[-1].minor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy57); }
+ case 227: /* like_pattern_opt ::= LIKE NK_STRING */
+{ yymsp[-1].minor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); }
break;
- case 222: /* cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options */
-{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, yymsp[-4].minor.yy481, &yymsp[-3].minor.yy57, &yymsp[-1].minor.yy57, NULL, yymsp[0].minor.yy392); }
+ case 228: /* table_name_cond ::= table_name */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy361); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 223: /* cmd ::= CREATE FULLTEXT INDEX not_exists_opt index_name ON table_name NK_LP col_name_list NK_RP */
-{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_FULLTEXT, yymsp[-6].minor.yy481, &yymsp[-5].minor.yy57, &yymsp[-3].minor.yy57, yymsp[-1].minor.yy600, NULL); }
+ case 230: /* from_db_opt ::= FROM db_name */
+{ yymsp[-1].minor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy361); }
break;
- case 224: /* cmd ::= DROP INDEX exists_opt index_name ON table_name */
-{ pCxt->pRootNode = createDropIndexStmt(pCxt, yymsp[-3].minor.yy481, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57); }
+ case 231: /* cmd ::= CREATE SMA INDEX not_exists_opt index_name ON table_name index_options */
+{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, yymsp[-4].minor.yy151, &yymsp[-3].minor.yy361, &yymsp[-1].minor.yy361, NULL, yymsp[0].minor.yy616); }
break;
- case 226: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt */
-{ yymsp[-8].minor.yy392 = createIndexOption(pCxt, yymsp[-6].minor.yy600, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), NULL, yymsp[0].minor.yy392); }
+ case 232: /* cmd ::= DROP INDEX exists_opt index_name */
+{ pCxt->pRootNode = createDropIndexStmt(pCxt, yymsp[-1].minor.yy151, &yymsp[0].minor.yy361); }
break;
- case 227: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt */
-{ yymsp[-10].minor.yy392 = createIndexOption(pCxt, yymsp[-8].minor.yy600, releaseRawExprNode(pCxt, yymsp[-4].minor.yy392), releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), yymsp[0].minor.yy392); }
+ case 233: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt */
+{ yymsp[-9].minor.yy616 = createIndexOption(pCxt, yymsp[-7].minor.yy356, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), NULL, yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 230: /* func ::= function_name NK_LP expression_list NK_RP */
-{ yylhsminor.yy392 = createFunctionNode(pCxt, &yymsp[-3].minor.yy57, yymsp[-1].minor.yy600); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 234: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt */
+{ yymsp[-11].minor.yy616 = createIndexOption(pCxt, yymsp[-9].minor.yy356, releaseRawExprNode(pCxt, yymsp[-5].minor.yy616), releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 231: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression */
-{ pCxt->pRootNode = createCreateTopicStmt(pCxt, yymsp[-3].minor.yy481, &yymsp[-2].minor.yy57, yymsp[0].minor.yy392, NULL, NULL); }
+ case 237: /* func ::= function_name NK_LP expression_list NK_RP */
+{ yylhsminor.yy616 = createFunctionNode(pCxt, &yymsp[-3].minor.yy361, yymsp[-1].minor.yy356); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 232: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */
-{ pCxt->pRootNode = createCreateTopicStmt(pCxt, yymsp[-4].minor.yy481, &yymsp[-3].minor.yy57, NULL, &yymsp[0].minor.yy57, NULL); }
+ case 238: /* sma_stream_opt ::= */
+ case 268: /* stream_options ::= */ yytestcase(yyruleno==268);
+{ yymsp[1].minor.yy616 = createStreamOptions(pCxt); }
break;
- case 233: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */
-{ pCxt->pRootNode = createCreateTopicStmt(pCxt, yymsp[-4].minor.yy481, &yymsp[-3].minor.yy57, NULL, NULL, yymsp[0].minor.yy392); }
+ case 239: /* sma_stream_opt ::= stream_options WATERMARK duration_literal */
+ case 272: /* stream_options ::= stream_options WATERMARK duration_literal */ yytestcase(yyruleno==272);
+{ ((SStreamOptions*)yymsp[-2].minor.yy616)->pWatermark = releaseRawExprNode(pCxt, yymsp[0].minor.yy616); yylhsminor.yy616 = yymsp[-2].minor.yy616; }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 234: /* cmd ::= DROP TOPIC exists_opt topic_name */
-{ pCxt->pRootNode = createDropTopicStmt(pCxt, yymsp[-1].minor.yy481, &yymsp[0].minor.yy57); }
+ case 240: /* sma_stream_opt ::= stream_options MAX_DELAY duration_literal */
+{ ((SStreamOptions*)yymsp[-2].minor.yy616)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy616); yylhsminor.yy616 = yymsp[-2].minor.yy616; }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 235: /* cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */
-{ pCxt->pRootNode = createDropCGroupStmt(pCxt, yymsp[-3].minor.yy481, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57); }
+ case 241: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_expression */
+{ pCxt->pRootNode = createCreateTopicStmtUseQuery(pCxt, yymsp[-3].minor.yy151, &yymsp[-2].minor.yy361, yymsp[0].minor.yy616); }
break;
- case 236: /* cmd ::= DESC full_table_name */
- case 237: /* cmd ::= DESCRIBE full_table_name */ yytestcase(yyruleno==237);
-{ pCxt->pRootNode = createDescribeStmt(pCxt, yymsp[0].minor.yy392); }
+ case 242: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */
+{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-4].minor.yy151, &yymsp[-3].minor.yy361, &yymsp[0].minor.yy361, false); }
break;
- case 238: /* cmd ::= RESET QUERY CACHE */
-{ pCxt->pRootNode = createResetQueryCacheStmt(pCxt); }
+ case 243: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name */
+{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-6].minor.yy151, &yymsp[-5].minor.yy361, &yymsp[0].minor.yy361, true); }
+ break;
+ case 244: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */
+{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-4].minor.yy151, &yymsp[-3].minor.yy361, yymsp[0].minor.yy616, false); }
break;
- case 239: /* cmd ::= EXPLAIN analyze_opt explain_options query_expression */
-{ pCxt->pRootNode = createExplainStmt(pCxt, yymsp[-2].minor.yy481, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); }
+ case 245: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name */
+{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-6].minor.yy151, &yymsp[-5].minor.yy361, yymsp[0].minor.yy616, true); }
break;
- case 241: /* analyze_opt ::= ANALYZE */
- case 249: /* agg_func_opt ::= AGGREGATE */ yytestcase(yyruleno==249);
- case 400: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==400);
-{ yymsp[0].minor.yy481 = true; }
+ case 246: /* cmd ::= DROP TOPIC exists_opt topic_name */
+{ pCxt->pRootNode = createDropTopicStmt(pCxt, yymsp[-1].minor.yy151, &yymsp[0].minor.yy361); }
break;
- case 242: /* explain_options ::= */
-{ yymsp[1].minor.yy392 = createDefaultExplainOptions(pCxt); }
+ case 247: /* cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */
+{ pCxt->pRootNode = createDropCGroupStmt(pCxt, yymsp[-3].minor.yy151, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361); }
break;
- case 243: /* explain_options ::= explain_options VERBOSE NK_BOOL */
-{ yylhsminor.yy392 = setExplainVerbose(pCxt, yymsp[-2].minor.yy392, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 248: /* cmd ::= DESC full_table_name */
+ case 249: /* cmd ::= DESCRIBE full_table_name */ yytestcase(yyruleno==249);
+{ pCxt->pRootNode = createDescribeStmt(pCxt, yymsp[0].minor.yy616); }
+ break;
+ case 250: /* cmd ::= RESET QUERY CACHE */
+{ pCxt->pRootNode = createResetQueryCacheStmt(pCxt); }
break;
- case 244: /* explain_options ::= explain_options RATIO NK_FLOAT */
-{ yylhsminor.yy392 = setExplainRatio(pCxt, yymsp[-2].minor.yy392, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 251: /* cmd ::= EXPLAIN analyze_opt explain_options query_expression */
+{ pCxt->pRootNode = createExplainStmt(pCxt, yymsp[-2].minor.yy151, yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 245: /* cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP */
-{ pCxt->pRootNode = createCompactStmt(pCxt, yymsp[-1].minor.yy600); }
+ case 253: /* analyze_opt ::= ANALYZE */
+ case 261: /* agg_func_opt ::= AGGREGATE */ yytestcase(yyruleno==261);
+ case 426: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==426);
+{ yymsp[0].minor.yy151 = true; }
break;
- case 246: /* cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt */
-{ pCxt->pRootNode = createCreateFunctionStmt(pCxt, yymsp[-6].minor.yy481, yymsp[-8].minor.yy481, &yymsp[-5].minor.yy57, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy448, yymsp[0].minor.yy228); }
+ case 254: /* explain_options ::= */
+{ yymsp[1].minor.yy616 = createDefaultExplainOptions(pCxt); }
break;
- case 247: /* cmd ::= DROP FUNCTION exists_opt function_name */
-{ pCxt->pRootNode = createDropFunctionStmt(pCxt, yymsp[-1].minor.yy481, &yymsp[0].minor.yy57); }
+ case 255: /* explain_options ::= explain_options VERBOSE NK_BOOL */
+{ yylhsminor.yy616 = setExplainVerbose(pCxt, yymsp[-2].minor.yy616, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 250: /* bufsize_opt ::= */
-{ yymsp[1].minor.yy228 = 0; }
+ case 256: /* explain_options ::= explain_options RATIO NK_FLOAT */
+{ yylhsminor.yy616 = setExplainRatio(pCxt, yymsp[-2].minor.yy616, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 251: /* bufsize_opt ::= BUFSIZE NK_INTEGER */
-{ yymsp[-1].minor.yy228 = taosStr2Int32(yymsp[0].minor.yy0.z, NULL, 10); }
+ case 257: /* cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP */
+{ pCxt->pRootNode = createCompactStmt(pCxt, yymsp[-1].minor.yy356); }
break;
- case 252: /* cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression */
-{ pCxt->pRootNode = createCreateStreamStmt(pCxt, yymsp[-5].minor.yy481, &yymsp[-4].minor.yy57, yymsp[-2].minor.yy392, yymsp[-3].minor.yy392, yymsp[0].minor.yy392); }
+ case 258: /* cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt */
+{ pCxt->pRootNode = createCreateFunctionStmt(pCxt, yymsp[-6].minor.yy151, yymsp[-8].minor.yy151, &yymsp[-5].minor.yy361, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy600, yymsp[0].minor.yy734); }
break;
- case 253: /* cmd ::= DROP STREAM exists_opt stream_name */
-{ pCxt->pRootNode = createDropStreamStmt(pCxt, yymsp[-1].minor.yy481, &yymsp[0].minor.yy57); }
+ case 259: /* cmd ::= DROP FUNCTION exists_opt function_name */
+{ pCxt->pRootNode = createDropFunctionStmt(pCxt, yymsp[-1].minor.yy151, &yymsp[0].minor.yy361); }
break;
- case 255: /* into_opt ::= INTO full_table_name */
- case 381: /* from_clause ::= FROM table_reference_list */ yytestcase(yyruleno==381);
- case 411: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==411);
- case 434: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==434);
-{ yymsp[-1].minor.yy392 = yymsp[0].minor.yy392; }
+ case 262: /* bufsize_opt ::= */
+{ yymsp[1].minor.yy734 = 0; }
break;
- case 256: /* stream_options ::= */
-{ yymsp[1].minor.yy392 = createStreamOptions(pCxt); }
+ case 263: /* bufsize_opt ::= BUFSIZE NK_INTEGER */
+{ yymsp[-1].minor.yy734 = taosStr2Int32(yymsp[0].minor.yy0.z, NULL, 10); }
break;
- case 257: /* stream_options ::= stream_options TRIGGER AT_ONCE */
-{ ((SStreamOptions*)yymsp[-2].minor.yy392)->triggerType = STREAM_TRIGGER_AT_ONCE; yylhsminor.yy392 = yymsp[-2].minor.yy392; }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 264: /* cmd ::= CREATE STREAM not_exists_opt stream_name stream_options into_opt AS query_expression */
+{ pCxt->pRootNode = createCreateStreamStmt(pCxt, yymsp[-5].minor.yy151, &yymsp[-4].minor.yy361, yymsp[-2].minor.yy616, yymsp[-3].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 258: /* stream_options ::= stream_options TRIGGER WINDOW_CLOSE */
-{ ((SStreamOptions*)yymsp[-2].minor.yy392)->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; yylhsminor.yy392 = yymsp[-2].minor.yy392; }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 265: /* cmd ::= DROP STREAM exists_opt stream_name */
+{ pCxt->pRootNode = createDropStreamStmt(pCxt, yymsp[-1].minor.yy151, &yymsp[0].minor.yy361); }
break;
- case 259: /* stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */
-{ ((SStreamOptions*)yymsp[-3].minor.yy392)->triggerType = STREAM_TRIGGER_MAX_DELAY; ((SStreamOptions*)yymsp[-3].minor.yy392)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy392); yylhsminor.yy392 = yymsp[-3].minor.yy392; }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 267: /* into_opt ::= INTO full_table_name */
+ case 407: /* from_clause_opt ::= FROM table_reference_list */ yytestcase(yyruleno==407);
+ case 436: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==436);
+ case 459: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==459);
+{ yymsp[-1].minor.yy616 = yymsp[0].minor.yy616; }
break;
- case 260: /* stream_options ::= stream_options WATERMARK duration_literal */
-{ ((SStreamOptions*)yymsp[-2].minor.yy392)->pWatermark = releaseRawExprNode(pCxt, yymsp[0].minor.yy392); yylhsminor.yy392 = yymsp[-2].minor.yy392; }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 269: /* stream_options ::= stream_options TRIGGER AT_ONCE */
+{ ((SStreamOptions*)yymsp[-2].minor.yy616)->triggerType = STREAM_TRIGGER_AT_ONCE; yylhsminor.yy616 = yymsp[-2].minor.yy616; }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 261: /* cmd ::= KILL CONNECTION NK_INTEGER */
+ case 270: /* stream_options ::= stream_options TRIGGER WINDOW_CLOSE */
+{ ((SStreamOptions*)yymsp[-2].minor.yy616)->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; yylhsminor.yy616 = yymsp[-2].minor.yy616; }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 271: /* stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */
+{ ((SStreamOptions*)yymsp[-3].minor.yy616)->triggerType = STREAM_TRIGGER_MAX_DELAY; ((SStreamOptions*)yymsp[-3].minor.yy616)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy616); yylhsminor.yy616 = yymsp[-3].minor.yy616; }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 273: /* stream_options ::= stream_options IGNORE EXPIRED */
+{ ((SStreamOptions*)yymsp[-2].minor.yy616)->ignoreExpired = true; yylhsminor.yy616 = yymsp[-2].minor.yy616; }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 274: /* cmd ::= KILL CONNECTION NK_INTEGER */
{ pCxt->pRootNode = createKillStmt(pCxt, QUERY_NODE_KILL_CONNECTION_STMT, &yymsp[0].minor.yy0); }
break;
- case 262: /* cmd ::= KILL QUERY NK_STRING */
+ case 275: /* cmd ::= KILL QUERY NK_STRING */
{ pCxt->pRootNode = createKillQueryStmt(pCxt, &yymsp[0].minor.yy0); }
break;
- case 263: /* cmd ::= KILL TRANSACTION NK_INTEGER */
+ case 276: /* cmd ::= KILL TRANSACTION NK_INTEGER */
{ pCxt->pRootNode = createKillStmt(pCxt, QUERY_NODE_KILL_TRANSACTION_STMT, &yymsp[0].minor.yy0); }
break;
- case 264: /* cmd ::= BALANCE VGROUP */
+ case 277: /* cmd ::= BALANCE VGROUP */
{ pCxt->pRootNode = createBalanceVgroupStmt(pCxt); }
break;
- case 265: /* cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */
+ case 278: /* cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */
{ pCxt->pRootNode = createMergeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); }
break;
- case 266: /* cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */
-{ pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy600); }
+ case 279: /* cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */
+{ pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy356); }
break;
- case 267: /* cmd ::= SPLIT VGROUP NK_INTEGER */
+ case 280: /* cmd ::= SPLIT VGROUP NK_INTEGER */
{ pCxt->pRootNode = createSplitVgroupStmt(pCxt, &yymsp[0].minor.yy0); }
break;
- case 268: /* dnode_list ::= DNODE NK_INTEGER */
-{ yymsp[-1].minor.yy600 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
- break;
- case 270: /* cmd ::= SYNCDB db_name REPLICA */
-{ pCxt->pRootNode = createSyncdbStmt(pCxt, &yymsp[-1].minor.yy57); }
- break;
- case 271: /* cmd ::= DELETE FROM full_table_name where_clause_opt */
-{ pCxt->pRootNode = createDeleteStmt(pCxt, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); }
- break;
- case 273: /* literal ::= NK_INTEGER */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 274: /* literal ::= NK_FLOAT */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 275: /* literal ::= NK_STRING */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 276: /* literal ::= NK_BOOL */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 277: /* literal ::= TIMESTAMP NK_STRING */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
- break;
- case 278: /* literal ::= duration_literal */
- case 288: /* signed_literal ::= signed */ yytestcase(yyruleno==288);
- case 308: /* expression ::= literal */ yytestcase(yyruleno==308);
- case 309: /* expression ::= pseudo_column */ yytestcase(yyruleno==309);
- case 310: /* expression ::= column_reference */ yytestcase(yyruleno==310);
- case 311: /* expression ::= function_expression */ yytestcase(yyruleno==311);
- case 312: /* expression ::= subquery */ yytestcase(yyruleno==312);
- case 337: /* function_expression ::= literal_func */ yytestcase(yyruleno==337);
- case 373: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==373);
- case 377: /* boolean_primary ::= predicate */ yytestcase(yyruleno==377);
- case 379: /* common_expression ::= expression */ yytestcase(yyruleno==379);
- case 380: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==380);
- case 382: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==382);
- case 384: /* table_reference ::= table_primary */ yytestcase(yyruleno==384);
- case 385: /* table_reference ::= joined_table */ yytestcase(yyruleno==385);
- case 389: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==389);
- case 440: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==440);
- case 443: /* query_primary ::= query_specification */ yytestcase(yyruleno==443);
-{ yylhsminor.yy392 = yymsp[0].minor.yy392; }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 279: /* literal ::= NULL */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 280: /* literal ::= NK_QUESTION */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 281: /* duration_literal ::= NK_VARIABLE */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 282: /* signed ::= NK_INTEGER */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 283: /* signed ::= NK_PLUS NK_INTEGER */
-{ yymsp[-1].minor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0); }
- break;
- case 284: /* signed ::= NK_MINUS NK_INTEGER */
+ case 281: /* dnode_list ::= DNODE NK_INTEGER */
+{ yymsp[-1].minor.yy356 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
+ break;
+ case 283: /* cmd ::= SYNCDB db_name REPLICA */
+{ pCxt->pRootNode = createSyncdbStmt(pCxt, &yymsp[-1].minor.yy361); }
+ break;
+ case 284: /* cmd ::= DELETE FROM full_table_name where_clause_opt */
+{ pCxt->pRootNode = createDeleteStmt(pCxt, yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
+ break;
+ case 286: /* cmd ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_expression */
+{ pCxt->pRootNode = createInsertStmt(pCxt, yymsp[-4].minor.yy616, yymsp[-2].minor.yy356, yymsp[0].minor.yy616); }
+ break;
+ case 287: /* cmd ::= INSERT INTO full_table_name query_expression */
+{ pCxt->pRootNode = createInsertStmt(pCxt, yymsp[-1].minor.yy616, NULL, yymsp[0].minor.yy616); }
+ break;
+ case 288: /* literal ::= NK_INTEGER */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 289: /* literal ::= NK_FLOAT */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 290: /* literal ::= NK_STRING */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 291: /* literal ::= NK_BOOL */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 292: /* literal ::= TIMESTAMP NK_STRING */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 293: /* literal ::= duration_literal */
+ case 303: /* signed_literal ::= signed */ yytestcase(yyruleno==303);
+ case 324: /* expression ::= literal */ yytestcase(yyruleno==324);
+ case 325: /* expression ::= pseudo_column */ yytestcase(yyruleno==325);
+ case 326: /* expression ::= column_reference */ yytestcase(yyruleno==326);
+ case 327: /* expression ::= function_expression */ yytestcase(yyruleno==327);
+ case 328: /* expression ::= subquery */ yytestcase(yyruleno==328);
+ case 356: /* function_expression ::= literal_func */ yytestcase(yyruleno==356);
+ case 398: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==398);
+ case 402: /* boolean_primary ::= predicate */ yytestcase(yyruleno==402);
+ case 404: /* common_expression ::= expression */ yytestcase(yyruleno==404);
+ case 405: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==405);
+ case 408: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==408);
+ case 410: /* table_reference ::= table_primary */ yytestcase(yyruleno==410);
+ case 411: /* table_reference ::= joined_table */ yytestcase(yyruleno==411);
+ case 415: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==415);
+ case 465: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==465);
+ case 468: /* query_primary ::= query_specification */ yytestcase(yyruleno==468);
+{ yylhsminor.yy616 = yymsp[0].minor.yy616; }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 294: /* literal ::= NULL */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 295: /* literal ::= NK_QUESTION */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 296: /* duration_literal ::= NK_VARIABLE */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 297: /* signed ::= NK_INTEGER */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 298: /* signed ::= NK_PLUS NK_INTEGER */
+{ yymsp[-1].minor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0); }
+ break;
+ case 299: /* signed ::= NK_MINUS NK_INTEGER */
{
SToken t = yymsp[-1].minor.yy0;
t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z;
- yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t);
+ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t);
}
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 285: /* signed ::= NK_FLOAT */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 300: /* signed ::= NK_FLOAT */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 286: /* signed ::= NK_PLUS NK_FLOAT */
-{ yymsp[-1].minor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); }
+ case 301: /* signed ::= NK_PLUS NK_FLOAT */
+{ yymsp[-1].minor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); }
break;
- case 287: /* signed ::= NK_MINUS NK_FLOAT */
+ case 302: /* signed ::= NK_MINUS NK_FLOAT */
{
SToken t = yymsp[-1].minor.yy0;
t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z;
- yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &t);
+ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &t);
}
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 304: /* signed_literal ::= NK_STRING */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 289: /* signed_literal ::= NK_STRING */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 305: /* signed_literal ::= NK_BOOL */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 290: /* signed_literal ::= NK_BOOL */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 306: /* signed_literal ::= TIMESTAMP NK_STRING */
+{ yymsp[-1].minor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); }
break;
- case 291: /* signed_literal ::= TIMESTAMP NK_STRING */
-{ yymsp[-1].minor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); }
+ case 307: /* signed_literal ::= duration_literal */
+ case 309: /* signed_literal ::= literal_func */ yytestcase(yyruleno==309);
+ case 376: /* star_func_para ::= expression */ yytestcase(yyruleno==376);
+ case 431: /* select_item ::= common_expression */ yytestcase(yyruleno==431);
+ case 481: /* search_condition ::= common_expression */ yytestcase(yyruleno==481);
+{ yylhsminor.yy616 = releaseRawExprNode(pCxt, yymsp[0].minor.yy616); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 292: /* signed_literal ::= duration_literal */
- case 294: /* signed_literal ::= literal_func */ yytestcase(yyruleno==294);
- case 351: /* star_func_para ::= expression */ yytestcase(yyruleno==351);
- case 406: /* select_item ::= common_expression */ yytestcase(yyruleno==406);
- case 456: /* search_condition ::= common_expression */ yytestcase(yyruleno==456);
-{ yylhsminor.yy392 = releaseRawExprNode(pCxt, yymsp[0].minor.yy392); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 308: /* signed_literal ::= NULL */
+{ yylhsminor.yy616 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 293: /* signed_literal ::= NULL */
-{ yylhsminor.yy392 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
+ case 310: /* signed_literal ::= NK_QUESTION */
+{ yylhsminor.yy616 = createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 313: /* expression ::= NK_LP expression NK_RP */
- case 378: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==378);
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 329: /* expression ::= NK_LP expression NK_RP */
+ case 403: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==403);
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy616)); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 314: /* expression ::= NK_PLUS expression */
+ case 330: /* expression ::= NK_PLUS expression */
{
- SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy392));
+ SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy616));
}
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 315: /* expression ::= NK_MINUS expression */
+ case 331: /* expression ::= NK_MINUS expression */
{
- SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, yymsp[0].minor.yy392), NULL));
+ SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, yymsp[0].minor.yy616), NULL));
}
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 316: /* expression ::= expression NK_PLUS expression */
+ case 332: /* expression ::= expression NK_PLUS expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 317: /* expression ::= expression NK_MINUS expression */
+ case 333: /* expression ::= expression NK_MINUS expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 318: /* expression ::= expression NK_STAR expression */
+ case 334: /* expression ::= expression NK_STAR expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 319: /* expression ::= expression NK_SLASH expression */
+ case 335: /* expression ::= expression NK_SLASH expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 320: /* expression ::= expression NK_REM expression */
+ case 336: /* expression ::= expression NK_REM expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 321: /* expression ::= column_reference NK_ARROW NK_STRING */
+ case 337: /* expression ::= column_reference NK_ARROW NK_STRING */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 324: /* column_reference ::= column_name */
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy57, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy57)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 325: /* column_reference ::= table_name NK_DOT column_name */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57, createColumnNode(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy57)); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 326: /* pseudo_column ::= ROWTS */
- case 327: /* pseudo_column ::= TBNAME */ yytestcase(yyruleno==327);
- case 329: /* pseudo_column ::= QSTARTTS */ yytestcase(yyruleno==329);
- case 330: /* pseudo_column ::= QENDTS */ yytestcase(yyruleno==330);
- case 331: /* pseudo_column ::= WSTARTTS */ yytestcase(yyruleno==331);
- case 332: /* pseudo_column ::= WENDTS */ yytestcase(yyruleno==332);
- case 333: /* pseudo_column ::= WDURATION */ yytestcase(yyruleno==333);
- case 339: /* literal_func ::= NOW */ yytestcase(yyruleno==339);
-{ yylhsminor.yy392 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL)); }
- yymsp[0].minor.yy392 = yylhsminor.yy392;
- break;
- case 328: /* pseudo_column ::= table_name NK_DOT TBNAME */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-2].minor.yy57)))); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 334: /* function_expression ::= function_name NK_LP expression_list NK_RP */
- case 335: /* function_expression ::= star_func NK_LP star_func_para_list NK_RP */ yytestcase(yyruleno==335);
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy57, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy57, yymsp[-1].minor.yy600)); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
- break;
- case 336: /* function_expression ::= CAST NK_LP expression AS type_name NK_RP */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), yymsp[-1].minor.yy448)); }
- yymsp[-5].minor.yy392 = yylhsminor.yy392;
- break;
- case 338: /* literal_func ::= noarg_func NK_LP NK_RP */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-2].minor.yy57, NULL)); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 347: /* star_func_para_list ::= NK_STAR */
-{ yylhsminor.yy600 = createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0)); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
- break;
- case 352: /* star_func_para ::= table_name NK_DOT NK_STAR */
- case 409: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==409);
-{ yylhsminor.yy392 = createColumnNode(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
- break;
- case 353: /* predicate ::= expression compare_op expression */
- case 358: /* predicate ::= expression in_op in_predicate_value */ yytestcase(yyruleno==358);
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 338: /* expression ::= expression NK_BITAND expression */
+{
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
+ }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 339: /* expression ::= expression NK_BITOR expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy324, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 342: /* column_reference ::= column_name */
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy361, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy361)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 343: /* column_reference ::= table_name NK_DOT column_name */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361, createColumnNode(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy361)); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 344: /* pseudo_column ::= ROWTS */
+ case 345: /* pseudo_column ::= TBNAME */ yytestcase(yyruleno==345);
+ case 347: /* pseudo_column ::= QSTART */ yytestcase(yyruleno==347);
+ case 348: /* pseudo_column ::= QEND */ yytestcase(yyruleno==348);
+ case 349: /* pseudo_column ::= QDURATION */ yytestcase(yyruleno==349);
+ case 350: /* pseudo_column ::= WSTART */ yytestcase(yyruleno==350);
+ case 351: /* pseudo_column ::= WEND */ yytestcase(yyruleno==351);
+ case 352: /* pseudo_column ::= WDURATION */ yytestcase(yyruleno==352);
+ case 358: /* literal_func ::= NOW */ yytestcase(yyruleno==358);
+{ yylhsminor.yy616 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL)); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 346: /* pseudo_column ::= table_name NK_DOT TBNAME */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-2].minor.yy361)))); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 353: /* function_expression ::= function_name NK_LP expression_list NK_RP */
+ case 354: /* function_expression ::= star_func NK_LP star_func_para_list NK_RP */ yytestcase(yyruleno==354);
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy361, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy361, yymsp[-1].minor.yy356)); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 355: /* function_expression ::= CAST NK_LP expression AS type_name NK_RP */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), yymsp[-1].minor.yy600)); }
+ yymsp[-5].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 357: /* literal_func ::= noarg_func NK_LP NK_RP */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-2].minor.yy361, NULL)); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 372: /* star_func_para_list ::= NK_STAR */
+{ yylhsminor.yy356 = createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0)); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
+ break;
+ case 377: /* star_func_para ::= table_name NK_DOT NK_STAR */
+ case 434: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==434);
+{ yylhsminor.yy616 = createColumnNode(pCxt, &yymsp[-2].minor.yy361, &yymsp[0].minor.yy0); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
+ break;
+ case 378: /* predicate ::= expression compare_op expression */
+ case 383: /* predicate ::= expression in_op in_predicate_value */ yytestcase(yyruleno==383);
+{
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy526, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
+ }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 354: /* predicate ::= expression BETWEEN expression AND expression */
+ case 379: /* predicate ::= expression BETWEEN expression AND expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy392), releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy616), releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-4].minor.yy392 = yylhsminor.yy392;
+ yymsp[-4].minor.yy616 = yylhsminor.yy616;
break;
- case 355: /* predicate ::= expression NOT BETWEEN expression AND expression */
+ case 380: /* predicate ::= expression NOT BETWEEN expression AND expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy392), releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy616), releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-5].minor.yy392 = yylhsminor.yy392;
+ yymsp[-5].minor.yy616 = yylhsminor.yy616;
break;
- case 356: /* predicate ::= expression IS NULL */
+ case 381: /* predicate ::= expression IS NULL */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), NULL));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), NULL));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 357: /* predicate ::= expression IS NOT NULL */
+ case 382: /* predicate ::= expression IS NOT NULL */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), NULL));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), NULL));
}
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 359: /* compare_op ::= NK_LT */
-{ yymsp[0].minor.yy324 = OP_TYPE_LOWER_THAN; }
+ case 384: /* compare_op ::= NK_LT */
+{ yymsp[0].minor.yy526 = OP_TYPE_LOWER_THAN; }
break;
- case 360: /* compare_op ::= NK_GT */
-{ yymsp[0].minor.yy324 = OP_TYPE_GREATER_THAN; }
+ case 385: /* compare_op ::= NK_GT */
+{ yymsp[0].minor.yy526 = OP_TYPE_GREATER_THAN; }
break;
- case 361: /* compare_op ::= NK_LE */
-{ yymsp[0].minor.yy324 = OP_TYPE_LOWER_EQUAL; }
+ case 386: /* compare_op ::= NK_LE */
+{ yymsp[0].minor.yy526 = OP_TYPE_LOWER_EQUAL; }
break;
- case 362: /* compare_op ::= NK_GE */
-{ yymsp[0].minor.yy324 = OP_TYPE_GREATER_EQUAL; }
+ case 387: /* compare_op ::= NK_GE */
+{ yymsp[0].minor.yy526 = OP_TYPE_GREATER_EQUAL; }
break;
- case 363: /* compare_op ::= NK_NE */
-{ yymsp[0].minor.yy324 = OP_TYPE_NOT_EQUAL; }
+ case 388: /* compare_op ::= NK_NE */
+{ yymsp[0].minor.yy526 = OP_TYPE_NOT_EQUAL; }
break;
- case 364: /* compare_op ::= NK_EQ */
-{ yymsp[0].minor.yy324 = OP_TYPE_EQUAL; }
+ case 389: /* compare_op ::= NK_EQ */
+{ yymsp[0].minor.yy526 = OP_TYPE_EQUAL; }
break;
- case 365: /* compare_op ::= LIKE */
-{ yymsp[0].minor.yy324 = OP_TYPE_LIKE; }
+ case 390: /* compare_op ::= LIKE */
+{ yymsp[0].minor.yy526 = OP_TYPE_LIKE; }
break;
- case 366: /* compare_op ::= NOT LIKE */
-{ yymsp[-1].minor.yy324 = OP_TYPE_NOT_LIKE; }
+ case 391: /* compare_op ::= NOT LIKE */
+{ yymsp[-1].minor.yy526 = OP_TYPE_NOT_LIKE; }
break;
- case 367: /* compare_op ::= MATCH */
-{ yymsp[0].minor.yy324 = OP_TYPE_MATCH; }
+ case 392: /* compare_op ::= MATCH */
+{ yymsp[0].minor.yy526 = OP_TYPE_MATCH; }
break;
- case 368: /* compare_op ::= NMATCH */
-{ yymsp[0].minor.yy324 = OP_TYPE_NMATCH; }
+ case 393: /* compare_op ::= NMATCH */
+{ yymsp[0].minor.yy526 = OP_TYPE_NMATCH; }
break;
- case 369: /* compare_op ::= CONTAINS */
-{ yymsp[0].minor.yy324 = OP_TYPE_JSON_CONTAINS; }
+ case 394: /* compare_op ::= CONTAINS */
+{ yymsp[0].minor.yy526 = OP_TYPE_JSON_CONTAINS; }
break;
- case 370: /* in_op ::= IN */
-{ yymsp[0].minor.yy324 = OP_TYPE_IN; }
+ case 395: /* in_op ::= IN */
+{ yymsp[0].minor.yy526 = OP_TYPE_IN; }
break;
- case 371: /* in_op ::= NOT IN */
-{ yymsp[-1].minor.yy324 = OP_TYPE_NOT_IN; }
+ case 396: /* in_op ::= NOT IN */
+{ yymsp[-1].minor.yy526 = OP_TYPE_NOT_IN; }
break;
- case 372: /* in_predicate_value ::= NK_LP expression_list NK_RP */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy600)); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 397: /* in_predicate_value ::= NK_LP literal_list NK_RP */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy356)); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 374: /* boolean_value_expression ::= NOT boolean_primary */
+ case 399: /* boolean_value_expression ::= NOT boolean_primary */
{
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy392), NULL));
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy616), NULL));
}
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 375: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */
+ case 400: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 376: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */
+ case 401: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */
{
- SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy392);
- SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy392);
- yylhsminor.yy392 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), releaseRawExprNode(pCxt, yymsp[0].minor.yy392)));
+ SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy616);
+ SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy616);
+ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), releaseRawExprNode(pCxt, yymsp[0].minor.yy616)));
}
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 383: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */
-{ yylhsminor.yy392 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy392, yymsp[0].minor.yy392, NULL); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 409: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */
+{ yylhsminor.yy616 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy616, yymsp[0].minor.yy616, NULL); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 386: /* table_primary ::= table_name alias_opt */
-{ yylhsminor.yy392 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 412: /* table_primary ::= table_name alias_opt */
+{ yylhsminor.yy616 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy361, &yymsp[0].minor.yy361); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 387: /* table_primary ::= db_name NK_DOT table_name alias_opt */
-{ yylhsminor.yy392 = createRealTableNode(pCxt, &yymsp[-3].minor.yy57, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 413: /* table_primary ::= db_name NK_DOT table_name alias_opt */
+{ yylhsminor.yy616 = createRealTableNode(pCxt, &yymsp[-3].minor.yy361, &yymsp[-1].minor.yy361, &yymsp[0].minor.yy361); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 388: /* table_primary ::= subquery alias_opt */
-{ yylhsminor.yy392 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392), &yymsp[0].minor.yy57); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 414: /* table_primary ::= subquery alias_opt */
+{ yylhsminor.yy616 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy616), &yymsp[0].minor.yy361); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 390: /* alias_opt ::= */
-{ yymsp[1].minor.yy57 = nil_token; }
+ case 416: /* alias_opt ::= */
+{ yymsp[1].minor.yy361 = nil_token; }
break;
- case 391: /* alias_opt ::= table_alias */
-{ yylhsminor.yy57 = yymsp[0].minor.yy57; }
- yymsp[0].minor.yy57 = yylhsminor.yy57;
+ case 417: /* alias_opt ::= table_alias */
+{ yylhsminor.yy361 = yymsp[0].minor.yy361; }
+ yymsp[0].minor.yy361 = yylhsminor.yy361;
break;
- case 392: /* alias_opt ::= AS table_alias */
-{ yymsp[-1].minor.yy57 = yymsp[0].minor.yy57; }
+ case 418: /* alias_opt ::= AS table_alias */
+{ yymsp[-1].minor.yy361 = yymsp[0].minor.yy361; }
break;
- case 393: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */
- case 394: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==394);
-{ yymsp[-2].minor.yy392 = yymsp[-1].minor.yy392; }
+ case 419: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */
+ case 420: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==420);
+{ yymsp[-2].minor.yy616 = yymsp[-1].minor.yy616; }
break;
- case 395: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */
-{ yylhsminor.yy392 = createJoinTableNode(pCxt, yymsp[-4].minor.yy204, yymsp[-5].minor.yy392, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); }
- yymsp[-5].minor.yy392 = yylhsminor.yy392;
+ case 421: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */
+{ yylhsminor.yy616 = createJoinTableNode(pCxt, yymsp[-4].minor.yy504, yymsp[-5].minor.yy616, yymsp[-2].minor.yy616, yymsp[0].minor.yy616); }
+ yymsp[-5].minor.yy616 = yylhsminor.yy616;
break;
- case 396: /* join_type ::= */
-{ yymsp[1].minor.yy204 = JOIN_TYPE_INNER; }
+ case 422: /* join_type ::= */
+{ yymsp[1].minor.yy504 = JOIN_TYPE_INNER; }
break;
- case 397: /* join_type ::= INNER */
-{ yymsp[0].minor.yy204 = JOIN_TYPE_INNER; }
+ case 423: /* join_type ::= INNER */
+{ yymsp[0].minor.yy504 = JOIN_TYPE_INNER; }
break;
- case 398: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */
+ case 424: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */
{
- yymsp[-11].minor.yy392 = createSelectStmt(pCxt, yymsp[-10].minor.yy481, yymsp[-9].minor.yy600, yymsp[-8].minor.yy392);
- yymsp[-11].minor.yy392 = addWhereClause(pCxt, yymsp[-11].minor.yy392, yymsp[-7].minor.yy392);
- yymsp[-11].minor.yy392 = addPartitionByClause(pCxt, yymsp[-11].minor.yy392, yymsp[-6].minor.yy600);
- yymsp[-11].minor.yy392 = addWindowClauseClause(pCxt, yymsp[-11].minor.yy392, yymsp[-2].minor.yy392);
- yymsp[-11].minor.yy392 = addGroupByClause(pCxt, yymsp[-11].minor.yy392, yymsp[-1].minor.yy600);
- yymsp[-11].minor.yy392 = addHavingClause(pCxt, yymsp[-11].minor.yy392, yymsp[0].minor.yy392);
- yymsp[-11].minor.yy392 = addRangeClause(pCxt, yymsp[-11].minor.yy392, yymsp[-5].minor.yy392);
- yymsp[-11].minor.yy392 = addEveryClause(pCxt, yymsp[-11].minor.yy392, yymsp[-4].minor.yy392);
- yymsp[-11].minor.yy392 = addFillClause(pCxt, yymsp[-11].minor.yy392, yymsp[-3].minor.yy392);
+ yymsp[-11].minor.yy616 = createSelectStmt(pCxt, yymsp[-10].minor.yy151, yymsp[-9].minor.yy356, yymsp[-8].minor.yy616);
+ yymsp[-11].minor.yy616 = addWhereClause(pCxt, yymsp[-11].minor.yy616, yymsp[-7].minor.yy616);
+ yymsp[-11].minor.yy616 = addPartitionByClause(pCxt, yymsp[-11].minor.yy616, yymsp[-6].minor.yy356);
+ yymsp[-11].minor.yy616 = addWindowClauseClause(pCxt, yymsp[-11].minor.yy616, yymsp[-2].minor.yy616);
+ yymsp[-11].minor.yy616 = addGroupByClause(pCxt, yymsp[-11].minor.yy616, yymsp[-1].minor.yy356);
+ yymsp[-11].minor.yy616 = addHavingClause(pCxt, yymsp[-11].minor.yy616, yymsp[0].minor.yy616);
+ yymsp[-11].minor.yy616 = addRangeClause(pCxt, yymsp[-11].minor.yy616, yymsp[-5].minor.yy616);
+ yymsp[-11].minor.yy616 = addEveryClause(pCxt, yymsp[-11].minor.yy616, yymsp[-4].minor.yy616);
+ yymsp[-11].minor.yy616 = addFillClause(pCxt, yymsp[-11].minor.yy616, yymsp[-3].minor.yy616);
}
break;
- case 401: /* set_quantifier_opt ::= ALL */
-{ yymsp[0].minor.yy481 = false; }
+ case 427: /* set_quantifier_opt ::= ALL */
+{ yymsp[0].minor.yy151 = false; }
break;
- case 402: /* select_list ::= NK_STAR */
-{ yymsp[0].minor.yy600 = NULL; }
+ case 430: /* select_item ::= NK_STAR */
+{ yylhsminor.yy616 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0); }
+ yymsp[0].minor.yy616 = yylhsminor.yy616;
break;
- case 407: /* select_item ::= common_expression column_alias */
-{ yylhsminor.yy392 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392), &yymsp[0].minor.yy57); }
- yymsp[-1].minor.yy392 = yylhsminor.yy392;
+ case 432: /* select_item ::= common_expression column_alias */
+{ yylhsminor.yy616 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy616), &yymsp[0].minor.yy361); }
+ yymsp[-1].minor.yy616 = yylhsminor.yy616;
break;
- case 408: /* select_item ::= common_expression AS column_alias */
-{ yylhsminor.yy392 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), &yymsp[0].minor.yy57); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 433: /* select_item ::= common_expression AS column_alias */
+{ yylhsminor.yy616 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), &yymsp[0].minor.yy361); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 413: /* partition_by_clause_opt ::= PARTITION BY expression_list */
- case 430: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==430);
- case 446: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==446);
-{ yymsp[-2].minor.yy600 = yymsp[0].minor.yy600; }
+ case 438: /* partition_by_clause_opt ::= PARTITION BY expression_list */
+ case 455: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==455);
+ case 471: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==471);
+{ yymsp[-2].minor.yy356 = yymsp[0].minor.yy356; }
break;
- case 415: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */
-{ yymsp[-5].minor.yy392 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); }
+ case 440: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */
+{ yymsp[-5].minor.yy616 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), releaseRawExprNode(pCxt, yymsp[-1].minor.yy616)); }
break;
- case 416: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */
-{ yymsp[-3].minor.yy392 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); }
+ case 441: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */
+{ yymsp[-3].minor.yy616 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy616)); }
break;
- case 417: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */
-{ yymsp[-5].minor.yy392 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), NULL, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); }
+ case 442: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */
+{ yymsp[-5].minor.yy616 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), NULL, yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 418: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */
-{ yymsp[-7].minor.yy392 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy392), releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), yymsp[-1].minor.yy392, yymsp[0].minor.yy392); }
+ case 443: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */
+{ yymsp[-7].minor.yy616 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy616), releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), yymsp[-1].minor.yy616, yymsp[0].minor.yy616); }
break;
- case 420: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */
- case 438: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==438);
-{ yymsp[-3].minor.yy392 = releaseRawExprNode(pCxt, yymsp[-1].minor.yy392); }
+ case 445: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */
+ case 463: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==463);
+{ yymsp[-3].minor.yy616 = releaseRawExprNode(pCxt, yymsp[-1].minor.yy616); }
break;
- case 422: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */
-{ yymsp[-3].minor.yy392 = createFillNode(pCxt, yymsp[-1].minor.yy270, NULL); }
+ case 447: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */
+{ yymsp[-3].minor.yy616 = createFillNode(pCxt, yymsp[-1].minor.yy494, NULL); }
break;
- case 423: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */
-{ yymsp[-5].minor.yy392 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy600)); }
+ case 448: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */
+{ yymsp[-5].minor.yy616 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy356)); }
break;
- case 424: /* fill_mode ::= NONE */
-{ yymsp[0].minor.yy270 = FILL_MODE_NONE; }
+ case 449: /* fill_mode ::= NONE */
+{ yymsp[0].minor.yy494 = FILL_MODE_NONE; }
break;
- case 425: /* fill_mode ::= PREV */
-{ yymsp[0].minor.yy270 = FILL_MODE_PREV; }
+ case 450: /* fill_mode ::= PREV */
+{ yymsp[0].minor.yy494 = FILL_MODE_PREV; }
break;
- case 426: /* fill_mode ::= NULL */
-{ yymsp[0].minor.yy270 = FILL_MODE_NULL; }
+ case 451: /* fill_mode ::= NULL */
+{ yymsp[0].minor.yy494 = FILL_MODE_NULL; }
break;
- case 427: /* fill_mode ::= LINEAR */
-{ yymsp[0].minor.yy270 = FILL_MODE_LINEAR; }
+ case 452: /* fill_mode ::= LINEAR */
+{ yymsp[0].minor.yy494 = FILL_MODE_LINEAR; }
break;
- case 428: /* fill_mode ::= NEXT */
-{ yymsp[0].minor.yy270 = FILL_MODE_NEXT; }
+ case 453: /* fill_mode ::= NEXT */
+{ yymsp[0].minor.yy494 = FILL_MODE_NEXT; }
break;
- case 431: /* group_by_list ::= expression */
-{ yylhsminor.yy600 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy392))); }
- yymsp[0].minor.yy600 = yylhsminor.yy600;
+ case 456: /* group_by_list ::= expression */
+{ yylhsminor.yy356 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy616))); }
+ yymsp[0].minor.yy356 = yylhsminor.yy356;
break;
- case 432: /* group_by_list ::= group_by_list NK_COMMA expression */
-{ yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy392))); }
- yymsp[-2].minor.yy600 = yylhsminor.yy600;
+ case 457: /* group_by_list ::= group_by_list NK_COMMA expression */
+{ yylhsminor.yy356 = addNodeToList(pCxt, yymsp[-2].minor.yy356, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy616))); }
+ yymsp[-2].minor.yy356 = yylhsminor.yy356;
break;
- case 436: /* range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */
-{ yymsp[-5].minor.yy392 = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); }
+ case 461: /* range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */
+{ yymsp[-5].minor.yy616 = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy616), releaseRawExprNode(pCxt, yymsp[-1].minor.yy616)); }
break;
- case 439: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
+ case 464: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
{
- yylhsminor.yy392 = addOrderByClause(pCxt, yymsp[-3].minor.yy392, yymsp[-2].minor.yy600);
- yylhsminor.yy392 = addSlimitClause(pCxt, yylhsminor.yy392, yymsp[-1].minor.yy392);
- yylhsminor.yy392 = addLimitClause(pCxt, yylhsminor.yy392, yymsp[0].minor.yy392);
+ yylhsminor.yy616 = addOrderByClause(pCxt, yymsp[-3].minor.yy616, yymsp[-2].minor.yy356);
+ yylhsminor.yy616 = addSlimitClause(pCxt, yylhsminor.yy616, yymsp[-1].minor.yy616);
+ yylhsminor.yy616 = addLimitClause(pCxt, yylhsminor.yy616, yymsp[0].minor.yy616);
}
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 441: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */
-{ yylhsminor.yy392 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy392, yymsp[0].minor.yy392); }
- yymsp[-3].minor.yy392 = yylhsminor.yy392;
+ case 466: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */
+{ yylhsminor.yy616 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy616, yymsp[0].minor.yy616); }
+ yymsp[-3].minor.yy616 = yylhsminor.yy616;
break;
- case 442: /* query_expression_body ::= query_expression_body UNION query_expression_body */
-{ yylhsminor.yy392 = createSetOperator(pCxt, SET_OP_TYPE_UNION, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 467: /* query_expression_body ::= query_expression_body UNION query_expression_body */
+{ yylhsminor.yy616 = createSetOperator(pCxt, SET_OP_TYPE_UNION, yymsp[-2].minor.yy616, yymsp[0].minor.yy616); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 444: /* query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */
-{ yymsp[-5].minor.yy392 = yymsp[-4].minor.yy392; }
- yy_destructor(yypParser,356,&yymsp[-3].minor);
- yy_destructor(yypParser,357,&yymsp[-2].minor);
- yy_destructor(yypParser,358,&yymsp[-1].minor);
+ case 469: /* query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */
+{
+ yymsp[-5].minor.yy616 = addOrderByClause(pCxt, yymsp[-4].minor.yy616, yymsp[-3].minor.yy356);
+ yymsp[-5].minor.yy616 = addSlimitClause(pCxt, yymsp[-5].minor.yy616, yymsp[-2].minor.yy616);
+ yymsp[-5].minor.yy616 = addLimitClause(pCxt, yymsp[-5].minor.yy616, yymsp[-1].minor.yy616);
+ }
break;
- case 448: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */
- case 452: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==452);
-{ yymsp[-1].minor.yy392 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); }
+ case 473: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */
+ case 477: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==477);
+{ yymsp[-1].minor.yy616 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); }
break;
- case 449: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
- case 453: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==453);
-{ yymsp[-3].minor.yy392 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); }
+ case 474: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
+ case 478: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==478);
+{ yymsp[-3].minor.yy616 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); }
break;
- case 450: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
- case 454: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==454);
-{ yymsp[-3].minor.yy392 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); }
+ case 475: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
+ case 479: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==479);
+{ yymsp[-3].minor.yy616 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); }
break;
- case 455: /* subquery ::= NK_LP query_expression NK_RP */
-{ yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy392); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 480: /* subquery ::= NK_LP query_expression NK_RP */
+{ yylhsminor.yy616 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy616); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 459: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */
-{ yylhsminor.yy392 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), yymsp[-1].minor.yy162, yymsp[0].minor.yy529); }
- yymsp[-2].minor.yy392 = yylhsminor.yy392;
+ case 484: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */
+{ yylhsminor.yy616 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy616), yymsp[-1].minor.yy58, yymsp[0].minor.yy613); }
+ yymsp[-2].minor.yy616 = yylhsminor.yy616;
break;
- case 460: /* ordering_specification_opt ::= */
-{ yymsp[1].minor.yy162 = ORDER_ASC; }
+ case 485: /* ordering_specification_opt ::= */
+{ yymsp[1].minor.yy58 = ORDER_ASC; }
break;
- case 461: /* ordering_specification_opt ::= ASC */
-{ yymsp[0].minor.yy162 = ORDER_ASC; }
+ case 486: /* ordering_specification_opt ::= ASC */
+{ yymsp[0].minor.yy58 = ORDER_ASC; }
break;
- case 462: /* ordering_specification_opt ::= DESC */
-{ yymsp[0].minor.yy162 = ORDER_DESC; }
+ case 487: /* ordering_specification_opt ::= DESC */
+{ yymsp[0].minor.yy58 = ORDER_DESC; }
break;
- case 463: /* null_ordering_opt ::= */
-{ yymsp[1].minor.yy529 = NULL_ORDER_DEFAULT; }
+ case 488: /* null_ordering_opt ::= */
+{ yymsp[1].minor.yy613 = NULL_ORDER_DEFAULT; }
break;
- case 464: /* null_ordering_opt ::= NULLS FIRST */
-{ yymsp[-1].minor.yy529 = NULL_ORDER_FIRST; }
+ case 489: /* null_ordering_opt ::= NULLS FIRST */
+{ yymsp[-1].minor.yy613 = NULL_ORDER_FIRST; }
break;
- case 465: /* null_ordering_opt ::= NULLS LAST */
-{ yymsp[-1].minor.yy529 = NULL_ORDER_LAST; }
+ case 490: /* null_ordering_opt ::= NULLS LAST */
+{ yymsp[-1].minor.yy613 = NULL_ORDER_LAST; }
break;
default:
break;
diff --git a/source/libs/parser/test/CMakeLists.txt b/source/libs/parser/test/CMakeLists.txt
index 0e8adb978dd0e9fca5a67e9999ce7c5faa877cc0..45431b69b7a87d31929ddc4ace05ee095dae4787 100644
--- a/source/libs/parser/test/CMakeLists.txt
+++ b/source/libs/parser/test/CMakeLists.txt
@@ -1,32 +1,34 @@
MESSAGE(STATUS "build parser unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(parserTest ${SOURCE_LIST})
+ ADD_EXECUTABLE(parserTest ${SOURCE_LIST})
-TARGET_INCLUDE_DIRECTORIES(
- parserTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/parser/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/parser/inc"
-)
-
-TARGET_LINK_LIBRARIES(
- parserTest
- PUBLIC os util common nodes parser catalog transport gtest function planner qcom
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ parserTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/parser/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/parser/inc"
+ )
-if(${BUILD_WINGETOPT})
- target_include_directories(
- parserTest
- PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
+ TARGET_LINK_LIBRARIES(
+ parserTest
+ PUBLIC os util common nodes parser catalog transport gtest function planner qcom
)
- target_link_libraries(parserTest PUBLIC wingetopt)
-endif()
-add_test(
- NAME parserTest
- COMMAND parserTest
-)
+ if(${BUILD_WINGETOPT})
+ target_include_directories(
+ parserTest
+ PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
+ )
+ target_link_libraries(parserTest PUBLIC wingetopt)
+ endif()
+
+ add_test(
+ NAME parserTest
+ COMMAND parserTest
+ )
+ENDIF()
\ No newline at end of file
diff --git a/source/libs/parser/test/mockCatalog.cpp b/source/libs/parser/test/mockCatalog.cpp
index 0213a3a8542098381c52d56f70029fe3d830461b..6eafa0555b2882893fa30d9d1bb405e7f10d860f 100644
--- a/source/libs/parser/test/mockCatalog.cpp
+++ b/source/libs/parser/test/mockCatalog.cpp
@@ -25,95 +25,125 @@
#ifdef WINDOWS
#define TD_USE_WINSOCK
#endif
+
#include "mockCatalog.h"
+
+#include "systable.h"
namespace {
void generateInformationSchema(MockCatalogService* mcs) {
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "dnodes", TSDB_SYSTEM_TABLE, 1)
- .addColumn("id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_DNODES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("id", TSDB_DATA_TYPE_INT);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "mnodes", TSDB_SYSTEM_TABLE, 1)
- .addColumn("id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_MNODES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("id", TSDB_DATA_TYPE_INT);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "modules", TSDB_SYSTEM_TABLE, 1)
- .addColumn("id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_MODULES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("id", TSDB_DATA_TYPE_INT);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "qnodes", TSDB_SYSTEM_TABLE, 1)
- .addColumn("id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_QNODES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("id", TSDB_DATA_TYPE_INT);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_databases", TSDB_SYSTEM_TABLE, 1)
- .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_DATABASES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_functions", TSDB_SYSTEM_TABLE, 1)
- .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_FUNC_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_FUNCTIONS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_FUNC_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_indexes", TSDB_SYSTEM_TABLE, 2)
- .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
- .addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_INDEXES, TSDB_SYSTEM_TABLE, 2)
+ .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
+ .addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_stables", TSDB_SYSTEM_TABLE, 2)
- .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
- .addColumn("stable_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_STABLES, TSDB_SYSTEM_TABLE, 2)
+ .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
+ .addColumn("stable_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_tables", TSDB_SYSTEM_TABLE, 2)
- .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
- .addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_TABLES, TSDB_SYSTEM_TABLE, 2)
+ .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
+ .addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
builder.done();
}
{
ITableBuilder& builder =
- mcs->createTableBuilder("information_schema", "user_table_distributed", TSDB_SYSTEM_TABLE, 1)
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_TABLE_DISTRIBUTED, TSDB_SYSTEM_TABLE, 1)
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "user_users", TSDB_SYSTEM_TABLE, 1)
- .addColumn("user_name", TSDB_DATA_TYPE_BINARY, TSDB_USER_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_USERS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("user_name", TSDB_DATA_TYPE_BINARY, TSDB_USER_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "vgroups", TSDB_SYSTEM_TABLE, 1)
- .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_VGROUPS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "configs", TSDB_SYSTEM_TABLE, 1)
- .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_CONFIG_OPTION_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_CONFIGS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("name", TSDB_DATA_TYPE_BINARY, TSDB_CONFIG_OPTION_LEN);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("information_schema", "dnode_variables", TSDB_SYSTEM_TABLE, 1)
- .addColumn("dnode_id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_DNODE_VARIABLES, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("dnode_id", TSDB_DATA_TYPE_INT);
builder.done();
}
}
void generatePerformanceSchema(MockCatalogService* mcs) {
{
- ITableBuilder& builder = mcs->createTableBuilder("performance_schema", "trans", TSDB_SYSTEM_TABLE, 1)
- .addColumn("id", TSDB_DATA_TYPE_INT);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_TRANS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("id", TSDB_DATA_TYPE_INT);
builder.done();
}
{
- ITableBuilder& builder = mcs->createTableBuilder("performance_schema", "streams", TSDB_SYSTEM_TABLE, 1)
- .addColumn("stream_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_STREAMS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("stream_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ builder.done();
+ }
+ {
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_CONSUMERS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("stream_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
+ builder.done();
+ }
+ {
+ ITableBuilder& builder =
+ mcs->createTableBuilder(TSDB_PERFORMANCE_SCHEMA_DB, TSDB_PERFS_TABLE_SUBSCRIPTIONS, TSDB_SYSTEM_TABLE, 1)
+ .addColumn("stream_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN);
builder.done();
}
}
@@ -129,7 +159,7 @@ void generatePerformanceSchema(MockCatalogService* mcs) {
* c4 | column | DOUBLE | 8 |
* c5 | column | DOUBLE | 8 |
*/
-void generateTestT1(MockCatalogService* mcs) {
+void generateTestTables(MockCatalogService* mcs) {
ITableBuilder& builder = mcs->createTableBuilder("test", "t1", TSDB_NORMAL_TABLE, 6)
.setPrecision(TSDB_TIME_PRECISION_MILLI)
.setVgid(1)
@@ -153,23 +183,7 @@ void generateTestT1(MockCatalogService* mcs) {
* tag2 | tag | VARCHAR | 20 |
* tag3 | tag | TIMESTAMP | 8 |
* Child Table: st1s1, st1s2
- */
-void generateTestST1(MockCatalogService* mcs) {
- ITableBuilder& builder = mcs->createTableBuilder("test", "st1", TSDB_SUPER_TABLE, 3, 3)
- .setPrecision(TSDB_TIME_PRECISION_MILLI)
- .addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
- .addColumn("c1", TSDB_DATA_TYPE_INT)
- .addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
- .addTag("tag1", TSDB_DATA_TYPE_INT)
- .addTag("tag2", TSDB_DATA_TYPE_BINARY, 20)
- .addTag("tag3", TSDB_DATA_TYPE_TIMESTAMP);
- builder.done();
- mcs->createSubTable("test", "st1", "st1s1", 1);
- mcs->createSubTable("test", "st1", "st1s2", 2);
- mcs->createSubTable("test", "st1", "st1s3", 1);
-}
-
-/*
+ *
* Super Table: st2
* Field | Type | DataType | Bytes |
* ==========================================================================
@@ -179,16 +193,32 @@ void generateTestST1(MockCatalogService* mcs) {
* jtag | tag | json | -- |
* Child Table: st2s1, st2s2
*/
-void generateTestST2(MockCatalogService* mcs) {
- ITableBuilder& builder = mcs->createTableBuilder("test", "st2", TSDB_SUPER_TABLE, 3, 1)
- .setPrecision(TSDB_TIME_PRECISION_MILLI)
- .addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
- .addColumn("c1", TSDB_DATA_TYPE_INT)
- .addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
- .addTag("jtag", TSDB_DATA_TYPE_JSON);
- builder.done();
- mcs->createSubTable("test", "st2", "st2s1", 1);
- mcs->createSubTable("test", "st2", "st2s2", 2);
+void generateTestStables(MockCatalogService* mcs) {
+ {
+ ITableBuilder& builder = mcs->createTableBuilder("test", "st1", TSDB_SUPER_TABLE, 3, 3)
+ .setPrecision(TSDB_TIME_PRECISION_MILLI)
+ .addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
+ .addColumn("c1", TSDB_DATA_TYPE_INT)
+ .addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
+ .addTag("tag1", TSDB_DATA_TYPE_INT)
+ .addTag("tag2", TSDB_DATA_TYPE_BINARY, 20)
+ .addTag("tag3", TSDB_DATA_TYPE_TIMESTAMP);
+ builder.done();
+ mcs->createSubTable("test", "st1", "st1s1", 1);
+ mcs->createSubTable("test", "st1", "st1s2", 2);
+ mcs->createSubTable("test", "st1", "st1s3", 1);
+ }
+ {
+ ITableBuilder& builder = mcs->createTableBuilder("test", "st2", TSDB_SUPER_TABLE, 3, 1)
+ .setPrecision(TSDB_TIME_PRECISION_MILLI)
+ .addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
+ .addColumn("c1", TSDB_DATA_TYPE_INT)
+ .addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
+ .addTag("jtag", TSDB_DATA_TYPE_JSON);
+ builder.done();
+ mcs->createSubTable("test", "st2", "st2s1", 1);
+ mcs->createSubTable("test", "st2", "st2s2", 2);
+ }
}
void generateFunctions(MockCatalogService* mcs) {
@@ -203,6 +233,11 @@ void generateDnodes(MockCatalogService* mcs) {
mcs->createDnode(3, "host3", 7030);
}
+void generateDatabases(MockCatalogService* mcs) {
+ mcs->createDatabase("test");
+ mcs->createDatabase("rollup_db", true);
+}
+
} // namespace
int32_t __catalogGetHandle(const char* clusterId, struct SCatalog** catalogHandle) { return 0; }
@@ -232,7 +267,7 @@ int32_t __catalogGetDBVgInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char
}
int32_t __catalogGetDBCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const char* dbFName, SDbCfgInfo* pDbCfg) {
- return 0;
+ return g_mockCatalogService->catalogGetDBCfg(dbFName, pDbCfg);
}
int32_t __catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type,
@@ -261,6 +296,12 @@ int32_t __catalogGetDnodeList(SCatalog* pCatalog, SRequestConnInfo* pConn, SArra
return g_mockCatalogService->catalogGetDnodeList(pDnodeList);
}
+int32_t __catalogRefreshGetTableCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName,
+ STableCfg** pCfg) {
+ *pCfg = (STableCfg*)taosMemoryCalloc(1, sizeof(STableCfg));
+ return 0;
+}
+
void initMetaDataEnv() {
g_mockCatalogService.reset(new MockCatalogService());
@@ -279,6 +320,7 @@ void initMetaDataEnv() {
stub.set(catalogRemoveTableMeta, __catalogRemoveTableMeta);
stub.set(catalogGetTableIndex, __catalogGetTableIndex);
stub.set(catalogGetDnodeList, __catalogGetDnodeList);
+ stub.set(catalogRefreshGetTableCfg, __catalogRefreshGetTableCfg);
// {
// AddrAny any("libcatalog.so");
// std::map result;
@@ -322,11 +364,11 @@ void initMetaDataEnv() {
}
void generateMetaData() {
+ generateDatabases(g_mockCatalogService.get());
generateInformationSchema(g_mockCatalogService.get());
generatePerformanceSchema(g_mockCatalogService.get());
- generateTestT1(g_mockCatalogService.get());
- generateTestST1(g_mockCatalogService.get());
- generateTestST2(g_mockCatalogService.get());
+ generateTestTables(g_mockCatalogService.get());
+ generateTestStables(g_mockCatalogService.get());
generateFunctions(g_mockCatalogService.get());
generateDnodes(g_mockCatalogService.get());
g_mockCatalogService->showTables();
diff --git a/source/libs/parser/test/mockCatalogService.cpp b/source/libs/parser/test/mockCatalogService.cpp
index 7915c32437323be187bc4510a5a25147e7c31b67..0f759018d9f797f6674cc098193651c9de60e8cc 100644
--- a/source/libs/parser/test/mockCatalogService.cpp
+++ b/source/libs/parser/test/mockCatalogService.cpp
@@ -140,6 +140,17 @@ class MockCatalogServiceImpl {
return TSDB_CODE_SUCCESS;
}
+ int32_t catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const {
+ std::string dbFName(pDbFName);
+ DbCfgCache::const_iterator it = dbCfg_.find(dbFName.substr(std::string(pDbFName).find_last_of('.') + 1));
+ if (dbCfg_.end() == it) {
+ return TSDB_CODE_FAILED;
+ }
+
+ memcpy(pDbCfg, &(it->second), sizeof(SDbCfgInfo));
+ return TSDB_CODE_SUCCESS;
+ }
+
int32_t catalogGetUdfInfo(const std::string& funcName, SFuncInfo* pInfo) const {
auto it = udf_.find(funcName);
if (udf_.end() == it) {
@@ -197,7 +208,10 @@ class MockCatalogServiceImpl {
code = getAllTableIndex(pCatalogReq->pTableIndex, &pMetaData->pTableIndex);
}
if (TSDB_CODE_SUCCESS == code && pCatalogReq->dNodeRequired) {
- code = catalogGetDnodeList(&pMetaData->pDnodeList);
+ code = getAllDnodeList(&pMetaData->pDnodeList);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = getAllTableCfg(pCatalogReq->pTableCfg, &pMetaData->pTableCfg);
}
return code;
}
@@ -320,12 +334,21 @@ class MockCatalogServiceImpl {
dnode_.insert(std::make_pair(dnodeId, epSet));
}
+ void createDatabase(const std::string& db, bool rollup) {
+ SDbCfgInfo cfg = {0};
+ if (rollup) {
+ cfg.pRetensions = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SRetention));
+ }
+ dbCfg_.insert(std::make_pair(db, cfg));
+ }
+
private:
typedef std::map> TableMetaCache;
typedef std::map DbMetaCache;
typedef std::map> UdfMetaCache;
typedef std::map> IndexMetaCache;
typedef std::map DnodeCache;
+ typedef std::map DbCfgCache;
uint64_t getNextId() { return id_++; }
@@ -483,6 +506,7 @@ class MockCatalogServiceImpl {
for (int32_t i = 0; i < ndbs; ++i) {
SMetaRes res = {0};
res.pRes = taosMemoryCalloc(1, sizeof(SDbCfgInfo));
+ res.code = catalogGetDBCfg((const char*)taosArrayGet(pDbCfgReq, i), (SDbCfgInfo*)res.pRes);
taosArrayPush(*pDbCfgData, &res);
}
}
@@ -545,12 +569,35 @@ class MockCatalogServiceImpl {
return TSDB_CODE_SUCCESS;
}
+ int32_t getAllTableCfg(SArray* pTableCfgReq, SArray** pTableCfgData) const {
+ if (NULL != pTableCfgReq) {
+ int32_t ntables = taosArrayGetSize(pTableCfgReq);
+ *pTableCfgData = taosArrayInit(ntables, sizeof(SMetaRes));
+ for (int32_t i = 0; i < ntables; ++i) {
+ SMetaRes res = {0};
+ res.pRes = taosMemoryCalloc(1, sizeof(STableCfg));
+ res.code = TSDB_CODE_SUCCESS;
+ taosArrayPush(*pTableCfgData, &res);
+ }
+ }
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t getAllDnodeList(SArray** pDnodes) const {
+ SMetaRes res = {0};
+ catalogGetDnodeList((SArray**)&res.pRes);
+ *pDnodes = taosArrayInit(1, sizeof(SMetaRes));
+ taosArrayPush(*pDnodes, &res);
+ return TSDB_CODE_SUCCESS;
+ }
+
uint64_t id_;
std::unique_ptr builder_;
DbMetaCache meta_;
UdfMetaCache udf_;
IndexMetaCache index_;
DnodeCache dnode_;
+ DbCfgCache dbCfg_;
};
MockCatalogService::MockCatalogService() : impl_(new MockCatalogServiceImpl()) {}
@@ -580,6 +627,8 @@ void MockCatalogService::createDnode(int32_t dnodeId, const std::string& host, i
impl_->createDnode(dnodeId, host, port);
}
+void MockCatalogService::createDatabase(const std::string& db, bool rollup) { impl_->createDatabase(db, rollup); }
+
int32_t MockCatalogService::catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const {
return impl_->catalogGetTableMeta(pTableName, pTableMeta);
}
@@ -596,6 +645,10 @@ int32_t MockCatalogService::catalogGetDBVgInfo(const char* pDbFName, SArray** pV
return impl_->catalogGetDBVgInfo(pDbFName, pVgList);
}
+int32_t MockCatalogService::catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const {
+ return impl_->catalogGetDBCfg(pDbFName, pDbCfg);
+}
+
int32_t MockCatalogService::catalogGetUdfInfo(const std::string& funcName, SFuncInfo* pInfo) const {
return impl_->catalogGetUdfInfo(funcName, pInfo);
}
diff --git a/source/libs/parser/test/mockCatalogService.h b/source/libs/parser/test/mockCatalogService.h
index 932424823c226160d033430a2a95ac8c99d705b2..5c8a8acad12886804fcc91a6053ea5776e734ad5 100644
--- a/source/libs/parser/test/mockCatalogService.h
+++ b/source/libs/parser/test/mockCatalogService.h
@@ -63,11 +63,13 @@ class MockCatalogService {
void createFunction(const std::string& func, int8_t funcType, int8_t outputType, int32_t outputLen, int32_t bufSize);
void createSmaIndex(const SMCreateSmaReq* pReq);
void createDnode(int32_t dnodeId, const std::string& host, int16_t port);
+ void createDatabase(const std::string& db, bool rollup = false);
int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const;
int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const;
int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const;
int32_t catalogGetDBVgInfo(const char* pDbFName, SArray** pVgList) const;
+ int32_t catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const;
int32_t catalogGetUdfInfo(const std::string& funcName, SFuncInfo* pInfo) const;
int32_t catalogGetTableIndex(const SName* pTableName, SArray** pIndexes) const;
int32_t catalogGetDnodeList(SArray** pDnodes) const;
diff --git a/source/libs/parser/test/parExplainToSyncdbTest.cpp b/source/libs/parser/test/parExplainToSyncdbTest.cpp
index 4a5a92e62165bc3cec5868e3adf8f3d4246508a2..72083c68cafa78ed483217a42e2d374032cbf7f6 100644
--- a/source/libs/parser/test/parExplainToSyncdbTest.cpp
+++ b/source/libs/parser/test/parExplainToSyncdbTest.cpp
@@ -40,6 +40,12 @@ TEST_F(ParserExplainToSyncdbTest, grant) {
run("GRANT READ, WRITE ON test.* TO wxy");
}
+TEST_F(ParserExplainToSyncdbTest, insert) {
+ useDb("root", "test");
+
+ run("INSERT INTO t1 SELECT * FROM t1");
+}
+
// todo kill connection
// todo kill query
// todo kill stream
diff --git a/source/libs/parser/test/parInitialATest.cpp b/source/libs/parser/test/parInitialATest.cpp
index 021348dcc7310c819a1745fa244bbe158385d3c0..f4d0ba1cc8a0f0c446d0bf34506db3d74ba92402 100644
--- a/source/libs/parser/test/parInitialATest.cpp
+++ b/source/libs/parser/test/parInitialATest.cpp
@@ -38,9 +38,9 @@ TEST_F(ParserInitialATest, alterDnode) {
TEST_F(ParserInitialATest, alterDatabase) {
useDb("root", "test");
- run("ALTER DATABASE wxy_db CACHELAST 1 FSYNC 200 WAL 1");
+ run("ALTER DATABASE test CACHELAST 1 FSYNC 200 WAL 1");
- run("ALTER DATABASE wxy_db KEEP 2400");
+ run("ALTER DATABASE test KEEP 2400");
}
TEST_F(ParserInitialATest, alterLocal) {
@@ -77,8 +77,6 @@ TEST_F(ParserInitialATest, alterLocal) {
clearAlterLocal();
}
-// todo ALTER stable
-
/*
* ALTER TABLE [db_name.]tb_name alter_table_clause
*
@@ -121,7 +119,7 @@ TEST_F(ParserInitialATest, alterSTable) {
int32_t len = snprintf(expect.name, sizeof(expect.name), "0.test.%s", pTbname);
expect.name[len] = '\0';
expect.alterType = alterType;
-// expect.ttl = ttl;
+ // expect.ttl = ttl;
if (nullptr != pComment) {
expect.comment = strdup(pComment);
expect.commentLen = strlen(pComment);
@@ -157,7 +155,7 @@ TEST_F(ParserInitialATest, alterSTable) {
};
setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
- ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_TABLE_STMT);
+ ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_SUPER_TABLE_STMT);
SMAlterStbReq req = {0};
ASSERT_EQ(tDeserializeSMAlterStbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS);
ASSERT_EQ(std::string(req.name), std::string(expect.name));
@@ -180,45 +178,45 @@ TEST_F(ParserInitialATest, alterSTable) {
tFreeSMAltertbReq(&req);
});
-// setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_OPTIONS, 0, nullptr, 0, 0, nullptr, nullptr, 10);
-// run("ALTER TABLE st1 TTL 10");
-// clearAlterStbReq();
+ // setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_OPTIONS, 0, nullptr, 0, 0, nullptr, nullptr, 10);
+ // run("ALTER STABLE st1 TTL 10");
+ // clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_OPTIONS, 0, nullptr, 0, 0, nullptr, "test");
- run("ALTER TABLE st1 COMMENT 'test'");
+ run("ALTER STABLE st1 COMMENT 'test'");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_ADD_COLUMN, 1, "cc1", TSDB_DATA_TYPE_BIGINT);
- run("ALTER TABLE st1 ADD COLUMN cc1 BIGINT");
+ run("ALTER STABLE st1 ADD COLUMN cc1 BIGINT");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_DROP_COLUMN, 1, "c1");
- run("ALTER TABLE st1 DROP COLUMN c1");
+ run("ALTER STABLE st1 DROP COLUMN c1");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, 1, "c2", TSDB_DATA_TYPE_VARCHAR,
30 + VARSTR_HEADER_SIZE);
- run("ALTER TABLE st1 MODIFY COLUMN c2 VARCHAR(30)");
+ run("ALTER STABLE st1 MODIFY COLUMN c2 VARCHAR(30)");
clearAlterStbReq();
// setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, 2, "c1", 0, 0, "cc1");
- // run("ALTER TABLE st1 RENAME COLUMN c1 cc1");
+ // run("ALTER STABLE st1 RENAME COLUMN c1 cc1");
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_ADD_TAG, 1, "tag11", TSDB_DATA_TYPE_BIGINT);
- run("ALTER TABLE st1 ADD TAG tag11 BIGINT");
+ run("ALTER STABLE st1 ADD TAG tag11 BIGINT");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_DROP_TAG, 1, "tag1");
- run("ALTER TABLE st1 DROP TAG tag1");
+ run("ALTER STABLE st1 DROP TAG tag1");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, 1, "tag2", TSDB_DATA_TYPE_VARCHAR,
30 + VARSTR_HEADER_SIZE);
- run("ALTER TABLE st1 MODIFY TAG tag2 VARCHAR(30)");
+ run("ALTER STABLE st1 MODIFY TAG tag2 VARCHAR(30)");
clearAlterStbReq();
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_TAG_NAME, 2, "tag1", 0, 0, "tag11");
- run("ALTER TABLE st1 RENAME TAG tag1 tag11");
+ run("ALTER STABLE st1 RENAME TAG tag1 tag11");
clearAlterStbReq();
// todo
@@ -228,11 +226,11 @@ TEST_F(ParserInitialATest, alterSTable) {
TEST_F(ParserInitialATest, alterSTableSemanticCheck) {
useDb("root", "test");
- run("ALTER TABLE st1 RENAME COLUMN c1 cc1", TSDB_CODE_PAR_INVALID_ALTER_TABLE);
+ run("ALTER STABLE st1 RENAME COLUMN c1 cc1", TSDB_CODE_PAR_INVALID_ALTER_TABLE);
- run("ALTER TABLE st1 MODIFY COLUMN c2 NCHAR(10)", TSDB_CODE_PAR_INVALID_MODIFY_COL);
+ run("ALTER STABLE st1 MODIFY COLUMN c2 NCHAR(10)", TSDB_CODE_PAR_INVALID_MODIFY_COL);
- run("ALTER TABLE st1 MODIFY TAG tag2 NCHAR(10)", TSDB_CODE_PAR_INVALID_MODIFY_COL);
+ run("ALTER STABLE st1 MODIFY TAG tag2 NCHAR(10)", TSDB_CODE_PAR_INVALID_MODIFY_COL);
}
TEST_F(ParserInitialATest, alterTable) {
@@ -381,9 +379,48 @@ TEST_F(ParserInitialATest, alterTableSemanticCheck) {
TEST_F(ParserInitialATest, alterUser) {
useDb("root", "test");
- run("ALTER user wxy PASS '123456'");
+ SAlterUserReq expect = {0};
+
+ auto clearAlterUserReq = [&]() { memset(&expect, 0, sizeof(SAlterUserReq)); };
+
+ auto setAlterUserReq = [&](const char* pUser, int8_t alterType, const char* pPass = nullptr, int8_t sysInfo = 0,
+ int8_t enable = 0) {
+ strcpy(expect.user, pUser);
+ expect.alterType = alterType;
+ expect.superUser = 0;
+ expect.sysInfo = sysInfo;
+ expect.enable = enable;
+ if (nullptr != pPass) {
+ strcpy(expect.pass, pPass);
+ }
+ strcpy(expect.dbname, "test");
+ };
+
+ setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
+ ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_USER_STMT);
+ SAlterUserReq req = {0};
+ ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSAlterUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req));
+
+ ASSERT_EQ(req.alterType, expect.alterType);
+ ASSERT_EQ(req.superUser, expect.superUser);
+ ASSERT_EQ(req.sysInfo, expect.sysInfo);
+ ASSERT_EQ(req.enable, expect.enable);
+ ASSERT_EQ(std::string(req.user), std::string(expect.user));
+ ASSERT_EQ(std::string(req.pass), std::string(expect.pass));
+ ASSERT_EQ(std::string(req.dbname), std::string(expect.dbname));
+ });
+
+ setAlterUserReq("wxy", TSDB_ALTER_USER_PASSWD, "123456");
+ run("ALTER USER wxy PASS '123456'");
+ clearAlterUserReq();
+
+ setAlterUserReq("wxy", TSDB_ALTER_USER_ENABLE, nullptr, 0, 1);
+ run("ALTER USER wxy ENABLE 1");
+ clearAlterUserReq();
- run("ALTER user wxy privilege 'write'");
+ setAlterUserReq("wxy", TSDB_ALTER_USER_SYSINFO, nullptr, 1);
+ run("ALTER USER wxy SYSINFO 1");
+ clearAlterUserReq();
}
TEST_F(ParserInitialATest, balanceVgroup) {
diff --git a/source/libs/parser/test/parInitialCTest.cpp b/source/libs/parser/test/parInitialCTest.cpp
index d188744adf57385980279d6490f1d0e86db7ddac..e9c8fb53262706b6acb400dc23ba0a74f39ab78f 100644
--- a/source/libs/parser/test/parInitialCTest.cpp
+++ b/source/libs/parser/test/parInitialCTest.cpp
@@ -76,7 +76,8 @@ TEST_F(ParserInitialCTest, createDatabase) {
expect.db[len] = '\0';
expect.ignoreExist = igExists;
expect.buffer = TSDB_DEFAULT_BUFFER_PER_VNODE;
- expect.cacheLastRow = TSDB_DEFAULT_CACHE_LAST_ROW;
+ expect.cacheLast = TSDB_DEFAULT_CACHE_LAST;
+ expect.cacheLastSize = TSDB_DEFAULT_CACHE_LAST_SIZE;
expect.compression = TSDB_DEFAULT_COMP_LEVEL;
expect.daysPerFile = TSDB_DEFAULT_DAYS_PER_FILE;
expect.fsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
@@ -97,7 +98,8 @@ TEST_F(ParserInitialCTest, createDatabase) {
};
auto setDbBufferFunc = [&](int32_t buffer) { expect.buffer = buffer; };
- auto setDbCachelastFunc = [&](int8_t CACHELAST) { expect.cacheLastRow = CACHELAST; };
+ auto setDbCachelastFunc = [&](int8_t cachelast) { expect.cacheLast = cachelast; };
+ auto setDbCachelastSize = [&](int8_t cachelastSize) { expect.cacheLastSize = cachelastSize; };
auto setDbCompressionFunc = [&](int8_t compressionLevel) { expect.compression = compressionLevel; };
auto setDbDaysFunc = [&](int32_t daysPerFile) { expect.daysPerFile = daysPerFile; };
auto setDbFsyncFunc = [&](int32_t fsyncPeriod) { expect.fsyncPeriod = fsyncPeriod; };
@@ -153,7 +155,8 @@ TEST_F(ParserInitialCTest, createDatabase) {
ASSERT_EQ(req.compression, expect.compression);
ASSERT_EQ(req.replications, expect.replications);
ASSERT_EQ(req.strict, expect.strict);
- ASSERT_EQ(req.cacheLastRow, expect.cacheLastRow);
+ ASSERT_EQ(req.cacheLast, expect.cacheLast);
+ ASSERT_EQ(req.cacheLastSize, expect.cacheLastSize);
// ASSERT_EQ(req.schemaless, expect.schemaless);
ASSERT_EQ(req.ignoreExist, expect.ignoreExist);
ASSERT_EQ(req.numOfRetensions, expect.numOfRetensions);
@@ -179,6 +182,7 @@ TEST_F(ParserInitialCTest, createDatabase) {
setCreateDbReqFunc("wxy_db", 1);
setDbBufferFunc(64);
setDbCachelastFunc(2);
+ setDbCachelastSize(20);
setDbCompressionFunc(1);
setDbDaysFunc(100 * 1440);
setDbFsyncFunc(100);
@@ -200,6 +204,7 @@ TEST_F(ParserInitialCTest, createDatabase) {
run("CREATE DATABASE IF NOT EXISTS wxy_db "
"BUFFER 64 "
"CACHELAST 2 "
+ "CACHELASTSIZE 20 "
"COMP 1 "
"DURATION 100 "
"FSYNC 100 "
@@ -359,20 +364,20 @@ TEST_F(ParserInitialCTest, createStable) {
memset(&expect, 0, sizeof(SMCreateStbReq));
};
- auto setCreateStbReqFunc = [&](const char* pTbname, int8_t igExists = 0, int64_t delay1 = -1, int64_t delay2 = -1,
- int64_t watermark1 = TSDB_DEFAULT_ROLLUP_WATERMARK,
+ auto setCreateStbReqFunc = [&](const char* pDbName, const char* pTbName, int8_t igExists = 0, int64_t delay1 = -1,
+ int64_t delay2 = -1, int64_t watermark1 = TSDB_DEFAULT_ROLLUP_WATERMARK,
int64_t watermark2 = TSDB_DEFAULT_ROLLUP_WATERMARK,
int32_t ttl = TSDB_DEFAULT_TABLE_TTL, const char* pComment = nullptr) {
- int32_t len = snprintf(expect.name, sizeof(expect.name), "0.test.%s", pTbname);
+ int32_t len = snprintf(expect.name, sizeof(expect.name), "0.%s.%s", pDbName, pTbName);
expect.name[len] = '\0';
expect.igExists = igExists;
expect.delay1 = delay1;
expect.delay2 = delay2;
expect.watermark1 = watermark1;
expect.watermark2 = watermark2;
-// expect.ttl = ttl;
+ // expect.ttl = ttl;
if (nullptr != pComment) {
- expect.comment = strdup(pComment);
+ expect.pComment = strdup(pComment);
expect.commentLen = strlen(pComment);
}
};
@@ -414,7 +419,7 @@ TEST_F(ParserInitialCTest, createStable) {
ASSERT_EQ(req.ttl, expect.ttl);
ASSERT_EQ(req.numOfColumns, expect.numOfColumns);
ASSERT_EQ(req.numOfTags, expect.numOfTags);
-// ASSERT_EQ(req.commentLen, expect.commentLen);
+ // ASSERT_EQ(req.commentLen, expect.commentLen);
ASSERT_EQ(req.ast1Len, expect.ast1Len);
ASSERT_EQ(req.ast2Len, expect.ast2Len);
@@ -443,7 +448,7 @@ TEST_F(ParserInitialCTest, createStable) {
}
}
if (expect.commentLen > 0) {
- ASSERT_EQ(std::string(req.comment), std::string(expect.comment));
+ ASSERT_EQ(std::string(req.pComment), std::string(expect.pComment));
}
if (expect.ast1Len > 0) {
ASSERT_EQ(std::string(req.pAst1), std::string(expect.pAst1));
@@ -454,14 +459,14 @@ TEST_F(ParserInitialCTest, createStable) {
tFreeSMCreateStbReq(&req);
});
- setCreateStbReqFunc("t1");
+ setCreateStbReqFunc("test", "t1");
addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP);
addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT);
addFieldToCreateStbReqFunc(false, "id", TSDB_DATA_TYPE_INT);
run("CREATE STABLE t1(ts TIMESTAMP, c1 INT) TAGS(id INT)");
clearCreateStbReq();
- setCreateStbReqFunc("t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10,
+ setCreateStbReqFunc("rollup_db", "t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10,
1 * MILLISECOND_PER_MINUTE, 100, "test create table");
addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0);
addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT);
@@ -493,7 +498,7 @@ TEST_F(ParserInitialCTest, createStable) {
addFieldToCreateStbReqFunc(false, "a13", TSDB_DATA_TYPE_BOOL);
addFieldToCreateStbReqFunc(false, "a14", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE);
addFieldToCreateStbReqFunc(false, "a15", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE);
- run("CREATE STABLE IF NOT EXISTS test.t1("
+ run("CREATE STABLE IF NOT EXISTS rollup_db.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), "
"c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, "
"c13 NCHAR(30), c14 VARCHAR(50)) "
@@ -507,12 +512,13 @@ TEST_F(ParserInitialCTest, createStable) {
TEST_F(ParserInitialCTest, createStableSemanticCheck) {
useDb("root", "test");
- run("CREATE STABLE stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(CEIL)", TSDB_CODE_PAR_INVALID_ROLLUP_OPTION);
+ run("CREATE STABLE rollup_db.stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(CEIL)",
+ TSDB_CODE_PAR_INVALID_ROLLUP_OPTION);
- run("CREATE STABLE stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(MAX) MAX_DELAY 0s WATERMARK 1m",
+ run("CREATE STABLE rollup_db.stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(MAX) MAX_DELAY 0s WATERMARK 1m",
TSDB_CODE_PAR_INVALID_RANGE_OPTION);
- run("CREATE STABLE stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(MAX) MAX_DELAY 10s WATERMARK 18m",
+ run("CREATE STABLE rollup_db.stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(MAX) MAX_DELAY 10s WATERMARK 18m",
TSDB_CODE_PAR_INVALID_RANGE_OPTION);
}
@@ -526,20 +532,22 @@ TEST_F(ParserInitialCTest, createStream) {
memset(&expect, 0, sizeof(SCMCreateStreamReq));
};
- auto setCreateStreamReqFunc =
- [&](const char* pStream, const char* pSrcDb, const char* pSql, const char* pDstStb = nullptr, int8_t igExists = 0,
- int8_t triggerType = STREAM_TRIGGER_AT_ONCE, int64_t maxDelay = 0, int64_t watermark = 0) {
- snprintf(expect.name, sizeof(expect.name), "0.%s", pStream);
- snprintf(expect.sourceDB, sizeof(expect.sourceDB), "0.%s", pSrcDb);
- if (NULL != pDstStb) {
- snprintf(expect.targetStbFullName, sizeof(expect.targetStbFullName), "0.test.%s", pDstStb);
- }
- expect.igExists = igExists;
- expect.sql = strdup(pSql);
- expect.triggerType = triggerType;
- expect.maxDelay = maxDelay;
- expect.watermark = watermark;
- };
+ auto setCreateStreamReqFunc = [&](const char* pStream, const char* pSrcDb, const char* pSql,
+ const char* pDstStb = nullptr, int8_t igExists = 0,
+ int8_t triggerType = STREAM_TRIGGER_AT_ONCE, int64_t maxDelay = 0,
+ int64_t watermark = 0, int8_t igExpired = 0) {
+ snprintf(expect.name, sizeof(expect.name), "0.%s", pStream);
+ snprintf(expect.sourceDB, sizeof(expect.sourceDB), "0.%s", pSrcDb);
+ if (NULL != pDstStb) {
+ snprintf(expect.targetStbFullName, sizeof(expect.targetStbFullName), "0.test.%s", pDstStb);
+ }
+ expect.igExists = igExists;
+ expect.sql = strdup(pSql);
+ expect.triggerType = triggerType;
+ expect.maxDelay = maxDelay;
+ expect.watermark = watermark;
+ expect.igExpired = igExpired;
+ };
setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_STREAM_STMT);
@@ -555,32 +563,37 @@ TEST_F(ParserInitialCTest, createStream) {
ASSERT_EQ(req.triggerType, expect.triggerType);
ASSERT_EQ(req.maxDelay, expect.maxDelay);
ASSERT_EQ(req.watermark, expect.watermark);
+ ASSERT_EQ(req.igExpired, expect.igExpired);
tFreeSCMCreateStreamReq(&req);
});
- setCreateStreamReqFunc("s1", "test", "create stream s1 as select * from t1");
- run("CREATE STREAM s1 AS SELECT * FROM t1");
+ setCreateStreamReqFunc("s1", "test", "create stream s1 as select count(*) from t1 interval(10s)");
+ run("CREATE STREAM s1 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)");
clearCreateStreamReq();
- setCreateStreamReqFunc("s1", "test", "create stream if not exists s1 as select * from t1", nullptr, 1);
- run("CREATE STREAM IF NOT EXISTS s1 AS SELECT * FROM t1");
+ setCreateStreamReqFunc("s1", "test", "create stream if not exists s1 as select count(*) from t1 interval(10s)",
+ nullptr, 1);
+ run("CREATE STREAM IF NOT EXISTS s1 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)");
clearCreateStreamReq();
- setCreateStreamReqFunc("s1", "test", "create stream s1 into st1 as select * from t1", "st1");
- run("CREATE STREAM s1 INTO st1 AS SELECT * FROM t1");
+ setCreateStreamReqFunc("s1", "test", "create stream s1 into st1 as select count(*) from t1 interval(10s)", "st1");
+ run("CREATE STREAM s1 INTO st1 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)");
clearCreateStreamReq();
- setCreateStreamReqFunc(
- "s1", "test", "create stream if not exists s1 trigger max_delay 20s watermark 10s into st1 as select * from t1",
- "st1", 1, STREAM_TRIGGER_MAX_DELAY, 20 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_SECOND);
- run("CREATE STREAM IF NOT EXISTS s1 TRIGGER MAX_DELAY 20s WATERMARK 10s INTO st1 AS SELECT * FROM t1");
+ setCreateStreamReqFunc("s1", "test",
+ "create stream if not exists s1 trigger max_delay 20s watermark 10s ignore expired into st1 "
+ "as select count(*) from t1 interval(10s)",
+ "st1", 1, STREAM_TRIGGER_MAX_DELAY, 20 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_SECOND,
+ 1);
+ run("CREATE STREAM IF NOT EXISTS s1 TRIGGER MAX_DELAY 20s WATERMARK 10s IGNORE EXPIRED INTO st1 AS SELECT COUNT(*) "
+ "FROM t1 INTERVAL(10S)");
clearCreateStreamReq();
}
TEST_F(ParserInitialCTest, createStreamSemanticCheck) {
useDb("root", "test");
- run("CREATE STREAM s1 AS SELECT PERCENTILE(c1, 30) FROM t1", TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC);
+ run("CREATE STREAM s1 AS SELECT PERCENTILE(c1, 30) FROM t1 INTERVAL(10S)", TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC);
}
TEST_F(ParserInitialCTest, createTable) {
@@ -594,7 +607,7 @@ TEST_F(ParserInitialCTest, createTable) {
"c13 NCHAR(30), c15 VARCHAR(50)) "
"TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)");
- run("CREATE TABLE IF NOT EXISTS test.t1("
+ run("CREATE TABLE IF NOT EXISTS rollup_db.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), "
"c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, "
"c13 NCHAR(30), c14 VARCHAR(50)) "
@@ -613,6 +626,21 @@ TEST_F(ParserInitialCTest, createTable) {
// run("CREATE TABLE IF NOT EXISTS t1 USING st1 TAGS(1, 'wxy', NOW + 1S)");
}
+TEST_F(ParserInitialCTest, createTableSemanticCheck) {
+ useDb("root", "test");
+
+ string sql = "CREATE TABLE st1(ts TIMESTAMP, ";
+ for (int32_t i = 1; i < 4096; ++i) {
+ if (i > 1) {
+ sql.append(", ");
+ }
+ sql.append("c" + to_string(i) + " INT");
+ }
+ sql.append(") TAGS (t1 int)");
+
+ run(sql, TSDB_CODE_PAR_TOO_MANY_COLUMNS);
+}
+
TEST_F(ParserInitialCTest, createTopic) {
useDb("root", "test");
@@ -621,10 +649,11 @@ TEST_F(ParserInitialCTest, createTopic) {
auto clearCreateTopicReq = [&]() { memset(&expect, 0, sizeof(SCMCreateTopicReq)); };
auto setCreateTopicReqFunc = [&](const char* pTopicName, int8_t igExists, const char* pSql, const char* pAst,
- const char* pDbName = nullptr, const char* pTbname = nullptr) {
+ const char* pDbName = nullptr, const char* pTbname = nullptr, int8_t withMeta = 0) {
snprintf(expect.name, sizeof(expect.name), "0.%s", pTopicName);
expect.igExists = igExists;
expect.sql = (char*)pSql;
+ expect.withMeta = withMeta;
if (nullptr != pTbname) {
expect.subType = TOPIC_SUB_TYPE__TABLE;
snprintf(expect.subStbName, sizeof(expect.subStbName), "0.%s.%s", pDbName, pTbname);
@@ -647,6 +676,7 @@ TEST_F(ParserInitialCTest, createTopic) {
ASSERT_EQ(req.igExists, expect.igExists);
ASSERT_EQ(req.subType, expect.subType);
ASSERT_EQ(std::string(req.sql), std::string(expect.sql));
+ ASSERT_EQ(req.withMeta, expect.withMeta);
switch (expect.subType) {
case TOPIC_SUB_TYPE__DB:
ASSERT_EQ(std::string(req.subDbName), std::string(expect.subDbName));
@@ -675,15 +705,55 @@ TEST_F(ParserInitialCTest, createTopic) {
run("CREATE TOPIC tp1 AS DATABASE test");
clearCreateTopicReq();
+ setCreateTopicReqFunc("tp1", 0, "create topic tp1 with meta as database test", nullptr, "test", nullptr, 1);
+ run("CREATE TOPIC tp1 WITH META AS DATABASE test");
+ clearCreateTopicReq();
+
setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 as stable st1", nullptr, "test", "st1");
run("CREATE TOPIC IF NOT EXISTS tp1 AS STABLE st1");
clearCreateTopicReq();
+
+ setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 with meta as stable st1", nullptr, "test", "st1", 1);
+ run("CREATE TOPIC IF NOT EXISTS tp1 WITH META AS STABLE st1");
+ clearCreateTopicReq();
}
TEST_F(ParserInitialCTest, createUser) {
useDb("root", "test");
+ SCreateUserReq expect = {0};
+
+ auto clearCreateUserReq = [&]() { memset(&expect, 0, sizeof(SCreateUserReq)); };
+
+ auto setCreateUserReq = [&](const char* pUser, const char* pPass, int8_t sysInfo = 1) {
+ strcpy(expect.user, pUser);
+ strcpy(expect.pass, pPass);
+ expect.createType = 0;
+ expect.superUser = 0;
+ expect.sysInfo = sysInfo;
+ expect.enable = 1;
+ };
+
+ setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
+ ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_USER_STMT);
+ SCreateUserReq req = {0};
+ ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSCreateUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req));
+
+ ASSERT_EQ(req.createType, expect.createType);
+ ASSERT_EQ(req.superUser, expect.superUser);
+ ASSERT_EQ(req.sysInfo, expect.sysInfo);
+ ASSERT_EQ(req.enable, expect.enable);
+ ASSERT_EQ(std::string(req.user), std::string(expect.user));
+ ASSERT_EQ(std::string(req.pass), std::string(expect.pass));
+ });
+
+ setCreateUserReq("wxy", "123456");
run("CREATE USER wxy PASS '123456'");
+ clearCreateUserReq();
+
+ setCreateUserReq("wxy1", "a123456", 1);
+ run("CREATE USER wxy1 PASS 'a123456' SYSINFO 1");
+ clearCreateUserReq();
}
} // namespace ParserTest
diff --git a/source/libs/parser/test/parInitialDTest.cpp b/source/libs/parser/test/parInitialDTest.cpp
index c2039718d0924b3cc59d01c21874e8ae862fc8a7..870afa694a21623f7bd1816c5eeb7a769ce9a6e8 100644
--- a/source/libs/parser/test/parInitialDTest.cpp
+++ b/source/libs/parser/test/parInitialDTest.cpp
@@ -132,7 +132,31 @@ TEST_F(ParserInitialDTest, dropDnode) {
TEST_F(ParserInitialDTest, dropIndex) {
useDb("root", "test");
- run("DROP index index1 on t1");
+ SMDropSmaReq expect = {0};
+
+ auto clearDropSmaReq = [&]() { memset(&expect, 0, sizeof(SMDropSmaReq)); };
+
+ auto setDropSmaReq = [&](const char* pName, int8_t igNotExists = 0) {
+ sprintf(expect.name, "0.test.%s", pName);
+ expect.igNotExists = igNotExists;
+ };
+
+ setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
+ ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_DROP_INDEX_STMT);
+ SMDropSmaReq req = {0};
+ ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSMDropSmaReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req));
+
+ ASSERT_EQ(std::string(req.name), std::string(expect.name));
+ ASSERT_EQ(req.igNotExists, expect.igNotExists);
+ });
+
+ setDropSmaReq("index1");
+ run("DROP INDEX index1");
+ clearDropSmaReq();
+
+ setDropSmaReq("index2", 1);
+ run("DROP INDEX IF EXISTS index2");
+ clearDropSmaReq();
}
TEST_F(ParserInitialDTest, dropMnode) {
diff --git a/source/libs/parser/test/parInsertTest.cpp b/source/libs/parser/test/parInsertTest.cpp
index 3ebf9a417b437aee072a2286439d94927cd61398..22a1be25794e4c0ee19fd136cfc17586aea66c3c 100644
--- a/source/libs/parser/test/parInsertTest.cpp
+++ b/source/libs/parser/test/parInsertTest.cpp
@@ -265,6 +265,11 @@ TEST_F(InsertTest, autoCreateTableTest) {
"insert into st1s1 using st1 (tag1, tag2) tags(1, 'wxy') values (now, 1, \"beijing\")"
"(now+1s, 2, \"shanghai\")(now+2s, 3, \"guangzhou\")");
ASSERT_EQ(runAsync(), TSDB_CODE_SUCCESS);
+
+ bind(
+ "insert into st1s1 using st1 tags(1, 'wxy', now) values (now, 1, \"beijing\")"
+ "st1s1 using st1 tags(1, 'wxy', now) values (now+1s, 2, \"shanghai\")");
+ ASSERT_EQ(run(), TSDB_CODE_SUCCESS);
}
TEST_F(InsertTest, toleranceTest) {
diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp
index 11e09cd83d89f5ba02df18f5a439786ffe6d83c0..e68205979379a80f33be833a20205d344c32e330 100644
--- a/source/libs/parser/test/parSelectTest.cpp
+++ b/source/libs/parser/test/parSelectTest.cpp
@@ -58,6 +58,8 @@ TEST_F(ParserSelectTest, expression) {
run("SELECT ts > 0, c1 < 20 and c2 = 'qaz' FROM t1");
run("SELECT ts > 0, c1 between 10 and 20 and c2 = 'qaz' FROM t1");
+
+ run("SELECT c1 | 10, c2 & 20, c4 | c5 FROM t1");
}
TEST_F(ParserSelectTest, condition) {
@@ -73,7 +75,7 @@ TEST_F(ParserSelectTest, condition) {
TEST_F(ParserSelectTest, pseudoColumn) {
useDb("root", "test");
- run("SELECT _WSTARTTS, _WENDTS, COUNT(*) FROM t1 INTERVAL(10s)");
+ run("SELECT _WSTART, _WEND, COUNT(*) FROM t1 INTERVAL(10s)");
}
TEST_F(ParserSelectTest, pseudoColumnSemanticCheck) {
@@ -142,15 +144,17 @@ TEST_F(ParserSelectTest, IndefiniteRowsFunc) {
TEST_F(ParserSelectTest, IndefiniteRowsFuncSemanticCheck) {
useDb("root", "test");
- run("SELECT DIFF(c1), c2 FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC, PARSER_STAGE_TRANSLATE);
+ run("SELECT DIFF(c1), c2 FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
+
+ run("SELECT DIFF(c1), tbname FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
- run("SELECT DIFF(c1), tbname FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC, PARSER_STAGE_TRANSLATE);
+ run("SELECT DIFF(c1), count(*) FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
- run("SELECT DIFF(c1), count(*) FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC, PARSER_STAGE_TRANSLATE);
+ run("SELECT DIFF(c1), CSUM(c1) FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
- run("SELECT DIFF(c1), CSUM(c1) FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC, PARSER_STAGE_TRANSLATE);
+ run("SELECT CSUM(c3) FROM t1 STATE_WINDOW(c1)", TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC);
- // run("SELECT DIFF(c1) FROM t1 INTERVAL(10s)");
+ run("SELECT DIFF(c1) FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC);
}
TEST_F(ParserSelectTest, useDefinedFunc) {
@@ -195,6 +199,20 @@ TEST_F(ParserSelectTest, tailFuncSemanticCheck) {
run("SELECT TAIL(c1, 10) FROM t1 GROUP BY c2", TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC);
}
+TEST_F(ParserSelectTest, partitionBy) {
+ useDb("root", "test");
+
+ run("SELECT c1, c2 FROM t1 PARTITION BY c2");
+
+ run("SELECT SUM(c1), c2 FROM t1 PARTITION BY c2");
+}
+
+TEST_F(ParserSelectTest, partitionBySemanticCheck) {
+ useDb("root", "test");
+
+ run("SELECT SUM(c1), c2, c3 FROM t1 PARTITION BY c2", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
+}
+
TEST_F(ParserSelectTest, groupBy) {
useDb("root", "test");
@@ -209,6 +227,13 @@ TEST_F(ParserSelectTest, groupBy) {
run("SELECT COUNT(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c1 + 10, c2");
}
+TEST_F(ParserSelectTest, groupBySemanticCheck) {
+ useDb("root", "test");
+
+ run("SELECT COUNT(*) cnt, c1 FROM t1 WHERE c1 > 0", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
+ run("SELECT COUNT(*) cnt, c2 FROM t1 WHERE c1 > 0 GROUP BY c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
+}
+
TEST_F(ParserSelectTest, orderBy) {
useDb("root", "test");
@@ -220,13 +245,21 @@ TEST_F(ParserSelectTest, orderBy) {
TEST_F(ParserSelectTest, distinct) {
useDb("root", "test");
- // run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by c1");
+ run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by c1");
+
+ run("SELECT distinct c1 + 10, c2 FROM t1 WHERE c1 > 0 order by c1 + 10, c2");
+
+ run("SELECT distinct c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 order by cc1, c2");
+
+ run("SELECT distinct COUNT(c2) FROM t1 WHERE c1 > 0 GROUP BY c1 order by COUNT(c2)");
+}
- // run("SELECT distinct c1 + 10, c2 FROM t1 WHERE c1 > 0 order by c1 + 10, c2");
+TEST_F(ParserSelectTest, limit) {
+ useDb("root", "test");
- // run("SELECT distinct c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 order by cc1, c2");
+ run("SELECT c1, c2 FROM t1 LIMIT 10");
- // run("SELECT distinct COUNT(c2) FROM t1 WHERE c1 > 0 GROUP BY c1 order by COUNT(c2)");
+ run("(SELECT c1, c2 FROM t1 LIMIT 10)");
}
// INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
@@ -248,12 +281,12 @@ TEST_F(ParserSelectTest, interval) {
TEST_F(ParserSelectTest, intervalSemanticCheck) {
useDb("root", "test");
- run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
+ run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN);
run("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)", TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE);
run("SELECT HISTOGRAM(c1, 'log_bin', '{\"start\": -33,\"factor\": 55,\"count\": 5,\"infinity\": false}', 1) FROM t1 "
"WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' INTERVAL(10s) FILL(NULL)",
TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC);
- run("SELECT _WSTARTTS, _WENDTS, _WDURATION, sum(c1) FROM t1", TSDB_CODE_PAR_INVALID_WINDOW_PC);
+ run("SELECT _WSTART, _WEND, _WDURATION, sum(c1) FROM t1", TSDB_CODE_PAR_INVALID_WINDOW_PC);
}
TEST_F(ParserSelectTest, interp) {
@@ -277,11 +310,11 @@ TEST_F(ParserSelectTest, subquery) {
run("SELECT SUM(a) FROM (SELECT MAX(c1) a, ts FROM st1s1 INTERVAL(1m)) INTERVAL(1n)");
- run("SELECT SUM(a) FROM (SELECT MAX(c1) a, _wstartts FROM st1s1 INTERVAL(1m)) INTERVAL(1n)");
+ run("SELECT SUM(a) FROM (SELECT MAX(c1) a, _wstart FROM st1s1 INTERVAL(1m)) INTERVAL(1n)");
run("SELECT SUM(a) FROM (SELECT MAX(c1) a, ts FROM st1s1 PARTITION BY TBNAME INTERVAL(1m)) INTERVAL(1n)");
- run("SELECT SUM(a) FROM (SELECT MAX(c1) a, _wstartts FROM st1s1 PARTITION BY TBNAME INTERVAL(1m)) INTERVAL(1n)");
+ run("SELECT SUM(a) FROM (SELECT MAX(c1) a, _wstart FROM st1s1 PARTITION BY TBNAME INTERVAL(1m)) INTERVAL(1n)");
run("SELECT _C0 FROM (SELECT _ROWTS, ts FROM st1s1)");
@@ -304,70 +337,69 @@ TEST_F(ParserSelectTest, semanticCheck) {
useDb("root", "test");
// TSDB_CODE_PAR_INVALID_COLUMN
- run("SELECT c1, cc1 FROM t1", TSDB_CODE_PAR_INVALID_COLUMN, PARSER_STAGE_TRANSLATE);
+ run("SELECT c1, cc1 FROM t1", TSDB_CODE_PAR_INVALID_COLUMN);
- run("SELECT t1.c1, t1.cc1 FROM t1", TSDB_CODE_PAR_INVALID_COLUMN, PARSER_STAGE_TRANSLATE);
+ run("SELECT t1.c1, t1.cc1 FROM t1", TSDB_CODE_PAR_INVALID_COLUMN);
// TSDB_CODE_PAR_TABLE_NOT_EXIST
- run("SELECT * FROM t10", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
+ run("SELECT * FROM t10", TSDB_CODE_PAR_TABLE_NOT_EXIST);
- run("SELECT * FROM test.t10", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
+ run("SELECT * FROM test.t10", TSDB_CODE_PAR_TABLE_NOT_EXIST);
- run("SELECT t2.c1 FROM t1", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
+ run("SELECT t2.c1 FROM t1", TSDB_CODE_PAR_TABLE_NOT_EXIST);
// TSDB_CODE_PAR_AMBIGUOUS_COLUMN
- run("SELECT c2 FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1", TSDB_CODE_PAR_AMBIGUOUS_COLUMN, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1", TSDB_CODE_PAR_AMBIGUOUS_COLUMN);
- run("SELECT c2 FROM (SELECT c1 c2, c2 FROM t1)", TSDB_CODE_PAR_AMBIGUOUS_COLUMN, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM (SELECT c1 c2, c2 FROM t1)", TSDB_CODE_PAR_AMBIGUOUS_COLUMN);
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
- run("SELECT timestamp '2010a' FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
+ run("SELECT timestamp '2010a' FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE);
- run("SELECT LAST(*) + SUM(c1) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
+ run("SELECT LAST(*) + SUM(c1) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE);
- run("SELECT CEIL(LAST(ts, c1)) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
+ run("SELECT CEIL(LAST(ts, c1)) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE);
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
- run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
- run("SELECT c2 FROM t1 WHERE COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 WHERE COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
- run("SELECT c2 FROM t1 GROUP BY COUNT(*)", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 GROUP BY COUNT(*)", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
// TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT
- run("SELECT c2 FROM t1 order by 0", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 order by 0", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
- run("SELECT c2 FROM t1 order by 2", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, PARSER_STAGE_TRANSLATE);
+ run("SELECT c2 FROM t1 order by 2", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
// TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
- run("SELECT COUNT(*) cnt FROM t1 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION, PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*) cnt FROM t1 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
- run("SELECT COUNT(*) cnt FROM t1 GROUP BY c2 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*) cnt FROM t1 GROUP BY c2 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
- run("SELECT COUNT(*), c1 cnt FROM t1 GROUP BY c2 having c2 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*), c1 cnt FROM t1 GROUP BY c2 having c2 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
- run("SELECT COUNT(*) cnt FROM t1 GROUP BY c2 having c2 > 0 order by c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*) cnt FROM t1 GROUP BY c2 having c2 > 0 order by c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
// TSDB_CODE_PAR_NOT_SINGLE_GROUP
- run("SELECT COUNT(*), c1 FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*), c1 FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
- run("SELECT COUNT(*) FROM t1 order by c1", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
+ run("SELECT COUNT(*) FROM t1 order by c1", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
- run("SELECT c1 FROM t1 order by COUNT(*)", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
+ run("SELECT c1 FROM t1 order by COUNT(*)", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
// TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION
- run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by ts", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by ts", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION);
+
+ run("SELECT distinct c1 FROM t1 WHERE c1 > 0 order by COUNT(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION);
- run("SELECT distinct c1 FROM t1 WHERE c1 > 0 order by COUNT(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT distinct c2 FROM t1 WHERE c1 > 0 order by COUNT(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION);
+}
+
+TEST_F(ParserSelectTest, syntaxError) {
+ useDb("root", "test");
- run("SELECT distinct c2 FROM t1 WHERE c1 > 0 order by COUNT(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
- PARSER_STAGE_TRANSLATE);
+ run("SELECT CAST(? AS BINARY(10)) FROM t1", TSDB_CODE_PAR_SYNTAX_ERROR, PARSER_STAGE_PARSE);
}
TEST_F(ParserSelectTest, setOperator) {
@@ -382,10 +414,34 @@ TEST_F(ParserSelectTest, setOperator) {
run("SELECT c1, c2 FROM t1 UNION ALL SELECT c1 as a, c2 as b FROM t1 ORDER BY c1");
}
+TEST_F(ParserSelectTest, setOperatorSemanticCheck) {
+ useDb("root", "test");
+
+ run("SELECT c1, c2 FROM t1 UNION ALL SELECT c1, c2 FROM t1 ORDER BY ts", TSDB_CODE_PAR_INVALID_COLUMN);
+}
+
TEST_F(ParserSelectTest, informationSchema) {
useDb("root", "test");
run("SELECT * FROM information_schema.user_databases WHERE name = 'information_schema'");
}
+TEST_F(ParserSelectTest, withoutFrom) {
+ useDb("root", "test");
+
+ run("SELECT 1");
+
+ run("SELECT DATABASE()");
+
+ run("SELECT CLIENT_VERSION()");
+
+ run("SELECT SERVER_VERSION()");
+
+ run("SELECT SERVER_STATUS()");
+
+ run("SELECT CURRENT_USER()");
+
+ run("SELECT USER()");
+}
+
} // namespace ParserTest
diff --git a/source/libs/parser/test/parShowToUse.cpp b/source/libs/parser/test/parShowToUse.cpp
index 1a68e8087201a0f7cbd46fc622321bb21d602c36..eecb29155416f8c8ab1c42ede9e8df11be90e8b3 100644
--- a/source/libs/parser/test/parShowToUse.cpp
+++ b/source/libs/parser/test/parShowToUse.cpp
@@ -25,6 +25,15 @@ class ParserShowToUseTest : public ParserDdlTest {};
// todo SHOW apps
// todo SHOW connections
+TEST_F(ParserShowToUseTest, showConsumers) {
+ useDb("root", "test");
+
+ setCheckDdlFunc(
+ [&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_SELECT_STMT); });
+
+ run("SHOW CONSUMERS");
+}
+
TEST_F(ParserShowToUseTest, showCreateDatabase) {
useDb("root", "test");
@@ -45,7 +54,7 @@ TEST_F(ParserShowToUseTest, showCreateSTable) {
ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_SHOW_CREATE_STABLE_STMT);
ASSERT_EQ(pQuery->execMode, QUERY_EXEC_MODE_LOCAL);
ASSERT_TRUE(pQuery->haveResultSet);
- ASSERT_NE(((SShowCreateTableStmt*)pQuery->pRoot)->pMeta, nullptr);
+ ASSERT_NE(((SShowCreateTableStmt*)pQuery->pRoot)->pCfg, nullptr);
});
run("SHOW CREATE STABLE st1");
@@ -58,7 +67,7 @@ TEST_F(ParserShowToUseTest, showCreateTable) {
ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_SHOW_CREATE_TABLE_STMT);
ASSERT_EQ(pQuery->execMode, QUERY_EXEC_MODE_LOCAL);
ASSERT_TRUE(pQuery->haveResultSet);
- ASSERT_NE(((SShowCreateTableStmt*)pQuery->pRoot)->pMeta, nullptr);
+ ASSERT_NE(((SShowCreateTableStmt*)pQuery->pRoot)->pCfg, nullptr);
});
run("SHOW CREATE TABLE t1");
@@ -143,6 +152,15 @@ TEST_F(ParserShowToUseTest, showStreams) {
run("SHOW streams");
}
+TEST_F(ParserShowToUseTest, showSubscriptions) {
+ useDb("root", "test");
+
+ setCheckDdlFunc(
+ [&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_SELECT_STMT); });
+
+ run("SHOW SUBSCRIPTIONS");
+}
+
TEST_F(ParserShowToUseTest, showTransactions) {
useDb("root", "test");
@@ -204,6 +222,25 @@ TEST_F(ParserShowToUseTest, splitVgroup) {
run("SPLIT VGROUP 15");
}
+TEST_F(ParserShowToUseTest, trimDatabase) {
+ useDb("root", "test");
+
+ STrimDbReq expect = {0};
+
+ auto setTrimDbReq = [&](const char* pDb) { snprintf(expect.db, sizeof(expect.db), "0.%s", pDb); };
+
+ setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) {
+ ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_TRIM_DATABASE_STMT);
+ ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_TRIM_DB);
+ STrimDbReq req = {0};
+ ASSERT_EQ(tDeserializeSTrimDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS);
+ ASSERT_EQ(std::string(req.db), std::string(expect.db));
+ });
+
+ setTrimDbReq("wxy_db");
+ run("TRIM DATABASE wxy_db");
+}
+
TEST_F(ParserShowToUseTest, useDatabase) {
useDb("root", "test");
diff --git a/source/libs/parser/test/parTestUtil.cpp b/source/libs/parser/test/parTestUtil.cpp
index 663f456cb8b17487dd4b81481ce93dae096d4130..2b312642cd65e6bd3fce71f613d79c76f21945f8 100644
--- a/source/libs/parser/test/parTestUtil.cpp
+++ b/source/libs/parser/test/parTestUtil.cpp
@@ -203,6 +203,7 @@ class ParserTestBaseImpl {
pCxt->pMsg = stmtEnv_.msgBuf_.data();
pCxt->msgLen = stmtEnv_.msgBuf_.max_size();
pCxt->async = async;
+ pCxt->svrVer = "3.0.0.0";
}
void doParse(SParseContext* pCxt, SQuery** pQuery) {
diff --git a/source/libs/parser/test/parTestUtil.h b/source/libs/parser/test/parTestUtil.h
index 16c3d05b38cd66ba148696fa629728b04ccf4afa..3e5fab592729a9d98010900be1ef6dbbedc0d07f 100644
--- a/source/libs/parser/test/parTestUtil.h
+++ b/source/libs/parser/test/parTestUtil.h
@@ -54,12 +54,6 @@ class ParserDdlTest : public ParserTestBase {
virtual void checkDdl(const SQuery* pQuery, ParserStage stage) {
ASSERT_NE(pQuery, nullptr);
ASSERT_NE(pQuery->pRoot, nullptr);
- if (QUERY_EXEC_MODE_RPC == pQuery->execMode) {
- ASSERT_EQ(pQuery->haveResultSet, false);
- ASSERT_EQ(pQuery->numOfResCols, 0);
- ASSERT_EQ(pQuery->pResSchema, nullptr);
- ASSERT_EQ(pQuery->precision, 0);
- }
if (nullptr != checkDdl_) {
checkDdl_(pQuery, stage);
}
diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c
index c7490faa0c28524830f16515e2eb16278b894706..190ec3a1f6e8e49e5fea49c894ca95d4da4867a1 100644
--- a/source/libs/planner/src/planLogicCreater.c
+++ b/source/libs/planner/src/planLogicCreater.c
@@ -19,12 +19,14 @@
typedef struct SLogicPlanContext {
SPlanContext* pPlanCxt;
+ SLogicNode* pCurrRoot;
} SLogicPlanContext;
typedef int32_t (*FCreateLogicNode)(SLogicPlanContext*, void*, SLogicNode**);
typedef int32_t (*FCreateSelectLogicNode)(SLogicPlanContext*, SSelectStmt*, SLogicNode**);
typedef int32_t (*FCreateSetOpLogicNode)(SLogicPlanContext*, SSetOperator*, SLogicNode**);
typedef int32_t (*FCreateDeleteLogicNode)(SLogicPlanContext*, SDeleteStmt*, SLogicNode**);
+typedef int32_t (*FCreateInsertLogicNode)(SLogicPlanContext*, SInsertStmt*, SLogicNode**);
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable,
SLogicNode** pLogicNode);
@@ -56,8 +58,12 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
pCol->node.resType = pToBeRewrittenExpr->resType;
strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName);
strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName);
- if (QUERY_NODE_FUNCTION == nodeType(pExpr) && FUNCTION_TYPE_WSTARTTS == ((SFunctionNode*)pExpr)->funcType) {
- pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
+ if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
+ if (FUNCTION_TYPE_WSTART == ((SFunctionNode*)pExpr)->funcType) {
+ pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
+ } else if (FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pExpr)->funcType) {
+ pCol->colType = COLUMN_TYPE_TBNAME;
+ }
}
nodesDestroyNode(*pNode);
*pNode = (SNode*)pCol;
@@ -136,6 +142,7 @@ static int32_t createRootLogicNode(SLogicPlanContext* pCxt, void* pStmt, uint8_t
if (TSDB_CODE_SUCCESS == code && NULL != pNode) {
pNode->precision = precision;
code = pushLogicNode(pCxt, pRoot, pNode);
+ pCxt->pCurrRoot = pNode;
}
if (TSDB_CODE_SUCCESS != code) {
nodesDestroyNode((SNode*)pNode);
@@ -155,12 +162,11 @@ static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanPseudoCols
}
if (NULL == pScanCols) {
- // select count(*) from t
return NULL == pScanPseudoCols
? SCAN_TYPE_TABLE
: ((FUNCTION_TYPE_BLOCK_DIST_INFO == ((SFunctionNode*)nodesListGetNode(pScanPseudoCols, 0))->funcType)
? SCAN_TYPE_BLOCK_INFO
- : SCAN_TYPE_TAG);
+ : SCAN_TYPE_TABLE);
}
if (TSDB_SYSTEM_TABLE == tableType) {
@@ -174,7 +180,7 @@ static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanPseudoCols
}
}
- return SCAN_TYPE_TAG;
+ return SCAN_TYPE_TABLE;
}
static SNode* createPrimaryKeyCol(uint64_t tableId) {
@@ -292,6 +298,29 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
return code;
}
+static int32_t createColumnByLastRow(SNodeList* pFuncs, SNodeList** pOutput) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ SNodeList* pCols = NULL;
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, pFuncs) {
+ SFunctionNode* pLastRow = (SFunctionNode*)pFunc;
+ SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pLastRow->pParameterList, 0);
+ snprintf(pCol->colName, sizeof(pCol->colName), "%s", pLastRow->node.aliasName);
+ snprintf(pCol->node.aliasName, sizeof(pCol->colName), "%s", pLastRow->node.aliasName);
+ NODES_CLEAR_LIST(pLastRow->pParameterList);
+ code = nodesListMakeStrictAppend(&pCols, (SNode*)pCol);
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = pCols;
+ } else {
+ nodesDestroyList(pCols);
+ }
+ return code;
+}
+
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable,
SLogicNode** pLogicNode) {
return createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
@@ -386,6 +415,7 @@ static int32_t createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSel
}
pNode->precision = pSelect->precision;
*pLogicNode = pNode;
+ pCxt->pCurrRoot = pNode;
}
return code;
}
@@ -403,6 +433,33 @@ static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr)
return pCol;
}
+static SNode* createGroupingSetNode(SNode* pExpr) {
+ SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
+ if (NULL == pGroupingSet) {
+ return NULL;
+ }
+ pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
+ if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, nodesCloneNode(pExpr))) {
+ nodesDestroyNode((SNode*)pGroupingSet);
+ return NULL;
+ }
+ return (SNode*)pGroupingSet;
+}
+
+static int32_t createGroupKeysFromPartKeys(SNodeList* pPartKeys, SNodeList** pOutput) {
+ SNodeList* pGroupKeys = NULL;
+ SNode* pPartKey = NULL;
+ FOREACH(pPartKey, pPartKeys) {
+ int32_t code = nodesListMakeStrictAppend(&pGroupKeys, createGroupingSetNode(pPartKey));
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyList(pGroupKeys);
+ return code;
+ }
+ }
+ *pOutput = pGroupKeys;
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) {
return TSDB_CODE_SUCCESS;
@@ -413,28 +470,34 @@ static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
return TSDB_CODE_OUT_OF_MEMORY;
}
+ pAgg->hasLastRow = pSelect->hasLastRowFunc;
+
int32_t code = TSDB_CODE_SUCCESS;
// set grouyp keys, agg funcs and having conditions
- if (NULL != pSelect->pGroupByList) {
- pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
- if (NULL == pAgg->pGroupKeys) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, fmIsAggFunc, &pAgg->pAggFuncs);
}
// rewrite the expression in subsequent clauses
- if (TSDB_CODE_SUCCESS == code) {
- code = rewriteExprsForSelect(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY);
+ if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
+ code = rewriteExprsForSelect(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY);
}
- if (TSDB_CODE_SUCCESS == code && pSelect->hasAggFuncs) {
- code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, fmIsAggFunc, &pAgg->pAggFuncs);
+ if (NULL != pSelect->pGroupByList) {
+ if (NULL != pAgg->pGroupKeys) {
+ code = nodesListStrictAppendList(pAgg->pGroupKeys, nodesCloneList(pSelect->pGroupByList));
+ } else {
+ pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
+ if (NULL == pAgg->pGroupKeys) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
}
// rewrite the expression in subsequent clauses
if (TSDB_CODE_SUCCESS == code) {
- code = rewriteExprsForSelect(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY);
+ code = rewriteExprsForSelect(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY);
}
if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
@@ -473,6 +536,10 @@ static int32_t createIndefRowsFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt
return TSDB_CODE_OUT_OF_MEMORY;
}
+ pIdfRowsFunc->isTailFunc = pSelect->hasTailFunc;
+ pIdfRowsFunc->isUniqueFunc = pSelect->hasUniqueFunc;
+ pIdfRowsFunc->isTimeLineFunc = pSelect->hasTimeLineFunc;
+
// indefinite rows functions and _select_values functions
int32_t code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, fmIsVectorFunc, &pIdfRowsFunc->pFuncs);
if (TSDB_CODE_SUCCESS == code) {
@@ -544,10 +611,7 @@ static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStm
if (pCxt->pPlanCxt->streamQuery) {
pWindow->triggerType = pCxt->pPlanCxt->triggerType;
pWindow->watermark = pCxt->pPlanCxt->watermark;
- }
-
- if (pCxt->pPlanCxt->rSmaQuery) {
- /*pWindow->filesFactor = pCxt->pPlanCxt->filesFactor;*/
+ pWindow->igExpired = pCxt->pPlanCxt->igExpired;
}
if (TSDB_CODE_SUCCESS == code) {
@@ -660,6 +724,9 @@ static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
}
SFillNode* pFillNode = (SFillNode*)(((SIntervalWindowNode*)pSelect->pWindow)->pFill);
+ if (FILL_MODE_NONE == pFillNode->mode) {
+ return TSDB_CODE_SUCCESS;
+ }
SFillLogicNode* pFill = (SFillLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FILL);
if (NULL == pFill) {
@@ -667,6 +734,10 @@ static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
}
int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_WINDOW, NULL, COLLECT_COL_TYPE_ALL, &pFill->node.pTargets);
+ if (TSDB_CODE_SUCCESS == code && NULL == pFill->node.pTargets) {
+ code = nodesListMakeStrictAppend(&pFill->node.pTargets,
+ nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0)));
+ }
pFill->mode = pFillNode->mode;
pFill->timeRange = pFillNode->timeRange;
@@ -695,7 +766,13 @@ static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
return TSDB_CODE_OUT_OF_MEMORY;
}
+ pSort->groupSort = pSelect->groupSort;
+
int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_ORDER_BY, NULL, COLLECT_COL_TYPE_ALL, &pSort->node.pTargets);
+ if (TSDB_CODE_SUCCESS == code && NULL == pSort->node.pTargets) {
+ code = nodesListMakeStrictAppend(&pSort->node.pTargets,
+ nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0)));
+ }
if (TSDB_CODE_SUCCESS == code) {
pSort->pSortKeys = nodesCloneList(pSelect->pOrderByList);
@@ -738,21 +815,8 @@ static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSel
return TSDB_CODE_OUT_OF_MEMORY;
}
- if (NULL != pSelect->pLimit) {
- pProject->limit = pSelect->pLimit->limit;
- pProject->offset = pSelect->pLimit->offset;
- } else {
- pProject->limit = -1;
- pProject->offset = -1;
- }
-
- if (NULL != pSelect->pSlimit) {
- pProject->slimit = ((SLimitNode*)pSelect->pSlimit)->limit;
- pProject->soffset = ((SLimitNode*)pSelect->pSlimit)->offset;
- } else {
- pProject->slimit = -1;
- pProject->soffset = -1;
- }
+ TSWAP(pProject->node.pLimit, pSelect->pLimit);
+ TSWAP(pProject->node.pSlimit, pSelect->pSlimit);
int32_t code = TSDB_CODE_SUCCESS;
@@ -787,6 +851,9 @@ static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pS
int32_t code =
nodesCollectColumns(pSelect, SQL_CLAUSE_PARTITION_BY, NULL, COLLECT_COL_TYPE_ALL, &pPartition->node.pTargets);
+ if (TSDB_CODE_SUCCESS == code && NULL == pPartition->node.pTargets) {
+ code = nodesListMakeStrictAppend(&pPartition->node.pTargets, nodesListGetNode(pCxt->pCurrRoot->pTargets, 0));
+ }
if (TSDB_CODE_SUCCESS == code) {
pPartition->pPartitionKeys = nodesCloneList(pSelect->pPartitionByList);
@@ -840,7 +907,12 @@ static int32_t createDistinctLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSe
return code;
}
-static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
+static int32_t createSelectWithoutFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
+ SLogicNode** pLogicNode) {
+ return createProjectLogicNode(pCxt, pSelect, pLogicNode);
+}
+
+static int32_t createSelectFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
SLogicNode* pRoot = NULL;
int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot);
if (TSDB_CODE_SUCCESS == code) {
@@ -880,6 +952,14 @@ static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele
return code;
}
+static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
+ if (NULL == pSelect->pFromTable) {
+ return createSelectWithoutFromLogicNode(pCxt, pSelect, pLogicNode);
+ } else {
+ return createSelectFromLogicNode(pCxt, pSelect, pLogicNode);
+ }
+}
+
static int32_t createSetOpRootLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, FCreateSetOpLogicNode func,
SLogicNode** pRoot) {
return createRootLogicNode(pCxt, pSetOperator, pSetOperator->precision, (FCreateLogicNode)func, pRoot);
@@ -895,6 +975,8 @@ static int32_t createSetOpSortLogicNode(SLogicPlanContext* pCxt, SSetOperator* p
return TSDB_CODE_OUT_OF_MEMORY;
}
+ TSWAP(pSort->node.pLimit, pSetOperator->pLimit);
+
int32_t code = TSDB_CODE_SUCCESS;
pSort->node.pTargets = nodesCloneList(pSetOperator->pProjectionList);
@@ -925,12 +1007,8 @@ static int32_t createSetOpProjectLogicNode(SLogicPlanContext* pCxt, SSetOperator
return TSDB_CODE_OUT_OF_MEMORY;
}
- if (NULL != pSetOperator->pLimit) {
- pProject->limit = ((SLimitNode*)pSetOperator->pLimit)->limit;
- pProject->offset = ((SLimitNode*)pSetOperator->pLimit)->offset;
- } else {
- pProject->limit = -1;
- pProject->offset = -1;
+ if (NULL == pSetOperator->pOrderByList) {
+ TSWAP(pProject->node.pLimit, pSetOperator->pLimit);
}
int32_t code = TSDB_CODE_SUCCESS;
@@ -960,6 +1038,10 @@ static int32_t createSetOpAggLogicNode(SLogicPlanContext* pCxt, SSetOperator* pS
return TSDB_CODE_OUT_OF_MEMORY;
}
+ if (NULL == pSetOperator->pOrderByList) {
+ TSWAP(pAgg->node.pSlimit, pSetOperator->pLimit);
+ }
+
int32_t code = TSDB_CODE_SUCCESS;
pAgg->pGroupKeys = nodesCloneList(pSetOperator->pProjectionList);
if (NULL == pAgg->pGroupKeys) {
@@ -1050,6 +1132,8 @@ static int32_t getMsgType(ENodeType sqlType) {
return TDMT_VND_DROP_TABLE;
case QUERY_NODE_ALTER_TABLE_STMT:
return TDMT_VND_ALTER_TABLE;
+ case QUERY_NODE_FLUSH_DATABASE_STMT:
+ return TDMT_VND_COMMIT;
default:
break;
}
@@ -1086,8 +1170,8 @@ static int32_t createDeleteScanLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* p
}
}
- if (TSDB_CODE_SUCCESS == code && NULL != pDelete->pTagIndexCond) {
- pScan->pTagCond = nodesCloneNode(pDelete->pTagIndexCond);
+ if (TSDB_CODE_SUCCESS == code && NULL != pDelete->pTagCond) {
+ pScan->pTagCond = nodesCloneNode(pDelete->pTagCond);
if (NULL == pScan->pTagCond) {
code = TSDB_CODE_OUT_OF_MEMORY;
}
@@ -1175,6 +1259,53 @@ static int32_t createDeleteLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDele
return code;
}
+static int32_t creatInsertRootLogicNode(SLogicPlanContext* pCxt, SInsertStmt* pInsert, FCreateInsertLogicNode func,
+ SLogicNode** pRoot) {
+ return createRootLogicNode(pCxt, pInsert, pInsert->precision, (FCreateLogicNode)func, pRoot);
+}
+
+static int32_t createVnodeModifLogicNodeByInsert(SLogicPlanContext* pCxt, SInsertStmt* pInsert,
+ SLogicNode** pLogicNode) {
+ SVnodeModifyLogicNode* pModify = (SVnodeModifyLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY);
+ if (NULL == pModify) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ SRealTableNode* pRealTable = (SRealTableNode*)pInsert->pTable;
+
+ pModify->modifyType = MODIFY_TABLE_TYPE_INSERT;
+ pModify->tableId = pRealTable->pMeta->uid;
+ pModify->stableId = pRealTable->pMeta->suid;
+ pModify->tableType = pRealTable->pMeta->tableType;
+ snprintf(pModify->tableFName, sizeof(pModify->tableFName), "%d.%s.%s", pCxt->pPlanCxt->acctId,
+ pRealTable->table.dbName, pRealTable->table.tableName);
+ TSWAP(pModify->pVgroupList, pRealTable->pVgroupList);
+ pModify->pInsertCols = nodesCloneList(pInsert->pCols);
+ if (NULL == pModify->pInsertCols) {
+ nodesDestroyNode((SNode*)pModify);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ *pLogicNode = (SLogicNode*)pModify;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t createInsertLogicNode(SLogicPlanContext* pCxt, SInsertStmt* pInsert, SLogicNode** pLogicNode) {
+ SLogicNode* pRoot = NULL;
+ int32_t code = createQueryLogicNode(pCxt, pInsert->pQuery, &pRoot);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = creatInsertRootLogicNode(pCxt, pInsert, createVnodeModifLogicNodeByInsert, &pRoot);
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pLogicNode = pRoot;
+ } else {
+ nodesDestroyNode((SNode*)pRoot);
+ }
+
+ return code;
+}
+
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode) {
switch (nodeType(pStmt)) {
case QUERY_NODE_SELECT_STMT:
@@ -1187,6 +1318,8 @@ static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogi
return createSetOperatorLogicNode(pCxt, (SSetOperator*)pStmt, pLogicNode);
case QUERY_NODE_DELETE_STMT:
return createDeleteLogicNode(pCxt, (SDeleteStmt*)pStmt, pLogicNode);
+ case QUERY_NODE_INSERT_STMT:
+ return createInsertLogicNode(pCxt, (SInsertStmt*)pStmt, pLogicNode);
default:
break;
}
@@ -1201,6 +1334,17 @@ static void doSetLogicNodeParent(SLogicNode* pNode, SLogicNode* pParent) {
static void setLogicNodeParent(SLogicNode* pNode) { doSetLogicNodeParent(pNode, NULL); }
+static void setLogicSubplanType(SLogicSubplan* pSubplan) {
+ if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY != nodeType(pSubplan->pNode)) {
+ pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
+ } else {
+ SVnodeModifyLogicNode* pModify = (SVnodeModifyLogicNode*)pSubplan->pNode;
+ pSubplan->subplanType = (MODIFY_TABLE_TYPE_INSERT == pModify->modifyType && NULL != pModify->node.pChildren)
+ ? SUBPLAN_TYPE_SCAN
+ : SUBPLAN_TYPE_MODIFY;
+ }
+}
+
int32_t createLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
SLogicPlanContext cxt = {.pPlanCxt = pCxt};
@@ -1215,11 +1359,7 @@ int32_t createLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
int32_t code = createQueryLogicNode(&cxt, pCxt->pAstRoot, &pSubplan->pNode);
if (TSDB_CODE_SUCCESS == code) {
setLogicNodeParent(pSubplan->pNode);
- if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY == nodeType(pSubplan->pNode)) {
- pSubplan->subplanType = SUBPLAN_TYPE_MODIFY;
- } else {
- pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
- }
+ setLogicSubplanType(pSubplan);
}
if (TSDB_CODE_SUCCESS == code) {
diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c
index 5249bd913d4208c77a540133be7ed192aa24b0e9..7915f4a138f587e89304c2fedb7f8471389029b1 100644
--- a/source/libs/planner/src/planOptimizer.c
+++ b/source/libs/planner/src/planOptimizer.c
@@ -15,15 +15,13 @@
#include "filter.h"
#include "functionMgt.h"
-#include "index.h"
#include "planInt.h"
#include "ttime.h"
#define OPTIMIZE_FLAG_MASK(n) (1 << n)
-#define OPTIMIZE_FLAG_OSD OPTIMIZE_FLAG_MASK(0)
-#define OPTIMIZE_FLAG_CPD OPTIMIZE_FLAG_MASK(1)
-#define OPTIMIZE_FLAG_OPK OPTIMIZE_FLAG_MASK(2)
+#define OPTIMIZE_FLAG_SCAN_PATH OPTIMIZE_FLAG_MASK(0)
+#define OPTIMIZE_FLAG_PUSH_DOWN_CONDE OPTIMIZE_FLAG_MASK(1)
#define OPTIMIZE_FLAG_SET_MASK(val, mask) (val) |= (mask)
#define OPTIMIZE_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0)
@@ -77,46 +75,67 @@ static SLogicNode* optFindPossibleNode(SLogicNode* pNode, FMayBeOptimized func)
return NULL;
}
-EDealRes osdHaveNormalColImpl(SNode* pNode, void* pContext) {
+static void optResetParent(SLogicNode* pNode) {
+ SNode* pChild = NULL;
+ FOREACH(pChild, pNode->pChildren) { ((SLogicNode*)pChild)->pParent = pNode; }
+}
+
+static EDealRes optRebuildTbanme(SNode** pNode, void* pContext) {
+ if (QUERY_NODE_COLUMN == nodeType(*pNode) && COLUMN_TYPE_TBNAME == ((SColumnNode*)*pNode)->colType) {
+ SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ *(int32_t*)pContext = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
+ }
+ strcpy(pFunc->functionName, "tbname");
+ pFunc->funcType = FUNCTION_TYPE_TBNAME;
+ pFunc->node.resType = ((SColumnNode*)*pNode)->node.resType;
+ nodesDestroyNode(*pNode);
+ *pNode = (SNode*)pFunc;
+ return DEAL_RES_IGNORE_CHILD;
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+EDealRes scanPathOptHaveNormalColImpl(SNode* pNode, void* pContext) {
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
- *((bool*)pContext) = (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType);
+ // *((bool*)pContext) = (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType);
+ *((bool*)pContext) = true;
return *((bool*)pContext) ? DEAL_RES_END : DEAL_RES_IGNORE_CHILD;
}
return DEAL_RES_CONTINUE;
}
-static bool osdHaveNormalCol(SNodeList* pList) {
+static bool scanPathOptHaveNormalCol(SNodeList* pList) {
bool res = false;
- nodesWalkExprsPostOrder(pList, osdHaveNormalColImpl, &res);
+ nodesWalkExprsPostOrder(pList, scanPathOptHaveNormalColImpl, &res);
return res;
}
-static bool osdMayBeOptimized(SLogicNode* pNode) {
- if (OPTIMIZE_FLAG_TEST_MASK(pNode->optimizedFlag, OPTIMIZE_FLAG_OSD)) {
+static bool scanPathOptMayBeOptimized(SLogicNode* pNode) {
+ if (OPTIMIZE_FLAG_TEST_MASK(pNode->optimizedFlag, OPTIMIZE_FLAG_SCAN_PATH)) {
return false;
}
if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pNode)) {
return false;
}
- // todo: release after function splitting
- if (TSDB_SUPER_TABLE == ((SScanLogicNode*)pNode)->tableType &&
- SCAN_TYPE_STREAM != ((SScanLogicNode*)pNode)->scanType) {
- return false;
- }
if (NULL == pNode->pParent || (QUERY_NODE_LOGIC_PLAN_WINDOW != nodeType(pNode->pParent) &&
QUERY_NODE_LOGIC_PLAN_AGG != nodeType(pNode->pParent) &&
QUERY_NODE_LOGIC_PLAN_PARTITION != nodeType(pNode->pParent))) {
return false;
}
- if (QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent) ||
+ if ((QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent) && WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode->pParent)->winType) ||
(QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode->pParent) && pNode->pParent->pParent &&
- QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent->pParent))) {
+ QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode->pParent->pParent) && WINDOW_TYPE_INTERVAL == ((SWindowLogicNode*)pNode->pParent)->winType)) {
return true;
}
- return !osdHaveNormalCol(((SAggLogicNode*)pNode->pParent)->pGroupKeys);
+ if (QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode->pParent)) {
+ return !scanPathOptHaveNormalCol(((SAggLogicNode*)pNode->pParent)->pGroupKeys);
+ }
+ return false;
}
-static SNodeList* osdGetAllFuncs(SLogicNode* pNode) {
+static SNodeList* scanPathOptGetAllFuncs(SLogicNode* pNode) {
switch (nodeType(pNode)) {
case QUERY_NODE_LOGIC_PLAN_WINDOW:
return ((SWindowLogicNode*)pNode)->pFuncs;
@@ -128,7 +147,7 @@ static SNodeList* osdGetAllFuncs(SLogicNode* pNode) {
return NULL;
}
-static bool needOptimizeDataRequire(const SFunctionNode* pFunc) {
+static bool scanPathOptNeedOptimizeDataRequire(const SFunctionNode* pFunc) {
if (!fmIsSpecialDataRequiredFunc(pFunc->funcId)) {
return false;
}
@@ -141,7 +160,7 @@ static bool needOptimizeDataRequire(const SFunctionNode* pFunc) {
return true;
}
-static bool needOptimizeDynamicScan(const SFunctionNode* pFunc) {
+static bool scanPathOptNeedDynOptimize(const SFunctionNode* pFunc) {
if (!fmIsDynamicScanOptimizedFunc(pFunc->funcId)) {
return false;
}
@@ -154,17 +173,17 @@ static bool needOptimizeDynamicScan(const SFunctionNode* pFunc) {
return true;
}
-static int32_t osdGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSdrFuncs, SNodeList** pDsoFuncs) {
- SNodeList* pAllFuncs = osdGetAllFuncs(pScan->node.pParent);
+static int32_t scanPathOptGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSdrFuncs, SNodeList** pDsoFuncs) {
+ SNodeList* pAllFuncs = scanPathOptGetAllFuncs(pScan->node.pParent);
SNodeList* pTmpSdrFuncs = NULL;
SNodeList* pTmpDsoFuncs = NULL;
SNode* pFunc = NULL;
bool otherFunc = false;
FOREACH(pFunc, pAllFuncs) {
int32_t code = TSDB_CODE_SUCCESS;
- if (needOptimizeDataRequire((SFunctionNode*)pFunc)) {
+ if (scanPathOptNeedOptimizeDataRequire((SFunctionNode*)pFunc)) {
code = nodesListMakeStrictAppend(&pTmpSdrFuncs, nodesCloneNode(pFunc));
- } else if (needOptimizeDynamicScan((SFunctionNode*)pFunc)) {
+ } else if (scanPathOptNeedDynOptimize((SFunctionNode*)pFunc)) {
code = nodesListMakeStrictAppend(&pTmpDsoFuncs, nodesCloneNode(pFunc));
} else {
otherFunc = true;
@@ -185,15 +204,15 @@ static int32_t osdGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSdrFuncs,
return TSDB_CODE_SUCCESS;
}
-static int32_t osdMatch(SOptimizeContext* pCxt, SLogicNode* pLogicNode, SOsdInfo* pInfo) {
- pInfo->pScan = (SScanLogicNode*)optFindPossibleNode(pLogicNode, osdMayBeOptimized);
+static int32_t scanPathOptMatch(SOptimizeContext* pCxt, SLogicNode* pLogicNode, SOsdInfo* pInfo) {
+ pInfo->pScan = (SScanLogicNode*)optFindPossibleNode(pLogicNode, scanPathOptMayBeOptimized);
if (NULL == pInfo->pScan) {
return TSDB_CODE_SUCCESS;
}
- return osdGetRelatedFuncs(pInfo->pScan, &pInfo->pSdrFuncs, &pInfo->pDsoFuncs);
+ return scanPathOptGetRelatedFuncs(pInfo->pScan, &pInfo->pSdrFuncs, &pInfo->pDsoFuncs);
}
-static EFuncDataRequired osdPromoteDataRequired(EFuncDataRequired l, EFuncDataRequired r) {
+static EFuncDataRequired scanPathOptPromoteDataRequired(EFuncDataRequired l, EFuncDataRequired r) {
switch (l) {
case FUNC_DATA_REQUIRED_DATA_LOAD:
return l;
@@ -207,19 +226,19 @@ static EFuncDataRequired osdPromoteDataRequired(EFuncDataRequired l, EFuncDataRe
return r;
}
-static int32_t osdGetDataRequired(SNodeList* pFuncs) {
+static int32_t scanPathOptGetDataRequired(SNodeList* pFuncs) {
if (NULL == pFuncs) {
return FUNC_DATA_REQUIRED_DATA_LOAD;
}
EFuncDataRequired dataRequired = FUNC_DATA_REQUIRED_FILTEROUT;
SNode* pFunc = NULL;
FOREACH(pFunc, pFuncs) {
- dataRequired = osdPromoteDataRequired(dataRequired, fmFuncDataRequired((SFunctionNode*)pFunc, NULL));
+ dataRequired = scanPathOptPromoteDataRequired(dataRequired, fmFuncDataRequired((SFunctionNode*)pFunc, NULL));
}
return dataRequired;
}
-static void setScanWindowInfo(SScanLogicNode* pScan) {
+static void scanPathOptSetScanWin(SScanLogicNode* pScan) {
SLogicNode* pParent = pScan->node.pParent;
if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pParent) && pParent->pParent &&
QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pParent->pParent)) {
@@ -233,28 +252,27 @@ static void setScanWindowInfo(SScanLogicNode* pScan) {
pScan->slidingUnit = ((SWindowLogicNode*)pParent)->slidingUnit;
pScan->triggerType = ((SWindowLogicNode*)pParent)->triggerType;
pScan->watermark = ((SWindowLogicNode*)pParent)->watermark;
- pScan->tsColId = ((SColumnNode*)((SWindowLogicNode*)pParent)->pTspk)->colId;
- pScan->filesFactor = ((SWindowLogicNode*)pParent)->filesFactor;
+ pScan->igExpired = ((SWindowLogicNode*)pParent)->igExpired;
}
}
-static int32_t osdOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+static int32_t scanPathOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
SOsdInfo info = {0};
- int32_t code = osdMatch(pCxt, pLogicSubplan->pNode, &info);
+ int32_t code = scanPathOptMatch(pCxt, pLogicSubplan->pNode, &info);
if (TSDB_CODE_SUCCESS == code && info.pScan) {
- setScanWindowInfo((SScanLogicNode*)info.pScan);
+ scanPathOptSetScanWin((SScanLogicNode*)info.pScan);
}
if (TSDB_CODE_SUCCESS == code && (NULL != info.pDsoFuncs || NULL != info.pSdrFuncs)) {
- info.pScan->dataRequired = osdGetDataRequired(info.pSdrFuncs);
+ info.pScan->dataRequired = scanPathOptGetDataRequired(info.pSdrFuncs);
info.pScan->pDynamicScanFuncs = info.pDsoFuncs;
- OPTIMIZE_FLAG_SET_MASK(info.pScan->node.optimizedFlag, OPTIMIZE_FLAG_OSD);
+ OPTIMIZE_FLAG_SET_MASK(info.pScan->node.optimizedFlag, OPTIMIZE_FLAG_SCAN_PATH);
pCxt->optimized = true;
}
nodesDestroyList(info.pSdrFuncs);
return code;
}
-static int32_t cpdMergeCond(SNode** pDst, SNode** pSrc) {
+static int32_t pushDownCondOptMergeCond(SNode** pDst, SNode** pSrc) {
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION);
if (NULL == pLogicCond) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -275,86 +293,74 @@ static int32_t cpdMergeCond(SNode** pDst, SNode** pSrc) {
return code;
}
-static int32_t cpdCondAppend(SNode** pCond, SNode** pAdditionalCond) {
+static int32_t pushDownCondOptAppendCond(SNode** pCond, SNode** pAdditionalCond) {
if (NULL == *pCond) {
TSWAP(*pCond, *pAdditionalCond);
return TSDB_CODE_SUCCESS;
}
int32_t code = TSDB_CODE_SUCCESS;
- if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pCond)) {
+ if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pCond) &&
+ LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pCond)->condType) {
code = nodesListAppend(((SLogicConditionNode*)*pCond)->pParameterList, *pAdditionalCond);
if (TSDB_CODE_SUCCESS == code) {
*pAdditionalCond = NULL;
}
} else {
- code = cpdMergeCond(pCond, pAdditionalCond);
+ code = pushDownCondOptMergeCond(pCond, pAdditionalCond);
}
return code;
}
-static int32_t cpdCalcTimeRange(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pOtherCond) {
- bool isStrict = false;
- int32_t code = filterGetTimeRange(*pPrimaryKeyCond, &pScan->scanRange, &isStrict);
- if (TSDB_CODE_SUCCESS == code) {
- if (isStrict) {
- nodesDestroyNode(*pPrimaryKeyCond);
- } else {
- code = cpdCondAppend(pOtherCond, pPrimaryKeyCond);
+static int32_t pushDownCondOptCalcTimeRange(SOptimizeContext* pCxt, SScanLogicNode* pScan, SNode** pPrimaryKeyCond,
+ SNode** pOtherCond) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if (pCxt->pPlanCxt->topicQuery || pCxt->pPlanCxt->streamQuery) {
+ code = pushDownCondOptAppendCond(pOtherCond, pPrimaryKeyCond);
+ } else {
+ bool isStrict = false;
+ code = filterGetTimeRange(*pPrimaryKeyCond, &pScan->scanRange, &isStrict);
+ if (TSDB_CODE_SUCCESS == code) {
+ if (isStrict) {
+ nodesDestroyNode(*pPrimaryKeyCond);
+ } else {
+ code = pushDownCondOptAppendCond(pOtherCond, pPrimaryKeyCond);
+ }
+ *pPrimaryKeyCond = NULL;
}
- *pPrimaryKeyCond = NULL;
}
return code;
}
-static int32_t cpdApplyTagIndex(SScanLogicNode* pScan, SNode** pTagCond, SNode** pOtherCond) {
- int32_t code = TSDB_CODE_SUCCESS;
- SIdxFltStatus idxStatus = idxGetFltStatus(*pTagCond);
- switch (idxStatus) {
- case SFLT_NOT_INDEX:
- code = cpdCondAppend(pOtherCond, pTagCond);
- break;
- case SFLT_COARSE_INDEX:
- pScan->pTagCond = nodesCloneNode(*pTagCond);
- if (NULL == pScan->pTagCond) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- break;
- }
- code = cpdCondAppend(pOtherCond, pTagCond);
- break;
- case SFLT_ACCURATE_INDEX:
- pScan->pTagCond = *pTagCond;
- *pTagCond = NULL;
- break;
- default:
- code = TSDB_CODE_FAILED;
- break;
- }
+static int32_t pushDownCondOptRebuildTbanme(SNode** pTagCond) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ nodesRewriteExpr(pTagCond, optRebuildTbanme, &code);
return code;
}
-static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode* pScan) {
- if (NULL == pScan->node.pConditions || OPTIMIZE_FLAG_TEST_MASK(pScan->node.optimizedFlag, OPTIMIZE_FLAG_CPD) ||
+static int32_t pushDownCondOptDealScan(SOptimizeContext* pCxt, SScanLogicNode* pScan) {
+ if (NULL == pScan->node.pConditions ||
+ OPTIMIZE_FLAG_TEST_MASK(pScan->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE) ||
TSDB_SYSTEM_TABLE == pScan->tableType) {
return TSDB_CODE_SUCCESS;
}
SNode* pPrimaryKeyCond = NULL;
- SNode* pTagCond = NULL;
SNode* pOtherCond = NULL;
- int32_t code = nodesPartitionCond(&pScan->node.pConditions, &pPrimaryKeyCond, &pTagCond, &pOtherCond);
- if (TSDB_CODE_SUCCESS == code && NULL != pPrimaryKeyCond) {
- code = cpdCalcTimeRange(pScan, &pPrimaryKeyCond, &pOtherCond);
+ int32_t code = nodesPartitionCond(&pScan->node.pConditions, &pPrimaryKeyCond, &pScan->pTagIndexCond, &pScan->pTagCond,
+ &pOtherCond);
+ if (TSDB_CODE_SUCCESS == code && NULL != pScan->pTagCond) {
+ code = pushDownCondOptRebuildTbanme(&pScan->pTagCond);
}
- if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) {
- code = cpdApplyTagIndex(pScan, &pTagCond, &pOtherCond);
+ if (TSDB_CODE_SUCCESS == code && NULL != pPrimaryKeyCond) {
+ code = pushDownCondOptCalcTimeRange(pCxt, pScan, &pPrimaryKeyCond, &pOtherCond);
}
if (TSDB_CODE_SUCCESS == code) {
pScan->node.pConditions = pOtherCond;
}
if (TSDB_CODE_SUCCESS == code) {
- OPTIMIZE_FLAG_SET_MASK(pScan->node.optimizedFlag, OPTIMIZE_FLAG_CPD);
+ OPTIMIZE_FLAG_SET_MASK(pScan->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
pCxt->optimized = true;
} else {
nodesDestroyNode(pPrimaryKeyCond);
@@ -364,7 +370,7 @@ static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode*
return code;
}
-static bool cpdBelongThisTable(SNode* pCondCol, SNodeList* pTableCols) {
+static bool pushDownCondOptBelongThisTable(SNode* pCondCol, SNodeList* pTableCols) {
SNode* pTableCol = NULL;
FOREACH(pTableCol, pTableCols) {
if (nodesEqualNode(pCondCol, pTableCol)) {
@@ -374,12 +380,12 @@ static bool cpdBelongThisTable(SNode* pCondCol, SNodeList* pTableCols) {
return false;
}
-static EDealRes cpdIsMultiTableCondImpl(SNode* pNode, void* pContext) {
+static EDealRes pushDownCondOptIsCrossTableCond(SNode* pNode, void* pContext) {
SCpdIsMultiTableCondCxt* pCxt = pContext;
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
- if (cpdBelongThisTable(pNode, pCxt->pLeftCols)) {
+ if (pushDownCondOptBelongThisTable(pNode, pCxt->pLeftCols)) {
pCxt->havaLeftCol = true;
- } else if (cpdBelongThisTable(pNode, pCxt->pRightCols)) {
+ } else if (pushDownCondOptBelongThisTable(pNode, pCxt->pRightCols)) {
pCxt->haveRightCol = true;
}
return pCxt->havaLeftCol && pCxt->haveRightCol ? DEAL_RES_END : DEAL_RES_CONTINUE;
@@ -387,10 +393,11 @@ static EDealRes cpdIsMultiTableCondImpl(SNode* pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
-static ECondAction cpdCondAction(EJoinType joinType, SNodeList* pLeftCols, SNodeList* pRightCols, SNode* pNode) {
+static ECondAction pushDownCondOptGetCondAction(EJoinType joinType, SNodeList* pLeftCols, SNodeList* pRightCols,
+ SNode* pNode) {
SCpdIsMultiTableCondCxt cxt = {
.pLeftCols = pLeftCols, .pRightCols = pRightCols, .havaLeftCol = false, .haveRightCol = false};
- nodesWalkExpr(pNode, cpdIsMultiTableCondImpl, &cxt);
+ nodesWalkExpr(pNode, pushDownCondOptIsCrossTableCond, &cxt);
return (JOIN_TYPE_INNER != joinType
? COND_ACTION_STAY
: (cxt.havaLeftCol && cxt.haveRightCol
@@ -398,8 +405,8 @@ static ECondAction cpdCondAction(EJoinType joinType, SNodeList* pLeftCols, SNode
: (cxt.havaLeftCol ? COND_ACTION_PUSH_LEFT_CHILD : COND_ACTION_PUSH_RIGHT_CHILD)));
}
-static int32_t cpdPartitionLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
- SNode** pRightChildCond) {
+static int32_t pushDownCondOptPartLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
+ SNode** pRightChildCond) {
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pJoin->node.pConditions;
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
return TSDB_CODE_SUCCESS;
@@ -415,7 +422,7 @@ static int32_t cpdPartitionLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNo
SNodeList* pRemainConds = NULL;
SNode* pCond = NULL;
FOREACH(pCond, pLogicCond->pParameterList) {
- ECondAction condAction = cpdCondAction(pJoin->joinType, pLeftCols, pRightCols, pCond);
+ ECondAction condAction = pushDownCondOptGetCondAction(pJoin->joinType, pLeftCols, pRightCols, pCond);
if (COND_ACTION_PUSH_JOIN == condAction) {
code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond));
} else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) {
@@ -467,11 +474,12 @@ static int32_t cpdPartitionLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNo
return code;
}
-static int32_t cpdPartitionOpCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
- SNode** pRightChildCond) {
+static int32_t pushDownCondOptPartOpCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
+ SNode** pRightChildCond) {
SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets;
SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets;
- ECondAction condAction = cpdCondAction(pJoin->joinType, pLeftCols, pRightCols, pJoin->node.pConditions);
+ ECondAction condAction =
+ pushDownCondOptGetCondAction(pJoin->joinType, pLeftCols, pRightCols, pJoin->node.pConditions);
if (COND_ACTION_STAY == condAction) {
return TSDB_CODE_SUCCESS;
} else if (COND_ACTION_PUSH_JOIN == condAction) {
@@ -485,35 +493,36 @@ static int32_t cpdPartitionOpCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode*
return TSDB_CODE_SUCCESS;
}
-static int32_t cpdPartitionCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
- SNode** pRightChildCond) {
+static int32_t pushDownCondOptPartCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond,
+ SNode** pRightChildCond) {
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->node.pConditions)) {
- return cpdPartitionLogicCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond);
+ return pushDownCondOptPartLogicCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond);
} else {
- return cpdPartitionOpCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond);
+ return pushDownCondOptPartOpCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond);
}
}
-static int32_t cpdPushCondToOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode** pCond) {
- return cpdCondAppend(&pJoin->pOnConditions, pCond);
+static int32_t pushDownCondOptPushCondToOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode** pCond) {
+ return pushDownCondOptAppendCond(&pJoin->pOnConditions, pCond);
}
-static int32_t cpdPushCondToScan(SOptimizeContext* pCxt, SScanLogicNode* pScan, SNode** pCond) {
- return cpdCondAppend(&pScan->node.pConditions, pCond);
+static int32_t pushDownCondOptPushCondToScan(SOptimizeContext* pCxt, SScanLogicNode* pScan, SNode** pCond) {
+ return pushDownCondOptAppendCond(&pScan->node.pConditions, pCond);
}
-static int32_t cpdPushCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild, SNode** pCond) {
- switch (nodeType(pChild)) {
- case QUERY_NODE_LOGIC_PLAN_SCAN:
- return cpdPushCondToScan(pCxt, (SScanLogicNode*)pChild, pCond);
- default:
- break;
- }
- planError("cpdPushCondToChild failed, invalid logic plan node %s", nodesNodeName(nodeType(pChild)));
- return TSDB_CODE_PLAN_INTERNAL_ERROR;
+static int32_t pushDownCondOptPushCondToProject(SOptimizeContext* pCxt, SProjectLogicNode* pProject, SNode** pCond) {
+ return pushDownCondOptAppendCond(&pProject->node.pConditions, pCond);
+}
+
+static int32_t pushDownCondOptPushCondToJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode** pCond) {
+ return pushDownCondOptAppendCond(&pJoin->node.pConditions, pCond);
+}
+
+static int32_t pushDownCondOptPushCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild, SNode** pCond) {
+ return pushDownCondOptAppendCond(&pChild->pConditions, pCond);
}
-static bool cpdIsPrimaryKey(SNode* pNode, SNodeList* pTableCols) {
+static bool pushDownCondOptIsPriKey(SNode* pNode, SNodeList* pTableCols) {
if (QUERY_NODE_COLUMN != nodeType(pNode)) {
return false;
}
@@ -521,10 +530,10 @@ static bool cpdIsPrimaryKey(SNode* pNode, SNodeList* pTableCols) {
if (PRIMARYKEY_TIMESTAMP_COL_ID != pCol->colId) {
return false;
}
- return cpdBelongThisTable(pNode, pTableCols);
+ return pushDownCondOptBelongThisTable(pNode, pTableCols);
}
-static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
+static bool pushDownCondOptIsPriKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
if (QUERY_NODE_OPERATOR != nodeType(pCond)) {
return false;
}
@@ -536,15 +545,15 @@ static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets;
SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets;
- if (cpdIsPrimaryKey(pOper->pLeft, pLeftCols)) {
- return cpdIsPrimaryKey(pOper->pRight, pRightCols);
- } else if (cpdIsPrimaryKey(pOper->pLeft, pRightCols)) {
- return cpdIsPrimaryKey(pOper->pRight, pLeftCols);
+ if (pushDownCondOptIsPriKey(pOper->pLeft, pLeftCols)) {
+ return pushDownCondOptIsPriKey(pOper->pRight, pRightCols);
+ } else if (pushDownCondOptIsPriKey(pOper->pLeft, pRightCols)) {
+ return pushDownCondOptIsPriKey(pOper->pRight, pLeftCols);
}
return false;
}
-static bool cpdContainPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
+static bool pushDownCondOptContainPriKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pCond)) {
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pCond;
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
@@ -553,54 +562,129 @@ static bool cpdContainPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
bool hasPrimaryKeyEqualCond = false;
SNode* pCond = NULL;
FOREACH(pCond, pLogicCond->pParameterList) {
- if (cpdContainPrimaryKeyEqualCond(pJoin, pCond)) {
+ if (pushDownCondOptContainPriKeyEqualCond(pJoin, pCond)) {
hasPrimaryKeyEqualCond = true;
break;
}
}
return hasPrimaryKeyEqualCond;
} else {
- return cpdIsPrimaryKeyEqualCond(pJoin, pCond);
+ return pushDownCondOptIsPriKeyEqualCond(pJoin, pCond);
}
}
-static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
+static int32_t pushDownCondOptCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
if (NULL == pJoin->pOnConditions) {
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
}
- if (!cpdContainPrimaryKeyEqualCond(pJoin, pJoin->pOnConditions)) {
+ if (!pushDownCondOptContainPriKeyEqualCond(pJoin, pJoin->pOnConditions)) {
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
}
return TSDB_CODE_SUCCESS;
}
-static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
- if (OPTIMIZE_FLAG_TEST_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_CPD)) {
+static int32_t pushDownCondOptPartJoinOnCondLogicCond(SJoinLogicNode* pJoin, SNode** ppMergeCond, SNode** ppOnCond) {
+ SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(pJoin->pOnConditions);
+
+ int32_t code = TSDB_CODE_SUCCESS;
+ SNodeList* pOnConds = NULL;
+ SNode* pCond = NULL;
+ FOREACH(pCond, pLogicCond->pParameterList) {
+ if (pushDownCondOptIsPriKeyEqualCond(pJoin, pCond)) {
+ *ppMergeCond = nodesCloneNode(pCond);
+ } else {
+ code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond));
+ }
+ }
+
+ SNode* pTempOnCond = NULL;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesMergeConds(&pTempOnCond, &pOnConds);
+ }
+
+ if (TSDB_CODE_SUCCESS == code && NULL != *ppMergeCond) {
+ *ppOnCond = pTempOnCond;
+ nodesDestroyNode(pJoin->pOnConditions);
+ pJoin->pOnConditions = NULL;
+ return TSDB_CODE_SUCCESS;
+ } else {
+ nodesDestroyList(pOnConds);
+ nodesDestroyNode(pTempOnCond);
+ return TSDB_CODE_PLAN_INTERNAL_ERROR;
+ }
+}
+
+static int32_t pushDownCondOptPartJoinOnCond(SJoinLogicNode* pJoin, SNode** ppMergeCond, SNode** ppOnCond) {
+ if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions) &&
+ LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)(pJoin->pOnConditions))->condType) {
+ return pushDownCondOptPartJoinOnCondLogicCond(pJoin, ppMergeCond, ppOnCond);
+ }
+
+ if (pushDownCondOptIsPriKeyEqualCond(pJoin, pJoin->pOnConditions)) {
+ *ppMergeCond = nodesCloneNode(pJoin->pOnConditions);
+ *ppOnCond = NULL;
+ nodesDestroyNode(pJoin->pOnConditions);
+ pJoin->pOnConditions = NULL;
+ return TSDB_CODE_SUCCESS;
+ } else {
+ return TSDB_CODE_PLAN_INTERNAL_ERROR;
+ }
+}
+
+static int32_t pushDownCondOptJoinExtractMergeCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
+ int32_t code = pushDownCondOptCheckJoinOnCond(pCxt, pJoin);
+ SNode* pJoinMergeCond = NULL;
+ SNode* pJoinOnCond = NULL;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = pushDownCondOptPartJoinOnCond(pJoin, &pJoinMergeCond, &pJoinOnCond);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ pJoin->pMergeCondition = pJoinMergeCond;
+ pJoin->pOnConditions = pJoinOnCond;
+ } else {
+ nodesDestroyNode(pJoinMergeCond);
+ nodesDestroyNode(pJoinOnCond);
+ }
+ return code;
+}
+
+static int32_t pushDownCondOptDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
+ if (OPTIMIZE_FLAG_TEST_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE)) {
return TSDB_CODE_SUCCESS;
}
if (NULL == pJoin->node.pConditions) {
- return cpdCheckJoinOnCond(pCxt, pJoin);
+ int32_t code = pushDownCondOptJoinExtractMergeCond(pCxt, pJoin);
+ if (TSDB_CODE_SUCCESS == code) {
+ OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
+ pCxt->optimized = true;
+ }
+ return code;
}
SNode* pOnCond = NULL;
SNode* pLeftChildCond = NULL;
SNode* pRightChildCond = NULL;
- int32_t code = cpdPartitionCond(pJoin, &pOnCond, &pLeftChildCond, &pRightChildCond);
+ int32_t code = pushDownCondOptPartCond(pJoin, &pOnCond, &pLeftChildCond, &pRightChildCond);
if (TSDB_CODE_SUCCESS == code && NULL != pOnCond) {
- code = cpdPushCondToOnCond(pCxt, pJoin, &pOnCond);
+ code = pushDownCondOptPushCondToOnCond(pCxt, pJoin, &pOnCond);
}
if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) {
- code = cpdPushCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond);
+ code =
+ pushDownCondOptPushCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond);
}
if (TSDB_CODE_SUCCESS == code && NULL != pRightChildCond) {
- code = cpdPushCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1), &pRightChildCond);
+ code =
+ pushDownCondOptPushCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1), &pRightChildCond);
}
if (TSDB_CODE_SUCCESS == code) {
- OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_CPD);
+ code = pushDownCondOptJoinExtractMergeCond(pCxt, pJoin);
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
pCxt->optimized = true;
- code = cpdCheckJoinOnCond(pCxt, pJoin);
} else {
nodesDestroyNode(pOnCond);
nodesDestroyNode(pLeftChildCond);
@@ -610,22 +694,263 @@ static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoi
return code;
}
-static int32_t cpdPushAggCondition(SOptimizeContext* pCxt, SAggLogicNode* pAgg) {
- // todo
+typedef struct SPartAggCondContext {
+ SAggLogicNode* pAgg;
+ bool hasAggFunc;
+} SPartAggCondContext;
+
+static EDealRes partAggCondHasAggFuncImpl(SNode* pNode, void* pContext) {
+ SPartAggCondContext* pCxt = pContext;
+ if (QUERY_NODE_COLUMN == nodeType(pNode)) {
+ SNode* pAggFunc = NULL;
+ FOREACH(pAggFunc, pCxt->pAgg->pAggFuncs) {
+ if (strcmp(((SColumnNode*)pNode)->colName, ((SFunctionNode*)pAggFunc)->node.aliasName) == 0) {
+ pCxt->hasAggFunc = true;
+ return DEAL_RES_END;
+ }
+ }
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+static int32_t partitionAggCondHasAggFunc(SAggLogicNode* pAgg, SNode* pCond) {
+ SPartAggCondContext cxt = {.pAgg = pAgg, .hasAggFunc = false};
+ nodesWalkExpr(pCond, partAggCondHasAggFuncImpl, &cxt);
+ return cxt.hasAggFunc;
+}
+
+static int32_t partitionAggCondConj(SAggLogicNode* pAgg, SNode** ppAggFuncCond, SNode** ppGroupKeyCond) {
+ SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pAgg->node.pConditions;
+ int32_t code = TSDB_CODE_SUCCESS;
+
+ SNodeList* pAggFuncConds = NULL;
+ SNodeList* pGroupKeyConds = NULL;
+ SNode* pCond = NULL;
+ FOREACH(pCond, pLogicCond->pParameterList) {
+ if (partitionAggCondHasAggFunc(pAgg, pCond)) {
+ code = nodesListMakeAppend(&pAggFuncConds, nodesCloneNode(pCond));
+ } else {
+ code = nodesListMakeAppend(&pGroupKeyConds, nodesCloneNode(pCond));
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+
+ SNode* pTempAggFuncCond = NULL;
+ SNode* pTempGroupKeyCond = NULL;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesMergeConds(&pTempAggFuncCond, &pAggFuncConds);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesMergeConds(&pTempGroupKeyCond, &pGroupKeyConds);
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *ppAggFuncCond = pTempAggFuncCond;
+ *ppGroupKeyCond = pTempGroupKeyCond;
+ } else {
+ nodesDestroyList(pAggFuncConds);
+ nodesDestroyList(pGroupKeyConds);
+ nodesDestroyNode(pTempAggFuncCond);
+ nodesDestroyNode(pTempGroupKeyCond);
+ }
+ pAgg->node.pConditions = NULL;
+ return code;
+}
+
+static int32_t partitionAggCond(SAggLogicNode* pAgg, SNode** ppAggFunCond, SNode** ppGroupKeyCond) {
+ SNode* pAggNodeCond = pAgg->node.pConditions;
+ if (QUERY_NODE_LOGIC_CONDITION == nodeType(pAggNodeCond) &&
+ LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)(pAggNodeCond))->condType) {
+ return partitionAggCondConj(pAgg, ppAggFunCond, ppGroupKeyCond);
+ }
+ if (partitionAggCondHasAggFunc(pAgg, pAggNodeCond)) {
+ *ppAggFunCond = pAggNodeCond;
+ } else {
+ *ppGroupKeyCond = pAggNodeCond;
+ }
+ pAgg->node.pConditions = NULL;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t pushCondToAggCond(SOptimizeContext* pCxt, SAggLogicNode* pAgg, SNode** pAggFuncCond) {
+ pushDownCondOptAppendCond(&pAgg->node.pConditions, pAggFuncCond);
return TSDB_CODE_SUCCESS;
}
-static int32_t cpdPushCondition(SOptimizeContext* pCxt, SLogicNode* pLogicNode) {
+typedef struct SRewriteAggGroupKeyCondContext {
+ SAggLogicNode* pAgg;
+ int32_t errCode;
+} SRewriteAggGroupKeyCondContext;
+
+static EDealRes rewriteAggGroupKeyCondForPushDownImpl(SNode** pNode, void* pContext) {
+ SRewriteAggGroupKeyCondContext* pCxt = pContext;
+ SAggLogicNode* pAgg = pCxt->pAgg;
+ if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
+ SNode* pGroupKey = NULL;
+ FOREACH(pGroupKey, pAgg->pGroupKeys) {
+ SNode* pGroup = NULL;
+ FOREACH(pGroup, ((SGroupingSetNode*)pGroupKey)->pParameterList) {
+ if (0 == strcmp(((SExprNode*)pGroup)->aliasName, ((SColumnNode*)(*pNode))->colName)) {
+ SNode* pExpr = nodesCloneNode(pGroup);
+ if (pExpr == NULL) {
+ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
+ }
+ nodesDestroyNode(*pNode);
+ *pNode = pExpr;
+ return DEAL_RES_IGNORE_CHILD;
+ }
+ }
+ }
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+static int32_t rewriteAggGroupKeyCondForPushDown(SOptimizeContext* pCxt, SAggLogicNode* pAgg, SNode* pGroupKeyCond) {
+ SRewriteAggGroupKeyCondContext cxt = {.pAgg = pAgg, .errCode = TSDB_CODE_SUCCESS};
+ nodesRewriteExpr(&pGroupKeyCond, rewriteAggGroupKeyCondForPushDownImpl, &cxt);
+ return cxt.errCode;
+}
+
+static int32_t pushDownCondOptDealAgg(SOptimizeContext* pCxt, SAggLogicNode* pAgg) {
+ if (NULL == pAgg->node.pConditions ||
+ OPTIMIZE_FLAG_TEST_MASK(pAgg->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE)) {
+ return TSDB_CODE_SUCCESS;
+ }
+ // TODO: remove it after full implementation of pushing down to child
+ if (1 != LIST_LENGTH(pAgg->node.pChildren)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SNode* pAggFuncCond = NULL;
+ SNode* pGroupKeyCond = NULL;
+ int32_t code = partitionAggCond(pAgg, &pAggFuncCond, &pGroupKeyCond);
+ if (TSDB_CODE_SUCCESS == code && NULL != pAggFuncCond) {
+ code = pushCondToAggCond(pCxt, pAgg, &pAggFuncCond);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pGroupKeyCond) {
+ code = rewriteAggGroupKeyCondForPushDown(pCxt, pAgg, pGroupKeyCond);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pGroupKeyCond) {
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0);
+ code = pushDownCondOptPushCondToChild(pCxt, pChild, &pGroupKeyCond);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ OPTIMIZE_FLAG_SET_MASK(pAgg->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
+ pCxt->optimized = true;
+ } else {
+ nodesDestroyNode(pGroupKeyCond);
+ nodesDestroyNode(pAggFuncCond);
+ }
+ return code;
+}
+
+typedef struct SRewriteProjCondContext {
+ SProjectLogicNode* pProj;
+ int32_t errCode;
+} SRewriteProjCondContext;
+
+static EDealRes rewriteProjectCondForPushDownImpl(SNode** ppNode, void* pContext) {
+ SRewriteProjCondContext* pCxt = pContext;
+ SProjectLogicNode* pProj = pCxt->pProj;
+ if (QUERY_NODE_COLUMN == nodeType(*ppNode)) {
+ SNode* pTarget = NULL;
+ FOREACH(pTarget, pProj->node.pTargets) {
+ if (nodesEqualNode(pTarget, *ppNode)) {
+ SNode* pProjection = NULL;
+ FOREACH(pProjection, pProj->pProjections) {
+ if (0 == strcmp(((SExprNode*)pProjection)->aliasName, ((SColumnNode*)(*ppNode))->colName)) {
+ SNode* pExpr = nodesCloneNode(pProjection);
+ if (pExpr == NULL) {
+ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
+ }
+ nodesDestroyNode(*ppNode);
+ *ppNode = pExpr;
+ return DEAL_RES_IGNORE_CHILD;
+ } // end if expr alias name equal column name
+ } // end for each project
+ } // end if target node equals cond column node
+ } // end for each targets
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+static int32_t rewriteProjectCondForPushDown(SOptimizeContext* pCxt, SProjectLogicNode* pProject,
+ SNode** ppProjectCond) {
+ SRewriteProjCondContext cxt = {.pProj = pProject, .errCode = TSDB_CODE_SUCCESS};
+ SNode* pProjectCond = pProject->node.pConditions;
+ nodesRewriteExpr(&pProjectCond, rewriteProjectCondForPushDownImpl, &cxt);
+ *ppProjectCond = pProjectCond;
+ pProject->node.pConditions = NULL;
+ return cxt.errCode;
+}
+
+static int32_t pushDownCondOptDealProject(SOptimizeContext* pCxt, SProjectLogicNode* pProject) {
+ if (NULL == pProject->node.pConditions ||
+ OPTIMIZE_FLAG_TEST_MASK(pProject->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE)) {
+ return TSDB_CODE_SUCCESS;
+ }
+ // TODO: remove it after full implementation of pushing down to child
+ if (1 != LIST_LENGTH(pProject->node.pChildren)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (NULL != pProject->node.pLimit || NULL != pProject->node.pSlimit) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t code = TSDB_CODE_SUCCESS;
+ SNode* pProjCond = NULL;
+ code = rewriteProjectCondForPushDown(pCxt, pProject, &pProjCond);
+ if (TSDB_CODE_SUCCESS == code) {
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pProject->node.pChildren, 0);
+ code = pushDownCondOptPushCondToChild(pCxt, pChild, &pProjCond);
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ OPTIMIZE_FLAG_SET_MASK(pProject->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
+ pCxt->optimized = true;
+ } else {
+ nodesDestroyNode(pProjCond);
+ }
+ return code;
+}
+
+static int32_t pushDownCondOptTrivialPushDown(SOptimizeContext* pCxt, SLogicNode* pLogicNode) {
+ if (NULL == pLogicNode->pConditions ||
+ OPTIMIZE_FLAG_TEST_MASK(pLogicNode->optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE)) {
+ return TSDB_CODE_SUCCESS;
+ }
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pLogicNode->pChildren, 0);
+ int32_t code = pushDownCondOptPushCondToChild(pCxt, pChild, &pLogicNode->pConditions);
+ if (TSDB_CODE_SUCCESS == code) {
+ OPTIMIZE_FLAG_SET_MASK(pLogicNode->optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE);
+ pCxt->optimized = true;
+ }
+ return code;
+}
+
+static int32_t pushDownCondOptimizeImpl(SOptimizeContext* pCxt, SLogicNode* pLogicNode) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pLogicNode)) {
case QUERY_NODE_LOGIC_PLAN_SCAN:
- code = cpdOptimizeScanCondition(pCxt, (SScanLogicNode*)pLogicNode);
+ code = pushDownCondOptDealScan(pCxt, (SScanLogicNode*)pLogicNode);
break;
case QUERY_NODE_LOGIC_PLAN_JOIN:
- code = cpdPushJoinCondition(pCxt, (SJoinLogicNode*)pLogicNode);
+ code = pushDownCondOptDealJoin(pCxt, (SJoinLogicNode*)pLogicNode);
break;
case QUERY_NODE_LOGIC_PLAN_AGG:
- code = cpdPushAggCondition(pCxt, (SAggLogicNode*)pLogicNode);
+ code = pushDownCondOptDealAgg(pCxt, (SAggLogicNode*)pLogicNode);
+ break;
+ case QUERY_NODE_LOGIC_PLAN_PROJECT:
+ code = pushDownCondOptDealProject(pCxt, (SProjectLogicNode*)pLogicNode);
+ break;
+ case QUERY_NODE_LOGIC_PLAN_SORT:
+ case QUERY_NODE_LOGIC_PLAN_PARTITION:
+ code = pushDownCondOptTrivialPushDown(pCxt, pLogicNode);
break;
default:
break;
@@ -633,7 +958,7 @@ static int32_t cpdPushCondition(SOptimizeContext* pCxt, SLogicNode* pLogicNode)
if (TSDB_CODE_SUCCESS == code) {
SNode* pChild = NULL;
FOREACH(pChild, pLogicNode->pChildren) {
- code = cpdPushCondition(pCxt, (SLogicNode*)pChild);
+ code = pushDownCondOptimizeImpl(pCxt, (SLogicNode*)pChild);
if (TSDB_CODE_SUCCESS != code) {
break;
}
@@ -642,11 +967,11 @@ static int32_t cpdPushCondition(SOptimizeContext* pCxt, SLogicNode* pLogicNode)
return code;
}
-static int32_t cpdOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
- return cpdPushCondition(pCxt, pLogicSubplan->pNode);
+static int32_t pushDownCondOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ return pushDownCondOptimizeImpl(pCxt, pLogicSubplan->pNode);
}
-static bool opkIsPrimaryKeyOrderBy(SNodeList* pSortKeys) {
+static bool sortPriKeyOptIsPriKeyOrderBy(SNodeList* pSortKeys) {
if (1 != LIST_LENGTH(pSortKeys)) {
return false;
}
@@ -654,17 +979,18 @@ static bool opkIsPrimaryKeyOrderBy(SNodeList* pSortKeys) {
return (QUERY_NODE_COLUMN == nodeType(pNode) ? (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pNode)->colId) : false);
}
-static bool opkSortMayBeOptimized(SLogicNode* pNode) {
+static bool sortPriKeyOptMayBeOptimized(SLogicNode* pNode) {
if (QUERY_NODE_LOGIC_PLAN_SORT != nodeType(pNode)) {
return false;
}
- if (OPTIMIZE_FLAG_TEST_MASK(pNode->optimizedFlag, OPTIMIZE_FLAG_OPK)) {
- return false;
+ SSortLogicNode* pSort = (SSortLogicNode*)pNode;
+ if (pSort->groupSort || !sortPriKeyOptIsPriKeyOrderBy(pSort->pSortKeys) || 1 != LIST_LENGTH(pSort->node.pChildren)) {
+ return TSDB_CODE_SUCCESS;
}
return true;
}
-static int32_t opkGetScanNodesImpl(SLogicNode* pNode, bool* pNotOptimize, SNodeList** pScanNodes) {
+static int32_t sortPriKeyOptGetScanNodesImpl(SLogicNode* pNode, bool* pNotOptimize, SNodeList** pScanNodes) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pNode)) {
@@ -674,9 +1000,11 @@ static int32_t opkGetScanNodesImpl(SLogicNode* pNode, bool* pNotOptimize, SNodeL
}
break;
case QUERY_NODE_LOGIC_PLAN_JOIN:
- code = opkGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), pNotOptimize, pScanNodes);
+ code =
+ sortPriKeyOptGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), pNotOptimize, pScanNodes);
if (TSDB_CODE_SUCCESS == code) {
- code = opkGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 1), pNotOptimize, pScanNodes);
+ code =
+ sortPriKeyOptGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 1), pNotOptimize, pScanNodes);
}
return code;
case QUERY_NODE_LOGIC_PLAN_AGG:
@@ -691,77 +1019,64 @@ static int32_t opkGetScanNodesImpl(SLogicNode* pNode, bool* pNotOptimize, SNodeL
return TSDB_CODE_SUCCESS;
}
- return opkGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), pNotOptimize, pScanNodes);
+ return sortPriKeyOptGetScanNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), pNotOptimize, pScanNodes);
}
-static int32_t opkGetScanNodes(SLogicNode* pNode, SNodeList** pScanNodes) {
+static int32_t sortPriKeyOptGetScanNodes(SLogicNode* pNode, SNodeList** pScanNodes) {
bool notOptimize = false;
- int32_t code = opkGetScanNodesImpl(pNode, ¬Optimize, pScanNodes);
+ int32_t code = sortPriKeyOptGetScanNodesImpl(pNode, ¬Optimize, pScanNodes);
if (TSDB_CODE_SUCCESS != code || notOptimize) {
nodesClearList(*pScanNodes);
}
return code;
}
-static EOrder opkGetPrimaryKeyOrder(SSortLogicNode* pSort) {
+static EOrder sortPriKeyOptGetPriKeyOrder(SSortLogicNode* pSort) {
return ((SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0))->order;
}
-static SNode* opkRewriteDownNode(SSortLogicNode* pSort) {
- SNode* pDownNode = nodesListGetNode(pSort->node.pChildren, 0);
- // todo
- pSort->node.pChildren = NULL;
- return pDownNode;
-}
-
-static int32_t opkDoOptimized(SOptimizeContext* pCxt, SSortLogicNode* pSort, SNodeList* pScanNodes) {
- EOrder order = opkGetPrimaryKeyOrder(pSort);
+static int32_t sortPriKeyOptApply(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SSortLogicNode* pSort,
+ SNodeList* pScanNodes) {
+ EOrder order = sortPriKeyOptGetPriKeyOrder(pSort);
if (ORDER_DESC == order) {
- SNode* pScan = NULL;
- FOREACH(pScan, pScanNodes) { TSWAP(((SScanLogicNode*)pScan)->scanSeq[0], ((SScanLogicNode*)pScan)->scanSeq[1]); }
- }
-
- if (NULL == pSort->node.pParent) {
- // todo
- return TSDB_CODE_SUCCESS;
+ SNode* pScanNode = NULL;
+ FOREACH(pScanNode, pScanNodes) {
+ SScanLogicNode* pScan = (SScanLogicNode*)pScanNode;
+ if (pScan->scanSeq[0] > 0) {
+ TSWAP(pScan->scanSeq[0], pScan->scanSeq[1]);
+ }
+ }
}
- SNode* pDownNode = opkRewriteDownNode(pSort);
- SNode* pNode;
- FOREACH(pNode, pSort->node.pParent->pChildren) {
- if (nodesEqualNode(pNode, (SNode*)pSort)) {
- REPLACE_NODE(pDownNode);
- ((SLogicNode*)pDownNode)->pParent = pSort->node.pParent;
- break;
- }
+ int32_t code =
+ replaceLogicNode(pLogicSubplan, (SLogicNode*)pSort, (SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0));
+ if (TSDB_CODE_SUCCESS == code) {
+ NODES_CLEAR_LIST(pSort->node.pChildren);
+ nodesDestroyNode((SNode*)pSort);
}
- nodesDestroyNode((SNode*)pSort);
- return TSDB_CODE_SUCCESS;
+ pCxt->optimized = true;
+ return code;
}
-static int32_t opkOptimizeImpl(SOptimizeContext* pCxt, SSortLogicNode* pSort) {
- OPTIMIZE_FLAG_SET_MASK(pSort->node.optimizedFlag, OPTIMIZE_FLAG_OPK);
- if (!opkIsPrimaryKeyOrderBy(pSort->pSortKeys) || 1 != LIST_LENGTH(pSort->node.pChildren)) {
- return TSDB_CODE_SUCCESS;
- }
+static int32_t sortPrimaryKeyOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SSortLogicNode* pSort) {
SNodeList* pScanNodes = NULL;
- int32_t code = opkGetScanNodes((SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0), &pScanNodes);
+ int32_t code = sortPriKeyOptGetScanNodes((SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0), &pScanNodes);
if (TSDB_CODE_SUCCESS == code && NULL != pScanNodes) {
- code = opkDoOptimized(pCxt, pSort, pScanNodes);
+ code = sortPriKeyOptApply(pCxt, pLogicSubplan, pSort, pScanNodes);
}
nodesClearList(pScanNodes);
return code;
}
-static int32_t opkOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
- SSortLogicNode* pSort = (SSortLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, opkSortMayBeOptimized);
+static int32_t sortPrimaryKeyOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SSortLogicNode* pSort = (SSortLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, sortPriKeyOptMayBeOptimized);
if (NULL == pSort) {
return TSDB_CODE_SUCCESS;
}
- return opkOptimizeImpl(pCxt, pSort);
+ return sortPrimaryKeyOptimizeImpl(pCxt, pLogicSubplan, pSort);
}
-static bool smaOptMayBeOptimized(SLogicNode* pNode) {
+static bool smaIndexOptMayBeOptimized(SLogicNode* pNode) {
if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pNode) || NULL == pNode->pParent ||
QUERY_NODE_LOGIC_PLAN_WINDOW != nodeType(pNode->pParent) ||
WINDOW_TYPE_INTERVAL != ((SWindowLogicNode*)pNode->pParent)->winType) {
@@ -769,14 +1084,15 @@ static bool smaOptMayBeOptimized(SLogicNode* pNode) {
}
SScanLogicNode* pScan = (SScanLogicNode*)pNode;
- if (0 == pScan->interval || NULL == pScan->pSmaIndexes || NULL != pScan->node.pConditions) {
+ if (NULL == pScan->pSmaIndexes || NULL != pScan->node.pConditions) {
return false;
}
return true;
}
-static int32_t smaOptCreateMerge(SLogicNode* pChild, SNodeList* pMergeKeys, SNodeList* pTargets, SLogicNode** pOutput) {
+static int32_t smaIndexOptCreateMerge(SLogicNode* pChild, SNodeList* pMergeKeys, SNodeList* pTargets,
+ SLogicNode** pOutput) {
SMergeLogicNode* pMerge = (SMergeLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_MERGE);
if (NULL == pMerge) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -795,8 +1111,8 @@ static int32_t smaOptCreateMerge(SLogicNode* pChild, SNodeList* pMergeKeys, SNod
return TSDB_CODE_SUCCESS;
}
-static int32_t smaOptRecombinationNode(SLogicSubplan* pLogicSubplan, SLogicNode* pInterval, SLogicNode* pMerge,
- SLogicNode* pSmaScan) {
+static int32_t smaIndexOptRecombinationNode(SLogicSubplan* pLogicSubplan, SLogicNode* pInterval, SLogicNode* pMerge,
+ SLogicNode* pSmaScan) {
int32_t code = nodesListMakeAppend(&pMerge->pChildren, (SNode*)pInterval);
if (TSDB_CODE_SUCCESS == code) {
code = nodesListMakeAppend(&pMerge->pChildren, (SNode*)pSmaScan);
@@ -809,8 +1125,8 @@ static int32_t smaOptRecombinationNode(SLogicSubplan* pLogicSubplan, SLogicNode*
return code;
}
-static int32_t smaOptCreateSmaScan(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList* pCols,
- SLogicNode** pOutput) {
+static int32_t smaIndexOptCreateSmaScan(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList* pCols,
+ SLogicNode** pOutput) {
SScanLogicNode* pSmaScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
if (NULL == pSmaScan) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -839,7 +1155,7 @@ static int32_t smaOptCreateSmaScan(SScanLogicNode* pScan, STableIndexInfo* pInde
return TSDB_CODE_SUCCESS;
}
-static bool smaOptEqualInterval(SScanLogicNode* pScan, SWindowLogicNode* pWindow, STableIndexInfo* pIndex) {
+static bool smaIndexOptEqualInterval(SScanLogicNode* pScan, SWindowLogicNode* pWindow, STableIndexInfo* pIndex) {
if (pWindow->interval != pIndex->interval || pWindow->intervalUnit != pIndex->intervalUnit ||
pWindow->offset != pIndex->offset || pWindow->sliding != pIndex->sliding ||
pWindow->slidingUnit != pIndex->slidingUnit) {
@@ -859,7 +1175,7 @@ static bool smaOptEqualInterval(SScanLogicNode* pScan, SWindowLogicNode* pWindow
return true;
}
-static SNode* smaOptCreateSmaCol(SNode* pFunc, uint64_t tableId, int32_t colId) {
+static SNode* smaIndexOptCreateSmaCol(SNode* pFunc, uint64_t tableId, int32_t colId) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
return NULL;
@@ -874,7 +1190,7 @@ static SNode* smaOptCreateSmaCol(SNode* pFunc, uint64_t tableId, int32_t colId)
return (SNode*)pCol;
}
-static int32_t smaOptFindSmaFunc(SNode* pQueryFunc, SNodeList* pSmaFuncs) {
+static int32_t smaIndexOptFindSmaFunc(SNode* pQueryFunc, SNodeList* pSmaFuncs) {
int32_t index = 0;
SNode* pSmaFunc = NULL;
FOREACH(pSmaFunc, pSmaFuncs) {
@@ -886,8 +1202,8 @@ static int32_t smaOptFindSmaFunc(SNode* pQueryFunc, SNodeList* pSmaFuncs) {
return -1;
}
-static int32_t smaOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs, SNodeList** pOutput,
- int32_t* pWStrartIndex) {
+static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs, SNodeList** pOutput,
+ int32_t* pWStrartIndex) {
SNodeList* pCols = NULL;
SNode* pFunc = NULL;
int32_t code = TSDB_CODE_SUCCESS;
@@ -895,14 +1211,14 @@ static int32_t smaOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeLis
int32_t smaFuncIndex = -1;
*pWStrartIndex = -1;
FOREACH(pFunc, pFuncs) {
- if (FUNCTION_TYPE_WSTARTTS == ((SFunctionNode*)pFunc)->funcType) {
+ if (FUNCTION_TYPE_WSTART == ((SFunctionNode*)pFunc)->funcType) {
*pWStrartIndex = index;
}
- smaFuncIndex = smaOptFindSmaFunc(pFunc, pSmaFuncs);
+ smaFuncIndex = smaIndexOptFindSmaFunc(pFunc, pSmaFuncs);
if (smaFuncIndex < 0) {
break;
} else {
- code = nodesListMakeStrictAppend(&pCols, smaOptCreateSmaCol(pFunc, tableId, smaFuncIndex + 2));
+ code = nodesListMakeStrictAppend(&pCols, smaIndexOptCreateSmaCol(pFunc, tableId, smaFuncIndex + 1));
if (TSDB_CODE_SUCCESS != code) {
break;
}
@@ -919,27 +1235,27 @@ static int32_t smaOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeLis
return code;
}
-static int32_t smaOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols,
- int32_t* pWStrartIndex) {
+static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols,
+ int32_t* pWStrartIndex) {
SWindowLogicNode* pWindow = (SWindowLogicNode*)pScan->node.pParent;
- if (!smaOptEqualInterval(pScan, pWindow, pIndex)) {
+ if (!smaIndexOptEqualInterval(pScan, pWindow, pIndex)) {
return TSDB_CODE_SUCCESS;
}
SNodeList* pSmaFuncs = NULL;
int32_t code = nodesStringToList(pIndex->expr, &pSmaFuncs);
if (TSDB_CODE_SUCCESS == code) {
- code = smaOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols, pWStrartIndex);
+ code = smaIndexOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols, pWStrartIndex);
}
nodesDestroyList(pSmaFuncs);
return code;
}
-static SNode* smaOptCreateWStartTs() {
+static SNode* smaIndexOptCreateWStartTs() {
SFunctionNode* pWStart = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
if (NULL == pWStart) {
return NULL;
}
- strcpy(pWStart->functionName, "_wstartts");
+ strcpy(pWStart->functionName, "_wstart");
snprintf(pWStart->node.aliasName, sizeof(pWStart->node.aliasName), "%s.%p", pWStart->functionName, pWStart);
if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pWStart, NULL, 0)) {
nodesDestroyNode((SNode*)pWStart);
@@ -948,7 +1264,7 @@ static SNode* smaOptCreateWStartTs() {
return (SNode*)pWStart;
}
-static int32_t smaOptCreateMergeKey(SNode* pCol, SNodeList** pMergeKeys) {
+static int32_t smaIndexOptCreateMergeKey(SNode* pCol, SNodeList** pMergeKeys) {
SOrderByExprNode* pMergeKey = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR);
if (NULL == pMergeKey) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -963,9 +1279,9 @@ static int32_t smaOptCreateMergeKey(SNode* pCol, SNodeList** pMergeKeys) {
return nodesListMakeStrictAppend(pMergeKeys, (SNode*)pMergeKey);
}
-static int32_t smaOptRewriteInterval(SWindowLogicNode* pInterval, int32_t wstrartIndex, SNodeList** pMergeKeys) {
+static int32_t smaIndexOptRewriteInterval(SWindowLogicNode* pInterval, int32_t wstrartIndex, SNodeList** pMergeKeys) {
if (wstrartIndex < 0) {
- SNode* pWStart = smaOptCreateWStartTs();
+ SNode* pWStart = smaIndexOptCreateWStartTs();
if (NULL == pWStart) {
return TSDB_CODE_OUT_OF_MEMORY;
}
@@ -976,11 +1292,11 @@ static int32_t smaOptRewriteInterval(SWindowLogicNode* pInterval, int32_t wstrar
}
wstrartIndex = LIST_LENGTH(pInterval->node.pTargets) - 1;
}
- return smaOptCreateMergeKey(nodesListGetNode(pInterval->node.pTargets, wstrartIndex), pMergeKeys);
+ return smaIndexOptCreateMergeKey(nodesListGetNode(pInterval->node.pTargets, wstrartIndex), pMergeKeys);
}
-static int32_t smaOptApplyIndexExt(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
- SNodeList* pSmaCols, int32_t wstrartIndex) {
+static int32_t smaIndexOptApplyIndexExt(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
+ SNodeList* pSmaCols, int32_t wstrartIndex) {
SWindowLogicNode* pInterval = (SWindowLogicNode*)pScan->node.pParent;
SNodeList* pMergeTargets = nodesCloneList(pInterval->node.pTargets);
if (NULL == pMergeTargets) {
@@ -989,60 +1305,61 @@ static int32_t smaOptApplyIndexExt(SLogicSubplan* pLogicSubplan, SScanLogicNode*
SLogicNode* pSmaScan = NULL;
SLogicNode* pMerge = NULL;
SNodeList* pMergeKeys = NULL;
- int32_t code = smaOptRewriteInterval(pInterval, wstrartIndex, &pMergeKeys);
+ int32_t code = smaIndexOptRewriteInterval(pInterval, wstrartIndex, &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
- code = smaOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
+ code = smaIndexOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
}
if (TSDB_CODE_SUCCESS == code) {
- code = smaOptCreateMerge(pScan->node.pParent, pMergeKeys, pMergeTargets, &pMerge);
+ code = smaIndexOptCreateMerge(pScan->node.pParent, pMergeKeys, pMergeTargets, &pMerge);
}
if (TSDB_CODE_SUCCESS == code) {
- code = smaOptRecombinationNode(pLogicSubplan, pScan->node.pParent, pMerge, pSmaScan);
+ code = smaIndexOptRecombinationNode(pLogicSubplan, pScan->node.pParent, pMerge, pSmaScan);
}
return code;
}
-static int32_t smaOptApplyIndex(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
- SNodeList* pSmaCols, int32_t wstrartIndex) {
+static int32_t smaIndexOptApplyIndex(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex,
+ SNodeList* pSmaCols, int32_t wstrartIndex) {
SLogicNode* pSmaScan = NULL;
- int32_t code = smaOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
+ int32_t code = smaIndexOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan);
if (TSDB_CODE_SUCCESS == code) {
code = replaceLogicNode(pLogicSubplan, pScan->node.pParent, pSmaScan);
}
return code;
}
-static void smaOptDestroySmaIndex(void* p) { taosMemoryFree(((STableIndexInfo*)p)->expr); }
+static void smaIndexOptDestroySmaIndex(void* p) { taosMemoryFree(((STableIndexInfo*)p)->expr); }
-static int32_t smaOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan) {
+static int32_t smaIndexOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan) {
int32_t code = TSDB_CODE_SUCCESS;
int32_t nindexes = taosArrayGetSize(pScan->pSmaIndexes);
for (int32_t i = 0; i < nindexes; ++i) {
STableIndexInfo* pIndex = taosArrayGet(pScan->pSmaIndexes, i);
SNodeList* pSmaCols = NULL;
int32_t wstrartIndex = -1;
- code = smaOptCouldApplyIndex(pScan, pIndex, &pSmaCols, &wstrartIndex);
+ code = smaIndexOptCouldApplyIndex(pScan, pIndex, &pSmaCols, &wstrartIndex);
if (TSDB_CODE_SUCCESS == code && NULL != pSmaCols) {
- code = smaOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex);
- taosArrayDestroyEx(pScan->pSmaIndexes, smaOptDestroySmaIndex);
+ code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex);
+ taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex);
pScan->pSmaIndexes = NULL;
+ pCxt->optimized = true;
break;
}
}
return code;
}
-static int32_t smaOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
- SScanLogicNode* pScan = (SScanLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, smaOptMayBeOptimized);
+static int32_t smaIndexOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SScanLogicNode* pScan = (SScanLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, smaIndexOptMayBeOptimized);
if (NULL == pScan) {
return TSDB_CODE_SUCCESS;
}
- return smaOptimizeImpl(pCxt, pLogicSubplan, pScan);
+ return smaIndexOptimizeImpl(pCxt, pLogicSubplan, pScan);
}
static EDealRes partTagsOptHasColImpl(SNode* pNode, void* pContext) {
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
- if (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType) {
+ if (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType && COLUMN_TYPE_TBNAME != ((SColumnNode*)pNode)->colType) {
*(bool*)pContext = true;
return DEAL_RES_END;
}
@@ -1050,16 +1367,16 @@ static EDealRes partTagsOptHasColImpl(SNode* pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
-static bool partTagsOptHasCol(SNodeList* pPartKeys) {
+static bool planOptNodeListHasCol(SNodeList* pKeys) {
bool hasCol = false;
- nodesWalkExprs(pPartKeys, partTagsOptHasColImpl, &hasCol);
+ nodesWalkExprs(pKeys, partTagsOptHasColImpl, &hasCol);
return hasCol;
}
static bool partTagsIsOptimizableNode(SLogicNode* pNode) {
- return ((QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode) /*||
+ return ((QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode) ||
(QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode) && NULL != ((SAggLogicNode*)pNode)->pGroupKeys &&
- NULL != ((SAggLogicNode*)pNode)->pAggFuncs)*/) &&
+ NULL != ((SAggLogicNode*)pNode)->pAggFuncs)) &&
1 == LIST_LENGTH(pNode->pChildren) &&
QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(nodesListGetNode(pNode->pChildren, 0)));
}
@@ -1072,12 +1389,94 @@ static SNodeList* partTagsGetPartKeys(SLogicNode* pNode) {
}
}
+static SNodeList* partTagsGetFuncs(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
+ return NULL;
+ } else {
+ return ((SAggLogicNode*)pNode)->pAggFuncs;
+ }
+}
+
+static bool partTagsOptAreSupportedFuncs(SNodeList* pFuncs) {
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, pFuncs) {
+ if (fmIsIndefiniteRowsFunc(((SFunctionNode*)pFunc)->funcId) && !fmIsSelectFunc(((SFunctionNode*)pFunc)->funcId)) {
+ return false;
+ }
+ }
+ return true;
+}
+
static bool partTagsOptMayBeOptimized(SLogicNode* pNode) {
if (!partTagsIsOptimizableNode(pNode)) {
return false;
}
- return !partTagsOptHasCol(partTagsGetPartKeys(pNode));
+ return !planOptNodeListHasCol(partTagsGetPartKeys(pNode)) && partTagsOptAreSupportedFuncs(partTagsGetFuncs(pNode));
+}
+
+static int32_t partTagsOptRebuildTbanme(SNodeList* pPartKeys) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ nodesRewriteExprs(pPartKeys, optRebuildTbanme, &code);
+ return code;
+}
+
+// todo refact: just to mask compilation warnings
+static void partTagsSetAlias(char* pAlias, int32_t len, const char* pTableAlias, const char* pColName) {
+ snprintf(pAlias, len, "%s.%s", pTableAlias, pColName);
+}
+
+static SNode* partTagsCreateWrapperFunc(const char* pFuncName, SNode* pNode) {
+ SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ return NULL;
+ }
+
+ strcpy(pFunc->functionName, pFuncName);
+ if (QUERY_NODE_COLUMN == nodeType(pNode) && COLUMN_TYPE_TBNAME != ((SColumnNode*)pNode)->colType) {
+ SColumnNode* pCol = (SColumnNode*)pNode;
+ partTagsSetAlias(pFunc->node.aliasName, sizeof(pFunc->node.aliasName), pCol->tableAlias, pCol->colName);
+ } else {
+ strcpy(pFunc->node.aliasName, ((SExprNode*)pNode)->aliasName);
+ }
+ int32_t code = nodesListMakeStrictAppend(&pFunc->pParameterList, nodesCloneNode(pNode));
+ if (TSDB_CODE_SUCCESS == code) {
+ code = fmGetFuncInfo(pFunc, NULL, 0);
+ }
+
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyNode((SNode*)pFunc);
+ return NULL;
+ }
+
+ return (SNode*)pFunc;
+}
+
+static bool partTagsHasIndefRowsSelectFunc(SNodeList* pFuncs) {
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, pFuncs) {
+ if (fmIsIndefiniteRowsFunc(((SFunctionNode*)pFunc)->funcId)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static int32_t partTagsRewriteGroupTagsToFuncs(SNodeList* pGroupTags, SNodeList* pAggFuncs) {
+ bool hasIndefRowsSelectFunc = partTagsHasIndefRowsSelectFunc(pAggFuncs);
+ int32_t code = TSDB_CODE_SUCCESS;
+ SNode* pNode = NULL;
+ FOREACH(pNode, pGroupTags) {
+ if (hasIndefRowsSelectFunc) {
+ code = nodesListStrictAppend(pAggFuncs, partTagsCreateWrapperFunc("_select_value", pNode));
+ } else {
+ code = nodesListStrictAppend(pAggFuncs, partTagsCreateWrapperFunc("_group_key", pNode));
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+ return code;
}
static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
@@ -1089,43 +1488,35 @@ static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSub
int32_t code = TSDB_CODE_SUCCESS;
SScanLogicNode* pScan = (SScanLogicNode*)nodesListGetNode(pNode->pChildren, 0);
if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
- TSWAP(((SPartitionLogicNode*)pNode)->pPartitionKeys, pScan->pPartTags);
+ TSWAP(((SPartitionLogicNode*)pNode)->pPartitionKeys, pScan->pGroupTags);
int32_t code = replaceLogicNode(pLogicSubplan, pNode, (SLogicNode*)pScan);
if (TSDB_CODE_SUCCESS == code) {
NODES_CLEAR_LIST(pNode->pChildren);
nodesDestroyNode((SNode*)pNode);
}
} else {
- TSWAP(((SAggLogicNode*)pNode)->pGroupKeys, pScan->pPartTags);
+ SAggLogicNode* pAgg = (SAggLogicNode*)pNode;
+ SNode* pGroupKey = NULL;
+ FOREACH(pGroupKey, pAgg->pGroupKeys) {
+ code = nodesListMakeStrictAppend(
+ &pScan->pGroupTags, nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0)));
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+ NODES_DESTORY_LIST(pAgg->pGroupKeys);
+ code = partTagsRewriteGroupTagsToFuncs(pScan->pGroupTags, pAgg->pAggFuncs);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = partTagsOptRebuildTbanme(pScan->pGroupTags);
}
return code;
}
-static bool eliminateProjOptMayBeOptimized(SLogicNode* pNode) {
- // TODO: enable this optimization after new mechanising that map projection and targets of project node
- if (NULL != pNode->pParent) {
- return false;
- }
-
- if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren)) {
- return false;
- }
-
- SProjectLogicNode* pProjectNode = (SProjectLogicNode*)pNode;
- if (-1 != pProjectNode->limit || -1 != pProjectNode->slimit || -1 != pProjectNode->offset ||
- -1 != pProjectNode->soffset) {
- return false;
- }
-
+static bool eliminateProjOptCheckProjColumnNames(SProjectLogicNode* pProjectNode) {
SHashObj* pProjColNameHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
SNode* pProjection;
FOREACH(pProjection, pProjectNode->pProjections) {
- SExprNode* pExprNode = (SExprNode*)pProjection;
- if (QUERY_NODE_COLUMN != nodeType(pExprNode)) {
- taosHashCleanup(pProjColNameHash);
- return false;
- }
-
char* projColumnName = ((SColumnNode*)pProjection)->colName;
int32_t* pExist = taosHashGet(pProjColNameHash, projColumnName, strlen(projColumnName));
if (NULL != pExist) {
@@ -1137,10 +1528,36 @@ static bool eliminateProjOptMayBeOptimized(SLogicNode* pNode) {
}
}
taosHashCleanup(pProjColNameHash);
-
return true;
}
+static bool eliminateProjOptMayBeOptimized(SLogicNode* pNode) {
+ // TODO: enable this optimization after new mechanising that map projection and targets of project node
+ if (NULL != pNode->pParent) {
+ return false;
+ }
+
+ if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren)) {
+ return false;
+ }
+
+ SProjectLogicNode* pProjectNode = (SProjectLogicNode*)pNode;
+ if (NULL != pProjectNode->node.pLimit || NULL != pProjectNode->node.pSlimit ||
+ NULL != pProjectNode->node.pConditions) {
+ return false;
+ }
+
+ SNode* pProjection;
+ FOREACH(pProjection, pProjectNode->pProjections) {
+ SExprNode* pExprNode = (SExprNode*)pProjection;
+ if (QUERY_NODE_COLUMN != nodeType(pExprNode)) {
+ return false;
+ }
+ }
+
+ return eliminateProjOptCheckProjColumnNames(pProjectNode);
+}
+
static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
SProjectLogicNode* pProjectNode) {
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pProjectNode->node.pChildren, 0);
@@ -1164,6 +1581,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
NODES_CLEAR_LIST(pProjectNode->node.pChildren);
nodesDestroyNode((SNode*)pProjectNode);
}
+ pCxt->optimized = true;
return code;
}
@@ -1178,30 +1596,589 @@ static int32_t eliminateProjOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLog
return eliminateProjOptimizeImpl(pCxt, pLogicSubplan, pProjectNode);
}
+static bool rewriteTailOptMayBeOptimized(SLogicNode* pNode) {
+ return QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC == nodeType(pNode) && ((SIndefRowsFuncLogicNode*)pNode)->isTailFunc;
+}
+
+static SNode* rewriteTailOptCreateOrderByExpr(SNode* pSortKey) {
+ SOrderByExprNode* pOrder = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR);
+ if (NULL == pOrder) {
+ return NULL;
+ }
+ pOrder->order = ORDER_DESC;
+ pOrder->pExpr = nodesCloneNode(pSortKey);
+ if (NULL == pOrder->pExpr) {
+ nodesDestroyNode((SNode*)pOrder);
+ return NULL;
+ }
+ return (SNode*)pOrder;
+}
+
+static int32_t rewriteTailOptCreateLimit(SNode* pLimit, SNode* pOffset, SNode** pOutput) {
+ SLimitNode* pLimitNode = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT);
+ if (NULL == pLimitNode) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ pLimitNode->limit = NULL == pLimit ? -1 : ((SValueNode*)pLimit)->datum.i;
+ pLimitNode->offset = NULL == pOffset ? -1 : ((SValueNode*)pOffset)->datum.i;
+ *pOutput = (SNode*)pLimitNode;
+ return TSDB_CODE_SUCCESS;
+}
+
+static bool rewriteTailOptNeedGroupSort(SIndefRowsFuncLogicNode* pIndef) {
+ if (1 != LIST_LENGTH(pIndef->node.pChildren)) {
+ return false;
+ }
+ SNode* pChild = nodesListGetNode(pIndef->node.pChildren, 0);
+ return QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pChild) ||
+ (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pChild) && NULL != ((SScanLogicNode*)pChild)->pGroupTags);
+}
+
+static int32_t rewriteTailOptCreateSort(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
+ SSortLogicNode* pSort = (SSortLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SORT);
+ if (NULL == pSort) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ pSort->groupSort = rewriteTailOptNeedGroupSort(pIndef);
+ TSWAP(pSort->node.pChildren, pIndef->node.pChildren);
+ optResetParent((SLogicNode*)pSort);
+ pSort->node.precision = pIndef->node.precision;
+
+ SFunctionNode* pTail = NULL;
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, pIndef->pFuncs) {
+ if (FUNCTION_TYPE_TAIL == ((SFunctionNode*)pFunc)->funcType) {
+ pTail = (SFunctionNode*)pFunc;
+ break;
+ }
+ }
+
+ // tail(expr, [limit, offset,] _rowts)
+ int32_t rowtsIndex = LIST_LENGTH(pTail->pParameterList) - 1;
+
+ int32_t code = nodesListMakeStrictAppend(
+ &pSort->pSortKeys, rewriteTailOptCreateOrderByExpr(nodesListGetNode(pTail->pParameterList, rowtsIndex)));
+ if (TSDB_CODE_SUCCESS == code) {
+ pSort->node.pTargets = nodesCloneList(((SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0))->pTargets);
+ if (NULL == pSort->node.pTargets) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = (SLogicNode*)pSort;
+ } else {
+ nodesDestroyNode((SNode*)pSort);
+ }
+
+ return code;
+}
+
+static SNode* rewriteTailOptCreateProjectExpr(SFunctionNode* pFunc) {
+ SNode* pExpr = nodesCloneNode(nodesListGetNode(pFunc->pParameterList, 0));
+ if (NULL == pExpr) {
+ return NULL;
+ }
+ strcpy(((SExprNode*)pExpr)->aliasName, pFunc->node.aliasName);
+ return pExpr;
+}
+
+static int32_t rewriteTailOptCreateProject(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
+ SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
+ if (NULL == pProject) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ TSWAP(pProject->node.pTargets, pIndef->node.pTargets);
+ pProject->node.precision = pIndef->node.precision;
+
+ int32_t code = TSDB_CODE_SUCCESS;
+ SFunctionNode* pTail = NULL;
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, pIndef->pFuncs) {
+ code = nodesListMakeStrictAppend(&pProject->pProjections, rewriteTailOptCreateProjectExpr((SFunctionNode*)pFunc));
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ if (FUNCTION_TYPE_TAIL == ((SFunctionNode*)pFunc)->funcType) {
+ pTail = (SFunctionNode*)pFunc;
+ }
+ }
+
+ // tail(expr, [limit, offset,] _rowts)
+ int32_t limitIndex = LIST_LENGTH(pTail->pParameterList) > 2 ? 1 : -1;
+ int32_t offsetIndex = LIST_LENGTH(pTail->pParameterList) > 3 ? 2 : -1;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = rewriteTailOptCreateLimit(limitIndex < 0 ? NULL : nodesListGetNode(pTail->pParameterList, limitIndex),
+ offsetIndex < 0 ? NULL : nodesListGetNode(pTail->pParameterList, offsetIndex),
+ &pProject->node.pLimit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = (SLogicNode*)pProject;
+ } else {
+ nodesDestroyNode((SNode*)pProject);
+ }
+ return code;
+}
+
+static int32_t rewriteTailOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
+ SIndefRowsFuncLogicNode* pIndef) {
+ SLogicNode* pSort = NULL;
+ SLogicNode* pProject = NULL;
+ int32_t code = rewriteTailOptCreateSort(pIndef, &pSort);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = rewriteTailOptCreateProject(pIndef, &pProject);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeAppend(&pProject->pChildren, (SNode*)pSort);
+ pSort->pParent = pProject;
+ pSort = NULL;
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pIndef, pProject);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ nodesDestroyNode((SNode*)pIndef);
+ } else {
+ nodesDestroyNode((SNode*)pSort);
+ nodesDestroyNode((SNode*)pProject);
+ }
+ pCxt->optimized = true;
+ return code;
+}
+
+static int32_t rewriteTailOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SIndefRowsFuncLogicNode* pIndef =
+ (SIndefRowsFuncLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, rewriteTailOptMayBeOptimized);
+
+ if (NULL == pIndef) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return rewriteTailOptimizeImpl(pCxt, pLogicSubplan, pIndef);
+}
+
+static bool eliminateSetOpMayBeOptimized(SLogicNode* pNode) {
+ SLogicNode* pParent = pNode->pParent;
+ if (NULL == pParent ||
+ QUERY_NODE_LOGIC_PLAN_AGG != nodeType(pParent) && QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pParent) ||
+ LIST_LENGTH(pParent->pChildren) < 2) {
+ return false;
+ }
+ if (nodeType(pNode) != nodeType(pNode->pParent) || LIST_LENGTH(pNode->pChildren) < 2) {
+ return false;
+ }
+ return true;
+}
+
+static int32_t eliminateSetOpOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
+ SLogicNode* pSetOpNode) {
+ SNode* pSibling;
+ FOREACH(pSibling, pSetOpNode->pParent->pChildren) {
+ if (nodesEqualNode(pSibling, (SNode*)pSetOpNode)) {
+ SNode* pChild;
+ FOREACH(pChild, pSetOpNode->pChildren) { ((SLogicNode*)pChild)->pParent = pSetOpNode->pParent; }
+ INSERT_LIST(pSetOpNode->pParent->pChildren, pSetOpNode->pChildren);
+
+ pSetOpNode->pChildren = NULL;
+ ERASE_NODE(pSetOpNode->pParent->pChildren);
+ pCxt->optimized = true;
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+
+ return TSDB_CODE_PLAN_INTERNAL_ERROR;
+}
+
+static int32_t eliminateSetOpOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SLogicNode* pSetOpNode = optFindPossibleNode(pLogicSubplan->pNode, eliminateSetOpMayBeOptimized);
+ if (NULL == pSetOpNode) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return eliminateSetOpOptimizeImpl(pCxt, pLogicSubplan, pSetOpNode);
+}
+
+static bool rewriteUniqueOptMayBeOptimized(SLogicNode* pNode) {
+ return QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC == nodeType(pNode) && ((SIndefRowsFuncLogicNode*)pNode)->isUniqueFunc;
+}
+
+static SNode* rewriteUniqueOptCreateGroupingSet(SNode* pExpr) {
+ SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
+ if (NULL == pGroupingSet) {
+ return NULL;
+ }
+ pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
+ SExprNode* pGroupExpr = (SExprNode*)nodesCloneNode(pExpr);
+ if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, (SNode*)pGroupExpr)) {
+ nodesDestroyNode((SNode*)pGroupingSet);
+ return NULL;
+ }
+ return (SNode*)pGroupingSet;
+}
+
+static SNode* rewriteUniqueOptCreateFirstFunc(SFunctionNode* pSelectValue, SNode* pCol) {
+ SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ return NULL;
+ }
+
+ strcpy(pFunc->functionName, "first");
+ if (NULL != pSelectValue) {
+ strcpy(pFunc->node.aliasName, pSelectValue->node.aliasName);
+ } else {
+ snprintf(pFunc->node.aliasName, sizeof(pFunc->node.aliasName), "%s.%p", pFunc->functionName, pFunc);
+ }
+ int32_t code = nodesListMakeStrictAppend(&pFunc->pParameterList, nodesCloneNode(pCol));
+ if (TSDB_CODE_SUCCESS == code) {
+ code = fmGetFuncInfo(pFunc, NULL, 0);
+ }
+
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyNode((SNode*)pFunc);
+ return NULL;
+ }
+
+ return (SNode*)pFunc;
+}
+
+static int32_t rewriteUniqueOptCreateAgg(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
+ SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
+ if (NULL == pAgg) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ TSWAP(pAgg->node.pChildren, pIndef->node.pChildren);
+ optResetParent((SLogicNode*)pAgg);
+ pAgg->node.precision = pIndef->node.precision;
+
+ int32_t code = TSDB_CODE_SUCCESS;
+ bool hasSelectPrimaryKey = false;
+ SNode* pPrimaryKey = NULL;
+ SNode* pNode = NULL;
+ FOREACH(pNode, pIndef->pFuncs) {
+ SFunctionNode* pFunc = (SFunctionNode*)pNode;
+ SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
+ if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
+ pPrimaryKey = nodesListGetNode(pFunc->pParameterList, 1);
+ code = nodesListMakeStrictAppend(&pAgg->pGroupKeys, rewriteUniqueOptCreateGroupingSet(pExpr));
+ } else if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId) { // _select_value(ts) => first(ts)
+ hasSelectPrimaryKey = true;
+ code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, rewriteUniqueOptCreateFirstFunc(pFunc, pExpr));
+ } else { // _select_value(other_col)
+ code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, nodesCloneNode(pNode));
+ }
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ code = createColumnByRewriteExprs(pAgg->pGroupKeys, &pAgg->node.pTargets);
+ }
+ if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
+ code = createColumnByRewriteExprs(pAgg->pAggFuncs, &pAgg->node.pTargets);
+ }
+
+ if (TSDB_CODE_SUCCESS == code && !hasSelectPrimaryKey && NULL != pAgg->pAggFuncs) {
+ code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, rewriteUniqueOptCreateFirstFunc(NULL, pPrimaryKey));
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = (SLogicNode*)pAgg;
+ } else {
+ nodesDestroyNode((SNode*)pAgg);
+ }
+ return code;
+}
+
+static SNode* rewriteUniqueOptCreateProjectCol(SFunctionNode* pFunc) {
+ SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
+ if (NULL == pCol) {
+ return NULL;
+ }
+
+ pCol->node.resType = pFunc->node.resType;
+ if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
+ SExprNode* pExpr = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
+ if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
+ strcpy(pCol->tableAlias, ((SColumnNode*)pExpr)->tableAlias);
+ strcpy(pCol->colName, ((SColumnNode*)pExpr)->colName);
+ } else {
+ strcpy(pCol->colName, pExpr->aliasName);
+ }
+ } else {
+ strcpy(pCol->colName, pFunc->node.aliasName);
+ }
+ strcpy(pCol->node.aliasName, pFunc->node.aliasName);
+
+ return (SNode*)pCol;
+}
+
+static int32_t rewriteUniqueOptCreateProject(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
+ SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
+ if (NULL == pProject) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ TSWAP(pProject->node.pTargets, pIndef->node.pTargets);
+ pProject->node.precision = pIndef->node.precision;
+
+ int32_t code = TSDB_CODE_SUCCESS;
+ SNode* pNode = NULL;
+ FOREACH(pNode, pIndef->pFuncs) {
+ code = nodesListMakeStrictAppend(&pProject->pProjections, rewriteUniqueOptCreateProjectCol((SFunctionNode*)pNode));
+ if (TSDB_CODE_SUCCESS != code) {
+ break;
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pOutput = (SLogicNode*)pProject;
+ } else {
+ nodesDestroyNode((SNode*)pProject);
+ }
+ return code;
+}
+
+static int32_t rewriteUniqueOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
+ SIndefRowsFuncLogicNode* pIndef) {
+ SLogicNode* pAgg = NULL;
+ SLogicNode* pProject = NULL;
+ int32_t code = rewriteUniqueOptCreateAgg(pIndef, &pAgg);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = rewriteUniqueOptCreateProject(pIndef, &pProject);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeAppend(&pProject->pChildren, (SNode*)pAgg);
+ pAgg->pParent = pProject;
+ pAgg = NULL;
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pIndef, pProject);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ nodesDestroyNode((SNode*)pIndef);
+ } else {
+ nodesDestroyNode((SNode*)pAgg);
+ nodesDestroyNode((SNode*)pProject);
+ }
+ pCxt->optimized = true;
+ return code;
+}
+
+static int32_t rewriteUniqueOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SIndefRowsFuncLogicNode* pIndef =
+ (SIndefRowsFuncLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, rewriteUniqueOptMayBeOptimized);
+
+ if (NULL == pIndef) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return rewriteUniqueOptimizeImpl(pCxt, pLogicSubplan, pIndef);
+}
+
+static bool lastRowScanOptMayBeOptimized(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_AGG != nodeType(pNode) || !(((SAggLogicNode*)pNode)->hasLastRow) ||
+ NULL != ((SAggLogicNode*)pNode)->pGroupKeys || 1 != LIST_LENGTH(pNode->pChildren) ||
+ QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(nodesListGetNode(pNode->pChildren, 0)) ||
+ NULL != ((SScanLogicNode*)nodesListGetNode(pNode->pChildren, 0))->node.pConditions) {
+ return false;
+ }
+
+ SNode* pFunc = NULL;
+ FOREACH(pFunc, ((SAggLogicNode*)pNode)->pAggFuncs) {
+ if (FUNCTION_TYPE_LAST_ROW != ((SFunctionNode*)pFunc)->funcType &&
+ FUNCTION_TYPE_SELECT_VALUE != ((SFunctionNode*)pFunc)->funcType) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int32_t lastRowScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SAggLogicNode* pAgg = (SAggLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, lastRowScanOptMayBeOptimized);
+
+ if (NULL == pAgg) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SNode* pNode = NULL;
+ FOREACH(pNode, pAgg->pAggFuncs) {
+ SFunctionNode* pFunc = (SFunctionNode*)pNode;
+ int32_t len = snprintf(pFunc->functionName, sizeof(pFunc->functionName), "_cache_last_row");
+ pFunc->functionName[len] = '\0';
+ fmGetFuncInfo(pFunc, NULL, 0);
+ }
+ pAgg->hasLastRow = false;
+
+ ((SScanLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0))->scanType = SCAN_TYPE_LAST_ROW;
+
+ pCxt->optimized = true;
+ return TSDB_CODE_SUCCESS;
+}
+
+// merge projects
+static bool mergeProjectsMayBeOptimized(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren)) {
+ return false;
+ }
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pNode->pChildren, 0);
+ if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pChild) || 1 < LIST_LENGTH(pChild->pChildren) ||
+ NULL != pChild->pConditions || NULL != pChild->pLimit || NULL != pChild->pSlimit) {
+ return false;
+ }
+ return true;
+}
+
+typedef struct SMergeProjectionsContext {
+ SProjectLogicNode* pChildProj;
+ int32_t errCode;
+} SMergeProjectionsContext;
+
+static EDealRes mergeProjectionsExpr(SNode** pNode, void* pContext) {
+ SMergeProjectionsContext* pCxt = pContext;
+ SProjectLogicNode* pChildProj = pCxt->pChildProj;
+ if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
+ SNode* pTarget;
+ FOREACH(pTarget, ((SLogicNode*)pChildProj)->pTargets) {
+ if (nodesEqualNode(pTarget, *pNode)) {
+ SNode* pProjection;
+ FOREACH(pProjection, pChildProj->pProjections) {
+ if (0 == strcmp(((SColumnNode*)pTarget)->colName, ((SExprNode*)pProjection)->aliasName)) {
+ SNode* pExpr = nodesCloneNode(pProjection);
+ if (pExpr == NULL) {
+ pCxt->errCode = terrno;
+ return DEAL_RES_ERROR;
+ }
+ snprintf(((SExprNode*)pExpr)->aliasName, sizeof(((SExprNode*)pExpr)->aliasName), "%s",
+ ((SExprNode*)*pNode)->aliasName);
+ nodesDestroyNode(*pNode);
+ *pNode = pExpr;
+ return DEAL_RES_IGNORE_CHILD;
+ }
+ }
+ }
+ }
+ }
+ return DEAL_RES_CONTINUE;
+}
+
+static int32_t mergeProjectsOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SLogicNode* pSelfNode) {
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pSelfNode->pChildren, 0);
+
+ SMergeProjectionsContext cxt = {.pChildProj = (SProjectLogicNode*)pChild, .errCode = TSDB_CODE_SUCCESS};
+ nodesRewriteExprs(((SProjectLogicNode*)pSelfNode)->pProjections, mergeProjectionsExpr, &cxt);
+ int32_t code = cxt.errCode;
+
+ if (TSDB_CODE_SUCCESS == code) {
+ if (1 == LIST_LENGTH(pChild->pChildren)) {
+ SLogicNode* pGrandChild = (SLogicNode*)nodesListGetNode(pChild->pChildren, 0);
+ code = replaceLogicNode(pLogicSubplan, pChild, pGrandChild);
+ } else { // no grand child
+ NODES_CLEAR_LIST(pSelfNode->pChildren);
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ NODES_CLEAR_LIST(pChild->pChildren);
+ }
+ nodesDestroyNode((SNode*)pChild);
+ pCxt->optimized = true;
+ return code;
+}
+
+static int32_t mergeProjectsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SLogicNode* pProjectNode = optFindPossibleNode(pLogicSubplan->pNode, mergeProjectsMayBeOptimized);
+ if (NULL == pProjectNode) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return mergeProjectsOptimizeImpl(pCxt, pLogicSubplan, pProjectNode);
+}
+
+static bool tagScanMayBeOptimized(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pNode) || (SCAN_TYPE_TAG == ((SScanLogicNode*)pNode)->scanType)) {
+ return false;
+ }
+ SScanLogicNode* pScan = (SScanLogicNode*)pNode;
+ if (NULL != pScan->pScanCols) {
+ return false;
+ }
+ if (NULL == pNode->pParent || QUERY_NODE_LOGIC_PLAN_AGG != nodeType(pNode->pParent) ||
+ 1 != LIST_LENGTH(pNode->pParent->pChildren)) {
+ return false;
+ }
+
+ SAggLogicNode* pAgg = (SAggLogicNode*)(pNode->pParent);
+ if (NULL == pAgg->pGroupKeys || NULL != pAgg->pAggFuncs || planOptNodeListHasCol(pAgg->pGroupKeys)) {
+ return false;
+ }
+
+ return true;
+}
+
+static int32_t tagScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SScanLogicNode* pScanNode = (SScanLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, tagScanMayBeOptimized);
+ if (NULL == pScanNode) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ pScanNode->scanType = SCAN_TYPE_TAG;
+ pCxt->optimized = true;
+ return TSDB_CODE_SUCCESS;
+}
+
// clang-format off
static const SOptimizeRule optimizeRuleSet[] = {
- {.pName = "OptimizeScanData", .optimizeFunc = osdOptimize},
- {.pName = "ConditionPushDown", .optimizeFunc = cpdOptimize},
- {.pName = "OrderByPrimaryKey", .optimizeFunc = opkOptimize},
- {.pName = "SmaIndex", .optimizeFunc = smaOptimize},
- {.pName = "PartitionByTags", .optimizeFunc = partTagsOptimize},
- {.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize}
+ {.pName = "ScanPath", .optimizeFunc = scanPathOptimize},
+ {.pName = "PushDownCondition", .optimizeFunc = pushDownCondOptimize},
+ {.pName = "SortPrimaryKey", .optimizeFunc = sortPrimaryKeyOptimize},
+ {.pName = "SmaIndex", .optimizeFunc = smaIndexOptimize},
+ {.pName = "PartitionTags", .optimizeFunc = partTagsOptimize},
+ {.pName = "MergeProjects", .optimizeFunc = mergeProjectsOptimize},
+ {.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize},
+ {.pName = "EliminateSetOperator", .optimizeFunc = eliminateSetOpOptimize},
+ {.pName = "RewriteTail", .optimizeFunc = rewriteTailOptimize},
+ {.pName = "RewriteUnique", .optimizeFunc = rewriteUniqueOptimize},
+ {.pName = "LastRowScan", .optimizeFunc = lastRowScanOptimize},
+ {.pName = "TagScan", .optimizeFunc = tagScanOptimize}
};
// clang-format on
static const int32_t optimizeRuleNum = (sizeof(optimizeRuleSet) / sizeof(SOptimizeRule));
+static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
+ char* pStr = NULL;
+ nodesNodeToString((SNode*)pSubplan, false, &pStr, NULL);
+ if (NULL == pRuleName) {
+ qDebugL("before optimize: %s", pStr);
+ } else {
+ qDebugL("apply optimize %s rule: %s", pRuleName, pStr);
+ }
+ taosMemoryFree(pStr);
+}
+
static int32_t applyOptimizeRule(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
SOptimizeContext cxt = {.pPlanCxt = pCxt, .optimized = false};
+ bool optimized = false;
+ dumpLogicSubplan(NULL, pLogicSubplan);
do {
- cxt.optimized = false;
+ optimized = false;
for (int32_t i = 0; i < optimizeRuleNum; ++i) {
+ cxt.optimized = false;
int32_t code = optimizeRuleSet[i].optimizeFunc(&cxt, pLogicSubplan);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
+ if (cxt.optimized) {
+ optimized = true;
+ dumpLogicSubplan(optimizeRuleSet[i].pName, pLogicSubplan);
+ }
}
- } while (cxt.optimized);
+ } while (optimized);
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c
index ff78370c522fc8f17c885a8248091e5baee64601..8c9c06be353919aa3990f8acfedba890d80fcc6e 100644
--- a/source/libs/planner/src/planPhysiCreater.c
+++ b/source/libs/planner/src/planPhysiCreater.c
@@ -41,8 +41,12 @@ typedef struct SPhysiPlanContext {
static int32_t getSlotKey(SNode* pNode, const char* pStmtName, char* pKey) {
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
SColumnNode* pCol = (SColumnNode*)pNode;
- if (NULL != pStmtName && '\0' != pStmtName[0]) {
- return sprintf(pKey, "%s.%s", pStmtName, pCol->node.aliasName);
+ if (NULL != pStmtName) {
+ if ('\0' != pStmtName[0]) {
+ return sprintf(pKey, "%s.%s", pStmtName, pCol->node.aliasName);
+ } else {
+ return sprintf(pKey, "%s", pCol->node.aliasName);
+ }
}
if ('\0' == pCol->tableAlias[0]) {
return sprintf(pKey, "%s", pCol->colName);
@@ -56,11 +60,13 @@ static int32_t getSlotKey(SNode* pNode, const char* pStmtName, char* pKey) {
return sprintf(pKey, "%s", ((SExprNode*)pNode)->aliasName);
}
-static SNode* createSlotDesc(SPhysiPlanContext* pCxt, const SNode* pNode, int16_t slotId, bool output, bool reserve) {
+static SNode* createSlotDesc(SPhysiPlanContext* pCxt, const char* pName, const SNode* pNode, int16_t slotId,
+ bool output, bool reserve) {
SSlotDescNode* pSlot = (SSlotDescNode*)nodesMakeNode(QUERY_NODE_SLOT_DESC);
if (NULL == pSlot) {
return NULL;
}
+ strcpy(pSlot->name, pName);
pSlot->slotId = slotId;
pSlot->dataType = ((SExprNode*)pNode)->resType;
pSlot->reserve = reserve;
@@ -99,10 +105,8 @@ static int32_t putSlotToHashImpl(int16_t dataBlockId, int16_t slotId, const char
return taosHashPut(pHash, pName, len, &index, sizeof(SSlotIndex));
}
-static int32_t putSlotToHash(int16_t dataBlockId, int16_t slotId, SNode* pNode, SHashObj* pHash) {
- char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
- int32_t len = getSlotKey(pNode, NULL, name);
- return putSlotToHashImpl(dataBlockId, slotId, name, len, pHash);
+static int32_t putSlotToHash(const char* pName, int16_t dataBlockId, int16_t slotId, SNode* pNode, SHashObj* pHash) {
+ return putSlotToHashImpl(dataBlockId, slotId, pName, strlen(pName), pHash);
}
static int32_t createDataBlockDescHash(SPhysiPlanContext* pCxt, int32_t capacity, int16_t dataBlockId,
@@ -131,9 +135,11 @@ static int32_t buildDataBlockSlots(SPhysiPlanContext* pCxt, SNodeList* pList, SD
int16_t slotId = 0;
SNode* pNode = NULL;
FOREACH(pNode, pList) {
- code = nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, pNode, slotId, true, false));
+ char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
+ getSlotKey(pNode, NULL, name);
+ code = nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, name, pNode, slotId, true, false));
if (TSDB_CODE_SUCCESS == code) {
- code = putSlotToHash(pDataBlockDesc->dataBlockId, slotId, pNode, pHash);
+ code = putSlotToHash(name, pDataBlockDesc->dataBlockId, slotId, pNode, pHash);
}
if (TSDB_CODE_SUCCESS == code) {
pDataBlockDesc->totalRowSize += ((SExprNode*)pNode)->resType.bytes;
@@ -196,7 +202,8 @@ static int32_t addDataBlockSlotsImpl(SPhysiPlanContext* pCxt, SNodeList* pList,
int32_t len = getSlotKey(pExpr, pStmtName, name);
SSlotIndex* pIndex = taosHashGet(pHash, name, len);
if (NULL == pIndex) {
- code = nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, pExpr, nextSlotId, output, reserve));
+ code =
+ nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, name, pExpr, nextSlotId, output, reserve));
if (TSDB_CODE_SUCCESS == code) {
code = putSlotToHashImpl(pDataBlockDesc->dataBlockId, nextSlotId, name, len, pHash);
}
@@ -348,6 +355,9 @@ static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode
return NULL;
}
+ TSWAP(pPhysiNode->pLimit, pLogicNode->pLimit);
+ TSWAP(pPhysiNode->pSlimit, pLogicNode->pSlimit);
+
int32_t code = createDataBlockDesc(pCxt, pLogicNode->pTargets, &pPhysiNode->pOutputDataBlockDesc);
if (TSDB_CODE_SUCCESS != code) {
nodesDestroyNode((SNode*)pPhysiNode);
@@ -436,6 +446,15 @@ static int32_t createScanPhysiNodeFinalize(SPhysiPlanContext* pCxt, SSubplan* pS
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ if (NULL != pScanLogicNode->pTagIndexCond) {
+ pSubplan->pTagIndexCond = nodesCloneNode(pScanLogicNode->pTagIndexCond);
+ if (NULL == pSubplan->pTagIndexCond) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pScanPhysiNode;
} else {
@@ -462,6 +481,8 @@ static ENodeType getScanOperatorType(EScanType scanType) {
return QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN;
case SCAN_TYPE_BLOCK_INFO:
return QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN;
+ case SCAN_TYPE_LAST_ROW:
+ return QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN;
default:
break;
}
@@ -499,12 +520,13 @@ static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubp
tNameGetFullDbName(&pScanLogicNode->tableName, pSubplan->dbFName);
pTableScan->dataRequired = pScanLogicNode->dataRequired;
pTableScan->pDynamicScanFuncs = nodesCloneList(pScanLogicNode->pDynamicScanFuncs);
- pTableScan->pPartitionTags = nodesCloneList(pScanLogicNode->pPartTags);
+ pTableScan->pGroupTags = nodesCloneList(pScanLogicNode->pGroupTags);
if ((NULL != pScanLogicNode->pDynamicScanFuncs && NULL == pTableScan->pDynamicScanFuncs) ||
- (NULL != pScanLogicNode->pPartTags && NULL == pTableScan->pPartitionTags)) {
+ (NULL != pScanLogicNode->pGroupTags && NULL == pTableScan->pGroupTags)) {
nodesDestroyNode((SNode*)pTableScan);
return TSDB_CODE_OUT_OF_MEMORY;
}
+ pTableScan->groupSort = pScanLogicNode->groupSort;
pTableScan->interval = pScanLogicNode->interval;
pTableScan->offset = pScanLogicNode->offset;
pTableScan->sliding = pScanLogicNode->sliding;
@@ -512,8 +534,7 @@ static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubp
pTableScan->slidingUnit = pScanLogicNode->slidingUnit;
pTableScan->triggerType = pScanLogicNode->triggerType;
pTableScan->watermark = pScanLogicNode->watermark;
- pTableScan->tsColId = pScanLogicNode->tsColId;
- pTableScan->filesFactor = pScanLogicNode->filesFactor;
+ pTableScan->igExpired = pScanLogicNode->igExpired;
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pTableScan, pPhyNode);
}
@@ -531,6 +552,9 @@ static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan*
if (0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_USER_TABLES) ||
0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_USER_TABLE_DISTRIBUTED)) {
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
+ } else {
+ pSubplan->execNode.nodeId = MNODE_HANDLE;
+ pSubplan->execNode.epSet = pCxt->pPlanCxt->mgmtEpSet;
}
SQueryNodeLoad node = {.addr = {.nodeId = MNODE_HANDLE, .epSet = pCxt->pPlanCxt->mgmtEpSet}, .load = 0};
taosArrayPush(pCxt->pExecNodeList, &node);
@@ -559,6 +583,7 @@ static int32_t createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
switch (pScanLogicNode->scanType) {
case SCAN_TYPE_TAG:
case SCAN_TYPE_BLOCK_INFO:
+ case SCAN_TYPE_LAST_ROW:
return createSimpleScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
case SCAN_TYPE_TABLE:
return createTableScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
@@ -587,10 +612,8 @@ static int32_t createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
int32_t code = TSDB_CODE_SUCCESS;
pJoin->joinType = pJoinLogicNode->joinType;
- if (NULL != pJoinLogicNode->pOnConditions) {
- code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pOnConditions,
- &pJoin->pOnConditions);
- }
+ setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pMergeCondition,
+ &pJoin->pMergeCondition);
if (TSDB_CODE_SUCCESS == code) {
code = setListSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->node.pTargets,
&pJoin->pTargets);
@@ -598,6 +621,21 @@ static int32_t createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
if (TSDB_CODE_SUCCESS == code) {
code = addDataBlockSlots(pCxt, pJoin->pTargets, pJoin->node.pOutputDataBlockDesc);
}
+
+ SNodeList* condCols = nodesMakeList();
+ if (TSDB_CODE_SUCCESS == code && NULL != pJoinLogicNode->pOnConditions) {
+ code = nodesCollectColumnsFromNode(pJoinLogicNode->pOnConditions, NULL, COLLECT_COL_TYPE_ALL, &condCols);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = addDataBlockSlots(pCxt, condCols, pJoin->node.pOutputDataBlockDesc);
+ nodesDestroyList(condCols);
+ }
+
+ if (TSDB_CODE_SUCCESS == code && NULL != pJoinLogicNode->pOnConditions) {
+ code = setNodeSlotId(pCxt, ((SPhysiNode*)pJoin)->pOutputDataBlockDesc->dataBlockId, -1,
+ pJoinLogicNode->pOnConditions, &pJoin->pOnConditions);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
code = setConditionsSlotId(pCxt, (const SLogicNode*)pJoinLogicNode, (SPhysiNode*)pJoin);
}
@@ -732,7 +770,7 @@ static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SN
SRewritePrecalcExprsCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs};
nodesRewriteExprs(*pRewrittenList, doRewritePrecalcExprs, &cxt);
if (0 == LIST_LENGTH(cxt.pPrecalcExprs) || TSDB_CODE_SUCCESS != cxt.errCode) {
- DESTORY_LIST(*pPrecalcExprs);
+ NODES_DESTORY_LIST(*pPrecalcExprs);
}
return cxt.errCode;
}
@@ -841,12 +879,19 @@ static int32_t createIndefRowsFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList*
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pFuncLogicNode, (SPhysiNode*)pIdfRowsFunc);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pIdfRowsFunc;
} else {
nodesDestroyNode((SNode*)pIdfRowsFunc);
}
+ nodesDestroyList(pPrecalcExprs);
+ nodesDestroyList(pFuncs);
+
return code;
}
@@ -892,12 +937,19 @@ static int32_t createInterpFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pCh
code = setNodeSlotId(pCxt, pChildTupe->dataBlockId, -1, pFuncLogicNode->pTimeSeries, &pInterpFunc->pTimeSeries);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pFuncLogicNode, (SPhysiNode*)pInterpFunc);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pInterpFunc;
} else {
nodesDestroyNode((SNode*)pInterpFunc);
}
+ nodesDestroyList(pPrecalcExprs);
+ nodesDestroyList(pFuncs);
+
return code;
}
@@ -909,13 +961,16 @@ static int32_t createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChild
return TSDB_CODE_OUT_OF_MEMORY;
}
- pProject->limit = pProjectLogicNode->limit;
- pProject->offset = pProjectLogicNode->offset;
- pProject->slimit = pProjectLogicNode->slimit;
- pProject->soffset = pProjectLogicNode->soffset;
-
- int32_t code = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId,
- -1, pProjectLogicNode->pProjections, &pProject->pProjections);
+ int32_t code = TSDB_CODE_SUCCESS;
+ if (0 == LIST_LENGTH(pChildren)) {
+ pProject->pProjections = nodesCloneList(pProjectLogicNode->pProjections);
+ if (NULL == pProject->pProjections) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ } else {
+ code = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId, -1,
+ pProjectLogicNode->pProjections, &pProject->pProjections);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = addDataBlockSlotsForProject(pCxt, pProjectLogicNode->stmtName, pProject->pProjections,
pProject->node.pOutputDataBlockDesc);
@@ -1020,9 +1075,13 @@ static int32_t createWindowPhysiNodeFinalize(SPhysiPlanContext* pCxt, SNodeList*
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pWindowLogicNode, (SPhysiNode*)pWindow);
+ }
+
pWindow->triggerType = pWindowLogicNode->triggerType;
pWindow->watermark = pWindowLogicNode->watermark;
- pWindow->filesFactor = pWindowLogicNode->filesFactor;
+ pWindow->igExpired = pWindowLogicNode->igExpired;
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pWindow;
@@ -1030,6 +1089,9 @@ static int32_t createWindowPhysiNodeFinalize(SPhysiPlanContext* pCxt, SNodeList*
nodesDestroyNode((SNode*)pWindow);
}
+ nodesDestroyList(pPrecalcExprs);
+ nodesDestroyList(pFuncs);
+
return code;
}
@@ -1038,7 +1100,7 @@ static ENodeType getIntervalOperatorType(EWindowAlgorithm windowAlgo) {
case INTERVAL_ALGO_HASH:
return QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL;
case INTERVAL_ALGO_MERGE:
- return QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL;
+ return QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL;
case INTERVAL_ALGO_STREAM_FINAL:
return QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL;
case INTERVAL_ALGO_STREAM_SEMI:
@@ -1143,8 +1205,9 @@ static int32_t createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildr
static int32_t createSortPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SSortLogicNode* pSortLogicNode,
SPhysiNode** pPhyNode) {
- SSortPhysiNode* pSort =
- (SSortPhysiNode*)makePhysiNode(pCxt, (SLogicNode*)pSortLogicNode, QUERY_NODE_PHYSICAL_PLAN_SORT);
+ SSortPhysiNode* pSort = (SSortPhysiNode*)makePhysiNode(
+ pCxt, (SLogicNode*)pSortLogicNode,
+ pSortLogicNode->groupSort ? QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT : QUERY_NODE_PHYSICAL_PLAN_SORT);
if (NULL == pSort) {
return TSDB_CODE_OUT_OF_MEMORY;
}
@@ -1158,7 +1221,7 @@ static int32_t createSortPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
if (TSDB_CODE_SUCCESS == code && NULL != pPrecalcExprs) {
code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs, &pSort->pExprs);
if (TSDB_CODE_SUCCESS == code) {
- code = addDataBlockSlots(pCxt, pSort->pExprs, pChildTupe);
+ code = pushdownDataBlockSlots(pCxt, pSort->pExprs, pChildTupe);
}
}
@@ -1173,12 +1236,19 @@ static int32_t createSortPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pSortLogicNode, (SPhysiNode*)pSort);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pSort;
} else {
nodesDestroyNode((SNode*)pSort);
}
+ nodesDestroyList(pPrecalcExprs);
+ nodesDestroyList(pSortKeys);
+
return code;
}
@@ -1214,12 +1284,19 @@ static int32_t createPartitionPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChi
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pPartLogicNode, (SPhysiNode*)pPart);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pPart;
} else {
nodesDestroyNode((SNode*)pPart);
}
+ nodesDestroyList(pPrecalcExprs);
+ nodesDestroyList(pPartitionKeys);
+
return code;
}
@@ -1240,10 +1317,7 @@ static int32_t createFillPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
}
if (TSDB_CODE_SUCCESS == code) {
- pFill->pWStartTs = nodesCloneNode(pFillNode->pWStartTs);
- if (NULL == pFill->pWStartTs) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- }
+ code = setNodeSlotId(pCxt, pChildTupe->dataBlockId, -1, pFillNode->pWStartTs, &pFill->pWStartTs);
}
if (TSDB_CODE_SUCCESS == code && NULL != pFillNode->pValues) {
@@ -1253,6 +1327,10 @@ static int32_t createFillPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
}
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = setConditionsSlotId(pCxt, (const SLogicNode*)pFillNode, (SPhysiNode*)pFill);
+ }
+
if (TSDB_CODE_SUCCESS == code) {
*pPhyNode = (SPhysiNode*)pFill;
} else {
@@ -1289,6 +1367,7 @@ static int32_t createMergePhysiNode(SPhysiPlanContext* pCxt, SMergeLogicNode* pM
pMerge->numOfChannels = pMergeLogicNode->numOfChannels;
pMerge->srcGroupId = pMergeLogicNode->srcGroupId;
+ pMerge->groupSort = pMergeLogicNode->groupSort;
int32_t code = addDataBlockSlots(pCxt, pMergeLogicNode->pInputs, pMerge->node.pOutputDataBlockDesc);
@@ -1301,7 +1380,7 @@ static int32_t createMergePhysiNode(SPhysiPlanContext* pCxt, SMergeLogicNode* pM
}
}
- if (TSDB_CODE_SUCCESS == code) {
+ if (TSDB_CODE_SUCCESS == code && NULL != pMergeLogicNode->pMergeKeys) {
code = setListSlotId(pCxt, pMerge->node.pOutputDataBlockDesc->dataBlockId, -1, pMergeLogicNode->pMergeKeys,
&pMerge->pMergeKeys);
}
@@ -1432,15 +1511,70 @@ static SSubplan* makeSubplan(SPhysiPlanContext* pCxt, SLogicSubplan* pLogicSubpl
pSubplan->id = pLogicSubplan->id;
pSubplan->subplanType = pLogicSubplan->subplanType;
pSubplan->level = pLogicSubplan->level;
+ if (NULL != pCxt->pPlanCxt->pUser) {
+ strcpy(pSubplan->user, pCxt->pPlanCxt->pUser);
+ }
return pSubplan;
}
-static int32_t buildInsertSubplan(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, SSubplan* pSubplan) {
+static int32_t buildInsertValuesSubplan(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, SSubplan* pSubplan) {
pSubplan->msgType = pModify->msgType;
+ pSubplan->execNode.nodeId = pModify->pVgDataBlocks->vg.vgId;
pSubplan->execNode.epSet = pModify->pVgDataBlocks->vg.epSet;
return createDataInserter(pCxt, pModify->pVgDataBlocks, &pSubplan->pDataSink);
}
+static int32_t createQueryInserter(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, SSubplan* pSubplan,
+ SDataSinkNode** pSink) {
+ SQueryInserterNode* pInserter = (SQueryInserterNode*)nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT);
+ if (NULL == pInserter) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ pInserter->tableId = pModify->tableId;
+ pInserter->stableId = pModify->stableId;
+ pInserter->tableType = pModify->tableType;
+ strcpy(pInserter->tableFName, pModify->tableFName);
+ pInserter->vgId = pModify->pVgroupList->vgroups[0].vgId;
+ pInserter->epSet = pModify->pVgroupList->vgroups[0].epSet;
+ vgroupInfoToNodeAddr(pModify->pVgroupList->vgroups, &pSubplan->execNode);
+
+ int32_t code = setListSlotId(pCxt, pSubplan->pNode->pOutputDataBlockDesc->dataBlockId, -1, pModify->pInsertCols,
+ &pInserter->pCols);
+ if (TSDB_CODE_SUCCESS == code) {
+ pInserter->sink.pInputDataBlockDesc =
+ (SDataBlockDescNode*)nodesCloneNode((SNode*)pSubplan->pNode->pOutputDataBlockDesc);
+ if (NULL == pInserter->sink.pInputDataBlockDesc) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ *pSink = (SDataSinkNode*)pInserter;
+ } else {
+ nodesDestroyNode((SNode*)pInserter);
+ }
+
+ return code;
+}
+
+static int32_t buildInsertSelectSubplan(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, SSubplan* pSubplan) {
+ int32_t code =
+ createPhysiNode(pCxt, (SLogicNode*)nodesListGetNode(pModify->node.pChildren, 0), pSubplan, &pSubplan->pNode);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = createQueryInserter(pCxt, pModify, pSubplan, &pSubplan->pDataSink);
+ }
+ pSubplan->msgType = TDMT_SCH_MERGE_QUERY;
+ return code;
+}
+
+static int32_t buildInsertSubplan(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, SSubplan* pSubplan) {
+ if (NULL == pModify->node.pChildren) {
+ return buildInsertValuesSubplan(pCxt, pModify, pSubplan);
+ }
+ return buildInsertSelectSubplan(pCxt, pModify, pSubplan);
+}
+
static int32_t createDataDeleter(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* pModify, const SPhysiNode* pRoot,
SDataSinkNode** pSink) {
SDataDeleterNode* pDeleter = (SDataDeleterNode*)nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DELETE);
@@ -1509,7 +1643,11 @@ static int32_t createPhysiSubplan(SPhysiPlanContext* pCxt, SLogicSubplan* pLogic
if (SUBPLAN_TYPE_MODIFY == pLogicSubplan->subplanType) {
code = buildVnodeModifySubplan(pCxt, pLogicSubplan, pSubplan);
} else {
- pSubplan->msgType = TDMT_VND_QUERY;
+ if (SUBPLAN_TYPE_SCAN == pSubplan->subplanType) {
+ pSubplan->msgType = TDMT_SCH_QUERY;
+ } else {
+ pSubplan->msgType = TDMT_SCH_MERGE_QUERY;
+ }
code = createPhysiNode(pCxt, pLogicSubplan->pNode, pSubplan, &pSubplan->pNode);
if (TSDB_CODE_SUCCESS == code && !pCxt->pPlanCxt->streamQuery && !pCxt->pPlanCxt->topicQuery) {
code = createDataDispatcher(pCxt, pSubplan->pNode, &pSubplan->pDataSink);
diff --git a/source/libs/planner/src/planScaleOut.c b/source/libs/planner/src/planScaleOut.c
index a0b63ad6ff9d987fef2e31d7b0abdcf14d9b541b..1f43d543333c21bc27bf35dd582950a8601219d6 100644
--- a/source/libs/planner/src/planScaleOut.c
+++ b/source/libs/planner/src/planScaleOut.c
@@ -82,29 +82,41 @@ static int32_t scaleOutByVgroups(SScaleOutContext* pCxt, SLogicSubplan* pSubplan
return code;
}
-static int32_t scaleOutForModify(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
+static int32_t scaleOutForMerge(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
+ return nodesListStrictAppend(pGroup, (SNode*)singleCloneSubLogicPlan(pCxt, pSubplan, level));
+}
+
+static int32_t scaleOutForInsertValues(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level,
+ SNodeList* pGroup) {
SVnodeModifyLogicNode* pNode = (SVnodeModifyLogicNode*)pSubplan->pNode;
- if (MODIFY_TABLE_TYPE_DELETE == pNode->modifyType) {
- return scaleOutByVgroups(pCxt, pSubplan, level, pGroup);
- } else {
- size_t numOfVgroups = taosArrayGetSize(pNode->pDataBlocks);
- for (int32_t i = 0; i < numOfVgroups; ++i) {
- SLogicSubplan* pNewSubplan = singleCloneSubLogicPlan(pCxt, pSubplan, level);
- if (NULL == pNewSubplan) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- ((SVnodeModifyLogicNode*)pNewSubplan->pNode)->pVgDataBlocks =
- (SVgDataBlocks*)taosArrayGetP(pNode->pDataBlocks, i);
- if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pGroup, (SNode*)pNewSubplan)) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
+ size_t numOfVgroups = taosArrayGetSize(pNode->pDataBlocks);
+ for (int32_t i = 0; i < numOfVgroups; ++i) {
+ SLogicSubplan* pNewSubplan = singleCloneSubLogicPlan(pCxt, pSubplan, level);
+ if (NULL == pNewSubplan) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ ((SVnodeModifyLogicNode*)pNewSubplan->pNode)->pVgDataBlocks = (SVgDataBlocks*)taosArrayGetP(pNode->pDataBlocks, i);
+ if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pGroup, (SNode*)pNewSubplan)) {
+ return TSDB_CODE_OUT_OF_MEMORY;
}
- return TSDB_CODE_SUCCESS;
}
+ return TSDB_CODE_SUCCESS;
}
-static int32_t scaleOutForMerge(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
- return nodesListStrictAppend(pGroup, (SNode*)singleCloneSubLogicPlan(pCxt, pSubplan, level));
+static int32_t scaleOutForInsert(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
+ SVnodeModifyLogicNode* pNode = (SVnodeModifyLogicNode*)pSubplan->pNode;
+ if (NULL == pNode->node.pChildren) {
+ return scaleOutForInsertValues(pCxt, pSubplan, level, pGroup);
+ }
+ return scaleOutForMerge(pCxt, pSubplan, level, pGroup);
+}
+
+static int32_t scaleOutForModify(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
+ SVnodeModifyLogicNode* pNode = (SVnodeModifyLogicNode*)pSubplan->pNode;
+ if (MODIFY_TABLE_TYPE_DELETE == pNode->modifyType) {
+ return scaleOutByVgroups(pCxt, pSubplan, level, pGroup);
+ }
+ return scaleOutForInsert(pCxt, pSubplan, level, pGroup);
}
static int32_t scaleOutForScan(SScaleOutContext* pCxt, SLogicSubplan* pSubplan, int32_t level, SNodeList* pGroup) {
diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c
index 390d665760bcda5d5fd0acfecad27ca3bb82193b..7b9d553501a274e5ccaedcd09a8e4c622392de03 100644
--- a/source/libs/planner/src/planSpliter.c
+++ b/source/libs/planner/src/planSpliter.c
@@ -20,6 +20,7 @@
#define SPLIT_FLAG_MASK(n) (1 << n)
#define SPLIT_FLAG_STABLE_SPLIT SPLIT_FLAG_MASK(0)
+#define SPLIT_FLAG_INSERT_SPLIT SPLIT_FLAG_MASK(1)
#define SPLIT_FLAG_SET_MASK(val, mask) (val) |= (mask)
#define SPLIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0)
@@ -38,7 +39,6 @@ typedef struct SSplitRule {
FSplit splitFunc;
} SSplitRule;
-// typedef bool (*FSplFindSplitNode)(SSplitContext* pCxt, SLogicSubplan* pSubplan, void* pInfo);
typedef bool (*FSplFindSplitNode)(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pNode, void* pInfo);
static void splSetSubplanVgroups(SLogicSubplan* pSubplan, SLogicNode* pNode) {
@@ -66,6 +66,19 @@ static SLogicSubplan* splCreateScanSubplan(SSplitContext* pCxt, SLogicNode* pNod
return pSubplan;
}
+static SLogicSubplan* splCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode, ESubplanType subplanType) {
+ SLogicSubplan* pSubplan = (SLogicSubplan*)nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
+ if (NULL == pSubplan) {
+ return NULL;
+ }
+ pSubplan->id.queryId = pCxt->queryId;
+ pSubplan->id.groupId = pCxt->groupId;
+ pSubplan->subplanType = subplanType;
+ pSubplan->pNode = pNode;
+ pNode->pParent = NULL;
+ return pSubplan;
+}
+
static int32_t splCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pChild, SExchangeLogicNode** pOutput) {
SExchangeLogicNode* pExchange = (SExchangeLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE);
if (NULL == pExchange) {
@@ -97,6 +110,43 @@ static int32_t splCreateExchangeNodeForSubplan(SSplitContext* pCxt, SLogicSubpla
return code;
}
+static bool splIsChildSubplan(SLogicNode* pLogicNode, int32_t groupId) {
+ if (QUERY_NODE_LOGIC_PLAN_EXCHANGE == nodeType(pLogicNode)) {
+ return ((SExchangeLogicNode*)pLogicNode)->srcGroupId == groupId;
+ }
+
+ if (QUERY_NODE_LOGIC_PLAN_MERGE == nodeType(pLogicNode)) {
+ return ((SMergeLogicNode*)pLogicNode)->srcGroupId == groupId;
+ }
+
+ SNode* pChild;
+ FOREACH(pChild, pLogicNode->pChildren) {
+ bool isChild = splIsChildSubplan((SLogicNode*)pChild, groupId);
+ if (isChild) {
+ return isChild;
+ }
+ }
+ return false;
+}
+
+static int32_t splMountSubplan(SLogicSubplan* pParent, SNodeList* pChildren) {
+ SNode* pChild = NULL;
+ WHERE_EACH(pChild, pChildren) {
+ if (splIsChildSubplan(pParent->pNode, ((SLogicSubplan*)pChild)->id.groupId)) {
+ int32_t code = nodesListMakeAppend(&pParent->pChildren, pChild);
+ if (TSDB_CODE_SUCCESS == code) {
+ REPLACE_NODE(NULL);
+ ERASE_NODE(pChildren);
+ continue;
+ } else {
+ return code;
+ }
+ }
+ WHERE_NEXT;
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
static bool splMatchByNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pNode, FSplFindSplitNode func,
void* pInfo) {
if (func(pCxt, pSubplan, pNode, pInfo)) {
@@ -166,21 +216,43 @@ static bool stbSplHasMultiTbScan(bool streamQuery, SLogicNode* pNode) {
return (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pChild) && stbSplIsMultiTbScan(streamQuery, (SScanLogicNode*)pChild));
}
+static bool stbSplNeedSplitWindow(bool streamQuery, SLogicNode* pNode) {
+ SWindowLogicNode* pWindow = (SWindowLogicNode*)pNode;
+ if (WINDOW_TYPE_INTERVAL == pWindow->winType) {
+ return !stbSplHasGatherExecFunc(pWindow->pFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
+ }
+
+ if (WINDOW_TYPE_SESSION == pWindow->winType) {
+ if (!streamQuery) {
+ return stbSplHasMultiTbScan(streamQuery, pNode);
+ } else {
+ return !stbSplHasGatherExecFunc(pWindow->pFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
+ }
+ }
+
+ if (WINDOW_TYPE_STATE == pWindow->winType) {
+ if (!streamQuery) {
+ return stbSplHasMultiTbScan(streamQuery, pNode);
+ } else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
static bool stbSplNeedSplit(bool streamQuery, SLogicNode* pNode) {
switch (nodeType(pNode)) {
case QUERY_NODE_LOGIC_PLAN_SCAN:
return stbSplIsMultiTbScan(streamQuery, (SScanLogicNode*)pNode);
case QUERY_NODE_LOGIC_PLAN_JOIN:
return !(((SJoinLogicNode*)pNode)->isSingleTableJoin);
+ case QUERY_NODE_LOGIC_PLAN_PARTITION:
+ return stbSplHasMultiTbScan(streamQuery, pNode);
case QUERY_NODE_LOGIC_PLAN_AGG:
return !stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
- case QUERY_NODE_LOGIC_PLAN_WINDOW: {
- SWindowLogicNode* pWindow = (SWindowLogicNode*)pNode;
- if (WINDOW_TYPE_STATE == pWindow->winType || (!streamQuery && WINDOW_TYPE_SESSION == pWindow->winType) ) {
- return false;
- }
- return !stbSplHasGatherExecFunc(pWindow->pFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
- }
+ case QUERY_NODE_LOGIC_PLAN_WINDOW:
+ return stbSplNeedSplitWindow(streamQuery, pNode);
case QUERY_NODE_LOGIC_PLAN_SORT:
return stbSplHasMultiTbScan(streamQuery, pNode);
default:
@@ -236,7 +308,7 @@ static int32_t stbSplAppendWStart(SNodeList* pFuncs, int32_t* pIndex) {
int32_t index = 0;
SNode* pFunc = NULL;
FOREACH(pFunc, pFuncs) {
- if (FUNCTION_TYPE_WSTARTTS == ((SFunctionNode*)pFunc)->funcType) {
+ if (FUNCTION_TYPE_WSTART == ((SFunctionNode*)pFunc)->funcType) {
*pIndex = index;
return TSDB_CODE_SUCCESS;
}
@@ -247,7 +319,7 @@ static int32_t stbSplAppendWStart(SNodeList* pFuncs, int32_t* pIndex) {
if (NULL == pWStart) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- strcpy(pWStart->functionName, "_wstartts");
+ strcpy(pWStart->functionName, "_wstart");
snprintf(pWStart->node.aliasName, sizeof(pWStart->node.aliasName), "%s.%p", pWStart->functionName, pWStart);
int32_t code = fmGetFuncInfo(pWStart, NULL, 0);
if (TSDB_CODE_SUCCESS == code) {
@@ -261,7 +333,7 @@ static int32_t stbSplAppendWEnd(SWindowLogicNode* pWin, int32_t* pIndex) {
int32_t index = 0;
SNode* pFunc = NULL;
FOREACH(pFunc, pWin->pFuncs) {
- if (FUNCTION_TYPE_WENDTS == ((SFunctionNode*)pFunc)->funcType) {
+ if (FUNCTION_TYPE_WEND == ((SFunctionNode*)pFunc)->funcType) {
*pIndex = index;
return TSDB_CODE_SUCCESS;
}
@@ -272,7 +344,7 @@ static int32_t stbSplAppendWEnd(SWindowLogicNode* pWin, int32_t* pIndex) {
if (NULL == pWEnd) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- strcpy(pWEnd->functionName, "_wendts");
+ strcpy(pWEnd->functionName, "_wend");
snprintf(pWEnd->node.aliasName, sizeof(pWEnd->node.aliasName), "%s.%p", pWEnd->functionName, pWEnd);
int32_t code = fmGetFuncInfo(pWEnd, NULL, 0);
if (TSDB_CODE_SUCCESS == code) {
@@ -342,7 +414,7 @@ static int32_t stbSplGetNumOfVgroups(SLogicNode* pNode) {
}
static int32_t stbSplCreateMergeNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pSplitNode,
- SNodeList* pMergeKeys, SLogicNode* pPartChild) {
+ SNodeList* pMergeKeys, SLogicNode* pPartChild, bool groupSort) {
SMergeLogicNode* pMerge = (SMergeLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_MERGE);
if (NULL == pMerge) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -351,10 +423,11 @@ static int32_t stbSplCreateMergeNode(SSplitContext* pCxt, SLogicSubplan* pSubpla
pMerge->srcGroupId = pCxt->groupId;
pMerge->node.precision = pPartChild->precision;
pMerge->pMergeKeys = pMergeKeys;
+ pMerge->groupSort = groupSort;
int32_t code = TSDB_CODE_SUCCESS;
pMerge->pInputs = nodesCloneList(pPartChild->pTargets);
- // NULL == pSubplan means 'merge node' replaces 'split node'.
+ // NULL != pSubplan means 'merge node' replaces 'split node'.
if (NULL == pSubplan) {
pMerge->node.pTargets = nodesCloneList(pPartChild->pTargets);
} else {
@@ -380,6 +453,7 @@ static int32_t stbSplCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pParent
SExchangeLogicNode* pExchange = NULL;
int32_t code = splCreateExchangeNode(pCxt, pPartChild, &pExchange);
if (TSDB_CODE_SUCCESS == code) {
+ pExchange->node.pParent = pParent;
code = nodesListMakeAppend(&pParent->pChildren, (SNode*)pExchange);
}
return code;
@@ -409,7 +483,7 @@ static int32_t stbSplSplitIntervalForBatch(SSplitContext* pCxt, SStableSplitInfo
SNodeList* pMergeKeys = NULL;
code = stbSplCreateMergeKeysByPrimaryKey(((SWindowLogicNode*)pInfo->pSplitNode)->pTspk, &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
- code = stbSplCreateMergeNode(pCxt, NULL, pInfo->pSplitNode, pMergeKeys, pPartWindow);
+ code = stbSplCreateMergeNode(pCxt, NULL, pInfo->pSplitNode, pMergeKeys, pPartWindow, true);
}
if (TSDB_CODE_SUCCESS != code) {
nodesDestroyList(pMergeKeys);
@@ -476,26 +550,133 @@ static int32_t stbSplSplitSessionForStream(SSplitContext* pCxt, SStableSplitInfo
return code;
}
+static void stbSplSetTableMergeScan(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
+ SScanLogicNode* pScan = (SScanLogicNode*)pNode;
+ pScan->scanType = SCAN_TYPE_TABLE_MERGE;
+ if (NULL != pScan->pGroupTags) {
+ pScan->groupSort = true;
+ }
+ } else {
+ if (1 == LIST_LENGTH(pNode->pChildren)) {
+ stbSplSetTableMergeScan((SLogicNode*)nodesListGetNode(pNode->pChildren, 0));
+ }
+ }
+}
+
+static int32_t stbSplSplitSessionOrStateForBatch(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ SLogicNode* pWindow = pInfo->pSplitNode;
+ SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pWindow->pChildren, 0);
+
+ SNodeList* pMergeKeys = NULL;
+ int32_t code = stbSplCreateMergeKeysByPrimaryKey(((SWindowLogicNode*)pWindow)->pTspk, &pMergeKeys);
+
+ if (TSDB_CODE_SUCCESS == code) {
+ code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pChild, pMergeKeys, (SLogicNode*)pChild, true);
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
+ (SNode*)splCreateScanSubplan(pCxt, pChild, SPLIT_FLAG_STABLE_SPLIT));
+ }
+
+ if (TSDB_CODE_SUCCESS == code) {
+ stbSplSetTableMergeScan(pChild);
+ pInfo->pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
+ SPLIT_FLAG_SET_MASK(pInfo->pSubplan->splitFlag, SPLIT_FLAG_STABLE_SPLIT);
+ ++(pCxt->groupId);
+ } else {
+ nodesDestroyList(pMergeKeys);
+ }
+
+ return code;
+}
+
static int32_t stbSplSplitSession(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
if (pCxt->pPlanCxt->streamQuery) {
return stbSplSplitSessionForStream(pCxt, pInfo);
} else {
- return TSDB_CODE_PLAN_INTERNAL_ERROR;
+ return stbSplSplitSessionOrStateForBatch(pCxt, pInfo);
}
}
-static int32_t stbSplSplitWindowNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+static int32_t stbSplSplitStateForStream(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ return TSDB_CODE_PLAN_INTERNAL_ERROR;
+}
+
+static int32_t stbSplSplitState(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ if (pCxt->pPlanCxt->streamQuery) {
+ return stbSplSplitStateForStream(pCxt, pInfo);
+ } else {
+ return stbSplSplitSessionOrStateForBatch(pCxt, pInfo);
+ }
+}
+
+static SNodeList* stbSplGetPartKeys(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
+ return ((SScanLogicNode*)pNode)->pGroupTags;
+ } else if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
+ return ((SPartitionLogicNode*)pNode)->pPartitionKeys;
+ } else {
+ return NULL;
+ }
+}
+
+static bool stbSplIsPartTbanme(SNodeList* pPartKeys) {
+ if (NULL == pPartKeys || 1 != LIST_LENGTH(pPartKeys)) {
+ return false;
+ }
+ SNode* pPartKey = nodesListGetNode(pPartKeys, 0);
+ return (QUERY_NODE_FUNCTION == nodeType(pPartKey) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pPartKey)->funcType) ||
+ (QUERY_NODE_COLUMN == nodeType(pPartKey) && COLUMN_TYPE_TBNAME == ((SColumnNode*)pPartKey)->colType);
+}
+
+static bool stbSplIsPartTableWinodw(SWindowLogicNode* pWindow) {
+ return stbSplIsPartTbanme(stbSplGetPartKeys((SLogicNode*)nodesListGetNode(pWindow->node.pChildren, 0)));
+}
+
+static int32_t stbSplSplitWindowForCrossTable(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
switch (((SWindowLogicNode*)pInfo->pSplitNode)->winType) {
case WINDOW_TYPE_INTERVAL:
return stbSplSplitInterval(pCxt, pInfo);
case WINDOW_TYPE_SESSION:
return stbSplSplitSession(pCxt, pInfo);
+ case WINDOW_TYPE_STATE:
+ return stbSplSplitState(pCxt, pInfo);
default:
break;
}
return TSDB_CODE_PLAN_INTERNAL_ERROR;
}
+static int32_t stbSplSplitWindowForPartTable(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ if (pCxt->pPlanCxt->streamQuery) {
+ SPLIT_FLAG_SET_MASK(pInfo->pSubplan->splitFlag, SPLIT_FLAG_STABLE_SPLIT);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SExchangeLogicNode* pExchange = NULL;
+ int32_t code = splCreateExchangeNode(pCxt, pInfo->pSplitNode, &pExchange);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = replaceLogicNode(pInfo->pSubplan, pInfo->pSplitNode, (SLogicNode*)pExchange);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
+ (SNode*)splCreateScanSubplan(pCxt, pInfo->pSplitNode, SPLIT_FLAG_STABLE_SPLIT));
+ }
+ pInfo->pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
+ ++(pCxt->groupId);
+ return code;
+}
+
+static int32_t stbSplSplitWindowNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ if (stbSplIsPartTableWinodw((SWindowLogicNode*)pInfo->pSplitNode)) {
+ return stbSplSplitWindowForPartTable(pCxt, pInfo);
+ } else {
+ return stbSplSplitWindowForCrossTable(pCxt, pInfo);
+ }
+}
+
static int32_t stbSplCreatePartAggNode(SAggLogicNode* pMergeAgg, SLogicNode** pOutput) {
SNodeList* pFunc = pMergeAgg->pAggFuncs;
pMergeAgg->pAggFuncs = NULL;
@@ -648,6 +829,7 @@ static int32_t stbSplCreatePartSortNode(SSortLogicNode* pSort, SLogicNode** pOut
pPartSort->node.pChildren = pChildren;
splSetParent((SLogicNode*)pPartSort);
pPartSort->pSortKeys = pSortKeys;
+ pPartSort->groupSort = pSort->groupSort;
code = stbSplCreateMergeKeys(pPartSort->pSortKeys, pPartSort->node.pTargets, &pMergeKeys);
}
@@ -662,12 +844,29 @@ static int32_t stbSplCreatePartSortNode(SSortLogicNode* pSort, SLogicNode** pOut
return code;
}
+static void stbSplSetScanPartSort(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
+ SScanLogicNode* pScan = (SScanLogicNode*)pNode;
+ if (NULL != pScan->pGroupTags) {
+ pScan->groupSort = true;
+ }
+ } else {
+ if (1 == LIST_LENGTH(pNode->pChildren)) {
+ stbSplSetScanPartSort((SLogicNode*)nodesListGetNode(pNode->pChildren, 0));
+ }
+ }
+}
+
static int32_t stbSplSplitSortNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
SLogicNode* pPartSort = NULL;
SNodeList* pMergeKeys = NULL;
+ bool groupSort = ((SSortLogicNode*)pInfo->pSplitNode)->groupSort;
int32_t code = stbSplCreatePartSortNode((SSortLogicNode*)pInfo->pSplitNode, &pPartSort, &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
- code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, pMergeKeys, pPartSort);
+ code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, pMergeKeys, pPartSort, groupSort);
+ }
+ if (TSDB_CODE_SUCCESS == code && groupSort) {
+ stbSplSetScanPartSort(pPartSort);
}
if (TSDB_CODE_SUCCESS == code) {
code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
@@ -678,7 +877,7 @@ static int32_t stbSplSplitSortNode(SSplitContext* pCxt, SStableSplitInfo* pInfo)
return code;
}
-static int32_t stbSplSplitScanNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+static int32_t stbSplSplitScanNodeWithoutPartTags(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
int32_t code = splCreateExchangeNodeForSubplan(pCxt, pInfo->pSubplan, pInfo->pSplitNode, SUBPLAN_TYPE_MERGE);
if (TSDB_CODE_SUCCESS == code) {
code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
@@ -688,6 +887,25 @@ static int32_t stbSplSplitScanNode(SSplitContext* pCxt, SStableSplitInfo* pInfo)
return code;
}
+static int32_t stbSplSplitScanNodeWithPartTags(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ int32_t code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, NULL, pInfo->pSplitNode, true);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
+ (SNode*)splCreateScanSubplan(pCxt, pInfo->pSplitNode, SPLIT_FLAG_STABLE_SPLIT));
+ }
+ pInfo->pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
+ ++(pCxt->groupId);
+ return code;
+}
+
+static int32_t stbSplSplitScanNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ SScanLogicNode* pScan = (SScanLogicNode*)pInfo->pSplitNode;
+ if (NULL != pScan->pGroupTags) {
+ return stbSplSplitScanNodeWithPartTags(pCxt, pInfo);
+ }
+ return stbSplSplitScanNodeWithoutPartTags(pCxt, pInfo);
+}
+
static SNode* stbSplFindPrimaryKeyFromScan(SScanLogicNode* pScan) {
SNode* pCol = NULL;
FOREACH(pCol, pScan->pScanCols) {
@@ -702,7 +920,7 @@ static int32_t stbSplSplitScanNodeForJoin(SSplitContext* pCxt, SLogicSubplan* pS
SNodeList* pMergeKeys = NULL;
int32_t code = stbSplCreateMergeKeysByPrimaryKey(stbSplFindPrimaryKeyFromScan(pScan), &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
- code = stbSplCreateMergeNode(pCxt, pSubplan, (SLogicNode*)pScan, pMergeKeys, (SLogicNode*)pScan);
+ code = stbSplCreateMergeNode(pCxt, pSubplan, (SLogicNode*)pScan, pMergeKeys, (SLogicNode*)pScan, false);
}
if (TSDB_CODE_SUCCESS == code) {
code = nodesListMakeStrictAppend(&pSubplan->pChildren,
@@ -740,6 +958,17 @@ static int32_t stbSplSplitJoinNode(SSplitContext* pCxt, SStableSplitInfo* pInfo)
return code;
}
+static int32_t stbSplSplitPartitionNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
+ int32_t code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, NULL, pInfo->pSplitNode, true);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
+ (SNode*)splCreateScanSubplan(pCxt, pInfo->pSplitNode, SPLIT_FLAG_STABLE_SPLIT));
+ }
+ pInfo->pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
+ ++(pCxt->groupId);
+ return code;
+}
+
static int32_t stableSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
if (pCxt->pPlanCxt->rSmaQuery) {
return TSDB_CODE_SUCCESS;
@@ -758,6 +987,9 @@ static int32_t stableSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
case QUERY_NODE_LOGIC_PLAN_JOIN:
code = stbSplSplitJoinNode(pCxt, &info);
break;
+ case QUERY_NODE_LOGIC_PLAN_PARTITION:
+ code = stbSplSplitPartitionNode(pCxt, &info);
+ break;
case QUERY_NODE_LOGIC_PLAN_AGG:
code = stbSplSplitAggNode(pCxt, &info);
break;
@@ -819,52 +1051,6 @@ static int32_t singleTableJoinSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan
return code;
}
-static bool unionIsChildSubplan(SLogicNode* pLogicNode, int32_t groupId) {
- if (QUERY_NODE_LOGIC_PLAN_EXCHANGE == nodeType(pLogicNode)) {
- return ((SExchangeLogicNode*)pLogicNode)->srcGroupId == groupId;
- }
-
- SNode* pChild;
- FOREACH(pChild, pLogicNode->pChildren) {
- bool isChild = unionIsChildSubplan((SLogicNode*)pChild, groupId);
- if (isChild) {
- return isChild;
- }
- }
- return false;
-}
-
-static int32_t unionMountSubplan(SLogicSubplan* pParent, SNodeList* pChildren) {
- SNode* pChild = NULL;
- WHERE_EACH(pChild, pChildren) {
- if (unionIsChildSubplan(pParent->pNode, ((SLogicSubplan*)pChild)->id.groupId)) {
- int32_t code = nodesListMakeAppend(&pParent->pChildren, pChild);
- if (TSDB_CODE_SUCCESS == code) {
- REPLACE_NODE(NULL);
- ERASE_NODE(pChildren);
- continue;
- } else {
- return code;
- }
- }
- WHERE_NEXT;
- }
- return TSDB_CODE_SUCCESS;
-}
-
-static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode) {
- SLogicSubplan* pSubplan = (SLogicSubplan*)nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
- if (NULL == pSubplan) {
- return NULL;
- }
- pSubplan->id.queryId = pCxt->queryId;
- pSubplan->id.groupId = pCxt->groupId;
- pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
- pSubplan->pNode = pNode;
- pNode->pParent = NULL;
- return pSubplan;
-}
-
static int32_t unionSplitSubplan(SSplitContext* pCxt, SLogicSubplan* pUnionSubplan, SLogicNode* pSplitNode) {
SNodeList* pSubplanChildren = pUnionSubplan->pChildren;
pUnionSubplan->pChildren = NULL;
@@ -873,11 +1059,11 @@ static int32_t unionSplitSubplan(SSplitContext* pCxt, SLogicSubplan* pUnionSubpl
SNode* pChild = NULL;
FOREACH(pChild, pSplitNode->pChildren) {
- SLogicSubplan* pNewSubplan = unionCreateSubplan(pCxt, (SLogicNode*)pChild);
+ SLogicSubplan* pNewSubplan = splCreateSubplan(pCxt, (SLogicNode*)pChild, pUnionSubplan->subplanType);
code = nodesListMakeStrictAppend(&pUnionSubplan->pChildren, (SNode*)pNewSubplan);
if (TSDB_CODE_SUCCESS == code) {
REPLACE_NODE(NULL);
- code = unionMountSubplan(pNewSubplan, pSubplanChildren);
+ code = splMountSubplan(pNewSubplan, pSubplanChildren);
}
if (TSDB_CODE_SUCCESS != code) {
break;
@@ -885,7 +1071,7 @@ static int32_t unionSplitSubplan(SSplitContext* pCxt, SLogicSubplan* pUnionSubpl
}
if (TSDB_CODE_SUCCESS == code) {
nodesDestroyList(pSubplanChildren);
- DESTORY_LIST(pSplitNode->pChildren);
+ NODES_DESTORY_LIST(pSplitNode->pChildren);
}
return code;
}
@@ -916,6 +1102,7 @@ static int32_t unAllSplCreateExchangeNode(SSplitContext* pCxt, SLogicSubplan* pS
if (NULL == pExchange->node.pTargets) {
return TSDB_CODE_OUT_OF_MEMORY;
}
+ TSWAP(pExchange->node.pLimit, pProject->node.pLimit);
pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
@@ -1029,6 +1216,51 @@ static int32_t smaIndexSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
return code;
}
+typedef struct SInsertSelectSplitInfo {
+ SLogicNode* pQueryRoot;
+ SLogicSubplan* pSubplan;
+} SInsertSelectSplitInfo;
+
+static bool insSelSplFindSplitNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pNode,
+ SInsertSelectSplitInfo* pInfo) {
+ if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY == nodeType(pNode) && 1 == LIST_LENGTH(pNode->pChildren) &&
+ MODIFY_TABLE_TYPE_INSERT == ((SVnodeModifyLogicNode*)pNode)->modifyType) {
+ pInfo->pQueryRoot = (SLogicNode*)nodesListGetNode(pNode->pChildren, 0);
+ pInfo->pSubplan = pSubplan;
+ return true;
+ }
+ return false;
+}
+
+static int32_t insertSelectSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
+ SInsertSelectSplitInfo info = {0};
+ if (!splMatch(pCxt, pSubplan, SPLIT_FLAG_INSERT_SPLIT, (FSplFindSplitNode)insSelSplFindSplitNode, &info)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SLogicSubplan* pNewSubplan = NULL;
+ SNodeList* pSubplanChildren = info.pSubplan->pChildren;
+ ESubplanType subplanType = info.pSubplan->subplanType;
+ int32_t code = splCreateExchangeNodeForSubplan(pCxt, info.pSubplan, info.pQueryRoot, SUBPLAN_TYPE_MODIFY);
+ if (TSDB_CODE_SUCCESS == code) {
+ pNewSubplan = splCreateSubplan(pCxt, info.pQueryRoot, subplanType);
+ if (NULL == pNewSubplan) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodesListMakeStrictAppend(&info.pSubplan->pChildren, (SNode*)pNewSubplan);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = splMountSubplan(pNewSubplan, pSubplanChildren);
+ }
+
+ SPLIT_FLAG_SET_MASK(info.pSubplan->splitFlag, SPLIT_FLAG_INSERT_SPLIT);
+ ++(pCxt->groupId);
+ pCxt->split = true;
+ return code;
+}
+
typedef struct SQnodeSplitInfo {
SLogicNode* pSplitNode;
SLogicSubplan* pSubplan;
@@ -1036,7 +1268,8 @@ typedef struct SQnodeSplitInfo {
static bool qndSplFindSplitNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pNode,
SQnodeSplitInfo* pInfo) {
- if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode) && NULL != pNode->pParent) {
+ if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode) && NULL != pNode->pParent &&
+ ((SScanLogicNode*)pNode)->scanSeq[0] < 1 && ((SScanLogicNode*)pNode)->scanSeq[1] < 1) {
pInfo->pSplitNode = pNode;
pInfo->pSubplan = pSubplan;
return true;
@@ -1053,6 +1286,7 @@ static int32_t qnodeSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
if (!splMatch(pCxt, pSubplan, 0, (FSplFindSplitNode)qndSplFindSplitNode, &info)) {
return TSDB_CODE_SUCCESS;
}
+ ((SScanLogicNode*)info.pSplitNode)->dataRequired = FUNC_DATA_REQUIRED_DATA_LOAD;
int32_t code = splCreateExchangeNodeForSubplan(pCxt, info.pSubplan, info.pSplitNode, info.pSubplan->subplanType);
if (TSDB_CODE_SUCCESS == code) {
SLogicSubplan* pScanSubplan = splCreateScanSubplan(pCxt, info.pSplitNode, 0);
@@ -1080,7 +1314,8 @@ static const SSplitRule splitRuleSet[] = {
{.pName = "SingleTableJoinSplit", .splitFunc = singleTableJoinSplit},
{.pName = "UnionAllSplit", .splitFunc = unionAllSplit},
{.pName = "UnionDistinctSplit", .splitFunc = unionDistinctSplit},
- {.pName = "SmaIndexSplit", .splitFunc = smaIndexSplit}
+ {.pName = "SmaIndexSplit", .splitFunc = smaIndexSplit},
+ {.pName = "InsertSelectSplit", .splitFunc = insertSelectSplit}
};
// clang-format on
@@ -1089,7 +1324,11 @@ static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule));
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
char* pStr = NULL;
nodesNodeToString((SNode*)pSubplan, false, &pStr, NULL);
- qDebugL("apply %s rule: %s", pRuleName, pStr);
+ if (NULL == pRuleName) {
+ qDebugL("before split: %s", pStr);
+ } else {
+ qDebugL("apply split %s rule: %s", pRuleName, pStr);
+ }
taosMemoryFree(pStr);
}
@@ -1097,6 +1336,7 @@ static int32_t applySplitRule(SPlanContext* pCxt, SLogicSubplan* pSubplan) {
SSplitContext cxt = {
.pPlanCxt = pCxt, .queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false};
bool split = false;
+ dumpLogicSubplan(NULL, pSubplan);
do {
split = false;
for (int32_t i = 0; i < splitRuleNum; ++i) {
@@ -1124,8 +1364,16 @@ static void setVgroupsInfo(SLogicNode* pNode, SLogicSubplan* pSubplan) {
FOREACH(pChild, pNode->pChildren) { setVgroupsInfo((SLogicNode*)pChild, pSubplan); }
}
+static bool needSplitSubplan(SLogicSubplan* pLogicSubplan) {
+ if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY != nodeType(pLogicSubplan->pNode)) {
+ return true;
+ }
+ SVnodeModifyLogicNode* pModify = (SVnodeModifyLogicNode*)pLogicSubplan->pNode;
+ return (MODIFY_TABLE_TYPE_INSERT == pModify->modifyType && NULL != pModify->node.pChildren);
+}
+
int32_t splitLogicPlan(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
- if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY == nodeType(pLogicSubplan->pNode)) {
+ if (!needSplitSubplan(pLogicSubplan)) {
setVgroupsInfo(pLogicSubplan->pNode, pLogicSubplan);
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c
index e75c8375fb766a662b87c8e5c7e43af28a45b097..f3174ce70a14f335c945ba2f539deb85c1285d0b 100644
--- a/source/libs/planner/src/planner.c
+++ b/source/libs/planner/src/planner.c
@@ -85,6 +85,23 @@ int32_t qSetSubplanExecutionNode(SSubplan* subplan, int32_t groupId, SDownstream
return setSubplanExecutionNode(subplan->pNode, groupId, pSource);
}
+static void clearSubplanExecutionNode(SPhysiNode* pNode) {
+ if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == nodeType(pNode)) {
+ SExchangePhysiNode* pExchange = (SExchangePhysiNode*)pNode;
+ NODES_DESTORY_LIST(pExchange->pSrcEndPoints);
+ } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE == nodeType(pNode)) {
+ SMergePhysiNode* pMerge = (SMergePhysiNode*)pNode;
+ pMerge->numOfChannels = LIST_LENGTH(pMerge->node.pChildren);
+ SNode* pChild = NULL;
+ FOREACH(pChild, pMerge->node.pChildren) { NODES_DESTORY_LIST(((SExchangePhysiNode*)pChild)->pSrcEndPoints); }
+ }
+
+ SNode* pChild = NULL;
+ FOREACH(pChild, pNode->pChildren) { clearSubplanExecutionNode((SPhysiNode*)pChild); }
+}
+
+void qClearSubplanExecutionNode(SSubplan* pSubplan) { clearSubplanExecutionNode(pSubplan->pNode); }
+
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen) {
if (SUBPLAN_TYPE_MODIFY == pSubplan->subplanType && NULL == pSubplan->pNode) {
SDataInserterNode* insert = (SDataInserterNode*)pSubplan->pDataSink;
diff --git a/source/libs/planner/test/CMakeLists.txt b/source/libs/planner/test/CMakeLists.txt
index b34ffa7bb1017e25c2b08a7b077430fea74bd923..b9d5c85717c71cdcb73cf660ac796541896c85e0 100644
--- a/source/libs/planner/test/CMakeLists.txt
+++ b/source/libs/planner/test/CMakeLists.txt
@@ -1,40 +1,40 @@
MESSAGE(STATUS "build planner unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(plannerTest
+ ADD_EXECUTABLE(plannerTest
${SOURCE_LIST}
"${SOURCE_LIST}/../../../parser/test/mockCatalog.cpp"
"${SOURCE_LIST}/../../../parser/test/mockCatalogService.cpp"
-)
+ )
-TARGET_LINK_LIBRARIES(
- plannerTest
- PUBLIC os util common nodes planner parser catalog transport gtest function qcom
-)
+ TARGET_LINK_LIBRARIES(
+ plannerTest
+ PUBLIC os util common nodes planner parser catalog transport gtest function qcom
+ )
-TARGET_INCLUDE_DIRECTORIES(
- plannerTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/planner/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/planner/inc"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/parser/test"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ plannerTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/planner/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/planner/inc"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/parser/test"
+ )
-if(${BUILD_WINGETOPT})
- target_include_directories(
- plannerTest
- PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
- )
- target_link_libraries(plannerTest PUBLIC wingetopt)
-endif()
+ if(${BUILD_WINGETOPT})
+ target_include_directories(
+ plannerTest
+ PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
+ )
+ target_link_libraries(plannerTest PUBLIC wingetopt)
+ endif()
-# if(NOT TD_WINDOWS)
add_test(
NAME plannerTest
COMMAND plannerTest
)
-# endif(NOT TD_WINDOWS)
+ENDIF ()
\ No newline at end of file
diff --git a/source/libs/planner/test/planBasicTest.cpp b/source/libs/planner/test/planBasicTest.cpp
index f74c7df355ad74b1db1192caf83c60fca7673f79..0d6bab145a0a399f36500c4b34f89bfb3febddfb 100644
--- a/source/libs/planner/test/planBasicTest.cpp
+++ b/source/libs/planner/test/planBasicTest.cpp
@@ -35,13 +35,8 @@ TEST_F(PlanBasicTest, whereClause) {
run("SELECT * FROM t1 WHERE c1 > 10");
run("SELECT * FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59'");
-}
-
-TEST_F(PlanBasicTest, joinClause) {
- useDb("root", "test");
- run("SELECT t1.c1, t2.c2 FROM st1s1 t1, st1s2 t2 WHERE t1.ts = t2.ts");
- run("SELECT t1.c1, t2.c2 FROM st1s1 t1 JOIN st1s2 t2 ON t1.ts = t2.ts");
+ run("SELECT ts, c1 FROM t1 WHERE ts > NOW AND ts IS NULL AND (c1 > 0 OR c3 < 20)");
}
TEST_F(PlanBasicTest, func) {
@@ -63,9 +58,15 @@ TEST_F(PlanBasicTest, uniqueFunc) {
run("SELECT UNIQUE(c2 + 10) FROM t1 WHERE c1 > 10");
+ run("SELECT UNIQUE(c2 + 10), c2 FROM t1 WHERE c1 > 10");
+
run("SELECT UNIQUE(c2 + 10), ts, c2 FROM t1 WHERE c1 > 10");
run("SELECT UNIQUE(c1) a FROM t1 ORDER BY a");
+
+ run("SELECT ts, UNIQUE(c1) FROM st1 PARTITION BY TBNAME");
+
+ run("SELECT TBNAME, UNIQUE(c1) FROM st1 PARTITION BY TBNAME");
}
TEST_F(PlanBasicTest, tailFunc) {
@@ -74,6 +75,18 @@ TEST_F(PlanBasicTest, tailFunc) {
run("SELECT TAIL(c1, 10) FROM t1");
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10");
+
+ run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 PARTITION BY c1");
+
+ run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 ORDER BY 1");
+
+ run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 LIMIT 5");
+
+ run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 PARTITION BY c1 LIMIT 5");
+
+ run("SELECT TAIL(c1, 2, 1) FROM st1s1 UNION ALL SELECT c1 FROM st1s2");
+
+ run("SELECT TAIL(c1, 1) FROM st2 WHERE jtag->'tag1' > 10");
}
TEST_F(PlanBasicTest, interpFunc) {
@@ -83,3 +96,60 @@ TEST_F(PlanBasicTest, interpFunc) {
run("SELECT INTERP(c1) FROM t1 RANGE('2017-7-14 18:00:00', '2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR)");
}
+
+TEST_F(PlanBasicTest, lastRowFunc) {
+ useDb("root", "test");
+
+ run("SELECT LAST_ROW(c1) FROM t1");
+
+ run("SELECT LAST_ROW(*) FROM t1");
+
+ run("SELECT LAST_ROW(c1, c2) FROM t1");
+
+ run("SELECT LAST_ROW(c1) FROM st1");
+
+ run("SELECT LAST_ROW(c1), SUM(c3) FROM t1");
+}
+
+TEST_F(PlanBasicTest, timeLineFunc) {
+ useDb("root", "test");
+
+ run("SELECT CSUM(c1) FROM t1");
+
+ run("SELECT CSUM(c1) FROM st1");
+}
+
+TEST_F(PlanBasicTest, multiResFunc) {
+ useDb("root", "test");
+
+ run("SELECT LAST(*) FROM t1");
+
+ run("SELECT LAST(c1 + 10, c2) FROM st1");
+}
+
+TEST_F(PlanBasicTest, sampleFunc) {
+ useDb("root", "test");
+
+ run("SELECT SAMPLE(c1, 10) FROM t1");
+
+ run("SELECT SAMPLE(c1, 10) FROM st1");
+
+ run("SELECT SAMPLE(c1, 10) FROM st1 PARTITION BY TBNAME");
+}
+
+TEST_F(PlanBasicTest, pseudoColumn) {
+ useDb("root", "test");
+
+ run("SELECT _QSTART, _QEND, _QDURATION FROM t1");
+
+ run("SELECT _QSTART, _QEND, _QDURATION FROM t1 WHERE ts BETWEEN '2017-7-14 18:00:00' AND '2017-7-14 19:00:00'");
+
+ run("SELECT _QSTART, _QEND, _QDURATION, _WSTART, _WEND, _WDURATION, COUNT(*) FROM t1 "
+ "WHERE ts BETWEEN '2017-7-14 18:00:00' AND '2017-7-14 19:00:00' INTERVAL(10S)");
+}
+
+TEST_F(PlanBasicTest, withoutFrom) {
+ useDb("root", "test");
+
+ run("SELECT 1");
+}
diff --git a/source/libs/planner/test/planDistinctTest.cpp b/source/libs/planner/test/planDistinctTest.cpp
index 58473dcff27839654fe8ea4f33c9d408c2c4b24f..8caee01d353128b47168f82b434dd6c9f1ae5eb3 100644
--- a/source/libs/planner/test/planDistinctTest.cpp
+++ b/source/libs/planner/test/planDistinctTest.cpp
@@ -40,3 +40,9 @@ TEST_F(PlanDistinctTest, withOrderBy) {
run("select distinct c1 + 10 a from t1 order by a");
}
+
+TEST_F(PlanDistinctTest, withLimit) {
+ useDb("root", "test");
+
+ run("SELECT DISTINCT c1 FROM t1 LIMIT 3");
+}
diff --git a/source/libs/planner/test/planGroupByTest.cpp b/source/libs/planner/test/planGroupByTest.cpp
index a73c99bf68474ce18370c026aabcaaff36c1f736..657d8a62447f8f2c2f52caa0f9de6a6710d61bbb 100644
--- a/source/libs/planner/test/planGroupByTest.cpp
+++ b/source/libs/planner/test/planGroupByTest.cpp
@@ -53,14 +53,6 @@ TEST_F(PlanGroupByTest, aggFunc) {
run("SELECT SUM(10), COUNT(c1) FROM t1 GROUP BY c2");
}
-TEST_F(PlanGroupByTest, rewriteFunc) {
- useDb("root", "test");
-
- run("SELECT AVG(c1) FROM t1");
-
- run("SELECT AVG(c1) FROM t1 GROUP BY c2");
-}
-
TEST_F(PlanGroupByTest, selectFunc) {
useDb("root", "test");
@@ -81,6 +73,8 @@ TEST_F(PlanGroupByTest, stable) {
run("SELECT COUNT(*) FROM st1");
+ run("SELECT c1 FROM st1 GROUP BY c1");
+
run("SELECT COUNT(*) FROM st1 GROUP BY c1");
run("SELECT COUNT(*) FROM st1 PARTITION BY c2 GROUP BY c1");
diff --git a/source/libs/planner/test/planIntervalTest.cpp b/source/libs/planner/test/planIntervalTest.cpp
index 10ef09adb94c3708fc3098f609ee1b4fb7c89014..9f34ead6ffec789653e99ebba12a203e86e75e7e 100644
--- a/source/libs/planner/test/planIntervalTest.cpp
+++ b/source/libs/planner/test/planIntervalTest.cpp
@@ -29,7 +29,7 @@ TEST_F(PlanIntervalTest, basic) {
TEST_F(PlanIntervalTest, pseudoCol) {
useDb("root", "test");
- run("SELECT _WSTARTTS, _WDURATION, _WENDTS, COUNT(*) FROM t1 INTERVAL(10s)");
+ run("SELECT _WSTART, _WDURATION, _WEND, COUNT(*) FROM t1 INTERVAL(10s)");
}
TEST_F(PlanIntervalTest, fill) {
@@ -59,7 +59,9 @@ TEST_F(PlanIntervalTest, stable) {
run("SELECT COUNT(*) FROM st1 INTERVAL(10s)");
- run("SELECT _WSTARTTS, COUNT(*) FROM st1 INTERVAL(10s)");
+ run("SELECT _WSTART, COUNT(*) FROM st1 INTERVAL(10s)");
- run("SELECT _WSTARTTS, COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)");
+ run("SELECT _WSTART, COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)");
+
+ run("SELECT TBNAME, COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)");
}
diff --git a/source/libs/planner/test/planOptimizeTest.cpp b/source/libs/planner/test/planOptimizeTest.cpp
index 1bee43aa4968ce817c0777bb5679f6529deb3e8c..75b4aa0dc109e20ca59145d595bf095cd790f0ba 100644
--- a/source/libs/planner/test/planOptimizeTest.cpp
+++ b/source/libs/planner/test/planOptimizeTest.cpp
@@ -20,7 +20,7 @@ using namespace std;
class PlanOptimizeTest : public PlannerTestBase {};
-TEST_F(PlanOptimizeTest, optimizeScanData) {
+TEST_F(PlanOptimizeTest, scanPath) {
useDb("root", "test");
run("SELECT COUNT(*) FROM t1");
@@ -32,32 +32,46 @@ TEST_F(PlanOptimizeTest, optimizeScanData) {
run("SELECT PERCENTILE(c1, 40), COUNT(*) FROM t1");
}
-TEST_F(PlanOptimizeTest, ConditionPushDown) {
+TEST_F(PlanOptimizeTest, pushDownCondition) {
useDb("root", "test");
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4");
+ run("SELECT ts, c1 FROM st1 WHERE TBNAME = 'st1s1'");
+
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 or tag1 < 2");
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello'");
+
+ run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello' AND c1 > 10");
+
+ run("SELECT ts, c1 FROM (SELECT * FROM st1) WHERE tag1 > 4");
}
-TEST_F(PlanOptimizeTest, orderByPrimaryKey) {
+TEST_F(PlanOptimizeTest, sortPrimaryKey) {
useDb("root", "test");
run("SELECT c1 FROM t1 ORDER BY ts");
run("SELECT c1 FROM t1 ORDER BY ts DESC");
- run("SELECT COUNT(*) FROM t1 INTERVAL(10S) ORDER BY _WSTARTTS DESC");
+ run("SELECT COUNT(*) FROM t1 INTERVAL(10S) ORDER BY _WSTART DESC");
}
TEST_F(PlanOptimizeTest, PartitionTags) {
useDb("root", "test");
- run("SELECT c1 FROM st1 PARTITION BY tag1");
+ run("SELECT c1, tag1 FROM st1 PARTITION BY tag1");
+
+ run("SELECT SUM(c1), tag1 FROM st1 PARTITION BY tag1");
+
+ run("SELECT SUM(c1), tag1 + 10 FROM st1 PARTITION BY tag1 + 10");
+
+ run("SELECT SUM(c1), tag1 FROM st1 GROUP BY tag1");
- run("SELECT SUM(c1) FROM st1 GROUP BY tag1");
+ run("SELECT SUM(c1), tag1 + 10 FROM st1 GROUP BY tag1 + 10");
+
+ run("SELECT SUM(c1), tbname FROM st1 GROUP BY tbname");
}
TEST_F(PlanOptimizeTest, eliminateProjection) {
@@ -69,3 +83,15 @@ TEST_F(PlanOptimizeTest, eliminateProjection) {
run("SELECT c1 FROM st1s3");
// run("select 1-abs(c1) from (select unique(c1) c1 from st1s3) order by 1 nulls first");
}
+
+TEST_F(PlanOptimizeTest, pushDownProjectCond) {
+ useDb("root", "test");
+ run("select 1-abs(c1) from (select unique(c1) c1 from st1s3) where 1-c1>5 order by 1 nulls first");
+}
+
+TEST_F(PlanOptimizeTest, tagScan) {
+ useDb("root", "test");
+ run("select tag1 from st1 group by tag1");
+ run("select distinct tag1 from st1");
+ run("select tag1*tag1 from st1 group by tag1*tag1");
+}
\ No newline at end of file
diff --git a/source/libs/planner/test/planOrderByTest.cpp b/source/libs/planner/test/planOrderByTest.cpp
index 2ca662cf8665946faef361f9b557d4e32403b983..13dfbad78cfc1f2957bd48ef1e163a9c887881e0 100644
--- a/source/libs/planner/test/planOrderByTest.cpp
+++ b/source/libs/planner/test/planOrderByTest.cpp
@@ -31,6 +31,8 @@ TEST_F(PlanOrderByTest, basic) {
run("SELECT c1 AS a FROM t1 ORDER BY a");
run("SELECT c1 + 10 AS a FROM t1 ORDER BY a");
+
+ run("SELECT 1 FROM t1 ORDER BY c1");
}
TEST_F(PlanOrderByTest, expr) {
@@ -51,6 +53,12 @@ TEST_F(PlanOrderByTest, withGroupBy) {
run("SELECT SUM(c1) AS a FROM t1 GROUP BY c2 ORDER BY a");
}
+TEST_F(PlanOrderByTest, withSubquery) {
+ useDb("root", "test");
+
+ run("SELECT ts FROM (SELECT * FROM t1 ORDER BY ts DESC) ORDER BY ts DESC");
+}
+
TEST_F(PlanOrderByTest, stable) {
useDb("root", "test");
diff --git a/source/libs/planner/test/planOtherTest.cpp b/source/libs/planner/test/planOtherTest.cpp
index 12d14369dedb0b5e5823d52454182148855e3ad2..7107f8b3c94c616ae9db90132a59f2804b542aca 100644
--- a/source/libs/planner/test/planOtherTest.cpp
+++ b/source/libs/planner/test/planOtherTest.cpp
@@ -37,7 +37,9 @@ TEST_F(PlanOtherTest, createStream) {
TEST_F(PlanOtherTest, createStreamUseSTable) {
useDb("root", "test");
- run("create stream if not exists s1 as select count(*) from st1 interval(10s)");
+ run("CREATE STREAM IF NOT EXISTS s1 as SELECT COUNT(*) FROM st1 INTERVAL(10s)");
+
+ run("CREATE STREAM IF NOT EXISTS s1 as SELECT COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)");
}
TEST_F(PlanOtherTest, createSmaIndex) {
@@ -47,7 +49,7 @@ TEST_F(PlanOtherTest, createSmaIndex) {
run("SELECT SUM(c4) FROM t1 INTERVAL(10s)");
- run("SELECT _WSTARTTS, MIN(c3 + 10) FROM t1 "
+ run("SELECT _WSTART, MIN(c3 + 10) FROM t1 "
"WHERE ts BETWEEN TIMESTAMP '2022-04-01 00:00:00' AND TIMESTAMP '2022-04-30 23:59:59.999' INTERVAL(10s)");
run("SELECT SUM(c4), MAX(c3) FROM t1 INTERVAL(10s)");
@@ -90,9 +92,12 @@ TEST_F(PlanOtherTest, delete) {
run("DELETE FROM st1 WHERE ts > now - 2d and ts < now - 1d AND tag1 = 10");
}
-TEST_F(PlanOtherTest, queryPolicy) {
+TEST_F(PlanOtherTest, insert) {
useDb("root", "test");
- tsQueryPolicy = QUERY_POLICY_QNODE;
- run("SELECT COUNT(*) FROM st1");
+ run("INSERT INTO t1 SELECT * FROM t1");
+
+ run("INSERT INTO t1 (ts, c1, c2) SELECT ts, c1, c2 FROM st1");
+
+ run("INSERT INTO t1 (ts, c1, c2) SELECT ts, c1, c2 FROM st1s1 UNION ALL SELECT ts, c1, c2 FROM st2");
}
diff --git a/source/libs/planner/test/planPartByTest.cpp b/source/libs/planner/test/planPartByTest.cpp
index 9437f6ad3f08fdf471c605fae62f57826a03d057..f1dd9403dd9c03a4bd4e12a7c656f15017981d7b 100644
--- a/source/libs/planner/test/planPartByTest.cpp
+++ b/source/libs/planner/test/planPartByTest.cpp
@@ -34,6 +34,12 @@ TEST_F(PlanPartitionByTest, withAggFunc) {
useDb("root", "test");
run("select count(*) from t1 partition by c1");
+
+ run("select count(*) from st1 partition by c1");
+
+ run("select sample(c1, 2) from st1 partition by c1");
+
+ run("select count(*), c1 from t1 partition by c1");
}
TEST_F(PlanPartitionByTest, withInterval) {
@@ -41,12 +47,18 @@ TEST_F(PlanPartitionByTest, withInterval) {
// normal/child table
run("select count(*) from t1 partition by c1 interval(10s)");
+
+ run("select count(*), c1 from t1 partition by c1 interval(10s)");
// super table
run("select count(*) from st1 partition by tag1, tag2 interval(10s)");
+
+ run("select count(*), tag1 from st1 partition by tag1, tag2 interval(10s)");
}
TEST_F(PlanPartitionByTest, withGroupBy) {
useDb("root", "test");
run("select count(*) from t1 partition by c1 group by c2");
+
+ run("SELECT TBNAME, c1 FROM st1 PARTITION BY TBNAME GROUP BY c1");
}
diff --git a/source/libs/planner/test/planSessionTest.cpp b/source/libs/planner/test/planSessionTest.cpp
index 7d5d82692557207ad032e4a9172c52da86b75f44..f445bb5ffced5430aa7b6f0544c5d85c63bf8b49 100644
--- a/source/libs/planner/test/planSessionTest.cpp
+++ b/source/libs/planner/test/planSessionTest.cpp
@@ -34,3 +34,13 @@ TEST_F(PlanSessionTest, selectFunc) {
// select function along with the columns of select row, and with SESSION clause
run("SELECT MAX(c1), c2 FROM t1 SESSION(ts, 10s)");
}
+
+TEST_F(PlanSessionTest, stable) {
+ useDb("root", "test");
+
+ // select function for SESSION clause
+ run("SELECT MAX(c1), MIN(c1) FROM st1 SESSION(ts, 10s)");
+ // select function along with the columns of select row, and with SESSION clause
+ run("SELECT MAX(c1), c2 FROM st1 SESSION(ts, 10s)");
+ run("SELECT count(ts) FROM st1 PARTITION BY c1 SESSION(ts, 10s)");
+}
diff --git a/source/libs/planner/test/planSetOpTest.cpp b/source/libs/planner/test/planSetOpTest.cpp
index bf26f55c02b1c146c0ff8aad723a593956e4945f..de6d7466b8f715f0cb28e7832f07648bec8ab307 100644
--- a/source/libs/planner/test/planSetOpTest.cpp
+++ b/source/libs/planner/test/planSetOpTest.cpp
@@ -54,6 +54,14 @@ TEST_F(PlanSetOpTest, unionAllWithOrderBy) {
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 ORDER BY 1");
}
+TEST_F(PlanSetOpTest, unionAllWithLimit) {
+ useDb("root", "test");
+
+ run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 LIMIT 10, 20");
+
+ run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 ORDER BY 1 LIMIT 10, 20");
+}
+
TEST_F(PlanSetOpTest, union) {
useDb("root", "test");
@@ -65,6 +73,14 @@ TEST_F(PlanSetOpTest, union) {
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 30");
}
+TEST_F(PlanSetOpTest, unionWithLimit) {
+ useDb("root", "test");
+
+ run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20 LIMIT 10, 20");
+
+ run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20 ORDER BY 1 LIMIT 10, 20");
+}
+
TEST_F(PlanSetOpTest, unionContainJoin) {
useDb("root", "test");
@@ -81,7 +97,15 @@ TEST_F(PlanSetOpTest, unionSubquery) {
run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)");
}
-TEST_F(PlanSetOpTest, bug001) {
+TEST_F(PlanSetOpTest, unionWithSubquery) {
+ useDb("root", "test");
+
+ run("SELECT c1 FROM (SELECT c1 FROM st1) UNION SELECT c2 FROM (SELECT c1 AS c2 FROM st2)");
+
+ run("SELECT c1 FROM (SELECT c1 FROM st1 ORDER BY c2) UNION SELECT c1 FROM (SELECT c1 FROM st2)");
+}
+
+TEST_F(PlanSetOpTest, unionDataTypeConversion) {
useDb("root", "test");
run("SELECT c2 FROM t1 WHERE c1 IS NOT NULL GROUP BY c2 "
diff --git a/source/libs/planner/test/planStateTest.cpp b/source/libs/planner/test/planStateTest.cpp
index 9ff035e1480c5ccbf17c7ab889976c4a739d951f..6985bc88070e2340af28b51c716b1da3db54f0cb 100644
--- a/source/libs/planner/test/planStateTest.cpp
+++ b/source/libs/planner/test/planStateTest.cpp
@@ -40,3 +40,12 @@ TEST_F(PlanStateTest, selectFunc) {
// select function along with the columns of select row, and with STATE_WINDOW clause
run("SELECT MAX(c1), c2 FROM t1 STATE_WINDOW(c3)");
}
+
+TEST_F(PlanStateTest, stable) {
+ useDb("root", "test");
+
+ // select function for STATE_WINDOW clause
+ run("SELECT MAX(c1), MIN(c1) FROM st1 STATE_WINDOW(c2)");
+ // select function along with the columns of select row, and with STATE_WINDOW clause
+ run("SELECT MAX(c1), c2 FROM st1 STATE_WINDOW(c2)");
+}
diff --git a/source/libs/planner/test/planSubqueryTest.cpp b/source/libs/planner/test/planSubqueryTest.cpp
index 7d1ac84aea7aabf7b8cdbab568836a980e8c6eb9..4d4f7804733b4c4ec3b0f9c17a7a53deb2840eaf 100644
--- a/source/libs/planner/test/planSubqueryTest.cpp
+++ b/source/libs/planner/test/planSubqueryTest.cpp
@@ -33,7 +33,9 @@ TEST_F(PlanSubqeuryTest, basic) {
run("SELECT NOW() FROM (SELECT * FROM t1)");
- // run("SELECT NOW() FROM (SELECT * FROM t1) ORDER BY ts");
+ run("SELECT * FROM (SELECT NOW() FROM t1)");
+
+ run("SELECT NOW() FROM (SELECT * FROM t1) ORDER BY ts");
}
TEST_F(PlanSubqeuryTest, doubleGroupBy) {
diff --git a/source/libs/planner/test/planTestMain.cpp b/source/libs/planner/test/planTestMain.cpp
index acac3d505306e40e83bf9969273eba7cf61ad2a0..8f6fc832a2d8c4722c02781d2a357606a1eb481b 100644
--- a/source/libs/planner/test/planTestMain.cpp
+++ b/source/libs/planner/test/planTestMain.cpp
@@ -16,9 +16,11 @@
#include
#include
+
#include "functionMgt.h"
#include "getopt.h"
#include "mockCatalog.h"
+#include "parser.h"
#include "planTestUtil.h"
class PlannerEnv : public testing::Environment {
@@ -30,7 +32,12 @@ class PlannerEnv : public testing::Environment {
initLog(TD_TMP_DIR_PATH "td");
}
- virtual void TearDown() { destroyMetaDataEnv(); }
+ virtual void TearDown() {
+ destroyMetaDataEnv();
+ qCleanupKeywordsTable();
+ fmFuncMgtDestroy();
+ taosCloseLog();
+ }
PlannerEnv() {}
virtual ~PlannerEnv() {}
@@ -69,7 +76,9 @@ static void parseArg(int argc, char* argv[]) {
static struct option long_options[] = {
{"dump", optional_argument, NULL, 'd'},
{"skipSql", required_argument, NULL, 's'},
+ {"limitSql", required_argument, NULL, 'i'},
{"log", required_argument, NULL, 'l'},
+ {"queryPolicy", required_argument, NULL, 'q'},
{0, 0, 0, 0}
};
// clang-format on
@@ -81,9 +90,15 @@ static void parseArg(int argc, char* argv[]) {
case 's':
setSkipSqlNum(optarg);
break;
+ case 'i':
+ setLimitSqlNum(optarg);
+ break;
case 'l':
setLogLevel(optarg);
break;
+ case 'q':
+ setQueryPolicy(optarg);
+ break;
default:
break;
}
diff --git a/source/libs/planner/test/planTestUtil.cpp b/source/libs/planner/test/planTestUtil.cpp
index 57d7cb66084836e13dd1f26b4ea90b67c0064d9a..0f90b54adb6eb05918f5b5d3cdc9b90233f328ff 100644
--- a/source/libs/planner/test/planTestUtil.cpp
+++ b/source/libs/planner/test/planTestUtil.cpp
@@ -24,6 +24,7 @@
#include "mockCatalogService.h"
#include "parser.h"
#include "planInt.h"
+#include "tglobal.h"
using namespace std;
using namespace testing;
@@ -51,7 +52,9 @@ enum DumpModule {
DumpModule g_dumpModule = DUMP_MODULE_NOTHING;
int32_t g_skipSql = 0;
+int32_t g_limitSql = 0;
int32_t g_logLevel = 131;
+int32_t g_queryPolicy = QUERY_POLICY_VNODE;
void setDumpModule(const char* pModule) {
if (NULL == pModule) {
@@ -76,38 +79,64 @@ void setDumpModule(const char* pModule) {
}
void setSkipSqlNum(const char* pNum) { g_skipSql = stoi(pNum); }
-
+void setLimitSqlNum(const char* pNum) { g_limitSql = stoi(pNum); }
void setLogLevel(const char* pLogLevel) { g_logLevel = stoi(pLogLevel); }
+void setQueryPolicy(const char* pQueryPolicy) { g_queryPolicy = stoi(pQueryPolicy); }
int32_t getLogLevel() { return g_logLevel; }
class PlannerTestBaseImpl {
public:
- PlannerTestBaseImpl() : sqlNo_(0) {}
+ PlannerTestBaseImpl() : sqlNo_(0), sqlNum_(0) {}
- void useDb(const string& acctId, const string& db) {
- caseEnv_.acctId_ = acctId;
+ void useDb(const string& user, const string& db) {
+ caseEnv_.acctId_ = 0;
+ caseEnv_.user_ = user;
caseEnv_.db_ = db;
- caseEnv_.nsql_ = g_skipSql;
+ caseEnv_.numOfSkipSql_ = g_skipSql;
+ caseEnv_.numOfLimitSql_ = g_limitSql;
}
void run(const string& sql) {
++sqlNo_;
- if (caseEnv_.nsql_ > 0) {
- --(caseEnv_.nsql_);
+ if (caseEnv_.numOfSkipSql_ > 0) {
+ --(caseEnv_.numOfSkipSql_);
+ return;
+ }
+ if (caseEnv_.numOfLimitSql_ > 0 && caseEnv_.numOfLimitSql_ == sqlNum_) {
return;
}
+ ++sqlNum_;
+
+ switch (g_queryPolicy) {
+ case QUERY_POLICY_VNODE:
+ case QUERY_POLICY_HYBRID:
+ case QUERY_POLICY_QNODE:
+ runImpl(sql, g_queryPolicy);
+ break;
+ default:
+ runImpl(sql, QUERY_POLICY_VNODE);
+ runImpl(sql, QUERY_POLICY_HYBRID);
+ runImpl(sql, QUERY_POLICY_QNODE);
+ break;
+ }
+ }
+ void runImpl(const string& sql, int32_t queryPolicy) {
reset();
+ tsQueryPolicy = queryPolicy;
try {
SQuery* pQuery = nullptr;
doParseSql(sql, &pQuery);
+ unique_ptr query(pQuery, qDestroyQuery);
SPlanContext cxt = {0};
setPlanContext(pQuery, &cxt);
SLogicSubplan* pLogicSubplan = nullptr;
doCreateLogicPlan(&cxt, &pLogicSubplan);
+ unique_ptr logicSubplan(pLogicSubplan,
+ (void (*)(SLogicSubplan*))nodesDestroyNode);
doOptimizeLogicPlan(&cxt, pLogicSubplan);
@@ -115,9 +144,12 @@ class PlannerTestBaseImpl {
SQueryLogicPlan* pLogicPlan = nullptr;
doScaleOutLogicPlan(&cxt, pLogicSubplan, &pLogicPlan);
+ unique_ptr logicPlan(pLogicPlan,
+ (void (*)(SQueryLogicPlan*))nodesDestroyNode);
SQueryPlan* pPlan = nullptr;
doCreatePhysiPlan(&cxt, pLogicPlan, &pPlan);
+ unique_ptr plan(pPlan, (void (*)(SQueryPlan*))nodesDestroyNode);
dump(g_dumpModule);
} catch (...) {
@@ -127,7 +159,7 @@ class PlannerTestBaseImpl {
}
void prepare(const string& sql) {
- if (caseEnv_.nsql_ > 0) {
+ if (caseEnv_.numOfSkipSql_ > 0) {
return;
}
@@ -141,7 +173,7 @@ class PlannerTestBaseImpl {
}
void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
- if (caseEnv_.nsql_ > 0) {
+ if (caseEnv_.numOfSkipSql_ > 0) {
return;
}
@@ -154,8 +186,8 @@ class PlannerTestBaseImpl {
}
void exec() {
- if (caseEnv_.nsql_ > 0) {
- --(caseEnv_.nsql_);
+ if (caseEnv_.numOfSkipSql_ > 0) {
+ --(caseEnv_.numOfSkipSql_);
return;
}
@@ -187,11 +219,13 @@ class PlannerTestBaseImpl {
private:
struct caseEnv {
- string acctId_;
+ int32_t acctId_;
+ string user_;
string db_;
- int32_t nsql_;
+ int32_t numOfSkipSql_;
+ int32_t numOfLimitSql_;
- caseEnv() : nsql_(0) {}
+ caseEnv() : numOfSkipSql_(0) {}
};
struct stmtEnv {
@@ -289,12 +323,17 @@ class PlannerTestBaseImpl {
transform(stmtEnv_.sql_.begin(), stmtEnv_.sql_.end(), stmtEnv_.sql_.begin(), ::tolower);
SParseContext cxt = {0};
- cxt.acctId = atoi(caseEnv_.acctId_.c_str());
+ cxt.acctId = caseEnv_.acctId_;
cxt.db = caseEnv_.db_.c_str();
cxt.pSql = stmtEnv_.sql_.c_str();
cxt.sqlLen = stmtEnv_.sql_.length();
cxt.pMsg = stmtEnv_.msgBuf_.data();
cxt.msgLen = stmtEnv_.msgBuf_.max_size();
+ cxt.svrVer = "3.0.0.0";
+ if (prepare) {
+ SStmtCallback stmtCb = {0};
+ cxt.pStmtCb = &stmtCb;
+ }
DO_WITH_THROW(qParseSql, &cxt, pQuery);
if (prepare) {
@@ -313,12 +352,13 @@ class PlannerTestBaseImpl {
void doParseBoundSql(SQuery* pQuery) {
SParseContext cxt = {0};
- cxt.acctId = atoi(caseEnv_.acctId_.c_str());
+ cxt.acctId = caseEnv_.acctId_;
cxt.db = caseEnv_.db_.c_str();
cxt.pSql = stmtEnv_.sql_.c_str();
cxt.sqlLen = stmtEnv_.sql_.length();
cxt.pMsg = stmtEnv_.msgBuf_.data();
cxt.msgLen = stmtEnv_.msgBuf_.max_size();
+ cxt.pUser = caseEnv_.user_.c_str();
DO_WITH_THROW(qStmtParseQuerySql, &cxt, pQuery);
res_.ast_ = toString(pQuery->pRoot);
@@ -345,8 +385,9 @@ class PlannerTestBaseImpl {
}
void doCreatePhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan) {
- SArray* pExecNodeList = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SQueryNodeAddr));
- DO_WITH_THROW(createPhysiPlan, pCxt, pLogicPlan, pPlan, pExecNodeList);
+ unique_ptr execNodeList((SArray*)taosArrayInit(TARRAY_MIN_SIZE, sizeof(SQueryNodeAddr)),
+ (void (*)(SArray*))taosArrayDestroy);
+ DO_WITH_THROW(createPhysiPlan, pCxt, pLogicPlan, pPlan, execNodeList.get());
res_.physiPlan_ = toString((SNode*)(*pPlan));
SNode* pNode;
FOREACH(pNode, (*pPlan)->pSubplans) {
@@ -357,6 +398,7 @@ class PlannerTestBaseImpl {
void setPlanContext(SQuery* pQuery, SPlanContext* pCxt) {
pCxt->queryId = 1;
+ pCxt->pUser = caseEnv_.user_.c_str();
if (QUERY_NODE_CREATE_TOPIC_STMT == nodeType(pQuery->pRoot)) {
pCxt->pAstRoot = ((SCreateTopicStmt*)pQuery->pRoot)->pQuery;
pCxt->topicQuery = true;
@@ -390,13 +432,14 @@ class PlannerTestBaseImpl {
stmtEnv stmtEnv_;
stmtRes res_;
int32_t sqlNo_;
+ int32_t sqlNum_;
};
PlannerTestBase::PlannerTestBase() : impl_(new PlannerTestBaseImpl()) {}
PlannerTestBase::~PlannerTestBase() {}
-void PlannerTestBase::useDb(const std::string& acctId, const std::string& db) { impl_->useDb(acctId, db); }
+void PlannerTestBase::useDb(const std::string& user, const std::string& db) { impl_->useDb(user, db); }
void PlannerTestBase::run(const std::string& sql) { return impl_->run(sql); }
diff --git a/source/libs/planner/test/planTestUtil.h b/source/libs/planner/test/planTestUtil.h
index b188a7a054ed5c3b6e441c058f59733f20b6873e..b0ddd726a6d4c0cf3b9294990e593cf67839823b 100644
--- a/source/libs/planner/test/planTestUtil.h
+++ b/source/libs/planner/test/planTestUtil.h
@@ -30,7 +30,7 @@ class PlannerTestBase : public testing::Test {
PlannerTestBase();
virtual ~PlannerTestBase();
- void useDb(const std::string& acctId, const std::string& db);
+ void useDb(const std::string& user, const std::string& db);
void run(const std::string& sql);
// stmt mode APIs
void prepare(const std::string& sql);
@@ -43,7 +43,9 @@ class PlannerTestBase : public testing::Test {
extern void setDumpModule(const char* pModule);
extern void setSkipSqlNum(const char* pNum);
+extern void setLimitSqlNum(const char* pNum);
extern void setLogLevel(const char* pLogLevel);
+extern void setQueryPolicy(const char* pQueryPolicy);
extern int32_t getLogLevel();
#endif // PLAN_TEST_UTIL_H
diff --git a/source/libs/qcom/src/queryUtil.c b/source/libs/qcom/src/queryUtil.c
index 2120d24d2612e804a16827125cc7356449dd0d70..eeb44c4f82db68b445e944ed1b4870686187f740 100644
--- a/source/libs/qcom/src/queryUtil.c
+++ b/source/libs/qcom/src/queryUtil.c
@@ -19,6 +19,8 @@
#include "tmsg.h"
#include "trpc.h"
#include "tsched.h"
+// clang-format off
+#include "cJSON.h"
#define VALIDNUMOFCOLS(x) ((x) >= TSDB_MIN_COLUMNS && (x) <= TSDB_MAX_COLUMNS)
#define VALIDNUMOFTAGS(x) ((x) >= 0 && (x) <= TSDB_MAX_TAGS)
@@ -146,13 +148,15 @@ int32_t asyncSendMsgToServerExt(void* pTransporter, SEpSet* epSet, int64_t* pTra
}
memcpy(pMsg, pInfo->msgInfo.pData, pInfo->msgInfo.len);
- SRpcMsg rpcMsg = {.msgType = pInfo->msgType,
- .pCont = pMsg,
- .contLen = pInfo->msgInfo.len,
- .info.ahandle = (void*)pInfo,
- .info.handle = pInfo->msgInfo.handle,
- .info.persistHandle = persistHandle,
- .code = 0};
+ SRpcMsg rpcMsg = {
+ .msgType = pInfo->msgType,
+ .pCont = pMsg,
+ .contLen = pInfo->msgInfo.len,
+ .info.ahandle = (void*)pInfo,
+ .info.handle = pInfo->msgInfo.handle,
+ .info.persistHandle = persistHandle,
+ .code = 0
+ };
assert(pInfo->fp != NULL);
TRACE_SET_ROOTID(&rpcMsg.info.traceId, pInfo->requestId);
rpcSendRequestWithCtx(pTransporter, epSet, &rpcMsg, pTransporterId, rpcCtx);
@@ -167,17 +171,17 @@ char* jobTaskStatusStr(int32_t status) {
switch (status) {
case JOB_TASK_STATUS_NULL:
return "NULL";
- case JOB_TASK_STATUS_NOT_START:
- return "NOT_START";
- case JOB_TASK_STATUS_EXECUTING:
+ case JOB_TASK_STATUS_INIT:
+ return "INIT";
+ case JOB_TASK_STATUS_EXEC:
return "EXECUTING";
- case JOB_TASK_STATUS_PARTIAL_SUCCEED:
+ case JOB_TASK_STATUS_PART_SUCC:
return "PARTIAL_SUCCEED";
- case JOB_TASK_STATUS_SUCCEED:
+ case JOB_TASK_STATUS_SUCC:
return "SUCCEED";
- case JOB_TASK_STATUS_FAILED:
+ case JOB_TASK_STATUS_FAIL:
return "FAILED";
- case JOB_TASK_STATUS_DROPPING:
+ case JOB_TASK_STATUS_DROP:
return "DROPPING";
default:
break;
@@ -196,7 +200,7 @@ SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* nam
return s;
}
-void destroyQueryExecRes(SQueryExecRes* pRes) {
+void destroyQueryExecRes(SExecResult* pRes) {
if (NULL == pRes || NULL == pRes->res) {
return;
}
@@ -212,7 +216,8 @@ void destroyQueryExecRes(SQueryExecRes* pRes) {
tFreeSSubmitRsp((SSubmitRsp*)pRes->res);
break;
}
- case TDMT_VND_QUERY: {
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY: {
taosArrayDestroy((SArray*)pRes->res);
break;
}
@@ -220,3 +225,227 @@ void destroyQueryExecRes(SQueryExecRes* pRes) {
qError("invalid exec result for request type %d", pRes->msgType);
}
}
+// clang-format on
+
+int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t* len) {
+ int32_t n = 0;
+
+ switch (type) {
+ case TSDB_DATA_TYPE_NULL:
+ n = sprintf(str, "null");
+ break;
+
+ case TSDB_DATA_TYPE_BOOL:
+ n = sprintf(str, (*(int8_t*)buf) ? "true" : "false");
+ break;
+
+ case TSDB_DATA_TYPE_TINYINT:
+ n = sprintf(str, "%d", *(int8_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_SMALLINT:
+ n = sprintf(str, "%d", *(int16_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_INT:
+ n = sprintf(str, "%d", *(int32_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_BIGINT:
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ n = sprintf(str, "%" PRId64, *(int64_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_FLOAT:
+ n = sprintf(str, "%e", GET_FLOAT_VAL(buf));
+ break;
+
+ case TSDB_DATA_TYPE_DOUBLE:
+ n = sprintf(str, "%e", GET_DOUBLE_VAL(buf));
+ break;
+
+ case TSDB_DATA_TYPE_BINARY:
+ if (bufSize < 0) {
+ // tscError("invalid buf size");
+ return TSDB_CODE_TSC_INVALID_VALUE;
+ }
+
+ *str = '"';
+ memcpy(str + 1, buf, bufSize);
+ *(str + bufSize + 1) = '"';
+ n = bufSize + 2;
+ break;
+ case TSDB_DATA_TYPE_NCHAR:
+ if (bufSize < 0) {
+ // tscError("invalid buf size");
+ return TSDB_CODE_TSC_INVALID_VALUE;
+ }
+
+ *str = '"';
+ int32_t length = taosUcs4ToMbs((TdUcs4*)buf, bufSize, str + 1);
+ if (length <= 0) {
+ return TSDB_CODE_TSC_INVALID_VALUE;
+ }
+ *(str + length + 1) = '"';
+ n = length + 2;
+ break;
+ case TSDB_DATA_TYPE_UTINYINT:
+ n = sprintf(str, "%d", *(uint8_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_USMALLINT:
+ n = sprintf(str, "%d", *(uint16_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_UINT:
+ n = sprintf(str, "%u", *(uint32_t*)buf);
+ break;
+
+ case TSDB_DATA_TYPE_UBIGINT:
+ n = sprintf(str, "%" PRIu64, *(uint64_t*)buf);
+ break;
+
+ default:
+ // tscError("unsupported type:%d", type);
+ return TSDB_CODE_TSC_INVALID_VALUE;
+ }
+
+ if (len) *len = n;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+char* parseTagDatatoJson(void* p) {
+ char* string = NULL;
+ SArray* pTagVals = NULL;
+ cJSON* json = NULL;
+ if (tTagToValArray((const STag*)p, &pTagVals) != 0) {
+ goto end;
+ }
+
+ int16_t nCols = taosArrayGetSize(pTagVals);
+ if (nCols == 0) {
+ goto end;
+ }
+ char tagJsonKey[256] = {0};
+ json = cJSON_CreateObject();
+ if (json == NULL) {
+ goto end;
+ }
+ for (int j = 0; j < nCols; ++j) {
+ STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, j);
+ // json key encode by binary
+ memset(tagJsonKey, 0, sizeof(tagJsonKey));
+ memcpy(tagJsonKey, pTagVal->pKey, strlen(pTagVal->pKey));
+ // json value
+ char type = pTagVal->type;
+ if (type == TSDB_DATA_TYPE_NULL) {
+ cJSON* value = cJSON_CreateNull();
+ if (value == NULL) {
+ goto end;
+ }
+ cJSON_AddItemToObject(json, tagJsonKey, value);
+ } else if (type == TSDB_DATA_TYPE_NCHAR) {
+ cJSON* value = NULL;
+ if (pTagVal->nData > 0) {
+ char* tagJsonValue = taosMemoryCalloc(pTagVal->nData, 1);
+ int32_t length = taosUcs4ToMbs((TdUcs4*)pTagVal->pData, pTagVal->nData, tagJsonValue);
+ if (length < 0) {
+ qError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset,
+ pTagVal->pData);
+ taosMemoryFree(tagJsonValue);
+ goto end;
+ }
+ value = cJSON_CreateString(tagJsonValue);
+ taosMemoryFree(tagJsonValue);
+ if (value == NULL) {
+ goto end;
+ }
+ } else if (pTagVal->nData == 0) {
+ value = cJSON_CreateString("");
+ } else {
+ ASSERT(0);
+ }
+
+ cJSON_AddItemToObject(json, tagJsonKey, value);
+ } else if (type == TSDB_DATA_TYPE_DOUBLE) {
+ double jsonVd = *(double*)(&pTagVal->i64);
+ cJSON* value = cJSON_CreateNumber(jsonVd);
+ if (value == NULL) {
+ goto end;
+ }
+ cJSON_AddItemToObject(json, tagJsonKey, value);
+ } else if (type == TSDB_DATA_TYPE_BOOL) {
+ char jsonVd = *(char*)(&pTagVal->i64);
+ cJSON* value = cJSON_CreateBool(jsonVd);
+ if (value == NULL) {
+ goto end;
+ }
+ cJSON_AddItemToObject(json, tagJsonKey, value);
+ } else {
+ ASSERT(0);
+ }
+ }
+ string = cJSON_PrintUnformatted(json);
+end:
+ cJSON_Delete(json);
+ taosArrayDestroy(pTagVals);
+ if (string == NULL) {
+ string = strdup(TSDB_DATA_NULL_STR_L);
+ }
+ return string;
+}
+
+int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst) {
+ if (NULL == pSrc) {
+ *pDst = NULL;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t metaSize = (pSrc->tableInfo.numOfColumns + pSrc->tableInfo.numOfTags) * sizeof(SSchema);
+ *pDst = taosMemoryMalloc(metaSize);
+ if (NULL == *pDst) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+ memcpy(*pDst, pSrc, metaSize);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst) {
+ if (NULL == pSrc) {
+ *pDst = NULL;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ *pDst = taosMemoryMalloc(sizeof(*pSrc));
+ if (NULL == *pDst) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+ memcpy(*pDst, pSrc, sizeof(*pSrc));
+ if (pSrc->vgHash) {
+ (*pDst)->vgHash = taosHashInit(taosHashGetSize(pSrc->vgHash), taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true,
+ HASH_ENTRY_LOCK);
+ if (NULL == (*pDst)->vgHash) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+
+ SVgroupInfo* vgInfo = NULL;
+ void* pIter = taosHashIterate(pSrc->vgHash, NULL);
+ while (pIter) {
+ vgInfo = pIter;
+ int32_t* vgId = taosHashGetKey(pIter, NULL);
+
+ if (0 != taosHashPut((*pDst)->vgHash, vgId, sizeof(*vgId), vgInfo, sizeof(*vgInfo))) {
+ qError("taosHashPut failed, vgId:%d", vgInfo->vgId);
+ taosHashCancelIterate(pSrc->vgHash, pIter);
+ taosHashCleanup((*pDst)->vgHash);
+ taosMemoryFreeClear(*pDst);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ pIter = taosHashIterate(pSrc->vgHash, pIter);
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/libs/qcom/src/querymsg.c b/source/libs/qcom/src/querymsg.c
index b89c220519c60c3c3b67cc10f001ff3447448bbd..ed8786170d0e37f677d1b731d08eafb511875023 100644
--- a/source/libs/qcom/src/querymsg.c
+++ b/source/libs/qcom/src/querymsg.c
@@ -20,7 +20,9 @@
#include "systable.h"
#pragma GCC diagnostic push
+#ifdef COMPILER_SUPPORTS_CXX13
#pragma GCC diagnostic ignored "-Wformat-truncation"
+#endif
int32_t (*queryBuildMsg[TDMT_MAX])(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallocFp)(int32_t)) = {0};
int32_t (*queryProcessMsgRsp[TDMT_MAX])(void *output, char *msg, int32_t msgSize) = {0};
@@ -63,7 +65,7 @@ int32_t queryBuildUseDbOutput(SUseDbOutput *pOut, SUseDbRsp *usedbRsp) {
}
int32_t queryBuildTableMetaReqMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallcFp)(int32_t)) {
- SBuildTableMetaInput *pInput = input;
+ SBuildTableInput *pInput = input;
if (NULL == input || NULL == msg || NULL == msgLen) {
return TSDB_CODE_TSC_INVALID_INPUT;
}
@@ -126,6 +128,42 @@ int32_t queryBuildQnodeListMsg(void *input, char **msg, int32_t msgSize, int32_t
return TSDB_CODE_SUCCESS;
}
+int32_t queryBuildDnodeListMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallcFp)(int32_t)) {
+ if (NULL == msg || NULL == msgLen) {
+ return TSDB_CODE_TSC_INVALID_INPUT;
+ }
+
+ SDnodeListReq dnodeListReq = {0};
+ dnodeListReq.rowNum = -1;
+
+ int32_t bufLen = tSerializeSDnodeListReq(NULL, 0, &dnodeListReq);
+ void *pBuf = (*mallcFp)(bufLen);
+ tSerializeSDnodeListReq(pBuf, bufLen, &dnodeListReq);
+
+ *msg = pBuf;
+ *msgLen = bufLen;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t queryBuildGetSerVerMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallcFp)(int32_t)) {
+ if (NULL == msg || NULL == msgLen) {
+ return TSDB_CODE_TSC_INVALID_INPUT;
+ }
+
+ SServerVerReq req = {0};
+
+ int32_t bufLen = tSerializeSServerVerReq(NULL, 0, &req);
+ void *pBuf = (*mallcFp)(bufLen);
+ tSerializeSServerVerReq(pBuf, bufLen, &req);
+
+ *msg = pBuf;
+ *msgLen = bufLen;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
int32_t queryBuildGetDBCfgMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallcFp)(int32_t)) {
if (NULL == msg || NULL == msgLen) {
return TSDB_CODE_TSC_INVALID_INPUT;
@@ -221,6 +259,27 @@ int32_t queryBuildGetTbIndexMsg(void *input, char **msg, int32_t msgSize, int32_
return TSDB_CODE_SUCCESS;
}
+int32_t queryBuildGetTbCfgMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallcFp)(int32_t)) {
+ if (NULL == msg || NULL == msgLen) {
+ return TSDB_CODE_TSC_INVALID_INPUT;
+ }
+
+ SBuildTableInput *pInput = input;
+ STableCfgReq cfgReq = {0};
+ cfgReq.header.vgId = pInput->vgId;
+ strcpy(cfgReq.dbFName, pInput->dbFName);
+ strcpy(cfgReq.tbName, pInput->tbName);
+
+ int32_t bufLen = tSerializeSTableCfgReq(NULL, 0, &cfgReq);
+ void *pBuf = (*mallcFp)(bufLen);
+ tSerializeSTableCfgReq(pBuf, bufLen, &cfgReq);
+
+ *msg = pBuf;
+ *msgLen = bufLen;
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t queryProcessUseDBRsp(void *output, char *msg, int32_t msgSize) {
SUseDbOutput *pOut = output;
@@ -322,11 +381,11 @@ int32_t queryCreateTableMetaFromMsg(STableMetaRsp *msg, bool isStb, STableMeta *
pTableMeta->tableInfo.rowSize += pTableMeta->schema[i].bytes;
}
- qDebug("table %s uid %" PRIx64 " meta returned, type %d vgId %d db %s stb %s suid %" PRIx64 " sver %d tver %d" PRIx64
- " tagNum %d colNum %d precision %d rowSize %d",
- msg->tbName, pTableMeta->uid, pTableMeta->tableType, pTableMeta->vgId, msg->dbFName, msg->stbName, pTableMeta->suid,
- pTableMeta->sversion, pTableMeta->tversion, pTableMeta->tableInfo.numOfTags, pTableMeta->tableInfo.numOfColumns,
- pTableMeta->tableInfo.precision, pTableMeta->tableInfo.rowSize);
+ qDebug("table %s uid %" PRIx64 " meta returned, type %d vgId:%d db %s stb %s suid %" PRIx64 " sver %d tver %d" PRIx64
+ " tagNum %d colNum %d precision %d rowSize %d",
+ msg->tbName, pTableMeta->uid, pTableMeta->tableType, pTableMeta->vgId, msg->dbFName, msg->stbName,
+ pTableMeta->suid, pTableMeta->sversion, pTableMeta->tversion, pTableMeta->tableInfo.numOfTags,
+ pTableMeta->tableInfo.numOfColumns, pTableMeta->tableInfo.precision, pTableMeta->tableInfo.rowSize);
*pMeta = pTableMeta;
return TSDB_CODE_SUCCESS;
@@ -407,6 +466,47 @@ int32_t queryProcessQnodeListRsp(void *output, char *msg, int32_t msgSize) {
return code;
}
+int32_t queryProcessDnodeListRsp(void *output, char *msg, int32_t msgSize) {
+ SDnodeListRsp out = {0};
+ int32_t code = 0;
+
+ if (NULL == output || NULL == msg || msgSize <= 0) {
+ code = TSDB_CODE_TSC_INVALID_INPUT;
+ return code;
+ }
+
+ if (tDeserializeSDnodeListRsp(msg, msgSize, &out) != 0) {
+ qError("invalid dnode list rsp msg, msgSize:%d", msgSize);
+ code = TSDB_CODE_INVALID_MSG;
+ return code;
+ }
+
+ *(SArray**)output = out.dnodeList;
+
+ return code;
+}
+
+int32_t queryProcessGetSerVerRsp(void *output, char *msg, int32_t msgSize) {
+ SServerVerRsp out = {0};
+ int32_t code = 0;
+
+ if (NULL == output || NULL == msg || msgSize <= 0) {
+ code = TSDB_CODE_TSC_INVALID_INPUT;
+ return code;
+ }
+
+ if (tDeserializeSServerVerRsp(msg, msgSize, &out) != 0) {
+ qError("invalid svr ver rsp msg, msgSize:%d", msgSize);
+ code = TSDB_CODE_INVALID_MSG;
+ return code;
+ }
+
+ *(char**)output = strdup(out.ver);
+
+ return code;
+}
+
+
int32_t queryProcessGetDbCfgRsp(void *output, char *msg, int32_t msgSize) {
SDbCfgRsp out = {0};
@@ -493,27 +593,50 @@ int32_t queryProcessGetTbIndexRsp(void *output, char *msg, int32_t msgSize) {
return TSDB_CODE_SUCCESS;
}
+int32_t queryProcessGetTbCfgRsp(void *output, char *msg, int32_t msgSize) {
+ if (NULL == output || NULL == msg || msgSize <= 0) {
+ return TSDB_CODE_TSC_INVALID_INPUT;
+ }
+
+ STableCfgRsp *out = taosMemoryCalloc(1, sizeof(STableCfgRsp));
+ if (tDeserializeSTableCfgRsp(msg, msgSize, out) != 0) {
+ qError("tDeserializeSTableCfgRsp failed, msgSize:%d", msgSize);
+ return TSDB_CODE_INVALID_MSG;
+ }
+
+ *(STableCfgRsp**)output = out;
+
+ return TSDB_CODE_SUCCESS;
+}
void initQueryModuleMsgHandle() {
queryBuildMsg[TMSG_INDEX(TDMT_VND_TABLE_META)] = queryBuildTableMetaReqMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_TABLE_META)] = queryBuildTableMetaReqMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_USE_DB)] = queryBuildUseDbMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_QNODE_LIST)] = queryBuildQnodeListMsg;
+ queryBuildMsg[TMSG_INDEX(TDMT_MND_DNODE_LIST)] = queryBuildDnodeListMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_GET_DB_CFG)] = queryBuildGetDBCfgMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_GET_INDEX)] = queryBuildGetIndexMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_RETRIEVE_FUNC)] = queryBuildRetrieveFuncMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_GET_USER_AUTH)] = queryBuildGetUserAuthMsg;
queryBuildMsg[TMSG_INDEX(TDMT_MND_GET_TABLE_INDEX)] = queryBuildGetTbIndexMsg;
+ queryBuildMsg[TMSG_INDEX(TDMT_VND_TABLE_CFG)] = queryBuildGetTbCfgMsg;
+ queryBuildMsg[TMSG_INDEX(TDMT_MND_TABLE_CFG)] = queryBuildGetTbCfgMsg;
+ queryBuildMsg[TMSG_INDEX(TDMT_MND_SERVER_VERSION)] = queryBuildGetSerVerMsg;
queryProcessMsgRsp[TMSG_INDEX(TDMT_VND_TABLE_META)] = queryProcessTableMetaRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_TABLE_META)] = queryProcessTableMetaRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_USE_DB)] = queryProcessUseDBRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_QNODE_LIST)] = queryProcessQnodeListRsp;
+ queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_DNODE_LIST)] = queryProcessDnodeListRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_GET_DB_CFG)] = queryProcessGetDbCfgRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_GET_INDEX)] = queryProcessGetIndexRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_RETRIEVE_FUNC)] = queryProcessRetrieveFuncRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_GET_USER_AUTH)] = queryProcessGetUserAuthRsp;
queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_GET_TABLE_INDEX)] = queryProcessGetTbIndexRsp;
+ queryProcessMsgRsp[TMSG_INDEX(TDMT_VND_TABLE_CFG)] = queryProcessGetTbCfgRsp;
+ queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_TABLE_CFG)] = queryProcessGetTbCfgRsp;
+ queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_SERVER_VERSION)] = queryProcessGetSerVerRsp;
}
#pragma GCC diagnostic pop
diff --git a/source/libs/qworker/CMakeLists.txt b/source/libs/qworker/CMakeLists.txt
index 306753808bcca232f7c8b0f824f98ba0351a2b60..92ccde31634eb8051952ff313c86056fba08f075 100644
--- a/source/libs/qworker/CMakeLists.txt
+++ b/source/libs/qworker/CMakeLists.txt
@@ -13,4 +13,4 @@ target_link_libraries(qworker
if(${BUILD_TEST})
ADD_SUBDIRECTORY(test)
-endif(${BUILD_TEST})
\ No newline at end of file
+endif(${BUILD_TEST})
diff --git a/source/libs/qworker/inc/qwInt.h b/source/libs/qworker/inc/qwInt.h
index 2368b13dd67911b5ed404ac095016b559eaa056e..539643c3907cc20de3bee586d21135fbe8adb748 100644
--- a/source/libs/qworker/inc/qwInt.h
+++ b/source/libs/qworker/inc/qwInt.h
@@ -75,15 +75,24 @@ typedef struct SQWDebug {
bool lockEnable;
bool statusEnable;
bool dumpEnable;
+ bool tmp;
} SQWDebug;
extern SQWDebug gQWDebug;
+typedef struct SQWMsgInfo {
+ int8_t taskType;
+ int8_t explain;
+ int8_t needFetch;
+} SQWMsgInfo;
+
typedef struct SQWMsg {
void *node;
int32_t code;
+ int32_t msgType;
char *msg;
int32_t msgLen;
+ SQWMsgInfo msgInfo;
SRpcHandleInfo connInfo;
} SQWMsg;
@@ -100,6 +109,7 @@ typedef struct SQWHbInfo {
typedef struct SQWPhaseInput {
int32_t code;
+ int32_t msgType;
} SQWPhaseInput;
typedef struct SQWPhaseOutput {
@@ -119,12 +129,18 @@ typedef struct SQWTaskCtx {
int8_t phase;
int8_t taskType;
int8_t explain;
+ int8_t needFetch;
+ int32_t queryType;
+ int32_t fetchType;
+ int32_t execId;
+ bool queryRsped;
bool queryFetched;
bool queryEnd;
bool queryContinue;
bool queryInQueue;
int32_t rspCode;
+ int64_t affectedRows; // for insert ...select stmt
SRpcHandleInfo ctrlConnInfo;
SRpcHandleInfo dataConnInfo;
@@ -156,7 +172,7 @@ typedef struct SQWMsgStat {
uint64_t queryProcessed;
uint64_t cqueryProcessed;
uint64_t fetchProcessed;
- uint64_t fetchRspProcessed;
+ uint64_t rspProcessed;
uint64_t cancelProcessed;
uint64_t dropProcessed;
uint64_t hbProcessed;
@@ -197,8 +213,8 @@ typedef struct SQWorkerMgmt {
int32_t paramIdx;
} SQWorkerMgmt;
-#define QW_FPARAMS_DEF SQWorker *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int64_t rId
-#define QW_IDS() sId, qId, tId, rId
+#define QW_FPARAMS_DEF SQWorker *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int64_t rId, int32_t eId
+#define QW_IDS() sId, qId, tId, rId, eId
#define QW_FPARAMS() mgmt, QW_IDS()
#define QW_STAT_INC(_item, _n) atomic_add_fetch_64(&(_item), _n)
@@ -206,8 +222,8 @@ typedef struct SQWorkerMgmt {
#define QW_STAT_GET(_item) atomic_load_64(&(_item))
#define QW_GET_EVENT(ctx, event) atomic_load_8(&(ctx)->events[event])
-#define QW_IS_EVENT_RECEIVED(ctx, event) (QW_GET_EVENT(ctx, event) == QW_EVENT_RECEIVED)
-#define QW_IS_EVENT_PROCESSED(ctx, event) (QW_GET_EVENT(ctx, event) == QW_EVENT_PROCESSED)
+#define QW_EVENT_RECEIVED(ctx, event) (QW_GET_EVENT(ctx, event) == QW_EVENT_RECEIVED)
+#define QW_EVENT_PROCESSED(ctx, event) (QW_GET_EVENT(ctx, event) == QW_EVENT_PROCESSED)
#define QW_SET_EVENT_RECEIVED(ctx, event) atomic_store_8(&(ctx)->events[event], QW_EVENT_RECEIVED)
#define QW_SET_EVENT_PROCESSED(ctx, event) atomic_store_8(&(ctx)->events[event], QW_EVENT_PROCESSED)
@@ -216,22 +232,20 @@ typedef struct SQWorkerMgmt {
#define QW_SET_RSP_CODE(ctx, code) atomic_store_32(&(ctx)->rspCode, code)
#define QW_UPDATE_RSP_CODE(ctx, code) atomic_val_compare_exchange_32(&(ctx)->rspCode, 0, code)
-#define QW_IS_QUERY_RUNNING(ctx) (QW_GET_PHASE(ctx) == QW_PHASE_PRE_QUERY || QW_GET_PHASE(ctx) == QW_PHASE_PRE_CQUERY)
-
-#define QW_TASK_NOT_EXIST(code) (TSDB_CODE_QRY_SCH_NOT_EXIST == (code) || TSDB_CODE_QRY_TASK_NOT_EXIST == (code))
-#define QW_TASK_ALREADY_EXIST(code) (TSDB_CODE_QRY_TASK_ALREADY_EXIST == (code))
-#define QW_TASK_READY(status) \
- (status == JOB_TASK_STATUS_SUCCEED || status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_CANCELLED || \
- status == JOB_TASK_STATUS_PARTIAL_SUCCEED)
-#define QW_SET_QTID(id, qId, tId) \
- do { \
- *(uint64_t *)(id) = (qId); \
- *(uint64_t *)((char *)(id) + sizeof(qId)) = (tId); \
+#define QW_QUERY_RUNNING(ctx) (QW_GET_PHASE(ctx) == QW_PHASE_PRE_QUERY || QW_GET_PHASE(ctx) == QW_PHASE_PRE_CQUERY)
+
+#define QW_SET_QTID(id, qId, tId, eId) \
+ do { \
+ *(uint64_t *)(id) = (qId); \
+ *(uint64_t *)((char *)(id) + sizeof(qId)) = (tId); \
+ *(int32_t *)((char *)(id) + sizeof(qId) + sizeof(tId)) = (eId); \
} while (0)
-#define QW_GET_QTID(id, qId, tId) \
- do { \
- (qId) = *(uint64_t *)(id); \
- (tId) = *(uint64_t *)((char *)(id) + sizeof(qId)); \
+
+#define QW_GET_QTID(id, qId, tId, eId) \
+ do { \
+ (qId) = *(uint64_t *)(id); \
+ (tId) = *(uint64_t *)((char *)(id) + sizeof(qId)); \
+ (eId) = *(int32_t *)((char *)(id) + sizeof(qId) + sizeof(tId)); \
} while (0)
#define QW_ERR_RET(c) \
@@ -273,22 +287,22 @@ typedef struct SQWorkerMgmt {
#define QW_SCH_ELOG(param, ...) qError("QW:%p SID:%" PRIx64 " " param, mgmt, sId, __VA_ARGS__)
#define QW_SCH_DLOG(param, ...) qDebug("QW:%p SID:%" PRIx64 " " param, mgmt, sId, __VA_ARGS__)
-#define QW_TASK_ELOG(param, ...) qError("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId, __VA_ARGS__)
-#define QW_TASK_WLOG(param, ...) qWarn("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId, __VA_ARGS__)
-#define QW_TASK_DLOG(param, ...) qDebug("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId, __VA_ARGS__)
+#define QW_TASK_ELOG(param, ...) qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId, __VA_ARGS__)
+#define QW_TASK_WLOG(param, ...) qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId, __VA_ARGS__)
+#define QW_TASK_DLOG(param, ...) qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId, __VA_ARGS__)
#define QW_TASK_DLOGL(param, ...) \
- qDebugL("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId, __VA_ARGS__)
+ qDebugL("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId, __VA_ARGS__)
-#define QW_TASK_ELOG_E(param) qError("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId)
-#define QW_TASK_WLOG_E(param) qWarn("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId)
-#define QW_TASK_DLOG_E(param) qDebug("QW:%p QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, qId, tId)
+#define QW_TASK_ELOG_E(param) qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId)
+#define QW_TASK_WLOG_E(param) qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId)
+#define QW_TASK_DLOG_E(param) qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, tId, eId)
#define QW_SCH_TASK_ELOG(param, ...) \
- qError("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, sId, qId, tId, __VA_ARGS__)
+ qError("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, qId, tId, eId, __VA_ARGS__)
#define QW_SCH_TASK_WLOG(param, ...) \
- qWarn("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, sId, qId, tId, __VA_ARGS__)
+ qWarn("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, qId, tId, eId, __VA_ARGS__)
#define QW_SCH_TASK_DLOG(param, ...) \
- qDebug("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, mgmt, sId, qId, tId, __VA_ARGS__)
+ qDebug("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, qId, tId, eId, __VA_ARGS__)
#define QW_LOCK_DEBUG(...) \
do { \
@@ -362,6 +376,8 @@ void qwFreeTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx *ctx);
void qwDbgDumpMgmtInfo(SQWorker *mgmt);
int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, bool *ignore);
+int32_t qwDbgBuildAndSendRedirectRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SEpSet *pEpSet);
+int32_t qwAddTaskCtx(QW_FPARAMS_DEF);
#ifdef __cplusplus
diff --git a/source/libs/qworker/inc/qwMsg.h b/source/libs/qworker/inc/qwMsg.h
index 8c7c030dce584dca94d843d85876b3cf29538ac2..704cd3142845c07976f1d8a4b8a798bc99e775d3 100644
--- a/source/libs/qworker/inc/qwMsg.h
+++ b/source/libs/qworker/inc/qwMsg.h
@@ -25,21 +25,20 @@ extern "C" {
int32_t qwAbortPrerocessQuery(QW_FPARAMS_DEF);
int32_t qwPrerocessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg);
-int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t explain, const char* sql);
+int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, const char* sql);
int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg);
int32_t qwProcessReady(QW_FPARAMS_DEF, SQWMsg *qwMsg);
int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg);
int32_t qwProcessDrop(QW_FPARAMS_DEF, SQWMsg *qwMsg);
int32_t qwProcessHb(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req);
-int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SRpcMsg *pRsp, SDeleteRes *pRes);
+int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes);
int32_t qwBuildAndSendDropRsp(SRpcHandleInfo *pConn, int32_t code);
int32_t qwBuildAndSendCancelRsp(SRpcHandleInfo *pConn, int32_t code);
-int32_t qwBuildAndSendFetchRsp(SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength,
- int32_t code);
+int32_t qwBuildAndSendFetchRsp(int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code);
void qwBuildFetchRsp(void *msg, SOutputData *input, int32_t len, bool qComplete);
int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn);
-int32_t qwBuildAndSendQueryRsp(SRpcHandleInfo *pConn, int32_t code, STbVerInfo* tbInfo);
+int32_t qwBuildAndSendQueryRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SQWTaskCtx *ctx);
int32_t qwBuildAndSendExplainRsp(SRpcHandleInfo *pConn, SExplainExecInfo *execInfo, int32_t num);
void qwFreeFetchRsp(void *msg);
int32_t qwMallocFetchRsp(int32_t length, SRetrieveTableRsp **rsp);
diff --git a/source/libs/qworker/src/qwDbg.c b/source/libs/qworker/src/qwDbg.c
index add9700a3a68ea8b0b435be54e3df3c4d0d9d7d0..869eedf8f6e4970f548300b33b10c8bba246d92e 100644
--- a/source/libs/qworker/src/qwDbg.c
+++ b/source/libs/qworker/src/qwDbg.c
@@ -9,7 +9,7 @@
#include "tmsg.h"
#include "tname.h"
-SQWDebug gQWDebug = {.statusEnable = true, .dumpEnable = false};
+SQWDebug gQWDebug = {.statusEnable = true, .dumpEnable = false, .tmp = true};
int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, bool *ignore) {
if (!gQWDebug.statusEnable) {
@@ -19,7 +19,7 @@ int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus,
int32_t code = 0;
if (oriStatus == newStatus) {
- if (newStatus == JOB_TASK_STATUS_EXECUTING || newStatus == JOB_TASK_STATUS_FAILED) {
+ if (newStatus == JOB_TASK_STATUS_EXEC || newStatus == JOB_TASK_STATUS_FAIL) {
*ignore = true;
return TSDB_CODE_SUCCESS;
}
@@ -29,47 +29,47 @@ int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus,
switch (oriStatus) {
case JOB_TASK_STATUS_NULL:
- if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_FAILED &&
- newStatus != JOB_TASK_STATUS_NOT_START) {
+ if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_FAIL &&
+ newStatus != JOB_TASK_STATUS_INIT) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_NOT_START:
- if (newStatus != JOB_TASK_STATUS_DROPPING && newStatus != JOB_TASK_STATUS_EXECUTING
- && newStatus != JOB_TASK_STATUS_FAILED) {
+ case JOB_TASK_STATUS_INIT:
+ if (newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_EXEC
+ && newStatus != JOB_TASK_STATUS_FAIL) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_EXECUTING:
- if (newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED && newStatus != JOB_TASK_STATUS_SUCCEED &&
- newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_EXEC:
+ if (newStatus != JOB_TASK_STATUS_PART_SUCC && newStatus != JOB_TASK_STATUS_SUCC &&
+ newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_DROP) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_PARTIAL_SUCCEED:
- if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_SUCCEED &&
- newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_PART_SUCC:
+ if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_SUCC &&
+ newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_DROP) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_SUCCEED:
- if (newStatus != JOB_TASK_STATUS_DROPPING && newStatus != JOB_TASK_STATUS_FAILED) {
+ case JOB_TASK_STATUS_SUCC:
+ if (newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_FAIL) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_FAILED:
- if (newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_FAIL:
+ if (newStatus != JOB_TASK_STATUS_DROP) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_DROPPING:
- if (newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) {
+ case JOB_TASK_STATUS_DROP:
+ if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_PART_SUCC) {
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
@@ -121,3 +121,90 @@ void qwDbgDumpMgmtInfo(SQWorker *mgmt) {
}
+int32_t qwDbgBuildAndSendRedirectRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SEpSet *pEpSet) {
+ int32_t contLen = 0;
+ char* rsp = NULL;
+
+ if (pEpSet) {
+ contLen = tSerializeSEpSet(NULL, 0, pEpSet);
+ rsp = rpcMallocCont(contLen);
+ tSerializeSEpSet(rsp, contLen, pEpSet);
+ }
+
+ SRpcMsg rpcRsp = {
+ .msgType = rspType,
+ .pCont = rsp,
+ .contLen = contLen,
+ .code = code,
+ .info = *pConn,
+ };
+ rpcRsp.info.hasEpSet = 1;
+
+ tmsgSendRsp(&rpcRsp);
+
+ qDebug("response %s msg, code: %s", TMSG_INFO(rspType), tstrerror(code));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t qwDbgResponseREdirect(SQWMsg *qwMsg, SQWTaskCtx *ctx) {
+ if (gQWDebug.tmp) {
+ if (TDMT_SCH_QUERY == qwMsg->msgType) {
+ SEpSet epSet = {0};
+ epSet.inUse = 1;
+ epSet.numOfEps = 3;
+ strcpy(epSet.eps[0].fqdn, "localhost");
+ epSet.eps[0].port = 7100;
+ strcpy(epSet.eps[1].fqdn, "localhost");
+ epSet.eps[1].port = 7200;
+ strcpy(epSet.eps[2].fqdn, "localhost");
+ epSet.eps[2].port = 7300;
+
+ qwDbgBuildAndSendRedirectRsp(qwMsg->msgType + 1, &qwMsg->connInfo, TSDB_CODE_RPC_REDIRECT, &epSet);
+ gQWDebug.tmp = false;
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (TDMT_SCH_MERGE_QUERY == qwMsg->msgType) {
+ ctx->phase = QW_PHASE_POST_QUERY;
+ qwDbgBuildAndSendRedirectRsp(qwMsg->msgType + 1, &qwMsg->connInfo, TSDB_CODE_RPC_REDIRECT, NULL);
+ gQWDebug.tmp = false;
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t qwDbgEnableDebug(char *option) {
+ if (0 == strcasecmp(option, "lock")) {
+ gQWDebug.lockEnable = true;
+ qDebug("qw lock debug enabled");
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (0 == strcasecmp(option, "status")) {
+ gQWDebug.statusEnable = true;
+ qDebug("qw status debug enabled");
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (0 == strcasecmp(option, "dump")) {
+ gQWDebug.dumpEnable = true;
+ qDebug("qw dump debug enabled");
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (0 == strcasecmp(option, "tmp")) {
+ gQWDebug.tmp = true;
+ qDebug("qw tmp debug enabled");
+ return TSDB_CODE_SUCCESS;
+ }
+
+ qError("invalid qw debug option:%s", option);
+
+ return TSDB_CODE_APP_ERROR;
+}
+
+
diff --git a/source/libs/qworker/src/qwMsg.c b/source/libs/qworker/src/qwMsg.c
index 82a62b5c5a65c5a8e62e4103b674c81b4fe6b03a..73110472f7e35e71ee4bf478c422664212e9660c 100644
--- a/source/libs/qworker/src/qwMsg.c
+++ b/source/libs/qworker/src/qwMsg.c
@@ -43,17 +43,20 @@ void qwFreeFetchRsp(void *msg) {
}
}
-int32_t qwBuildAndSendQueryRsp(SRpcHandleInfo *pConn, int32_t code, STbVerInfo* tbInfo) {
+int32_t qwBuildAndSendQueryRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SQWTaskCtx *ctx) {
+ STbVerInfo* tbInfo = ctx ? &ctx->tbInfo : NULL;
+ int64_t affectedRows = ctx ? ctx->affectedRows : 0;
SQueryTableRsp *pRsp = (SQueryTableRsp *)rpcMallocCont(sizeof(SQueryTableRsp));
- pRsp->code = code;
+ pRsp->code = htonl(code);
+ pRsp->affectedRows = htobe64(affectedRows);
if (tbInfo) {
strcpy(pRsp->tbFName, tbInfo->tbFName);
- pRsp->sversion = tbInfo->sversion;
- pRsp->tversion = tbInfo->tversion;
+ pRsp->sversion = htonl(tbInfo->sversion);
+ pRsp->tversion = htonl(tbInfo->tversion);
}
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_QUERY_RSP,
+ .msgType = rspType,
.pCont = pRsp,
.contLen = sizeof(*pRsp),
.code = code,
@@ -73,7 +76,7 @@ int32_t qwBuildAndSendExplainRsp(SRpcHandleInfo *pConn, SExplainExecInfo *execIn
tSerializeSExplainRsp(pRsp, contLen, &rsp);
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_EXPLAIN_RSP,
+ .msgType = TDMT_SCH_EXPLAIN_RSP,
.pCont = pRsp,
.contLen = contLen,
.code = 0,
@@ -92,7 +95,7 @@ int32_t qwBuildAndSendHbRsp(SRpcHandleInfo *pConn, SSchedulerHbRsp *pStatus, int
tSerializeSSchedulerHbRsp(pRsp, contLen, pStatus);
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_QUERY_HEARTBEAT_RSP,
+ .msgType = TDMT_SCH_QUERY_HEARTBEAT_RSP,
.contLen = contLen,
.pCont = pRsp,
.code = code,
@@ -104,7 +107,7 @@ int32_t qwBuildAndSendHbRsp(SRpcHandleInfo *pConn, SSchedulerHbRsp *pStatus, int
return TSDB_CODE_SUCCESS;
}
-int32_t qwBuildAndSendFetchRsp(SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code) {
+int32_t qwBuildAndSendFetchRsp(int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code) {
if (NULL == pRsp) {
pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp));
memset(pRsp, 0, sizeof(SRetrieveTableRsp));
@@ -112,7 +115,7 @@ int32_t qwBuildAndSendFetchRsp(SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, i
}
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_FETCH_RSP,
+ .msgType = rspType,
.pCont = pRsp,
.contLen = sizeof(*pRsp) + dataLength,
.code = code,
@@ -129,7 +132,7 @@ int32_t qwBuildAndSendCancelRsp(SRpcHandleInfo *pConn, int32_t code) {
pRsp->code = code;
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_CANCEL_TASK_RSP,
+ .msgType = TDMT_SCH_CANCEL_TASK_RSP,
.pCont = pRsp,
.contLen = sizeof(*pRsp),
.code = code,
@@ -145,7 +148,7 @@ int32_t qwBuildAndSendDropRsp(SRpcHandleInfo *pConn, int32_t code) {
pRsp->code = code;
SRpcMsg rpcRsp = {
- .msgType = TDMT_VND_DROP_TASK_RSP,
+ .msgType = TDMT_SCH_DROP_TASK_RSP,
.pCont = pRsp,
.contLen = sizeof(*pRsp),
.code = code,
@@ -156,6 +159,41 @@ int32_t qwBuildAndSendDropRsp(SRpcHandleInfo *pConn, int32_t code) {
return TSDB_CODE_SUCCESS;
}
+int32_t qwBuildAndSendDropMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) {
+ STaskDropReq *req = (STaskDropReq *)rpcMallocCont(sizeof(STaskDropReq));
+ if (NULL == req) {
+ QW_SCH_TASK_ELOG("rpcMallocCont %d failed", (int32_t)sizeof(STaskDropReq));
+ QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ req->header.vgId = mgmt->nodeId;
+ req->sId = sId;
+ req->queryId = qId;
+ req->taskId = tId;
+ req->refId = rId;
+ req->execId = eId;
+
+ SRpcMsg pNewMsg = {
+ .msgType = TDMT_SCH_DROP_TASK,
+ .pCont = req,
+ .contLen = sizeof(STaskDropReq),
+ .code = 0,
+ .info = *pConn,
+ };
+
+ int32_t code = tmsgPutToQueue(&mgmt->msgCb, FETCH_QUEUE, &pNewMsg);
+ if (TSDB_CODE_SUCCESS != code) {
+ QW_SCH_TASK_ELOG("put drop task msg to queue failed, vgId:%d, code:%s", mgmt->nodeId, tstrerror(code));
+ rpcFreeCont(req);
+ QW_ERR_RET(code);
+ }
+
+ QW_SCH_TASK_DLOG("drop task msg put to queue, vgId:%d", mgmt->nodeId);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) {
SQueryContinueReq *req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq));
if (NULL == req) {
@@ -167,9 +205,10 @@ int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) {
req->sId = sId;
req->queryId = qId;
req->taskId = tId;
+ req->execId = eId;
SRpcMsg pNewMsg = {
- .msgType = TDMT_VND_QUERY_CONTINUE,
+ .msgType = TDMT_SCH_QUERY_CONTINUE,
.pCont = req,
.contLen = sizeof(SQueryContinueReq),
.code = 0,
@@ -202,10 +241,10 @@ int32_t qwRegisterQueryBrokenLinkArg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) {
req->refId = htobe64(rId);
SRpcMsg brokenMsg = {
- .msgType = TDMT_VND_DROP_TASK,
+ .msgType = TDMT_SCH_DROP_TASK,
.pCont = req,
.contLen = sizeof(STaskDropReq),
- .code = TSDB_CODE_RPC_NETWORK_UNAVAIL,
+ .code = TSDB_CODE_RPC_BROKEN_LINK,
.info = *pConn,
};
@@ -236,10 +275,10 @@ int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t sId, SRpcHandleInfo *
}
SRpcMsg brokenMsg = {
- .msgType = TDMT_VND_QUERY_HEARTBEAT,
+ .msgType = TDMT_SCH_QUERY_HEARTBEAT,
.pCont = msg,
.contLen = msgSize,
- .code = TSDB_CODE_RPC_NETWORK_UNAVAIL,
+ .code = TSDB_CODE_RPC_BROKEN_LINK,
.info = *pConn,
};
@@ -266,6 +305,7 @@ int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg) {
msg->queryId = be64toh(msg->queryId);
msg->taskId = be64toh(msg->taskId);
msg->refId = be64toh(msg->refId);
+ msg->execId = ntohl(msg->execId);
msg->phyLen = ntohl(msg->phyLen);
msg->sqlLen = ntohl(msg->sqlLen);
@@ -273,6 +313,7 @@ int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg) {
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = msg->refId;
+ int32_t eId = msg->execId;
SQWMsg qwMsg = {.msg = msg->msg + msg->sqlLen, .msgLen = msg->phyLen, .connInfo = pMsg->info};
@@ -295,6 +336,7 @@ int32_t qWorkerAbortPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg) {
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = msg->refId;
+ int32_t eId = msg->execId;
QW_SCH_TASK_DLOG("Abort prerocessQuery start, handle:%p", pMsg->info.handle);
qwAbortPrerocessQuery(QW_FPARAMS());
@@ -324,12 +366,17 @@ int32_t qWorkerProcessQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = msg->refId;
+ int32_t eId = msg->execId;
- SQWMsg qwMsg = {.node = node, .msg = msg->msg + msg->sqlLen, .msgLen = msg->phyLen, .connInfo = pMsg->info};
+ SQWMsg qwMsg = {.node = node, .msg = msg->msg + msg->sqlLen, .msgLen = msg->phyLen, .connInfo = pMsg->info, .msgType = pMsg->msgType};
+ qwMsg.msgInfo.explain = msg->explain;
+ qwMsg.msgInfo.taskType = msg->taskType;
+ qwMsg.msgInfo.needFetch = msg->needFetch;
+
char * sql = strndup(msg->msg, msg->sqlLen);
- QW_SCH_TASK_DLOG("processQuery start, node:%p, handle:%p, sql:%s", node, pMsg->info.handle, sql);
+ QW_SCH_TASK_DLOG("processQuery start, node:%p, type:%s, handle:%p, sql:%s", node, TMSG_INFO(pMsg->msgType), pMsg->info.handle, sql);
- QW_ERR_RET(qwProcessQuery(QW_FPARAMS(), &qwMsg, msg->taskType, msg->explain, sql));
+ QW_ERR_RET(qwProcessQuery(QW_FPARAMS(), &qwMsg, sql));
QW_SCH_TASK_DLOG("processQuery end, node:%p", node);
return TSDB_CODE_SUCCESS;
@@ -356,6 +403,7 @@ int32_t qWorkerProcessCQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, in
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = 0;
+ int32_t eId = msg->execId;
SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connInfo = pMsg->info};
@@ -387,13 +435,15 @@ int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int
msg->sId = be64toh(msg->sId);
msg->queryId = be64toh(msg->queryId);
msg->taskId = be64toh(msg->taskId);
+ msg->execId = ntohl(msg->execId);
uint64_t sId = msg->sId;
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = 0;
+ int32_t eId = msg->execId;
- SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connInfo = pMsg->info};
+ SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connInfo = pMsg->info, .msgType = pMsg->msgType};
QW_SCH_TASK_DLOG("processFetch start, node:%p, handle:%p", node, pMsg->info.handle);
@@ -404,14 +454,14 @@ int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int
return TSDB_CODE_SUCCESS;
}
-int32_t qWorkerProcessFetchRsp(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts) {
+int32_t qWorkerProcessRspMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts) {
SQWorker * mgmt = (SQWorker *)qWorkerMgmt;
if (mgmt) {
qwUpdateTimeInQueue(mgmt, ts, FETCH_QUEUE);
- QW_STAT_INC(mgmt->stat.msgStat.fetchRspProcessed, 1);
+ QW_STAT_INC(mgmt->stat.msgStat.rspProcessed, 1);
}
- qProcessFetchRsp(NULL, pMsg, NULL);
+ qProcessRspMsg(NULL, pMsg, NULL);
pMsg->pCont = NULL;
return TSDB_CODE_SUCCESS;
}
@@ -437,11 +487,13 @@ int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, in
msg->queryId = be64toh(msg->queryId);
msg->taskId = be64toh(msg->taskId);
msg->refId = be64toh(msg->refId);
+ msg->execId = ntohl(msg->execId);
uint64_t sId = msg->sId;
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = msg->refId;
+ int32_t eId = msg->execId;
SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connInfo = pMsg->info};
@@ -476,15 +528,17 @@ int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int6
msg->queryId = be64toh(msg->queryId);
msg->taskId = be64toh(msg->taskId);
msg->refId = be64toh(msg->refId);
+ msg->execId = ntohl(msg->execId);
uint64_t sId = msg->sId;
uint64_t qId = msg->queryId;
uint64_t tId = msg->taskId;
int64_t rId = msg->refId;
+ int32_t eId = msg->execId;
SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .code = pMsg->code, .connInfo = pMsg->info};
- if (TSDB_CODE_RPC_NETWORK_UNAVAIL == pMsg->code) {
+ if (TSDB_CODE_RPC_BROKEN_LINK == pMsg->code) {
QW_SCH_TASK_DLOG("receive drop task due to network broken, error:%s", tstrerror(pMsg->code));
}
@@ -522,7 +576,7 @@ int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_
uint64_t sId = req.sId;
SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .code = pMsg->code, .connInfo = pMsg->info};
- if (TSDB_CODE_RPC_NETWORK_UNAVAIL == pMsg->code) {
+ if (TSDB_CODE_RPC_BROKEN_LINK == pMsg->code) {
QW_SCH_DLOG("receive Hb msg due to network broken, error:%s", tstrerror(pMsg->code));
}
@@ -536,8 +590,8 @@ int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_
}
-int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SRpcMsg *pRsp, SDeleteRes *pRes) {
- if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg || NULL == pRsp) {
+int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SDeleteRes *pRes) {
+ if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) {
QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
}
@@ -553,12 +607,13 @@ int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SR
uint64_t qId = req.queryId;
uint64_t tId = req.taskId;
int64_t rId = 0;
+ int32_t eId = -1;
SQWMsg qwMsg = {.node = node, .msg = req.msg, .msgLen = req.phyLen, .connInfo = pMsg->info};
QW_SCH_TASK_DLOG("processDelete start, node:%p, handle:%p, sql:%s", node, pMsg->info.handle, req.sql);
taosMemoryFreeClear(req.sql);
- QW_ERR_JRET(qwProcessDelete(QW_FPARAMS(), &qwMsg, pRsp, pRes));
+ QW_ERR_JRET(qwProcessDelete(QW_FPARAMS(), &qwMsg, pRes));
QW_SCH_TASK_DLOG("processDelete end, node:%p", node);
diff --git a/source/libs/qworker/src/qwUtil.c b/source/libs/qworker/src/qwUtil.c
index 0759cf360a26d2d1c10acba8bdbfe35659b7158e..9c49cbcb1fd2f9cd735a74e6782d3ace298661ee 100644
--- a/source/libs/qworker/src/qwUtil.c
+++ b/source/libs/qworker/src/qwUtil.c
@@ -135,8 +135,8 @@ int32_t qwAcquireScheduler(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchS
void qwReleaseScheduler(int32_t rwType, SQWorker *mgmt) { QW_UNLOCK(rwType, &mgmt->schLock); }
int32_t qwAcquireTaskStatus(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus *sch, SQWTaskStatus **task) {
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
QW_LOCK(rwType, &sch->tasksLock);
*task = taosHashGet(sch->tasksHash, id, sizeof(id));
@@ -151,8 +151,8 @@ int32_t qwAcquireTaskStatus(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus *sch, S
int32_t qwAddTaskStatusImpl(QW_FPARAMS_DEF, SQWSchStatus *sch, int32_t rwType, int32_t status, SQWTaskStatus **task) {
int32_t code = 0;
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
SQWTaskStatus ntask = {0};
ntask.status = status;
@@ -207,8 +207,8 @@ int32_t qwAddAcquireTaskStatus(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus *sch
void qwReleaseTaskStatus(int32_t rwType, SQWSchStatus *sch) { QW_UNLOCK(rwType, &sch->tasksLock); }
int32_t qwAcquireTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) {
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
*ctx = taosHashAcquire(mgmt->ctxHash, id, sizeof(id));
if (NULL == (*ctx)) {
@@ -220,8 +220,8 @@ int32_t qwAcquireTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) {
}
int32_t qwGetTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) {
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
*ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id));
if (NULL == (*ctx)) {
@@ -233,8 +233,8 @@ int32_t qwGetTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) {
}
int32_t qwAddTaskCtxImpl(QW_FPARAMS_DEF, bool acquire, SQWTaskCtx **ctx) {
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
SQWTaskCtx nctx = {0};
@@ -314,8 +314,8 @@ void qwFreeTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx *ctx) {
}
int32_t qwDropTaskCtx(QW_FPARAMS_DEF) {
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
SQWTaskCtx octx;
SQWTaskCtx *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id));
@@ -348,8 +348,8 @@ int32_t qwDropTaskStatus(QW_FPARAMS_DEF) {
SQWTaskStatus *task = NULL;
int32_t code = 0;
- char id[sizeof(qId) + sizeof(tId)] = {0};
- QW_SET_QTID(id, qId, tId);
+ char id[sizeof(qId) + sizeof(tId) + sizeof(eId)] = {0};
+ QW_SET_QTID(id, qId, tId, eId);
if (qwAcquireScheduler(mgmt, sId, QW_WRITE, &sch)) {
QW_TASK_WLOG_E("scheduler does not exist");
@@ -433,10 +433,10 @@ void qwSetHbParam(int64_t refId, SQWHbParam **pParam) {
}
void qwSaveTbVersionInfo(qTaskInfo_t pTaskInfo, SQWTaskCtx *ctx) {
- char dbFName[TSDB_DB_FNAME_LEN];
- char tbName[TSDB_TABLE_NAME_LEN];
+ char dbFName[TSDB_DB_FNAME_LEN] = {0};
+ char tbName[TSDB_TABLE_NAME_LEN] = {0};
- qGetQueriedTableSchemaVersion(pTaskInfo, dbFName, tbName, &ctx->tbInfo.sversion, &ctx->tbInfo.tversion);
+ qGetQueryTableSchemaVersion(pTaskInfo, dbFName, tbName, &ctx->tbInfo.sversion, &ctx->tbInfo.tversion);
if (dbFName[0] && tbName[0]) {
sprintf(ctx->tbInfo.tbFName, "%s.%s", dbFName, tbName);
diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c
index 28181d7e11291a984ae53b0bff2bc46282977548..3e8ced318c4baa2f1eec3aee85db03c6c67547ba 100644
--- a/source/libs/qworker/src/qworker.c
+++ b/source/libs/qworker/src/qworker.c
@@ -57,6 +57,10 @@ int32_t qwHandleTaskComplete(QW_FPARAMS_DEF, SQWTaskCtx *ctx) {
connInfo.ahandle = NULL;
QW_ERR_RET(qwBuildAndSendExplainRsp(&connInfo, execInfo, resNum));
}
+
+ if (!ctx->needFetch) {
+ dsGetDataLength(ctx->sinkHandle, &ctx->affectedRows, NULL);
+ }
}
return TSDB_CODE_SUCCESS;
@@ -123,11 +127,11 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryEnd) {
break;
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_READY) && execNum >= QW_DEFAULT_SHORT_RUN_TIMES) {
+ if (ctx->needFetch && (!ctx->queryRsped) && execNum >= QW_DEFAULT_SHORT_RUN_TIMES) {
break;
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
break;
}
@@ -168,7 +172,7 @@ int32_t qwGenerateSchHbRsp(SQWorker *mgmt, SQWSchStatus *sch, SQWHbInfo *hbInfo)
// TODO GET EXECUTOR API TO GET MORE INFO
- QW_GET_QTID(key, status.queryId, status.taskId);
+ QW_GET_QTID(key, status.queryId, status.taskId, status.execId);
status.status = taskStatus->status;
status.refId = taskStatus->refId;
@@ -184,7 +188,7 @@ int32_t qwGenerateSchHbRsp(SQWorker *mgmt, SQWSchStatus *sch, SQWHbInfo *hbInfo)
}
int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, void **rspMsg, SOutputData *pOutput) {
- int32_t len = 0;
+ int64_t len = 0;
SRetrieveTableRsp *rsp = NULL;
bool queryEnd = false;
int32_t code = 0;
@@ -206,7 +210,7 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen,
QW_TASK_DLOG_E("no data in sink and query end");
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCC);
QW_ERR_RET(qwMallocFetchRsp(len, &rsp));
*rspMsg = rsp;
@@ -236,15 +240,14 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen,
if (DS_BUF_EMPTY == pOutput->bufStatus && pOutput->queryEnd) {
QW_TASK_DLOG_E("task all data fetched, done");
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCC);
}
return TSDB_CODE_SUCCESS;
}
-int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, void **rspMsg, SDeleteRes *pRes) {
- int32_t len = 0;
- SVDeleteRsp rsp = {0};
+int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SDeleteRes *pRes) {
+ int64_t len = 0;
bool queryEnd = false;
int32_t code = 0;
SOutputData output = {0};
@@ -252,7 +255,7 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen
dsGetDataLength(ctx->sinkHandle, &len, &queryEnd);
if (len <= 0 || len != sizeof(SDeleterRes)) {
- QW_TASK_ELOG("invalid length from dsGetDataLength, length:%d", len);
+ QW_TASK_ELOG("invalid length from dsGetDataLength, length:%" PRId64, len);
QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
}
@@ -270,21 +273,11 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen
SDeleterRes* pDelRes = (SDeleterRes*)output.pData;
- rsp.affectedRows = pDelRes->affectedRows;
- pRes->uid = pDelRes->uid;
+ pRes->suid = pDelRes->suid;
pRes->uidList = pDelRes->uidList;
pRes->skey = pDelRes->skey;
pRes->ekey = pDelRes->ekey;
-
- SEncoder coder = {0};
- tEncodeSize(tEncodeSVDeleteRsp, &rsp, len, code);
- void *msg = rpcMallocCont(len);
- tEncoderInit(&coder, msg, len);
- tEncodeSVDeleteRsp(&coder, &rsp);
- tEncoderClear(&coder);
-
- *rspMsg = msg;
- *dataLen = len;
+ pRes->affectedRows = pDelRes->affectedRows;
return TSDB_CODE_SUCCESS;
}
@@ -293,7 +286,6 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen
int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *input, SQWPhaseOutput *output) {
int32_t code = 0;
SQWTaskCtx *ctx = NULL;
- SRpcHandleInfo *cancelConnection = NULL;
QW_TASK_DLOG("start to handle event at phase %s", qwPhaseStr(phase));
@@ -314,13 +306,13 @@ int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inpu
switch (phase) {
case QW_PHASE_PRE_QUERY: {
- if (QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
QW_TASK_ELOG("task already dropped at wrong phase %s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_TASK_STATUS_ERROR);
break;
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
QW_ERR_JRET(qwDropTask(QW_FPARAMS()));
//qwBuildAndSendDropRsp(&ctx->ctrlConnInfo, code);
@@ -330,33 +322,33 @@ int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inpu
break;
}
- QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING));
+ QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXEC));
break;
}
case QW_PHASE_PRE_FETCH: {
- if (QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_DROP) || QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP) || QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
QW_TASK_WLOG("task dropping or already dropped, phase:%s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_TASK_DROPPED);
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
QW_TASK_WLOG("last fetch still not processed, phase:%s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_DUPLICATTED_OPERATION);
}
- if (!QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_READY)) {
+ if (!ctx->queryRsped) {
QW_TASK_ELOG("ready msg has not been processed, phase:%s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_TASK_MSG_ERROR);
}
break;
}
case QW_PHASE_PRE_CQUERY: {
- if (QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
QW_TASK_WLOG("task already dropped, phase:%s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_TASK_DROPPED);
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
QW_ERR_JRET(qwDropTask(QW_FPARAMS()));
//qwBuildAndSendDropRsp(&ctx->ctrlConnInfo, code);
@@ -385,11 +377,6 @@ _return:
qwReleaseTaskCtx(mgmt, ctx);
}
- if (cancelConnection) {
- qwBuildAndSendCancelRsp(cancelConnection, code);
- QW_TASK_DLOG("cancel rsp send, handle:%p, code:%x - %s", cancelConnection->handle, code, tstrerror(code));
- }
-
if (code != TSDB_CODE_SUCCESS) {
QW_TASK_ELOG("end to handle event at phase %s, code:%s", qwPhaseStr(phase), tstrerror(code));
} else {
@@ -411,26 +398,19 @@ int32_t qwHandlePostPhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inp
QW_LOCK(QW_WRITE, &ctx->lock);
- if (QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) {
QW_TASK_WLOG("task already dropped, phase:%s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_TASK_DROPPED);
}
if (QW_PHASE_POST_QUERY == phase) {
-#if 0
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_READY)) {
- readyConnection = &ctx->connInfo;
- QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_READY);
- }
-#else
connInfo = ctx->ctrlConnInfo;
rspConnection = &connInfo;
- QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_READY);
-#endif
+ ctx->queryRsped = true;
}
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
if (QW_PHASE_POST_FETCH == phase) {
QW_TASK_WLOG("drop received at wrong phase %s", qwPhaseStr(phase));
QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
@@ -454,12 +434,12 @@ int32_t qwHandlePostPhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inp
_return:
if (TSDB_CODE_SUCCESS == code && QW_PHASE_POST_QUERY == phase) {
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_PARTIAL_SUCCEED);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_PART_SUCC);
}
if (rspConnection) {
- qwBuildAndSendQueryRsp(rspConnection, code, ctx ? &ctx->tbInfo : NULL);
- QW_TASK_DLOG("ready msg rsped, handle:%p, code:%x - %s", rspConnection->handle, code, tstrerror(code));
+ qwBuildAndSendQueryRsp(input->msgType + 1, rspConnection, code, ctx);
+ QW_TASK_DLOG("query msg rsped, handle:%p, code:%x - %s", rspConnection->handle, code, tstrerror(code));
}
if (ctx) {
@@ -474,7 +454,7 @@ _return:
}
if (code) {
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAILED);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL);
}
QW_TASK_DLOG("end to handle event at phase %s, code:%x - %s", qwPhaseStr(phase), code, tstrerror(code));
@@ -500,11 +480,13 @@ int32_t qwPrerocessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
QW_ERR_JRET(qwRegisterQueryBrokenLinkArg(QW_FPARAMS(), &qwMsg->connInfo));
- QW_ERR_JRET(qwAddAcquireTaskCtx(QW_FPARAMS(), &ctx));
+ QW_ERR_JRET(qwAddTaskCtx(QW_FPARAMS()));
+
+ QW_ERR_JRET(qwAcquireTaskCtx(QW_FPARAMS(), &ctx));
ctx->ctrlConnInfo = qwMsg->connInfo;
- QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_NOT_START));
+ QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_INIT));
_return:
@@ -517,7 +499,7 @@ _return:
}
-int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t explain, const char* sql) {
+int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, const char* sql) {
int32_t code = 0;
bool queryRsped = false;
SSubplan *plan = NULL;
@@ -530,10 +512,12 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t ex
QW_ERR_JRET(qwGetTaskCtx(QW_FPARAMS(), &ctx));
- atomic_store_8(&ctx->taskType, taskType);
- atomic_store_8(&ctx->explain, explain);
+ ctx->taskType = qwMsg->msgInfo.taskType;
+ ctx->explain = qwMsg->msgInfo.explain;
+ ctx->needFetch = qwMsg->msgInfo.needFetch;
+ ctx->queryType = qwMsg->msgType;
- QW_TASK_DLOGL("subplan json string, len:%d, %s", qwMsg->msgLen, qwMsg->msg);
+ //QW_TASK_DLOGL("subplan json string, len:%d, %s", qwMsg->msgLen, qwMsg->msg);
code = qStringToSubplan(qwMsg->msg, &plan);
if (TSDB_CODE_SUCCESS != code) {
@@ -571,6 +555,7 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t ex
_return:
input.code = code;
+ input.msgType = qwMsg->msgType;
code = qwHandlePostPhaseEvents(QW_FPARAMS(), QW_PHASE_POST_QUERY, &input, NULL);
// if (!queryRsped) {
@@ -599,7 +584,7 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
QW_ERR_JRET(qwExecTask(QW_FPARAMS(), ctx, &queryEnd));
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
SOutputData sOutput = {0};
QW_ERR_JRET(qwGetQueryResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp, &sOutput));
@@ -620,7 +605,7 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
qwMsg->connInfo = ctx->dataConnInfo;
QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH);
- qwBuildAndSendFetchRsp(&qwMsg->connInfo, rsp, dataLen, code);
+ qwBuildAndSendFetchRsp(ctx->fetchType, &qwMsg->connInfo, rsp, dataLen, code);
rsp = NULL;
QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code,
@@ -636,13 +621,13 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
break;
}
- if (code && QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
+ if (code && QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) {
QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH);
qwFreeFetchRsp(rsp);
rsp = NULL;
qwMsg->connInfo = ctx->dataConnInfo;
- qwBuildAndSendFetchRsp(&qwMsg->connInfo, NULL, 0, code);
+ qwBuildAndSendFetchRsp(ctx->fetchType, &qwMsg->connInfo, NULL, 0, code);
QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code),
0);
}
@@ -675,6 +660,8 @@ int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
QW_ERR_JRET(qwGetTaskCtx(QW_FPARAMS(), &ctx));
+ ctx->queryType = qwMsg->msgType;
+
SOutputData sOutput = {0};
QW_ERR_JRET(qwGetQueryResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp, &sOutput));
@@ -698,10 +685,10 @@ int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
locked = true;
// RC WARNING
- if (QW_IS_QUERY_RUNNING(ctx)) {
+ if (QW_QUERY_RUNNING(ctx)) {
atomic_store_8((int8_t *)&ctx->queryContinue, 1);
} else if (0 == atomic_load_8((int8_t *)&ctx->queryInQueue)) {
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXEC);
atomic_store_8((int8_t *)&ctx->queryInQueue, 1);
@@ -725,8 +712,8 @@ _return:
}
if (code || rsp) {
- qwBuildAndSendFetchRsp(&qwMsg->connInfo, rsp, dataLen, code);
- QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code),
+ qwBuildAndSendFetchRsp(qwMsg->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code);
+ QW_TASK_DLOG("%s send, handle:%p, code:%x - %s, dataLen:%d", TMSG_INFO(qwMsg->msgType + 1), qwMsg->connInfo.handle, code, tstrerror(code),
dataLen);
}
@@ -739,22 +726,20 @@ int32_t qwProcessDrop(QW_FPARAMS_DEF, SQWMsg *qwMsg) {
SQWTaskCtx *ctx = NULL;
bool locked = false;
- // TODO : TASK ALREADY REMOVED AND A NEW DROP MSG RECEIVED
-
QW_ERR_JRET(qwAcquireTaskCtx(QW_FPARAMS(), &ctx));
QW_LOCK(QW_WRITE, &ctx->lock);
locked = true;
- if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
+ if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) {
QW_TASK_WLOG_E("task already dropping");
QW_ERR_JRET(TSDB_CODE_QRY_DUPLICATTED_OPERATION);
}
- if (QW_IS_QUERY_RUNNING(ctx)) {
+ if (QW_QUERY_RUNNING(ctx)) {
QW_ERR_JRET(qwKillTaskHandle(QW_FPARAMS(), ctx));
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_DROPPING);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_DROP);
} else if (ctx->phase > 0) {
QW_ERR_JRET(qwDropTask(QW_FPARAMS()));
rsped = true;
@@ -775,7 +760,7 @@ _return:
QW_UPDATE_RSP_CODE(ctx, code);
}
- qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAILED);
+ qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL);
}
if (locked) {
@@ -931,7 +916,7 @@ _return:
qwRelease(refId);
}
-int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SRpcMsg *pRsp, SDeleteRes *pRes) {
+int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes) {
int32_t code = 0;
SSubplan *plan = NULL;
qTaskInfo_t pTaskInfo = NULL;
@@ -946,7 +931,7 @@ int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SRpcMsg *pRsp, SDeleteRes
}
ctx.plan = plan;
-
+
code = qCreateExecTask(qwMsg->node, mgmt->nodeId, tId, plan, &pTaskInfo, &sinkHandle, NULL, OPTR_EXEC_MODEL_BATCH);
if (code) {
QW_TASK_ELOG("qCreateExecTask failed, code:%x - %s", code, tstrerror(code));
@@ -963,7 +948,7 @@ int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SRpcMsg *pRsp, SDeleteRes
QW_ERR_JRET(qwExecTask(QW_FPARAMS(), &ctx, NULL));
- QW_ERR_JRET(qwGetDeleteResFromSink(QW_FPARAMS(), &ctx, &pRsp->contLen, &pRsp->pCont, pRes));
+ QW_ERR_JRET(qwGetDeleteResFromSink(QW_FPARAMS(), &ctx, pRes));
_return:
@@ -1056,7 +1041,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qW
*qWorkerMgmt = mgmt;
- qDebug("qworker initialized for node, type:%d, id:%d, handle:%p", mgmt->nodeType, mgmt->nodeId, mgmt);
+ qDebug("qworker initialized, type:%d, id:%d, handle:%p", mgmt->nodeType, mgmt->nodeId, mgmt);
return TSDB_CODE_SUCCESS;
diff --git a/source/libs/qworker/test/CMakeLists.txt b/source/libs/qworker/test/CMakeLists.txt
index e7cc8b7c836187978da78531e866be864ed95869..780f5ae84be12a8b1feea24c25bfa148a1f9de5b 100644
--- a/source/libs/qworker/test/CMakeLists.txt
+++ b/source/libs/qworker/test/CMakeLists.txt
@@ -1,18 +1,19 @@
MESSAGE(STATUS "build qworker unit test")
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+ ADD_EXECUTABLE(qworkerTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ qworkerTest
+ PUBLIC os util common transport gtest qcom nodes planner qworker executor
+ )
-ADD_EXECUTABLE(qworkerTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- qworkerTest
- PUBLIC os util common transport gtest qcom nodes planner qworker executor
-)
-
-TARGET_INCLUDE_DIRECTORIES(
- qworkerTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/qworker/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/qworker/inc"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ qworkerTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/qworker/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/qworker/inc"
+ )
+ENDIF()
diff --git a/source/libs/qworker/test/qworkerTests.cpp b/source/libs/qworker/test/qworkerTests.cpp
index 5bb6acee6014fb9352b9ac11304500df33e3ffcd..1f76ea1e7e294090019d8f67e108b1b97cb84d6b 100644
--- a/source/libs/qworker/test/qworkerTests.cpp
+++ b/source/libs/qworker/test/qworkerTests.cpp
@@ -122,7 +122,7 @@ void qwtBuildQueryReqMsg(SRpcMsg *queryRpc) {
qwtqueryMsg.taskId = htobe64(1);
qwtqueryMsg.phyLen = htonl(100);
qwtqueryMsg.sqlLen = 0;
- queryRpc->msgType = TDMT_VND_QUERY;
+ queryRpc->msgType = TDMT_SCH_QUERY;
queryRpc->pCont = &qwtqueryMsg;
queryRpc->contLen = sizeof(SSubQueryMsg) + 100;
}
@@ -131,7 +131,7 @@ void qwtBuildFetchReqMsg(SResFetchReq *fetchMsg, SRpcMsg *fetchRpc) {
fetchMsg->sId = htobe64(1);
fetchMsg->queryId = htobe64(atomic_load_64(&qwtTestQueryId));
fetchMsg->taskId = htobe64(1);
- fetchRpc->msgType = TDMT_VND_FETCH;
+ fetchRpc->msgType = TDMT_SCH_FETCH;
fetchRpc->pCont = fetchMsg;
fetchRpc->contLen = sizeof(SResFetchReq);
}
@@ -140,7 +140,7 @@ void qwtBuildDropReqMsg(STaskDropReq *dropMsg, SRpcMsg *dropRpc) {
dropMsg->sId = htobe64(1);
dropMsg->queryId = htobe64(atomic_load_64(&qwtTestQueryId));
dropMsg->taskId = htobe64(1);
- dropRpc->msgType = TDMT_VND_DROP_TASK;
+ dropRpc->msgType = TDMT_SCH_DROP_TASK;
dropRpc->pCont = dropMsg;
dropRpc->contLen = sizeof(STaskDropReq);
}
@@ -202,7 +202,8 @@ void qwtSendReqToDnode(void* pVnode, struct SEpSet* epSet, struct SRpcMsg* pReq)
void qwtRpcSendResponse(const SRpcMsg *pRsp) {
switch (pRsp->msgType) {
- case TDMT_VND_QUERY_RSP: {
+ case TDMT_SCH_QUERY_RSP:
+ case TDMT_SCH_MERGE_QUERY_RSP: {
SQueryTableRsp *rsp = (SQueryTableRsp *)pRsp->pCont;
if (pRsp->code) {
@@ -213,7 +214,8 @@ void qwtRpcSendResponse(const SRpcMsg *pRsp) {
rpcFreeCont(rsp);
break;
}
- case TDMT_VND_FETCH_RSP: {
+ case TDMT_SCH_FETCH_RSP:
+ case TDMT_SCH_MERGE_FETCH_RSP: {
SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)pRsp->pCont;
if (0 == pRsp->code && 0 == rsp->completed) {
@@ -229,7 +231,7 @@ void qwtRpcSendResponse(const SRpcMsg *pRsp) {
break;
}
- case TDMT_VND_DROP_TASK_RSP: {
+ case TDMT_SCH_DROP_TASK_RSP: {
STaskDropRsp *rsp = (STaskDropRsp *)pRsp->pCont;
rpcFreeCont(rsp);
@@ -330,7 +332,7 @@ void qwtEndPut(DataSinkHandle handle, uint64_t useconds) {
qwtTestSinkQueryEnd = true;
}
-void qwtGetDataLength(DataSinkHandle handle, int32_t* pLen, bool* pQueryEnd) {
+void qwtGetDataLength(DataSinkHandle handle, int64_t* pLen, bool* pQueryEnd) {
static int32_t in = 0;
if (in > 0) {
@@ -756,9 +758,9 @@ void *queryQueueThread(void *param) {
}
}
- if (TDMT_VND_QUERY == queryRpc->msgType) {
+ if (TDMT_SCH_QUERY == queryRpc->msgType) {
qWorkerProcessQueryMsg(mockPointer, mgmt, queryRpc, 0);
- } else if (TDMT_VND_QUERY_CONTINUE == queryRpc->msgType) {
+ } else if (TDMT_SCH_QUERY_CONTINUE == queryRpc->msgType) {
qWorkerProcessCQueryMsg(mockPointer, mgmt, queryRpc, 0);
} else {
printf("unknown msg in query queue, type:%d\n", queryRpc->msgType);
@@ -813,13 +815,14 @@ void *fetchQueueThread(void *param) {
}
switch (fetchRpc->msgType) {
- case TDMT_VND_FETCH:
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH:
qWorkerProcessFetchMsg(mockPointer, mgmt, fetchRpc, 0);
break;
- case TDMT_VND_CANCEL_TASK:
+ case TDMT_SCH_CANCEL_TASK:
qWorkerProcessCancelMsg(mockPointer, mgmt, fetchRpc, 0);
break;
- case TDMT_VND_DROP_TASK:
+ case TDMT_SCH_DROP_TASK:
qWorkerProcessDropMsg(mockPointer, mgmt, fetchRpc, 0);
break;
default:
diff --git a/source/libs/scalar/inc/sclInt.h b/source/libs/scalar/inc/sclInt.h
index 4dd16098ff3df97185c4a6f249a12882456d111d..d423b92da7e83589aacc6d384c0e2cafa0949038 100644
--- a/source/libs/scalar/inc/sclInt.h
+++ b/source/libs/scalar/inc/sclInt.h
@@ -30,6 +30,7 @@ typedef struct SOperatorValueType {
typedef struct SScalarCtx {
int32_t code;
+ bool dual;
SArray *pBlockList; /* element is SSDataBlock* */
SHashObj *pRes; /* element is SScalarParam */
void *param; // additional parameter (meta actually) for acquire value such as tbname/tags values
@@ -56,8 +57,8 @@ typedef struct SScalarCtx {
#define SCL_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
#define SCL_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
-int32_t doConvertDataType(SValueNode* pValueNode, SScalarParam* out);
-SColumnInfoData* createColumnInfoData(SDataType* pType, int32_t numOfRows);
+int32_t doConvertDataType(SValueNode* pValueNode, SScalarParam* out, int32_t* overflow);
+int32_t sclCreateColumnInfoData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam);
int32_t sclConvertToTsValueNode(int8_t precision, SValueNode* valueNode);
#define GET_PARAM_TYPE(_c) ((_c)->columnData ? (_c)->columnData->info.type : (_c)->hashValueType)
diff --git a/source/libs/scalar/inc/sclvector.h b/source/libs/scalar/inc/sclvector.h
index f80ffc70a21a68460df747f087f6db808b3c7218..a1bf1ce1ef7fa899ccea3b40485925c5b519a97a 100644
--- a/source/libs/scalar/inc/sclvector.h
+++ b/source/libs/scalar/inc/sclvector.h
@@ -94,7 +94,7 @@ static FORCE_INLINE _getDoubleValue_fn_t getVectorDoubleValueFn(int32_t srcType)
return p;
}
-typedef void (*_bufConverteFunc)(char *buf, SScalarParam* pOut, int32_t outType);
+typedef void (*_bufConverteFunc)(char *buf, SScalarParam* pOut, int32_t outType, int32_t* overflow);
typedef void (*_bin_scalar_fn_t)(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *output, int32_t order);
_bin_scalar_fn_t getBinScalarOperatorFn(int32_t binOperator);
diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c
index a446aa7bdb5a35ad1cfaaa1e356ead7148804ef1..0348f1319197c31e41ee18005d716e73c5bce688 100644
--- a/source/libs/scalar/src/filter.c
+++ b/source/libs/scalar/src/filter.c
@@ -192,8 +192,11 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) {
case TSDB_DATA_TYPE_DOUBLE:
case TSDB_DATA_TYPE_TIMESTAMP:
return 18;
+ case TSDB_DATA_TYPE_JSON:
+ terrno = TSDB_CODE_QRY_JSON_IN_ERROR;
+ return 0;
default:
- assert(0);
+ return 0;
}
}
@@ -215,8 +218,11 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) {
case TSDB_DATA_TYPE_DOUBLE:
case TSDB_DATA_TYPE_TIMESTAMP:
return 24;
+ case TSDB_DATA_TYPE_JSON:
+ terrno = TSDB_CODE_QRY_JSON_IN_ERROR;
+ return 0;
default:
- assert(0);
+ return 0;
}
}
@@ -1036,12 +1042,18 @@ int32_t fltAddGroupUnitFromNode(SFilterInfo *info, SNode* tree, SArray *group) {
for (int32_t i = 0; i < listNode->pNodeList->length; ++i) {
SValueNode *valueNode = (SValueNode *)cell->pNode;
- if (valueNode->node.resType.type != type) {
- code = doConvertDataType(valueNode, &out);
+ if (valueNode->node.resType.type != type) {
+ int32_t overflow = 0;
+ code = doConvertDataType(valueNode, &out, &overflow);
if (code) {
// fltError("convert from %d to %d failed", in.type, out.type);
FLT_ERR_RET(code);
}
+
+ if (overflow) {
+ cell = cell->pNext;
+ continue;
+ }
len = tDataTypes[type].bytes;
@@ -1829,7 +1841,7 @@ int32_t fltInitValFieldData(SFilterInfo *info) {
}
// todo refactor the convert
- int32_t code = doConvertDataType(var, &out);
+ int32_t code = doConvertDataType(var, &out, NULL);
if (code != TSDB_CODE_SUCCESS) {
qError("convert value to type[%d] failed", type);
return TSDB_CODE_TSC_INVALID_OPERATION;
@@ -2059,7 +2071,7 @@ int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t
}
if (colIdxi > 1) {
- qsort(colIdx, colIdxi, sizeof(uint32_t), getComparFunc(TSDB_DATA_TYPE_USMALLINT, 0));
+ taosSort(colIdx, colIdxi, sizeof(uint32_t), getComparFunc(TSDB_DATA_TYPE_USMALLINT, 0));
}
for (uint32_t l = 0; l < colIdxi; ++l) {
@@ -2294,7 +2306,7 @@ int32_t filterMergeGroups(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t *gR
return TSDB_CODE_SUCCESS;
}
- qsort(gRes, *gResNum, POINTER_BYTES, filterCompareGroupCtx);
+ taosSort(gRes, *gResNum, POINTER_BYTES, filterCompareGroupCtx);
int32_t pEnd = 0, cStart = 0, cEnd = 0;
uint32_t pColNum = 0, cColNum = 0;
@@ -3611,7 +3623,8 @@ EDealRes fltReviseRewriter(SNode** pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
- if (FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP) && node->opType >= OP_TYPE_NOT_EQUAL) {
+ if (FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP) &&
+ (node->opType >= OP_TYPE_NOT_EQUAL) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) {
stat->scalarMode = true;
return DEAL_RES_CONTINUE;
}
@@ -3821,13 +3834,20 @@ bool filterExecute(SFilterInfo *info, SSDataBlock *pSrc, int8_t** p, SColumnData
SScalarParam output = {0};
SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
- output.columnData = createColumnInfoData(&type, pSrc->info.rows);
+ int32_t code = sclCreateColumnInfoData(&type, pSrc->info.rows, &output);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
SArray *pList = taosArrayInit(1, POINTER_BYTES);
taosArrayPush(pList, &pSrc);
FLT_ERR_RET(scalarCalculate(info->sclCtx.node, pList, &output));
- *p = (int8_t *)output.columnData->pData;
+ *p = taosMemoryMalloc(output.numOfRows * sizeof(bool));
+
+ memcpy(*p, output.columnData->pData, output.numOfRows);
+ colDataDestroy(output.columnData);
+ taosMemoryFree(output.columnData);
taosArrayDestroy(pList);
return false;
diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c
index 66e4af5ded0404b9f5b2ec7e9b8097178613c2c6..bdfc411fa6243864ab58402e449af988174f4866 100644
--- a/source/libs/scalar/src/scalar.c
+++ b/source/libs/scalar/src/scalar.c
@@ -35,12 +35,11 @@ int32_t sclConvertToTsValueNode(int8_t precision, SValueNode* valueNode) {
return TSDB_CODE_SUCCESS;
}
-
-SColumnInfoData* createColumnInfoData(SDataType* pType, int32_t numOfRows) {
+int32_t sclCreateColumnInfoData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
if (pColumnData == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
- return NULL;
+ return terrno;
}
pColumnData->info.type = pType->type;
@@ -48,23 +47,29 @@ SColumnInfoData* createColumnInfoData(SDataType* pType, int32_t numOfRows) {
pColumnData->info.scale = pType->scale;
pColumnData->info.precision = pType->precision;
- int32_t code = colInfoDataEnsureCapacity(pColumnData, 0, numOfRows);
+ int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows);
if (code != TSDB_CODE_SUCCESS) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
taosMemoryFree(pColumnData);
- return NULL;
- } else {
- return pColumnData;
+ return terrno;
}
+
+ pParam->columnData = pColumnData;
+ pParam->type = SHOULD_FREE_COLDATA;
+ return TSDB_CODE_SUCCESS;
}
-int32_t doConvertDataType(SValueNode* pValueNode, SScalarParam* out) {
+int32_t doConvertDataType(SValueNode* pValueNode, SScalarParam* out, int32_t* overflow) {
SScalarParam in = {.numOfRows = 1};
- in.columnData = createColumnInfoData(&pValueNode->node.resType, 1);
+ int32_t code = sclCreateColumnInfoData(&pValueNode->node.resType, 1, &in);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+
colDataAppend(in.columnData, 0, nodesGetValueFromNode(pValueNode), false);
- colInfoDataEnsureCapacity(out->columnData, 0, 1);
- int32_t code = vectorConvertImpl(&in, out);
+ colInfoDataEnsureCapacity(out->columnData, 1);
+ code = vectorConvertImpl(&in, out, overflow);
sclFreeParam(&in);
return code;
@@ -102,16 +107,21 @@ int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) {
out.columnData->info.bytes = tDataTypes[type].bytes;
}
- code = doConvertDataType(valueNode, &out);
+ int32_t overflow = 0;
+ code = doConvertDataType(valueNode, &out, &overflow);
if (code != TSDB_CODE_SUCCESS) {
// sclError("convert data from %d to %d failed", in.type, out.type);
SCL_ERR_JRET(code);
}
+ if (overflow) {
+ cell = cell->pNext;
+ continue;
+ }
+
if (IS_VAR_DATA_TYPE(type)) {
- char* data = colDataGetVarData(out.columnData, 0);
- len = varDataLen(data);
- buf = varDataVal(data);
+ buf = colDataGetVarData(out.columnData, 0);
+ len = varDataTLen(buf);
} else {
len = tDataTypes[type].bytes;
buf = out.columnData->pData;
@@ -119,8 +129,7 @@ int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) {
} else {
buf = nodesGetValueFromNode(valueNode);
if (IS_VAR_DATA_TYPE(type)) {
- len = varDataLen(buf);
- buf = varDataVal(buf);
+ len = varDataTLen(buf);
} else {
len = valueNode->node.resType.bytes;
}
@@ -159,7 +168,7 @@ void sclFreeRes(SHashObj *res) {
void sclFreeParam(SScalarParam *param) {
if (param->columnData != NULL) {
colDataDestroy(param->columnData);
- taosMemoryFree(param->columnData);
+ taosMemoryFreeClear(param->columnData);
}
if (param->pHashFilter != NULL) {
@@ -192,9 +201,10 @@ int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t
case QUERY_NODE_VALUE: {
SValueNode *valueNode = (SValueNode *)node;
+ ASSERT(param->columnData == NULL);
param->numOfRows = 1;
- param->columnData = createColumnInfoData(&valueNode->node.resType, 1);
- if (TSDB_DATA_TYPE_NULL == valueNode->node.resType.type) {
+ /*int32_t code = */sclCreateColumnInfoData(&valueNode->node.resType, 1, param);
+ if (TSDB_DATA_TYPE_NULL == valueNode->node.resType.type || valueNode->isNull) {
colDataAppendNULL(param->columnData, 0);
} else {
colDataAppend(param->columnData, 0, nodesGetValueFromNode(valueNode), false);
@@ -245,7 +255,7 @@ int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t
}
SSDataBlock *block = *(SSDataBlock **)taosArrayGet(ctx->pBlockList, index);
- if (NULL == block || ref->slotId >= block->info.numOfCols) {
+ if (NULL == block || ref->slotId >= taosArrayGetSize(block->pDataBlock)) {
sclError("column slotId is too big, slodId:%d, dataBlockSize:%d", ref->slotId, (int32_t)taosArrayGetSize(block->pDataBlock));
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
}
@@ -287,7 +297,7 @@ int32_t sclInitParamList(SScalarParam **pParams, SNodeList* pParamList, SScalarC
int32_t code = 0;
if (NULL == pParamList) {
if (ctx->pBlockList) {
- SSDataBlock *pBlock = taosArrayGet(ctx->pBlockList, 0);
+ SSDataBlock *pBlock = taosArrayGetP(ctx->pBlockList, 0);
*rowNum = pBlock->info.rows;
} else {
*rowNum = 1;
@@ -345,7 +355,7 @@ int32_t sclGetNodeType(SNode *pNode, SScalarCtx *ctx) {
return -1;
}
- switch (nodeType(pNode)) {
+ switch ((int)nodeType(pNode)) {
case QUERY_NODE_VALUE: {
SValueNode *valueNode = (SValueNode *)pNode;
return valueNode->node.resType.type;
@@ -431,10 +441,9 @@ int32_t sclExecFunction(SFunctionNode *node, SScalarCtx *ctx, SScalarParam *outp
SCL_ERR_JRET(code);
}
- output->columnData = createColumnInfoData(&node->node.resType, rowNum);
- if (output->columnData == NULL) {
- sclError("calloc %d failed", (int32_t)(rowNum * output->columnData->info.bytes));
- SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ code = sclCreateColumnInfoData(&node->node.resType, rowNum, output);
+ if (code != TSDB_CODE_SUCCESS) {
+ SCL_ERR_JRET(code);
}
code = (*ffpSet.process)(params, paramNum, output);
@@ -484,10 +493,9 @@ int32_t sclExecLogic(SLogicConditionNode *node, SScalarCtx *ctx, SScalarParam *o
output->numOfRows = rowNum;
SDataType t = {.type = type, .bytes = tDataTypes[type].bytes};
- output->columnData = createColumnInfoData(&t, rowNum);
- if (output->columnData == NULL) {
- sclError("calloc %d failed", (int32_t)(rowNum * sizeof(bool)));
- SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ code = sclCreateColumnInfoData(&t, rowNum, output);
+ if (code != TSDB_CODE_SUCCESS) {
+ SCL_ERR_JRET(code);
}
bool value = false;
@@ -538,11 +546,20 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp
int32_t rowNum = 0;
int32_t code = 0;
+ // json not support in in operator
+ if (nodeType(node->pLeft) == QUERY_NODE_VALUE) {
+ SValueNode *valueNode = (SValueNode *)node->pLeft;
+ if (valueNode->node.resType.type == TSDB_DATA_TYPE_JSON && (node->opType == OP_TYPE_IN || node->opType == OP_TYPE_NOT_IN)) {
+ SCL_RET(TSDB_CODE_QRY_JSON_IN_ERROR);
+ }
+ }
+
SCL_ERR_RET(sclInitOperatorParams(¶ms, node, ctx, &rowNum));
- output->columnData = createColumnInfoData(&node->node.resType, rowNum);
if (output->columnData == NULL) {
- sclError("calloc failed, size:%d", (int32_t)rowNum * node->node.resType.bytes);
- SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ code = sclCreateColumnInfoData(&node->node.resType, rowNum, output);
+ if (code != TSDB_CODE_SUCCESS) {
+ SCL_ERR_JRET(code);
+ }
}
_bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(node->opType);
@@ -551,18 +568,23 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp
SScalarParam* pLeft = ¶ms[0];
SScalarParam* pRight = paramNum > 1 ? ¶ms[1] : NULL;
+ terrno = TSDB_CODE_SUCCESS;
OperatorFn(pLeft, pRight, output, TSDB_ORDER_ASC);
+ code = terrno;
_return:
for (int32_t i = 0; i < paramNum; ++i) {
-// sclFreeParam(¶ms[i]);
+ if (params[i].type == SHOULD_FREE_COLDATA) {
+ colDataDestroy(params[i].columnData);
+ taosMemoryFreeClear(params[i].columnData);
+ }
}
taosMemoryFreeClear(params);
SCL_RET(code);
}
-EDealRes sclRewriteBasedOnOptr(SNode** pNode, SScalarCtx *ctx, EOperatorType opType) {
+EDealRes sclRewriteNullInOptr(SNode** pNode, SScalarCtx *ctx, EOperatorType opType) {
if (opType <= OP_TYPE_CALC_MAX) {
SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
if (NULL == res) {
@@ -594,6 +616,24 @@ EDealRes sclRewriteBasedOnOptr(SNode** pNode, SScalarCtx *ctx, EOperatorType opT
return DEAL_RES_CONTINUE;
}
+EDealRes sclAggFuncWalker(SNode* pNode, void* pContext) {
+ if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
+ SFunctionNode* pFunc = (SFunctionNode*)pNode;
+ *(bool*)pContext = fmIsAggFunc(pFunc->funcId);
+ if (*(bool*)pContext) {
+ return DEAL_RES_END;
+ }
+ }
+
+ return DEAL_RES_CONTINUE;
+}
+
+
+bool sclContainsAggFuncNode(SNode* pNode) {
+ bool aggFunc = false;
+ nodesWalkExpr(pNode, sclAggFuncWalker, (void *)&aggFunc);
+ return aggFunc;
+}
EDealRes sclRewriteNonConstOperator(SNode** pNode, SScalarCtx *ctx) {
SOperatorNode *node = (SOperatorNode *)*pNode;
@@ -601,8 +641,9 @@ EDealRes sclRewriteNonConstOperator(SNode** pNode, SScalarCtx *ctx) {
if (node->pLeft && (QUERY_NODE_VALUE == nodeType(node->pLeft))) {
SValueNode *valueNode = (SValueNode *)node->pLeft;
- if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) {
- return sclRewriteBasedOnOptr(pNode, ctx, node->opType);
+ if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)
+ && (!sclContainsAggFuncNode(node->pRight))) {
+ return sclRewriteNullInOptr(pNode, ctx, node->opType);
}
if (IS_STR_DATA_TYPE(valueNode->node.resType.type) && node->pRight && nodesIsExprNode(node->pRight)
@@ -617,8 +658,9 @@ EDealRes sclRewriteNonConstOperator(SNode** pNode, SScalarCtx *ctx) {
if (node->pRight && (QUERY_NODE_VALUE == nodeType(node->pRight))) {
SValueNode *valueNode = (SValueNode *)node->pRight;
- if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) {
- return sclRewriteBasedOnOptr(pNode, ctx, node->opType);
+ if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)
+ && (!sclContainsAggFuncNode(node->pLeft))) {
+ return sclRewriteNullInOptr(pNode, ctx, node->opType);
}
if (IS_STR_DATA_TYPE(valueNode->node.resType.type) && node->pLeft && nodesIsExprNode(node->pLeft)
@@ -640,7 +682,7 @@ EDealRes sclRewriteNonConstOperator(SNode** pNode, SScalarCtx *ctx) {
ERASE_NODE(listNode->pNodeList);
continue;
} else { //OP_TYPE_NOT_IN
- return sclRewriteBasedOnOptr(pNode, ctx, node->opType);
+ return sclRewriteNullInOptr(pNode, ctx, node->opType);
}
}
@@ -648,7 +690,7 @@ EDealRes sclRewriteNonConstOperator(SNode** pNode, SScalarCtx *ctx) {
}
if (listNode->pNodeList->length <= 0) {
- return sclRewriteBasedOnOptr(pNode, ctx, node->opType);
+ return sclRewriteNullInOptr(pNode, ctx, node->opType);
}
}
@@ -687,13 +729,18 @@ EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) {
if (colDataIsNull_s(output.columnData, 0)) {
res->node.resType.type = TSDB_DATA_TYPE_NULL;
+ res->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
} else {
res->node.resType.type = output.columnData->info.type;
res->node.resType.bytes = output.columnData->info.bytes;
res->node.resType.scale = output.columnData->info.scale;
res->node.resType.precision = output.columnData->info.precision;
int32_t type = output.columnData->info.type;
- if (IS_VAR_DATA_TYPE(type)) {
+ if (type == TSDB_DATA_TYPE_JSON){
+ int32_t len = getJsonValueLen(output.columnData->pData);
+ res->datum.p = taosMemoryCalloc(len, 1);
+ memcpy(res->datum.p, output.columnData->pData, len);
+ } else if (IS_VAR_DATA_TYPE(type)) {
res->datum.p = taosMemoryCalloc(res->node.resType.bytes + VARSTR_HEADER_SIZE + 1, 1);
memcpy(res->datum.p, output.columnData->pData, varDataTLen(output.columnData->pData));
} else {
@@ -754,7 +801,7 @@ EDealRes sclRewriteOperator(SNode** pNode, SScalarCtx *ctx) {
return sclRewriteNonConstOperator(pNode, ctx);
}
- SScalarParam output = {.columnData = taosMemoryCalloc(1, sizeof(SColumnInfoData))};
+ SScalarParam output = {0};
ctx->code = sclExecOperator(node, ctx, &output);
if (ctx->code) {
return DEAL_RES_ERROR;
@@ -771,7 +818,13 @@ EDealRes sclRewriteOperator(SNode** pNode, SScalarCtx *ctx) {
res->translate = true;
if (colDataIsNull_s(output.columnData, 0)) {
- res->node.resType.type = TSDB_DATA_TYPE_NULL;
+ if(node->node.resType.type != TSDB_DATA_TYPE_JSON){
+ res->node.resType.type = TSDB_DATA_TYPE_NULL;
+ res->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
+ }else{
+ res->node.resType = node->node.resType;
+ res->isNull = true;
+ }
} else {
res->node.resType = node->node.resType;
int32_t type = output.columnData->info.type;
@@ -817,6 +870,7 @@ EDealRes sclWalkFunction(SNode* pNode, SScalarCtx *ctx) {
return DEAL_RES_ERROR;
}
+ output.type = DELEGATED_MGMT_COLDATA;
if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
return DEAL_RES_ERROR;
@@ -851,6 +905,7 @@ EDealRes sclWalkOperator(SNode* pNode, SScalarCtx *ctx) {
return DEAL_RES_ERROR;
}
+ output.type = DELEGATED_MGMT_COLDATA;
if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
return DEAL_RES_ERROR;
@@ -901,7 +956,7 @@ EDealRes sclWalkTarget(SNode* pNode, SScalarCtx *ctx) {
return DEAL_RES_ERROR;
}
- colDataAssign(col, res->columnData, res->numOfRows);
+ colDataAssign(col, res->columnData, res->numOfRows, NULL);
block->info.rows = res->numOfRows;
sclFreeParam(res);
@@ -936,13 +991,33 @@ EDealRes sclCalcWalker(SNode* pNode, void* pContext) {
return DEAL_RES_ERROR;
}
-int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes) {
+int32_t sclExtendResRows(SScalarParam *pDst, SScalarParam *pSrc, SArray *pBlockList) {
+ SSDataBlock* pb = taosArrayGetP(pBlockList, 0);
+ SScalarParam *pLeft = taosMemoryCalloc(1, sizeof(SScalarParam));
+ if (NULL == pLeft) {
+ sclError("calloc %d failed", (int32_t)sizeof(SScalarParam));
+ SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ pLeft->numOfRows = pb->info.rows;
+ colInfoDataEnsureCapacity(pDst->columnData, pb->info.rows);
+
+ _bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(OP_TYPE_ASSIGN);
+ OperatorFn(pLeft, pSrc, pDst, TSDB_ORDER_ASC);
+
+ taosMemoryFree(pLeft);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t sclCalcConstants(SNode *pNode, bool dual, SNode **pRes) {
if (NULL == pNode) {
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
}
int32_t code = 0;
SScalarCtx ctx = {0};
+ ctx.dual = dual;
ctx.pRes = taosHashInit(SCL_DEFAULT_OP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
if (NULL == ctx.pRes) {
sclError("taosHashInit failed, num:%d", SCL_DEFAULT_OP_NUM);
@@ -954,10 +1029,88 @@ int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes) {
*pRes = pNode;
_return:
+
sclFreeRes(ctx.pRes);
return code;
}
+static int32_t sclGetMinusOperatorResType(SOperatorNode* pOp) {
+ if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+ pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
+ pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t sclGetMathOperatorResType(SOperatorNode* pOp) {
+ SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
+ SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
+ if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
+ (TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
+ (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+
+ if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) ||
+ (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) ||
+ (TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) ||
+ (TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) {
+ pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
+ pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
+ } else {
+ pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
+ pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t sclGetCompOperatorResType(SOperatorNode* pOp) {
+ SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
+ if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
+ ((SExprNode*)(pOp->pRight))->resType = ldt;
+ } else if (nodesIsRegularOp(pOp)) {
+ SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
+ if (!IS_VAR_DATA_TYPE(ldt.type) || QUERY_NODE_VALUE != nodeType(pOp->pRight) ||
+ (!IS_STR_DATA_TYPE(rdt.type) && (rdt.type != TSDB_DATA_TYPE_NULL))) {
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+ }
+ pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
+ pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t sclGetJsonOperatorResType(SOperatorNode* pOp) {
+ SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
+ SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
+ if (TSDB_DATA_TYPE_JSON != ldt.type || !IS_STR_DATA_TYPE(rdt.type)) {
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+ if (pOp->opType == OP_TYPE_JSON_GET_VALUE) {
+ pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
+ } else if (pOp->opType == OP_TYPE_JSON_CONTAINS) {
+ pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
+ }
+ pOp->node.resType.bytes = tDataTypes[pOp->node.resType.type].bytes;
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t sclGetBitwiseOperatorResType(SOperatorNode* pOp) {
+ pOp->node.resType.type = TSDB_DATA_TYPE_BIGINT;
+ pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes) {
+ return sclCalcConstants(pNode, false, pRes);
+}
+
+int32_t scalarCalculateConstantsFromDual(SNode *pNode, SNode **pRes) {
+ return sclCalcConstants(pNode, true, pRes);
+}
+
int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst) {
if (NULL == pNode || NULL == pBlockList) {
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
@@ -982,9 +1135,16 @@ int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst) {
sclError("no valid res in hash, node:%p, type:%d", pNode, nodeType(pNode));
SCL_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
-
- colDataAssign(pDst->columnData, res->columnData, res->numOfRows);
- pDst->numOfRows = res->numOfRows;
+
+ if (1 == res->numOfRows) {
+ SCL_ERR_JRET(sclExtendResRows(pDst, res, pBlockList));
+ } else {
+ colInfoDataEnsureCapacity(pDst->columnData, res->numOfRows);
+ colDataAssign(pDst->columnData, res->columnData, res->numOfRows, NULL);
+ pDst->numOfRows = res->numOfRows;
+ }
+
+ sclFreeParam(res);
taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES);
}
@@ -993,3 +1153,55 @@ _return:
sclFreeRes(ctx.pRes);
return code;
}
+
+int32_t scalarGetOperatorResultType(SOperatorNode* pOp) {
+ if (TSDB_DATA_TYPE_BLOB == ((SExprNode*)(pOp->pLeft))->resType.type ||
+ (NULL != pOp->pRight && TSDB_DATA_TYPE_BLOB == ((SExprNode*)(pOp->pRight))->resType.type)) {
+ return TSDB_CODE_TSC_INVALID_OPERATION;
+ }
+
+ switch (pOp->opType) {
+ case OP_TYPE_ADD:
+ case OP_TYPE_SUB:
+ case OP_TYPE_MULTI:
+ case OP_TYPE_DIV:
+ case OP_TYPE_REM:
+ return sclGetMathOperatorResType(pOp);
+ case OP_TYPE_MINUS:
+ return sclGetMinusOperatorResType(pOp);
+ case OP_TYPE_ASSIGN:
+ pOp->node.resType = ((SExprNode*)(pOp->pLeft))->resType;
+ break;
+ case OP_TYPE_BIT_AND:
+ case OP_TYPE_BIT_OR:
+ return sclGetBitwiseOperatorResType(pOp);
+ case OP_TYPE_GREATER_THAN:
+ case OP_TYPE_GREATER_EQUAL:
+ case OP_TYPE_LOWER_THAN:
+ case OP_TYPE_LOWER_EQUAL:
+ case OP_TYPE_EQUAL:
+ case OP_TYPE_NOT_EQUAL:
+ case OP_TYPE_IS_NULL:
+ case OP_TYPE_IS_NOT_NULL:
+ case OP_TYPE_IS_TRUE:
+ case OP_TYPE_IS_FALSE:
+ case OP_TYPE_IS_UNKNOWN:
+ case OP_TYPE_IS_NOT_TRUE:
+ case OP_TYPE_IS_NOT_FALSE:
+ case OP_TYPE_IS_NOT_UNKNOWN:
+ case OP_TYPE_LIKE:
+ case OP_TYPE_NOT_LIKE:
+ case OP_TYPE_MATCH:
+ case OP_TYPE_NMATCH:
+ case OP_TYPE_IN:
+ case OP_TYPE_NOT_IN:
+ return sclGetCompOperatorResType(pOp);
+ case OP_TYPE_JSON_GET_VALUE:
+ case OP_TYPE_JSON_CONTAINS:
+ return sclGetJsonOperatorResType(pOp);
+ default:
+ break;
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c
index 2369779105f06685be2120907531ee0a32869c84..df5df127f066beef7a64b40f95dc0909ed6d58a3 100644
--- a/source/libs/scalar/src/sclfunc.c
+++ b/source/libs/scalar/src/sclfunc.c
@@ -36,9 +36,6 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
SColumnInfoData *pOutputData = pOutput->columnData;
int32_t type = GET_PARAM_TYPE(pInput);
- if (!IS_NUMERIC_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
switch (type) {
case TSDB_DATA_TYPE_FLOAT: {
@@ -119,8 +116,15 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
break;
}
+ case TSDB_DATA_TYPE_NULL: {
+ for (int32_t i = 0; i < pInput->numOfRows; ++i) {
+ colDataAppendNULL(pOutputData, i);
+ }
+ break;
+ }
+
default: {
- colDataAssign(pOutputData, pInputData, pInput->numOfRows);
+ colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL);
}
}
@@ -130,9 +134,6 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SScalarParam* pOutput, _double_fn valFn) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (inputNum != 1 || !IS_NUMERIC_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
SColumnInfoData *pInputData = pInput->columnData;
SColumnInfoData *pOutputData = pOutput->columnData;
@@ -142,7 +143,7 @@ static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SS
double *out = (double *)pOutputData->pData;
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
- if (colDataIsNull_s(pInputData, i)) {
+ if (colDataIsNull_s(pInputData, i) || IS_NULL_TYPE(type)) {
colDataAppendNULL(pOutputData, i);
continue;
}
@@ -159,10 +160,6 @@ static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SS
}
static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, SScalarParam* pOutput, _double_fn_2 valFn) {
- if (inputNum != 2 || !IS_NUMERIC_TYPE(GET_PARAM_TYPE(&pInput[0])) || !IS_NUMERIC_TYPE(GET_PARAM_TYPE(&pInput[1]))) {
- return TSDB_CODE_FAILED;
- }
-
SColumnInfoData *pInputData[2];
SColumnInfoData *pOutputData = pOutput->columnData;
_getDoubleValue_fn_t getValueFn[2];
@@ -175,11 +172,15 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S
double *out = (double *)pOutputData->pData;
double result;
+ bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) ||
+ IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
+
int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
if (pInput[0].numOfRows == pInput[1].numOfRows) {
for (int32_t i = 0; i < numOfRows; ++i) {
if (colDataIsNull_s(pInputData[0], i) ||
- colDataIsNull_s(pInputData[1], i)) {
+ colDataIsNull_s(pInputData[1], i) ||
+ hasNullType) {
colDataAppendNULL(pOutputData, i);
continue;
}
@@ -191,7 +192,7 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S
}
}
} else if (pInput[0].numOfRows == 1) { //left operand is constant
- if (colDataIsNull_s(pInputData[0], 0)) {
+ if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
colDataAppendNNULL(pOutputData, 0, pInput[1].numOfRows);
} else {
for (int32_t i = 0; i < numOfRows; ++i) {
@@ -210,7 +211,7 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S
}
}
} else if (pInput[1].numOfRows == 1) {
- if (colDataIsNull_s(pInputData[1], 0)) {
+ if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
colDataAppendNNULL(pOutputData, 0, pInput[0].numOfRows);
} else {
for (int32_t i = 0; i < numOfRows; ++i) {
@@ -236,9 +237,6 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S
static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam* pOutput, _float_fn f1, _double_fn d1) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (inputNum != 1 || !IS_NUMERIC_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
SColumnInfoData *pInputData = pInput->columnData;
SColumnInfoData *pOutputData = pOutput->columnData;
@@ -272,8 +270,15 @@ static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP
break;
}
+ case TSDB_DATA_TYPE_NULL: {
+ for (int32_t i = 0; i < pInput->numOfRows; ++i) {
+ colDataAppendNULL(pOutputData, i);
+ }
+ break;
+ }
+
default: {
- colDataAssign(pOutputData, pInputData, pInput->numOfRows);
+ colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL);
}
}
@@ -355,9 +360,6 @@ static void trtrim(char *input, char *output, int32_t type, int32_t charLen) {
static int32_t doLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _len_fn lenFn) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (inputNum != 1 || !IS_VAR_DATA_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
SColumnInfoData *pInputData = pInput->columnData;
SColumnInfoData *pOutputData = pOutput->columnData;
@@ -581,9 +583,6 @@ DONE:
static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _conv_fn convFn) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (inputNum != 1 || !IS_VAR_DATA_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
SColumnInfoData *pInputData = pInput->columnData;
SColumnInfoData *pOutputData = pOutput->columnData;
@@ -623,9 +622,6 @@ static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScala
static int32_t doTrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _trim_fn trimFn) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (inputNum != 1 || !IS_VAR_DATA_TYPE(type)) {
- return TSDB_CODE_FAILED;
- }
SColumnInfoData *pInputData = pInput->columnData;
SColumnInfoData *pOutputData = pOutput->columnData;
@@ -659,16 +655,10 @@ static int32_t doTrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarPar
int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
int32_t subPos = 0;
GET_TYPED_DATA(subPos, int32_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
- if (subPos == 0) { //subPos needs to be positive or negative values;
- return TSDB_CODE_FAILED;
- }
int32_t subLen = INT16_MAX;
if (inputNum == 3) {
GET_TYPED_DATA(subLen, int32_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
- if (subLen < 0 || subLen > INT16_MAX) { //subLen cannot be negative
- return TSDB_CODE_FAILED;
- }
subLen = (GET_PARAM_TYPE(pInput) == TSDB_DATA_TYPE_VARCHAR) ? subLen : subLen * TSDB_NCHAR_SIZE;
}
@@ -730,6 +720,60 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
char *input = colDataGetData(pInput[0].columnData, i);
switch(outputType) {
+ case TSDB_DATA_TYPE_TINYINT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(int8_t *)output = taosStr2Int8(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(int8_t *)output = taosStr2Int8(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(int8_t *)output, int8_t, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_SMALLINT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(int16_t *)output = taosStr2Int16(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(int16_t *)output = taosStr2Int16(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(int16_t *)output, int16_t, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_INT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(int32_t *)output = taosStr2Int32(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(int32_t *)output = taosStr2Int32(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(int32_t *)output, int32_t, inputType, input);
+ }
+ break;
+ }
case TSDB_DATA_TYPE_BIGINT: {
if (inputType == TSDB_DATA_TYPE_BINARY) {
*(int64_t *)output = taosStr2Int64(varDataVal(input), NULL, 10);
@@ -748,6 +792,60 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
}
break;
}
+ case TSDB_DATA_TYPE_UTINYINT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(uint8_t *)output = taosStr2UInt8(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(uint8_t *)output = taosStr2UInt8(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(uint8_t *)output, uint8_t, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_USMALLINT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(uint16_t *)output = taosStr2UInt16(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(uint16_t *)output = taosStr2UInt16(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(uint16_t *)output, uint16_t, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_UINT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(uint32_t *)output = taosStr2UInt32(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(uint32_t *)output = taosStr2UInt32(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(uint32_t *)output, uint32_t, inputType, input);
+ }
+ break;
+ }
case TSDB_DATA_TYPE_UBIGINT: {
if (inputType == TSDB_DATA_TYPE_BINARY) {
*(uint64_t *)output = taosStr2UInt64(varDataVal(input), NULL, 10);
@@ -766,10 +864,71 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
}
break;
}
+ case TSDB_DATA_TYPE_FLOAT: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(float *)output = taosStr2Float(varDataVal(input), NULL);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(float *)output = taosStr2Float(newBuf, NULL);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(float *)output, float, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_DOUBLE: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(double *)output = taosStr2Double(varDataVal(input), NULL);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(double *)output = taosStr2Double(newBuf, NULL);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(double *)output, double, inputType, input);
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_BOOL: {
+ if (inputType == TSDB_DATA_TYPE_BINARY) {
+ *(bool *)output = taosStr2Int8(varDataVal(input), NULL, 10);
+ } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ newBuf[len] = 0;
+ *(bool *)output = taosStr2Int8(newBuf, NULL, 10);
+ taosMemoryFree(newBuf);
+ } else {
+ GET_TYPED_DATA(*(bool *)output, bool, inputType, input);
+ }
+ break;
+ }
case TSDB_DATA_TYPE_TIMESTAMP: {
+ int64_t timeVal;
if (inputType == TSDB_DATA_TYPE_BINARY || inputType == TSDB_DATA_TYPE_NCHAR) {
- //not support
- return TSDB_CODE_FAILED;
+ int64_t timePrec;
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
+ int32_t ret = convertStringToTimestamp(inputType, input, timePrec, &timeVal);
+ if (ret != TSDB_CODE_SUCCESS) {
+ *(int64_t *)output = 0;
+ } else {
+ *(int64_t *)output = timeVal;
+ }
} else {
GET_TYPED_DATA(*(int64_t *)output, int64_t, inputType, input);
}
@@ -784,8 +943,16 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
len = sprintf(varDataVal(output), "%.*s", len, varDataVal(input));
varDataSetLen(output, len);
} else if (inputType == TSDB_DATA_TYPE_NCHAR) {
- //not support
- return TSDB_CODE_FAILED;
+ char *newBuf = taosMemoryCalloc(1, inputLen);
+ int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), newBuf);
+ if (len < 0) {
+ taosMemoryFree(newBuf);
+ return TSDB_CODE_FAILED;
+ }
+ len = TMIN(len, outputLen - VARSTR_HEADER_SIZE);
+ memcpy(varDataVal(output), newBuf, len);
+ varDataSetLen(output, len);
+ taosMemoryFree(newBuf);
} else {
char tmp[400] = {0};
NUM_TO_STRING(inputType, input, sizeof(tmp), tmp);
@@ -856,10 +1023,13 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
int32_t type = GET_PARAM_TYPE(pInput);
+ bool tzPresent = (inputNum == 2) ? true : false;
char* tz;
int32_t tzLen;
- tz = varDataVal(pInput[1].columnData->pData);
- tzLen = varDataLen(pInput[1].columnData->pData);
+ if (tzPresent) {
+ tz = varDataVal(pInput[1].columnData->pData);
+ tzLen = varDataLen(pInput[1].columnData->pData);
+ }
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
if (colDataIsNull_s(pInput[0].columnData, i)) {
@@ -938,7 +1108,8 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *
int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
int32_t type = GET_PARAM_TYPE(pInput);
- int32_t timePrec = GET_PARAM_PRECISON(pInput);
+ int64_t timePrec;
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
if (colDataIsNull_s(pInput[0].columnData, i)) {
@@ -963,65 +1134,48 @@ int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarP
int32_t toJsonFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
int32_t type = GET_PARAM_TYPE(pInput);
- if (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR) {
- return TSDB_CODE_FAILED;
- }
-
- if (inputNum != 1) {
- return TSDB_CODE_FAILED;
- }
char tmp[TSDB_MAX_JSON_TAG_LEN] = {0};
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
- if (colDataIsNull_s(pInput[0].columnData, i)) {
- colDataAppendNULL(pOutput->columnData, i);
- continue;
- }
- char *input = pInput[0].columnData->pData + pInput[0].columnData->varmeta.offset[i];
+ SArray* pTagVals = taosArrayInit(8, sizeof(STagVal));
+ STag* pTag = NULL;
- if(type == TSDB_DATA_TYPE_NCHAR){
- if (varDataTLen(input) > TSDB_MAX_JSON_TAG_LEN){
- colDataAppendNULL(pOutput->columnData, i);
- continue;
- }
- int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), tmp);
- if (len < 0) {
- colDataAppendNULL(pOutput->columnData, i);
- continue;
- }
- tmp[len] = 0;
+ if (colDataIsNull_s(pInput[0].columnData, i)) {
+ tTagNew(pTagVals, 1, true, &pTag);
}else{
+ char *input = pInput[0].columnData->pData + pInput[0].columnData->varmeta.offset[i];
if (varDataLen(input) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE){
- colDataAppendNULL(pOutput->columnData, i);
- continue;
+ taosArrayDestroy(pTagVals);
+ return TSDB_CODE_FAILED;
}
memcpy(tmp, varDataVal(input), varDataLen(input));
tmp[varDataLen(input)] = 0;
+ if(parseJsontoTagData(tmp, pTagVals, &pTag, NULL)){
+ tTagNew(pTagVals, 1, true, &pTag);
+ }
}
- if(!tjsonValidateJson(tmp)){
- colDataAppendNULL(pOutput->columnData, i);
- continue;
- }
-
- colDataAppend(pOutput->columnData, i, input, false);
+ colDataAppend(pOutput->columnData, i, (const char*)pTag, false);
+ tTagFree(pTag);
+ taosArrayDestroy(pTagVals);
}
pOutput->numOfRows = pInput->numOfRows;
-
return TSDB_CODE_SUCCESS;
}
int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
int32_t type = GET_PARAM_TYPE(&pInput[0]);
- int32_t timePrec = GET_PARAM_PRECISON(&pInput[0]);
- int64_t timeUnit, timeVal = 0;
+ int64_t timeUnit, timePrec, timeVal = 0;
GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
(timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
+ int64_t unit = timeUnit * 1000 / factor;
+
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
if (colDataIsNull_s(pInput[0].columnData, i)) {
colDataAppendNULL(pOutput->columnData, i);
@@ -1054,14 +1208,15 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
char buf[20] = {0};
NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal, sizeof(buf), buf);
int32_t tsDigits = (int32_t)strlen(buf);
- timeUnit = timeUnit * 1000 / factor;
- switch (timeUnit) {
- case 0: { /* 1u */
+ switch (unit) {
+ case 0: { /* 1u or 1b */
if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
- timeVal = timeVal / 1000 * 1000;
- //} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
- // //timeVal = timeVal / 1000;
+ if (timePrec == TSDB_TIME_PRECISION_NANO && timeUnit == 1) {
+ timeVal = timeVal * 1;
+ } else {
+ timeVal = timeVal / 1000 * 1000;
+ }
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
timeVal = timeVal * factor;
} else {
@@ -1202,12 +1357,17 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
}
int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
- int32_t timePrec = GET_PARAM_PRECISON(&pInput[0]);
- int64_t timeUnit = -1, timeVal[2] = {0};
- if (inputNum == 3) {
+ int64_t timeUnit = -1, timePrec, timeVal[2] = {0};
+ if (inputNum == 4) {
GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[3]), pInput[3].columnData->pData);
+ } else {
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
}
+ int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
+ (timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
+
int32_t numOfRows = 0;
for (int32_t i = 0; i < inputNum; ++i) {
if (pInput[i].numOfRows > numOfRows) {
@@ -1287,12 +1447,14 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
}
}
} else {
- int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
- (timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
- timeUnit = timeUnit * 1000 / factor;
- switch(timeUnit) {
- case 0: { /* 1u */
- result = result / 1000;
+ int64_t unit = timeUnit * 1000 / factor;
+ switch(unit) {
+ case 0: { /* 1u or 1b */
+ if (timePrec == TSDB_TIME_PRECISION_NANO && timeUnit == 1) {
+ result = result / 1;
+ } else {
+ result = result / 1000;
+ }
break;
}
case 1: { /* 1a */
@@ -1334,7 +1496,10 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
}
int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
- int64_t ts = taosGetTimestamp(TSDB_TIME_PRECISION_MILLI);
+ int64_t timePrec;
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData);
+
+ int64_t ts = taosGetTimestamp(timePrec);
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
colDataAppendInt64(pOutput->columnData, i, &ts);
}
@@ -1343,7 +1508,10 @@ int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
}
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
- int64_t ts = taosGetTimestampToday(TSDB_TIME_PRECISION_MILLI);
+ int64_t timePrec;
+ GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData);
+
+ int64_t ts = taosGetTimestampToday(timePrec);
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
colDataAppendInt64(pOutput->columnData, i, &ts);
}
@@ -1415,11 +1583,19 @@ int32_t roundFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOut
}
int32_t lowerFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
+#ifdef WINDOWS
+ return doCaseConvFunction(pInput, inputNum, pOutput, towlower);
+#else
return doCaseConvFunction(pInput, inputNum, pOutput, tolower);
+#endif
}
int32_t upperFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
+#ifdef WINDOWS
+ return doCaseConvFunction(pInput, inputNum, pOutput, towupper);
+#else
return doCaseConvFunction(pInput, inputNum, pOutput, toupper);
+#endif
}
int32_t ltrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c
index bff49c2ca91d3b03ee0d832bfc7b996959576f18..39b2f04f3e29044a484b10fd1110b1695a4a1128 100644
--- a/source/libs/scalar/src/sclvector.c
+++ b/source/libs/scalar/src/sclvector.c
@@ -23,6 +23,7 @@
#include "sclvector.h"
#include "tcompare.h"
#include "tdatablock.h"
+#include "tdataformat.h"
#include "ttypes.h"
#include "ttime.h"
@@ -159,6 +160,9 @@ int64_t getVectorBigintValue_JSON(void *src, int32_t index){
return 0;
} else if(*data == TSDB_DATA_TYPE_NCHAR) { // json inner type can not be BINARY
convertNcharToDouble(data+CHAR_BYTES, &out);
+ } else if(tTagIsJson(data)){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return 0;
} else {
convertNumberToNumber(data+CHAR_BYTES, &out, *data, TSDB_DATA_TYPE_DOUBLE);
}
@@ -272,7 +276,7 @@ _getValueAddr_fn_t getVectorValueAddrFn(int32_t srcType) {
return p;
}
-static FORCE_INLINE void varToTimestamp(char *buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToTimestamp(char *buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
int64_t value = 0;
if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
value = 0;
@@ -281,10 +285,26 @@ static FORCE_INLINE void varToTimestamp(char *buf, SScalarParam* pOut, int32_t r
colDataAppendInt64(pOut->columnData, rowIndex, &value);
}
-static FORCE_INLINE void varToSigned(char *buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToSigned(char *buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
+ if (overflow) {
+ int64_t minValue = tDataTypes[pOut->columnData->info.type].minValue;
+ int64_t maxValue = tDataTypes[pOut->columnData->info.type].maxValue;
+ int64_t value = (int64_t)taosStr2Int64(buf, NULL, 10);
+ if (value > maxValue) {
+ *overflow = 1;
+ return;
+ } else if (value < minValue) {
+ *overflow = -1;
+ return;
+ } else {
+ *overflow = 0;
+ }
+ }
+
switch (pOut->columnData->info.type) {
case TSDB_DATA_TYPE_TINYINT: {
int8_t value = (int8_t)taosStr2Int8(buf, NULL, 10);
+
colDataAppendInt8(pOut->columnData, rowIndex, (int8_t*)&value);
break;
}
@@ -306,7 +326,22 @@ static FORCE_INLINE void varToSigned(char *buf, SScalarParam* pOut, int32_t rowI
}
}
-static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
+ if (overflow) {
+ uint64_t minValue = (uint64_t)tDataTypes[pOut->columnData->info.type].minValue;
+ uint64_t maxValue = (uint64_t)tDataTypes[pOut->columnData->info.type].maxValue;
+ uint64_t value = (uint64_t)taosStr2UInt64(buf, NULL, 10);
+ if (value > maxValue) {
+ *overflow = 1;
+ return;
+ } else if (value < minValue) {
+ *overflow = -1;
+ return;
+ } else {
+ *overflow = 0;
+ }
+ }
+
switch (pOut->columnData->info.type) {
case TSDB_DATA_TYPE_UTINYINT: {
uint8_t value = (uint8_t)taosStr2UInt8(buf, NULL, 10);
@@ -331,18 +366,24 @@ static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam* pOut, int32_t ro
}
}
-static FORCE_INLINE void varToFloat(char *buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToFloat(char *buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
+ if (TSDB_DATA_TYPE_FLOAT == pOut->columnData->info.type) {
+ float value = taosStr2Float(buf, NULL);
+ colDataAppendFloat(pOut->columnData, rowIndex, &value);
+ return;
+ }
+
double value = taosStr2Double(buf, NULL);
colDataAppendDouble(pOut->columnData, rowIndex, &value);
}
-static FORCE_INLINE void varToBool(char *buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToBool(char *buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
int64_t value = taosStr2Int64(buf, NULL, 10);
bool v = (value != 0)? true:false;
colDataAppendInt8(pOut->columnData, rowIndex, (int8_t*) &v);
}
-static FORCE_INLINE void varToNchar(char* buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void varToNchar(char* buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
int32_t len = 0;
int32_t inputLen = varDataLen(buf);
int32_t outputMaxLen = (inputLen + 1) * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
@@ -355,7 +396,7 @@ static FORCE_INLINE void varToNchar(char* buf, SScalarParam* pOut, int32_t rowIn
taosMemoryFree(t);
}
-static FORCE_INLINE void ncharToVar(char* buf, SScalarParam* pOut, int32_t rowIndex) {
+static FORCE_INLINE void ncharToVar(char* buf, SScalarParam* pOut, int32_t rowIndex, int32_t* overflow) {
int32_t inputLen = varDataLen(buf);
char* t = taosMemoryCalloc(1, inputLen + VARSTR_HEADER_SIZE);
@@ -372,7 +413,7 @@ static FORCE_INLINE void ncharToVar(char* buf, SScalarParam* pOut, int32_t rowIn
//TODO opt performance, tmp is not needed.
-int32_t vectorConvertFromVarData(const SScalarParam* pIn, SScalarParam* pOut, int32_t inType, int32_t outType) {
+int32_t vectorConvertFromVarData(const SScalarParam* pIn, SScalarParam* pOut, int32_t inType, int32_t outType, int32_t* overflow) {
bool vton = false;
_bufConverteFunc func = NULL;
@@ -411,10 +452,12 @@ int32_t vectorConvertFromVarData(const SScalarParam* pIn, SScalarParam* pOut, in
if(inType == TSDB_DATA_TYPE_JSON){
if(*data == TSDB_DATA_TYPE_NULL) {
ASSERT(0);
- }
- else if(*data == TSDB_DATA_TYPE_NCHAR) {
+ } else if(*data == TSDB_DATA_TYPE_NCHAR) {
data += CHAR_BYTES;
convertType = TSDB_DATA_TYPE_NCHAR;
+ } else if(tTagIsJson(data)){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return terrno;
} else {
convertNumberToNumber(data+CHAR_BYTES, colDataGetNumData(pOut->columnData, i), *data, outType);
continue;
@@ -446,7 +489,7 @@ int32_t vectorConvertFromVarData(const SScalarParam* pIn, SScalarParam* pOut, in
}
}
- (*func)(tmp, pOut, i);
+ (*func)(tmp, pOut, i, overflow);
taosMemoryFreeClear(tmp);
}
@@ -460,14 +503,17 @@ double getVectorDoubleValue_JSON(void *src, int32_t index){
return out;
} else if(*data == TSDB_DATA_TYPE_NCHAR) { // json inner type can not be BINARY
convertNcharToDouble(data+CHAR_BYTES, &out);
- } else {
+ } else if(tTagIsJson(data)){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return 0;
+ } else{
convertNumberToNumber(data+CHAR_BYTES, &out, *data, TSDB_DATA_TYPE_DOUBLE);
}
return out;
}
void* ncharTobinary(void *buf){ // todo need to remove , if tobinary is nchar
- int32_t inputLen = varDataLen(buf);
+ int32_t inputLen = varDataTLen(buf);
void* t = taosMemoryCalloc(1, inputLen);
int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(buf), varDataLen(buf), varDataVal(t));
@@ -492,10 +538,18 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
}
if(typeLeft == TSDB_DATA_TYPE_JSON){
+ if(tTagIsJson(*pLeftData)){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return false;
+ }
typeLeft = **pLeftData;
(*pLeftData) ++;
}
if(typeRight == TSDB_DATA_TYPE_JSON){
+ if(tTagIsJson(*pLeftData)){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ return false;
+ }
typeRight = **pRightData;
(*pRightData) ++;
}
@@ -506,6 +560,16 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
}
}
+ // if types can not comparable
+ if((IS_NUMERIC_TYPE(typeLeft) && !IS_NUMERIC_TYPE(typeRight)) ||
+ (IS_NUMERIC_TYPE(typeRight) && !IS_NUMERIC_TYPE(typeLeft)) ||
+ (IS_VAR_DATA_TYPE(typeLeft) && !IS_VAR_DATA_TYPE(typeRight)) ||
+ (IS_VAR_DATA_TYPE(typeRight) && !IS_VAR_DATA_TYPE(typeLeft)) ||
+ ((typeLeft == TSDB_DATA_TYPE_BOOL) && (typeRight != TSDB_DATA_TYPE_BOOL)) ||
+ ((typeRight == TSDB_DATA_TYPE_BOOL) && (typeLeft != TSDB_DATA_TYPE_BOOL)))
+ return false;
+
+
if(typeLeft == TSDB_DATA_TYPE_NULL || typeRight == TSDB_DATA_TYPE_NULL){
*isNull = true;
return true;
@@ -519,24 +583,28 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
*fp = filterGetCompFunc(type, optr);
- if(IS_NUMERIC_TYPE(type) || IS_FLOAT_TYPE(type)){
+ if(IS_NUMERIC_TYPE(type)){
if(typeLeft == TSDB_DATA_TYPE_NCHAR) {
- convertNcharToDouble(*pLeftData, pLeftOut);
- *pLeftData = pLeftOut;
+ ASSERT(0);
+// convertNcharToDouble(*pLeftData, pLeftOut);
+// *pLeftData = pLeftOut;
} else if(typeLeft == TSDB_DATA_TYPE_BINARY) {
- convertBinaryToDouble(*pLeftData, pLeftOut);
- *pLeftData = pLeftOut;
+ ASSERT(0);
+// convertBinaryToDouble(*pLeftData, pLeftOut);
+// *pLeftData = pLeftOut;
} else if(typeLeft != type) {
convertNumberToNumber(*pLeftData, pLeftOut, typeLeft, type);
*pLeftData = pLeftOut;
}
if(typeRight == TSDB_DATA_TYPE_NCHAR) {
- convertNcharToDouble(*pRightData, pRightOut);
- *pRightData = pRightOut;
+ ASSERT(0);
+// convertNcharToDouble(*pRightData, pRightOut);
+// *pRightData = pRightOut;
} else if(typeRight == TSDB_DATA_TYPE_BINARY) {
- convertBinaryToDouble(*pRightData, pRightOut);
- *pRightData = pRightOut;
+ ASSERT(0);
+// convertBinaryToDouble(*pRightData, pRightOut);
+// *pRightData = pRightOut;
} else if(typeRight != type) {
convertNumberToNumber(*pRightData, pRightOut, typeRight, type);
*pRightData = pRightOut;
@@ -574,7 +642,7 @@ int32_t vectorConvertToVarData(const SScalarParam* pIn, SScalarParam* pOut, int1
int32_t len = sprintf(varDataVal(tmp), "%" PRId64, value);
varDataLen(tmp) = len;
if (outType == TSDB_DATA_TYPE_NCHAR) {
- varToNchar(tmp, pOut, i);
+ varToNchar(tmp, pOut, i, NULL);
} else {
colDataAppend(pOutputCol, i, (char *)tmp, false);
}
@@ -591,7 +659,7 @@ int32_t vectorConvertToVarData(const SScalarParam* pIn, SScalarParam* pOut, int1
int32_t len = sprintf(varDataVal(tmp), "%" PRIu64, value);
varDataLen(tmp) = len;
if (outType == TSDB_DATA_TYPE_NCHAR) {
- varToNchar(tmp, pOut, i);
+ varToNchar(tmp, pOut, i, NULL);
} else {
colDataAppend(pOutputCol, i, (char *)tmp, false);
}
@@ -608,7 +676,7 @@ int32_t vectorConvertToVarData(const SScalarParam* pIn, SScalarParam* pOut, int1
int32_t len = sprintf(varDataVal(tmp), "%lf", value);
varDataLen(tmp) = len;
if (outType == TSDB_DATA_TYPE_NCHAR) {
- varToNchar(tmp, pOut, i);
+ varToNchar(tmp, pOut, i, NULL);
} else {
colDataAppend(pOutputCol, i, (char *)tmp, false);
}
@@ -621,9 +689,8 @@ int32_t vectorConvertToVarData(const SScalarParam* pIn, SScalarParam* pOut, int1
return TSDB_CODE_SUCCESS;
}
-
// TODO opt performance
-int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut) {
+int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut, int32_t* overflow) {
SColumnInfoData* pInputCol = pIn->columnData;
SColumnInfoData* pOutputCol = pOut->columnData;
@@ -636,7 +703,47 @@ int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut) {
int16_t outType = pOutputCol->info.type;
if (IS_VAR_DATA_TYPE(inType)) {
- return vectorConvertFromVarData(pIn, pOut, inType, outType);
+ return vectorConvertFromVarData(pIn, pOut, inType, outType, overflow);
+ }
+
+ if (overflow) {
+ ASSERT(1 == pIn->numOfRows);
+
+ pOut->numOfRows = 0;
+
+ if (IS_SIGNED_NUMERIC_TYPE(outType)) {
+ int64_t minValue = tDataTypes[outType].minValue;
+ int64_t maxValue = tDataTypes[outType].maxValue;
+
+ double value = 0;
+ GET_TYPED_DATA(value, double, inType, colDataGetData(pInputCol, 0));
+
+ if (value > maxValue) {
+ *overflow = 1;
+ return TSDB_CODE_SUCCESS;
+ } else if (value < minValue) {
+ *overflow = -1;
+ return TSDB_CODE_SUCCESS;
+ } else {
+ *overflow = 0;
+ }
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(outType)) {
+ uint64_t minValue = (uint64_t)tDataTypes[outType].minValue;
+ uint64_t maxValue = (uint64_t)tDataTypes[outType].maxValue;
+
+ double value = 0;
+ GET_TYPED_DATA(value, double, inType, colDataGetData(pInputCol, 0));
+
+ if (value > maxValue) {
+ *overflow = 1;
+ return TSDB_CODE_SUCCESS;
+ } else if (value < minValue) {
+ *overflow = -1;
+ return TSDB_CODE_SUCCESS;
+ } else {
+ *overflow = 0;
+ }
+ }
}
pOut->numOfRows = pIn->numOfRows;
@@ -797,6 +904,8 @@ int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut) {
return TSDB_CODE_SUCCESS;
}
+
+
int8_t gConvertTypes[TSDB_DATA_TYPE_BLOB+1][TSDB_DATA_TYPE_BLOB+1] = {
/* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB */
/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -833,16 +942,15 @@ int32_t vectorGetConvertType(int32_t type1, int32_t type2) {
}
int32_t vectorConvertScalarParam(SScalarParam *input, SScalarParam *output, int32_t type) {
- int32_t code = 0;
SDataType t = {.type = type, .bytes = tDataTypes[type].bytes};
output->numOfRows = input->numOfRows;
- output->columnData = createColumnInfoData(&t, input->numOfRows);
- if (output->columnData == NULL) {
+ int32_t code = sclCreateColumnInfoData(&t, input->numOfRows, output);
+ if (code != TSDB_CODE_SUCCESS) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- code = vectorConvertImpl(input, output);
+ code = vectorConvertImpl(input, output, NULL);
if (code) {
// taosMemoryFreeClear(paramOut1->data);
return code;
@@ -908,13 +1016,12 @@ static int32_t doConvertHelper(SScalarParam* pDest, int32_t* convert, const SSca
pDest->numOfRows = pParam->numOfRows;
SDataType t = {.type = type, .bytes = tDataTypes[type].bytes};
- pDest->columnData = createColumnInfoData(&t, pParam->numOfRows);
- if (pDest->columnData == NULL) {
- sclError("malloc %d failed", (int32_t)(pParam->numOfRows * sizeof(double)));
- return TSDB_CODE_OUT_OF_MEMORY;
+ int32_t code = sclCreateColumnInfoData(&t, pParam->numOfRows, pDest);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
}
- int32_t code = vectorConvertImpl(pParam, pDest);
+ code = vectorConvertImpl(pParam, pDest, NULL);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@@ -948,7 +1055,7 @@ static void vectorMathAddHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRig
}
}
-static void vectorMathBigintAddHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRightCol, SColumnInfoData* pOutputCol, int32_t numOfRows, int32_t step, int32_t i) {
+static void vectorMathTsAddHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRightCol, SColumnInfoData* pOutputCol, int32_t numOfRows, int32_t step, int32_t i) {
_getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type);
_getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type);
@@ -962,7 +1069,8 @@ static void vectorMathBigintAddHelper(SColumnInfoData* pLeftCol, SColumnInfoData
colDataAppendNULL(pOutputCol, i);
continue; // TODO set null or ignore
}
- *output = getVectorBigintValueFnLeft(pLeftCol->pData, i) + getVectorBigintValueFnRight(pRightCol->pData, 0);
+ *output = taosTimeAdd(getVectorBigintValueFnLeft(pLeftCol->pData, i), getVectorBigintValueFnRight(pRightCol->pData, 0),
+ pRightCol->info.scale, pRightCol->info.precision);
}
}
}
@@ -1009,7 +1117,17 @@ void vectorMathAdd(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut
_getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type);
_getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type);
- if (pLeft->numOfRows == pRight->numOfRows) {
+ if (pLeft->numOfRows == 1 && pRight->numOfRows == 1) {
+ if (GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_TIMESTAMP) {
+ vectorMathTsAddHelper(pLeftCol, pRightCol, pOutputCol, pRight->numOfRows, step, i);
+ } else {
+ vectorMathTsAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i);
+ }
+ } else if (pLeft->numOfRows == 1) {
+ vectorMathTsAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i);
+ } else if (pRight->numOfRows == 1) {
+ vectorMathTsAddHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i);
+ } else if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) {
colDataAppendNULL(pOutputCol, i);
@@ -1017,11 +1135,7 @@ void vectorMathAdd(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut
}
*output = getVectorBigintValueFnLeft(pLeftCol->pData, i) + getVectorBigintValueFnRight(pRightCol->pData, i);
}
- } else if (pLeft->numOfRows == 1) {
- vectorMathBigintAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i);
- } else if (pRight->numOfRows == 1) {
- vectorMathBigintAddHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i);
- }
+ }
} else {
double *output = (double *)pOutputCol->pData;
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type);
@@ -1067,7 +1181,7 @@ static void vectorMathSubHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRig
}
}
-static void vectorMathBigintSubHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRightCol, SColumnInfoData* pOutputCol, int32_t numOfRows, int32_t step, int32_t factor, int32_t i) {
+static void vectorMathTsSubHelper(SColumnInfoData* pLeftCol, SColumnInfoData* pRightCol, SColumnInfoData* pOutputCol, int32_t numOfRows, int32_t step, int32_t factor, int32_t i) {
_getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type);
_getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type);
@@ -1081,7 +1195,9 @@ static void vectorMathBigintSubHelper(SColumnInfoData* pLeftCol, SColumnInfoData
colDataAppendNULL(pOutputCol, i);
continue; // TODO set null or ignore
}
- *output = (getVectorBigintValueFnLeft(pLeftCol->pData, i) - getVectorBigintValueFnRight(pRightCol->pData, 0)) * factor;
+ *output = taosTimeSub(getVectorBigintValueFnLeft(pLeftCol->pData, i), getVectorBigintValueFnRight(pRightCol->pData, 0),
+ pRightCol->info.scale, pRightCol->info.precision);
+
}
}
}
@@ -1104,7 +1220,13 @@ void vectorMathSub(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut
_getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type);
_getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type);
- if (pLeft->numOfRows == pRight->numOfRows) {
+ if (pLeft->numOfRows == 1 && pRight->numOfRows == 1) {
+ vectorMathTsSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i);
+ } else if (pLeft->numOfRows == 1) {
+ vectorMathTsSubHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, -1, i);
+ } else if (pRight->numOfRows == 1) {
+ vectorMathTsSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i);
+ } else if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) {
colDataAppendNULL(pOutputCol, i);
@@ -1112,10 +1234,6 @@ void vectorMathSub(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut
}
*output = getVectorBigintValueFnLeft(pLeftCol->pData, i) - getVectorBigintValueFnRight(pRightCol->pData, i);
}
- } else if (pLeft->numOfRows == 1) {
- vectorMathBigintSubHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, -1, i);
- } else if (pRight->numOfRows == 1) {
- vectorMathBigintSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i);
}
} else {
double *output = (double *)pOutputCol->pData;
@@ -1561,7 +1679,11 @@ void vectorBitOr(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut,
void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t _ord, int32_t optr) {
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1;
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
+
__compar_fn_t fp = filterGetCompFunc(GET_PARAM_TYPE(pLeft), optr);
+ if(terrno != TSDB_CODE_SUCCESS){
+ return;
+ }
pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows);
@@ -1680,7 +1802,7 @@ void vectorNotNull(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut
}
void vectorIsTrue(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t _ord) {
- vectorConvertImpl(pLeft, pOut);
+ vectorConvertImpl(pLeft, pOut, NULL);
for(int32_t i = 0; i < pOut->numOfRows; ++i) {
if(colDataIsNull_s(pOut->columnData, i)) {
int8_t v = 0;
@@ -1693,6 +1815,14 @@ void vectorIsTrue(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut,
STagVal getJsonValue(char *json, char *key, bool *isExist) {
STagVal val = {.pKey = key};
+ if (tTagIsJson((const STag *)json) == false){
+ terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
+ if(isExist){
+ *isExist = false;
+ }
+ return val;
+ }
+
bool find = tTagGet(((const STag *)json), &val); // json value is null and not exist is different
if(isExist){
*isExist = find;
diff --git a/source/libs/scalar/test/filter/CMakeLists.txt b/source/libs/scalar/test/filter/CMakeLists.txt
index 8e3aeb6f9dcb71b9764fda0b9378e9ef2ef4ed20..a95a1655f892883b587437d399ebbc41910cc799 100644
--- a/source/libs/scalar/test/filter/CMakeLists.txt
+++ b/source/libs/scalar/test/filter/CMakeLists.txt
@@ -1,18 +1,20 @@
MESSAGE(STATUS "build filter unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(filterTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- filterTest
- PUBLIC os util common gtest qcom function nodes scalar
-)
+ ADD_EXECUTABLE(filterTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ filterTest
+ PUBLIC os util common gtest qcom function nodes scalar
+ )
-TARGET_INCLUDE_DIRECTORIES(
- filterTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/scalar/inc"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ filterTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/scalar/inc"
+ )
+ENDIF()
\ No newline at end of file
diff --git a/source/libs/scalar/test/filter/filterTests.cpp b/source/libs/scalar/test/filter/filterTests.cpp
index 7fb1ffbd64aecb2fee9d7c862f295070dbea8e09..d8c64eef55cf0452946184439264ca66ef925ec9 100644
--- a/source/libs/scalar/test/filter/filterTests.cpp
+++ b/source/libs/scalar/test/filter/filterTests.cpp
@@ -105,29 +105,14 @@ void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in
}
if (NULL == *block) {
- SSDataBlock *res = (SSDataBlock *)taosMemoryCalloc(1, sizeof(SSDataBlock));
- res->info.numOfCols = 3;
- res->info.rows = rowNum;
- res->pDataBlock = taosArrayInit(3, sizeof(SColumnInfoData));
+ SSDataBlock *res = createDataBlock();
for (int32_t i = 0; i < 2; ++i) {
- SColumnInfoData idata = {{0}};
- idata.info.type = TSDB_DATA_TYPE_NULL;
- idata.info.bytes = 10;
- idata.info.colId = i + 1;
-
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- taosArrayPush(res->pDataBlock, &idata);
+ SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_NULL, 10, 1+i);
+ blockDataAppendColInfo(res, &idata);
}
- SColumnInfoData idata = {{0}};
- idata.info.type = dataType;
- idata.info.bytes = dataBytes;
- idata.info.colId = 3;
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- taosArrayPush(res->pDataBlock, &idata);
-
+ SColumnInfoData idata = createColumnInfoData(dataType, dataBytes, 3);
+ blockDataAppendColInfo(res, &idata);
blockDataEnsureCapacity(res, rowNum);
SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock);
@@ -142,23 +127,18 @@ void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in
rnode->slotId = 2;
rnode->colId = 3;
+ res->info.rows = rowNum;
*block = res;
} else {
SSDataBlock *res = *block;
int32_t idx = taosArrayGetSize(res->pDataBlock);
- SColumnInfoData idata = {{0}};
- idata.info.type = dataType;
- idata.info.bytes = dataBytes;
- idata.info.colId = 1 + idx;
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- taosArrayPush(res->pDataBlock, &idata);
- res->info.numOfCols++;
+ SColumnInfoData idata = createColumnInfoData(dataType, dataBytes, 1+idx);
+ blockDataAppendColInfo(res, &idata);
+ blockDataEnsureCapacity(res, rowNum);
+
SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock);
-
- colInfoDataEnsureCapacity(pColumn, 0, rowNum);
for (int32_t i = 0; i < rowNum; ++i) {
colDataAppend(pColumn, i, (const char *)value, false);
@@ -225,13 +205,19 @@ void flttMakeListNode(SNode **pNode, SNodeList *list, int32_t resType) {
*pNode = (SNode *)lnode;
}
+void initScalarParam(SScalarParam* pParam) {
+ memset(pParam, 0, sizeof(SScalarParam));
+ pParam->type = SHOULD_FREE_COLDATA;
+}
}
TEST(timerangeTest, greater) {
SNode *pcol = NULL, *pval = NULL, *opNode1 = NULL;
bool eRes[5] = {false, false, true, true, true};
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
+
int64_t tsmall = 222, tbig = 333;
flttMakeColumnNode(&pcol, NULL, TSDB_DATA_TYPE_TIMESTAMP, sizeof(int64_t), 0, NULL);
flttMakeValueNode(&pval, TSDB_DATA_TYPE_TIMESTAMP, &tsmall);
@@ -254,7 +240,8 @@ TEST(timerangeTest, greater) {
TEST(timerangeTest, greater_and_lower) {
SNode *pcol = NULL, *pval = NULL, *opNode1 = NULL, *opNode2 = NULL, *logicNode = NULL;
bool eRes[5] = {false, false, true, true, true};
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int64_t tsmall = 222, tbig = 333;
flttMakeColumnNode(&pcol, NULL, TSDB_DATA_TYPE_TIMESTAMP, sizeof(int64_t), 0, NULL);
flttMakeValueNode(&pval, TSDB_DATA_TYPE_TIMESTAMP, &tsmall);
@@ -285,7 +272,8 @@ TEST(timerangeTest, greater_and_lower) {
TEST(timerangeTest, greater_equal_and_lower_equal) {
SNode *pcol = NULL, *pval = NULL, *opNode1 = NULL, *opNode2 = NULL, *logicNode = NULL;
bool eRes[5] = {false, false, true, true, true};
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int64_t tsmall = 222, tbig = 333;
flttMakeColumnNode(&pcol, NULL, TSDB_DATA_TYPE_TIMESTAMP, sizeof(int64_t), 0, NULL);
flttMakeValueNode(&pval, TSDB_DATA_TYPE_TIMESTAMP, &tsmall);
@@ -317,7 +305,8 @@ TEST(timerangeTest, greater_equal_and_lower_equal) {
TEST(timerangeTest, greater_and_lower_not_strict) {
SNode *pcol = NULL, *pval = NULL, *opNode1 = NULL, *opNode2 = NULL, *logicNode1 = NULL, *logicNode2 = NULL;
bool eRes[5] = {false, false, true, true, true};
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int64_t tsmall1 = 222, tbig1 = 333;
int64_t tsmall2 = 444, tbig2 = 555;
SNode *list[2] = {0};
@@ -370,7 +359,8 @@ TEST(columnTest, smallint_column_greater_double_value) {
double rightv= 2.5;
int8_t eRes[5] = {0, 0, 1, 1, 1};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, leftv);
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_DOUBLE, &rightv);
@@ -399,7 +389,7 @@ TEST(columnTest, smallint_column_greater_double_value) {
keep = filterRangeExecute(filter, &stat, 1, rowNum);
ASSERT_EQ(keep, true);
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -407,9 +397,9 @@ TEST(columnTest, smallint_column_greater_double_value) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -425,12 +415,13 @@ TEST(columnTest, int_column_greater_smallint_value) {
int16_t rightv= 4;
int8_t eRes[5] = {0, 0, 1, 1, 1};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, leftv);
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &rightv);
flttMakeOpNode(&opNode, OP_TYPE_GREATER_THAN, TSDB_DATA_TYPE_BOOL, pLeft, pRight);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
@@ -454,7 +445,7 @@ TEST(columnTest, int_column_greater_smallint_value) {
keep = filterRangeExecute(filter, &stat, 1, rowNum);
ASSERT_EQ(keep, false);
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -462,9 +453,9 @@ TEST(columnTest, int_column_greater_smallint_value) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -478,11 +469,12 @@ TEST(columnTest, int_column_in_double_list) {
SNode *pLeft = NULL, *pRight = NULL, *listNode = NULL, *opNode = NULL;
int32_t leftv[5] = {1, 2, 3, 4, 5};
double rightv1 = 1.1,rightv2 = 2.2,rightv3 = 3.3;
- bool eRes[5] = {true, true, true, false, false};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ bool eRes[5] = {true, true, true, false, false};
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, leftv);
SNodeList* list = nodesMakeList();
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_DOUBLE, &rightv1);
nodesListAppend(list, pRight);
@@ -498,7 +490,7 @@ TEST(columnTest, int_column_in_double_list) {
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -506,9 +498,9 @@ TEST(columnTest, int_column_in_double_list) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -521,9 +513,10 @@ TEST(columnTest, int_column_in_double_list) {
TEST(columnTest, binary_column_in_binary_list) {
SNode *pLeft = NULL, *pRight = NULL, *listNode = NULL, *opNode = NULL;
- bool eRes[5] = {true, true, false, false, false};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ bool eRes[5] = {true, true, false, false, false};
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
char leftv[5][5]= {0};
char rightv[3][5]= {0};
for (int32_t i = 0; i < 5; ++i) {
@@ -531,22 +524,22 @@ TEST(columnTest, binary_column_in_binary_list) {
leftv[i][3] = 'b' + i;
leftv[i][4] = '0' + i;
varDataSetLen(leftv[i], 3);
- }
+ }
for (int32_t i = 0; i < 2; ++i) {
rightv[i][2] = 'a' + i;
rightv[i][3] = 'b' + i;
rightv[i][4] = '0' + i;
varDataSetLen(rightv[i], 3);
- }
+ }
for (int32_t i = 2; i < 3; ++i) {
rightv[i][2] = 'a' + i;
rightv[i][3] = 'a' + i;
rightv[i][4] = 'a' + i;
varDataSetLen(rightv[i], 3);
}
-
+
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
SNodeList* list = nodesMakeList();
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_BINARY, rightv[0]);
nodesListAppend(list, pRight);
@@ -556,13 +549,13 @@ TEST(columnTest, binary_column_in_binary_list) {
nodesListAppend(list, pRight);
flttMakeListNode(&listNode,list, TSDB_DATA_TYPE_BINARY);
flttMakeOpNode(&opNode, OP_TYPE_IN, TSDB_DATA_TYPE_BOOL, pLeft, listNode);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -570,9 +563,9 @@ TEST(columnTest, binary_column_in_binary_list) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -586,31 +579,32 @@ TEST(columnTest, binary_column_like_binary) {
SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL;
char rightv[64] = {0};
char leftv[5][5]= {0};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
- bool eRes[5] = {true, false, true, false, true};
-
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
+ bool eRes[5] = {true, false, true, false, true};
+
for (int32_t i = 0; i < 5; ++i) {
leftv[i][2] = 'a';
leftv[i][3] = 'a';
leftv[i][4] = '0' + i % 2;
varDataSetLen(leftv[i], 3);
- }
-
+ }
+
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
sprintf(&rightv[2], "%s", "__0");
varDataSetLen(rightv, strlen(&rightv[2]));
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_BINARY, rightv);
flttMakeOpNode(&opNode, OP_TYPE_LIKE, TSDB_DATA_TYPE_BOOL, pLeft, pRight);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -618,9 +612,9 @@ TEST(columnTest, binary_column_like_binary) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -633,31 +627,32 @@ TEST(columnTest, binary_column_like_binary) {
TEST(columnTest, binary_column_is_null) {
SNode *pLeft = NULL, *opNode = NULL;
char leftv[5][5]= {0};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
- bool eRes[5] = {false, false, true, false, true};
-
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
+ bool eRes[5] = {false, false, true, false, true};
+
for (int32_t i = 0; i < 5; ++i) {
leftv[i][2] = '0' + i % 2;
leftv[i][3] = 'a';
leftv[i][4] = '0' + i % 2;
varDataSetLen(leftv[i], 3);
- }
-
+ }
+
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock);
colDataAppend(pcolumn, 2, NULL, true);
colDataAppend(pcolumn, 4, NULL, true);
flttMakeOpNode(&opNode, OP_TYPE_IS_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -665,9 +660,9 @@ TEST(columnTest, binary_column_is_null) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -680,31 +675,32 @@ TEST(columnTest, binary_column_is_null) {
TEST(columnTest, binary_column_is_not_null) {
SNode *pLeft = NULL, *opNode = NULL;
char leftv[5][5]= {0};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
- bool eRes[5] = {true, true, true, true, false};
-
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
+ bool eRes[5] = {true, true, true, true, false};
+
for (int32_t i = 0; i < 5; ++i) {
leftv[i][2] = '0' + i % 2;
leftv[i][3] = 'a';
leftv[i][4] = '0' + i % 2;
varDataSetLen(leftv[i], 3);
- }
-
+ }
+
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock);
colDataAppend(pcolumn, 4, NULL, true);
flttMakeOpNode(&opNode, OP_TYPE_IS_NOT_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -712,9 +708,9 @@ TEST(columnTest, binary_column_is_not_null) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -730,18 +726,19 @@ TEST(opTest, smallint_column_greater_int_column) {
int32_t rightv[5]= {0, -5, -4, 23, 100};
bool eRes[5] = {true, false, true, false, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(rightv)/sizeof(rightv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, leftv);
flttMakeColumnNode(&pRight, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, rightv);
flttMakeOpNode(&opNode, OP_TYPE_GREATER_THAN, TSDB_DATA_TYPE_BOOL, pLeft, pRight);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -749,9 +746,9 @@ TEST(opTest, smallint_column_greater_int_column) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -767,19 +764,20 @@ TEST(opTest, smallint_value_add_int_column) {
int16_t rightv[5]= {0, -1, -4, -1, 100};
bool eRes[5] = {true, false, true, false, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(rightv)/sizeof(rightv[0]);
flttMakeValueNode(&pLeft, TSDB_DATA_TYPE_INT, &leftv);
flttMakeColumnNode(&pRight, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, rightv);
flttMakeOpNode(&opNode, OP_TYPE_ADD, TSDB_DATA_TYPE_DOUBLE, pLeft, pRight);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, opNode, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -787,9 +785,9 @@ TEST(opTest, smallint_value_add_int_column) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -810,19 +808,20 @@ TEST(opTest, bigint_column_multi_binary_column) {
}
bool eRes[5] = {false, true, true, true, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(rightv)/sizeof(rightv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t), rowNum, leftv);
flttMakeColumnNode(&pRight, &src, TSDB_DATA_TYPE_BINARY, 5, rowNum, rightv);
flttMakeOpNode(&opNode, OP_TYPE_MULTI, TSDB_DATA_TYPE_DOUBLE, pLeft, pRight);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, opNode, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -830,9 +829,9 @@ TEST(opTest, bigint_column_multi_binary_column) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -853,19 +852,20 @@ TEST(opTest, smallint_column_and_binary_column) {
}
bool eRes[5] = {false, false, true, false, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(rightv)/sizeof(rightv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, leftv);
flttMakeColumnNode(&pRight, &src, TSDB_DATA_TYPE_BINARY, 5, rowNum, rightv);
flttMakeOpNode(&opNode, OP_TYPE_BIT_AND, TSDB_DATA_TYPE_BIGINT, pLeft, pRight);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, opNode, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -873,9 +873,9 @@ TEST(opTest, smallint_column_and_binary_column) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, (int32_t) taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -891,19 +891,20 @@ TEST(opTest, smallint_column_or_float_column) {
float rightv[5]= {2.0, 3.0, 0, 5.2, 6.0};
bool eRes[5] = {true, true, false, true, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(rightv)/sizeof(rightv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, leftv);
flttMakeColumnNode(&pRight, &src, TSDB_DATA_TYPE_FLOAT, sizeof(float), rowNum, rightv);
flttMakeOpNode(&opNode, OP_TYPE_BIT_OR, TSDB_DATA_TYPE_BIGINT, pLeft, pRight);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, opNode, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -911,9 +912,9 @@ TEST(opTest, smallint_column_or_float_column) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -929,19 +930,20 @@ TEST(opTest, smallint_column_or_double_value) {
double rightv= 10.2;
bool eRes[5] = {true, true, true, true, true};
SSDataBlock *src = NULL;
- SScalarParam res = {0};
+ SScalarParam res;
+ initScalarParam(&res);
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_SMALLINT, sizeof(int16_t), rowNum, leftv);
flttMakeValueNode(&pRight, TSDB_DATA_TYPE_DOUBLE, &rightv);
flttMakeOpNode(&opNode, OP_TYPE_BIT_OR, TSDB_DATA_TYPE_BIGINT, pLeft, pRight);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, opNode, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -949,9 +951,9 @@ TEST(opTest, smallint_column_or_double_value) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, true);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -964,28 +966,29 @@ TEST(opTest, smallint_column_or_double_value) {
TEST(opTest, binary_column_is_true) {
SNode *pLeft = NULL, *opNode = NULL;
char leftv[5][5]= {0};
- SSDataBlock *src = NULL;
- SScalarParam res = {0};
- bool eRes[5] = {false, true, false, true, false};
-
+ SSDataBlock *src = NULL;
+ SScalarParam res;
+ initScalarParam(&res);
+ bool eRes[5] = {false, true, false, true, false};
+
for (int32_t i = 0; i < 5; ++i) {
leftv[i][2] = '0' + i % 2;
leftv[i][3] = 'a';
leftv[i][4] = '0' + i % 2;
varDataSetLen(leftv[i], 3);
- }
-
+ }
+
int32_t rowNum = sizeof(leftv)/sizeof(leftv[0]);
- flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
+ flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv);
flttMakeOpNode(&opNode, OP_TYPE_IS_TRUE, TSDB_DATA_TYPE_BOOL, pLeft, NULL);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(opNode, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -993,9 +996,9 @@ TEST(opTest, binary_column_is_true) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -1027,12 +1030,12 @@ TEST(filterModelogicTest, diff_columns_and_or_and) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_AND, list);
list = nodesMakeList();
-
+
flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
flttMakeValueNode(&pRight1, TSDB_DATA_TYPE_INT, &rightv1);
flttMakeOpNode(&opNode1, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight1);
@@ -1042,7 +1045,7 @@ TEST(filterModelogicTest, diff_columns_and_or_and) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_GREATER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode2, LOGIC_COND_TYPE_AND, list);
list = nodesMakeList();
@@ -1050,13 +1053,13 @@ TEST(filterModelogicTest, diff_columns_and_or_and) {
nodesListAppend(list, logicNode2);
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_OR, list);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(logicNode1, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -1064,9 +1067,9 @@ TEST(filterModelogicTest, diff_columns_and_or_and) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -1096,13 +1099,13 @@ TEST(filterModelogicTest, same_column_and_or_and) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_AND, list);
list = nodesMakeList();
- flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
+ flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
flttMakeValueNode(&pRight1, TSDB_DATA_TYPE_INT, &rightv3);
flttMakeOpNode(&opNode1, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight1);
nodesListAppend(list, opNode1);
@@ -1111,7 +1114,7 @@ TEST(filterModelogicTest, same_column_and_or_and) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv4);
flttMakeOpNode(&opNode2, OP_TYPE_GREATER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode2, LOGIC_COND_TYPE_AND, list);
list = nodesMakeList();
@@ -1119,13 +1122,13 @@ TEST(filterModelogicTest, same_column_and_or_and) {
nodesListAppend(list, logicNode2);
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_OR, list);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(logicNode1, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -1133,9 +1136,9 @@ TEST(filterModelogicTest, same_column_and_or_and) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -1165,12 +1168,12 @@ TEST(filterModelogicTest, diff_columns_or_and_or) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
-
+
flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
flttMakeValueNode(&pRight1, TSDB_DATA_TYPE_INT, &rightv1);
flttMakeOpNode(&opNode1, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight1);
@@ -1180,7 +1183,7 @@ TEST(filterModelogicTest, diff_columns_or_and_or) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_GREATER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode2, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
@@ -1188,13 +1191,13 @@ TEST(filterModelogicTest, diff_columns_or_and_or) {
nodesListAppend(list, logicNode2);
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_AND, list);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(logicNode1, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t) taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -1202,9 +1205,9 @@ TEST(filterModelogicTest, diff_columns_or_and_or) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -1234,12 +1237,12 @@ TEST(filterModelogicTest, same_column_or_and_or) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
-
+
flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
flttMakeValueNode(&pRight1, TSDB_DATA_TYPE_INT, &rightv3);
flttMakeOpNode(&opNode1, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight1);
@@ -1249,7 +1252,7 @@ TEST(filterModelogicTest, same_column_or_and_or) {
flttMakeValueNode(&pRight2, TSDB_DATA_TYPE_INT, &rightv4);
flttMakeOpNode(&opNode2, OP_TYPE_GREATER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft1, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode2, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
@@ -1257,13 +1260,13 @@ TEST(filterModelogicTest, same_column_or_and_or) {
nodesListAppend(list, logicNode2);
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_AND, list);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(logicNode1, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -1271,9 +1274,9 @@ TEST(filterModelogicTest, same_column_or_and_or) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
-
+
for (int32_t i = 0; i < rowNum; ++i) {
ASSERT_EQ(*((int8_t *)rowRes + i), eRes[i]);
}
@@ -1305,12 +1308,12 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) {
flttMakeColumnNode(&pRight2, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_THAN, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
-
+
flttMakeColumnNode(&pLeft1, &src, TSDB_DATA_TYPE_DOUBLE, sizeof(double), rowNum, leftv1);
flttMakeColumnNode(&pRight1, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, rightv1);
flttMakeOpNode(&opNode1, OP_TYPE_GREATER_THAN, TSDB_DATA_TYPE_BOOL, pLeft1, pRight1);
@@ -1320,7 +1323,7 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) {
flttMakeColumnNode(&pRight2, &src, TSDB_DATA_TYPE_INT, sizeof(int32_t), rowNum, rightv2);
flttMakeOpNode(&opNode2, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft2, pRight2);
nodesListAppend(list, opNode2);
-
+
flttMakeLogicNodeFromList(&logicNode2, LOGIC_COND_TYPE_OR, list);
list = nodesMakeList();
@@ -1328,13 +1331,13 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) {
nodesListAppend(list, logicNode2);
flttMakeLogicNodeFromList(&logicNode1, LOGIC_COND_TYPE_AND, list);
-
+
SFilterInfo *filter = NULL;
int32_t code = filterInitFromNode(logicNode1, &filter, 0);
ASSERT_EQ(code, 0);
SColumnDataAgg stat = {0};
- SFilterColumnParam param = { src->info.numOfCols, src->pDataBlock };
+ SFilterColumnParam param = { (int32_t)taosArrayGetSize(src->pDataBlock), src->pDataBlock };
code = filterSetDataFromSlotId(filter, ¶m);
ASSERT_EQ(code, 0);
@@ -1342,7 +1345,7 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) {
stat.min = 1;
stat.numOfNull = 0;
int8_t *rowRes = NULL;
- bool keep = filterExecute(filter, src, &rowRes, &stat, src->info.numOfCols);
+ bool keep = filterExecute(filter, src, &rowRes, &stat, taosArrayGetSize(src->pDataBlock));
ASSERT_EQ(keep, false);
for (int32_t i = 0; i < rowNum; ++i) {
diff --git a/source/libs/scalar/test/scalar/CMakeLists.txt b/source/libs/scalar/test/scalar/CMakeLists.txt
index 86b936d93ae950e27069835cffcb0e8a99768ac9..4624c1a7fd939aa0cd7056758a1bba68295b7f46 100644
--- a/source/libs/scalar/test/scalar/CMakeLists.txt
+++ b/source/libs/scalar/test/scalar/CMakeLists.txt
@@ -1,23 +1,25 @@
MESSAGE(STATUS "build scalar unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(scalarTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- scalarTest
- PUBLIC os util common gtest qcom function nodes scalar parser catalog transport
-)
+ ADD_EXECUTABLE(scalarTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ scalarTest
+ PUBLIC os util common gtest qcom function nodes scalar parser catalog transport
+ )
-TARGET_INCLUDE_DIRECTORIES(
- scalarTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar/"
- PUBLIC "${TD_SOURCE_DIR}/source/libs/parser/inc"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/scalar/inc"
-)
-add_test(
- NAME scalarTest
- COMMAND scalarTest
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ scalarTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar/"
+ PUBLIC "${TD_SOURCE_DIR}/source/libs/parser/inc"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/scalar/inc"
+ )
+ add_test(
+ NAME scalarTest
+ COMMAND scalarTest
+ )
+ENDIF()
diff --git a/source/libs/scalar/test/scalar/scalarTests.cpp b/source/libs/scalar/test/scalar/scalarTests.cpp
index d8791502008755b6ac85949ca07be8b5225a774c..9b40f0a4659ee9a8a85131c9daf017b8c3b17ce2 100644
--- a/source/libs/scalar/test/scalar/scalarTests.cpp
+++ b/source/libs/scalar/test/scalar/scalarTests.cpp
@@ -84,30 +84,29 @@ void scltInitLogFile() {
void scltAppendReservedSlot(SArray *pBlockList, int16_t *dataBlockId, int16_t *slotId, bool newBlock, int32_t rows, SColumnInfo *colInfo) {
if (newBlock) {
- SSDataBlock *res = (SSDataBlock *)taosMemoryCalloc(1, sizeof(SSDataBlock));
- res->info.numOfCols = 1;
- res->info.rows = rows;
- res->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
+ SSDataBlock *res = createDataBlock();
+
SColumnInfoData idata = {0};
- idata.info = *colInfo;
+ idata.info = *colInfo;
+ colInfoDataEnsureCapacity(&idata, rows);
- taosArrayPush(res->pDataBlock, &idata);
- taosArrayPush(pBlockList, &res);
+ blockDataAppendColInfo(res, &idata);
- blockDataEnsureCapacity(res, rows);
+ res->info.capacity = rows;
+ res->info.rows = rows;
+ SColumnInfoData* p = static_cast(taosArrayGet(res->pDataBlock, 0));
+ ASSERT(p->pData != NULL && p->nullbitmap != NULL);
+ taosArrayPush(pBlockList, &res);
*dataBlockId = taosArrayGetSize(pBlockList) - 1;
res->info.blockId = *dataBlockId;
*slotId = 0;
} else {
SSDataBlock *res = *(SSDataBlock **)taosArrayGetLast(pBlockList);
- res->info.numOfCols++;
SColumnInfoData idata = {0};
idata.info = *colInfo;
-
- colInfoDataEnsureCapacity(&idata, 0, rows);
-
- taosArrayPush(res->pDataBlock, &idata);
+ colInfoDataEnsureCapacity(&idata, rows);
+ blockDataAppendColInfo(res, &idata);
*dataBlockId = taosArrayGetSize(pBlockList) - 1;
*slotId = taosArrayGetSize(res->pDataBlock) - 1;
@@ -144,29 +143,19 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in
}
if (NULL == *block) {
- SSDataBlock *res = (SSDataBlock *)taosMemoryCalloc(1, sizeof(SSDataBlock));
- res->info.numOfCols = 3;
- res->info.rows = rowNum;
- res->pDataBlock = taosArrayInit(3, sizeof(SColumnInfoData));
+ SSDataBlock *res = createDataBlock();
for (int32_t i = 0; i < 2; ++i) {
- SColumnInfoData idata = {{0}};
- idata.info.type = TSDB_DATA_TYPE_NULL;
- idata.info.bytes = 10;
- idata.info.colId = i + 1;
-
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- taosArrayPush(res->pDataBlock, &idata);
+ SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_INT, 10, i + 1);
+ colInfoDataEnsureCapacity(&idata, rowNum);
+ blockDataAppendColInfo(res, &idata);
}
- SColumnInfoData idata = {{0}};
- idata.info.type = dataType;
- idata.info.bytes = dataBytes;
- idata.info.colId = 3;
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- colInfoDataEnsureCapacity(&idata, 0, rowNum);
- taosArrayPush(res->pDataBlock, &idata);
+ SColumnInfoData idata = createColumnInfoData(dataType, dataBytes, 3);
+ colInfoDataEnsureCapacity(&idata, rowNum);
+ blockDataAppendColInfo(res, &idata);
+ res->info.capacity = rowNum;
+
+ res->info.rows = rowNum;
SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock);
for (int32_t i = 0; i < rowNum; ++i) {
colDataAppend(pColumn, i, (const char *)value, false);
@@ -185,17 +174,13 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in
SSDataBlock *res = *block;
int32_t idx = taosArrayGetSize(res->pDataBlock);
- SColumnInfoData idata = {{0}};
- idata.info.type = dataType;
- idata.info.bytes = dataBytes;
- idata.info.colId = 1 + idx;
- int32_t size = idata.info.bytes * rowNum;
- idata.pData = (char *)taosMemoryCalloc(1, size);
- taosArrayPush(res->pDataBlock, &idata);
- res->info.numOfCols++;
- SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock);
+ SColumnInfoData idata = createColumnInfoData(dataType, dataBytes, 1 + idx);
+ colInfoDataEnsureCapacity(&idata, rowNum);
- colInfoDataEnsureCapacity(pColumn, 0, rowNum);
+ res->info.capacity = rowNum;
+ blockDataAppendColInfo(res, &idata);
+
+ SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock);
for (int32_t i = 0; i < rowNum; ++i) {
colDataAppend(pColumn, i, (const char *)value, false);
@@ -279,9 +264,6 @@ void scltMakeTargetNode(SNode **pNode, int16_t dataBlockId, int16_t slotId, SNod
*pNode = (SNode *)onode;
}
-
-
-
}
TEST(constantTest, bigint_add_bigint) {
@@ -1110,7 +1092,7 @@ void makeCalculate(void *json, void *key, int32_t rightType, void *rightData, do
printf("op:%s,1result:%f,except:%f\n", gOptrStr[opType].str, *((double *)colDataGetData(column, 0)), exceptValue);
ASSERT_TRUE(fabs(*((double *)colDataGetData(column, 0)) - exceptValue) < 0.0001);
}else if(opType == OP_TYPE_BIT_AND || opType == OP_TYPE_BIT_OR){
- printf("op:%s,2result:%ld,except:%f\n", gOptrStr[opType].str, *((int64_t *)colDataGetData(column, 0)), exceptValue);
+ printf("op:%s,2result:%" PRId64 ",except:%f\n", gOptrStr[opType].str, *((int64_t *)colDataGetData(column, 0)), exceptValue);
ASSERT_EQ(*((int64_t *)colDataGetData(column, 0)), exceptValue);
}else if(opType == OP_TYPE_GREATER_THAN || opType == OP_TYPE_GREATER_EQUAL || opType == OP_TYPE_LOWER_THAN ||
opType == OP_TYPE_LOWER_EQUAL || opType == OP_TYPE_EQUAL || opType == OP_TYPE_NOT_EQUAL ||
@@ -1310,11 +1292,11 @@ TEST(columnTest, json_column_logic_op) {
printf("--------------------json string--0 {1, 8, 2, 2, 3, 0, 0, 0, 0}-------------------\n");
key = "k2";
- bool eRes1[len+len1] = {false, false, true, true, false, false, false, true, false, true, false, true, true};
+ bool eRes1[len+len1] = {false, false, false, false, false, false, false, true, false, true, false, true, true};
for(int i = 0; i < len; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes1[i], op[i], false);
}
- bool eRes_1[len0] = {true, true, false, false, false, false};
+ bool eRes_1[len0] = {false, false, false, false, false, false};
for(int i = 0; i < len0; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes_1[i], op[i], true);
}
@@ -1346,11 +1328,11 @@ TEST(columnTest, json_column_logic_op) {
printf("--------------------json bool--1 {1, 8, 2, 2, 3, 0, 0, 0, 0}-------------------\n");
key = "k4";
- bool eRes3[len+len1] = {false, false, true, true, false, true, false, true, true, false, false, false, false};
+ bool eRes3[len+len1] = {false, false, false, false, false, false, false, true, true, false, false, false, false};
for(int i = 0; i < len; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes3[i], op[i], false);
}
- bool eRes_3[len0] = {false, true, false, false, false, true};
+ bool eRes_3[len0] = {false, false, false, false, false, false};
for(int i = 0; i < len0; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes_3[i], op[i], true);
}
@@ -1419,11 +1401,11 @@ TEST(columnTest, json_column_logic_op) {
printf("--------------------json bool-- 0 {1, 8, 2, 2, 3, 0, 0, 0, 0}-------------------\n");
key = "k8";
- bool eRes7[len+len1] = {false, false, true, true, false, false, false, true, false, false, false, false, false};
+ bool eRes7[len+len1] = {false, false, false, false, false, false, false, true, false, false, false, false, false};
for(int i = 0; i < len; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes7[i], op[i], false);
}
- bool eRes_7[len0] = {true, true, false, false, false, false};
+ bool eRes_7[len0] = {false, false, false, false, false, false};
for(int i = 0; i < len0; i++) {
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes_7[i], op[i], true);
}
@@ -1438,11 +1420,11 @@ TEST(columnTest, json_column_logic_op) {
printf("--------------------json string-- 6.6hello {1, 8, 2, 2, 3, 0, 0, 0, 0}-------------------\n");
key = "k9";
- bool eRes8[len+len1] = {true, false, false, false, false, true, false, true, true, false, true, false, true};
+ bool eRes8[len+len1] = {false, false, false, false, false, false, false, true, true, false, true, false, true};
for(int i = 0; i < len; i++){
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes8[i], op[i], false);
}
- bool eRes_8[len0] = {false, true, true, true, false, true};
+ bool eRes_8[len0] = {false, false, false, false, false, false};
for(int i = 0; i < len0; i++) {
makeCalculate(row, key, TSDB_DATA_TYPE_INT, &input[i], eRes_8[i], op[i], true);
}
@@ -1529,6 +1511,7 @@ TEST(columnTest, bigint_column_multi_binary_column) {
SArray *blockList = taosArrayInit(1, POINTER_BYTES);
taosArrayPush(blockList, &src);
+
SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
int16_t dataBlockId = 0, slotId = 0;
scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo);
@@ -2033,7 +2016,7 @@ void scltMakeDataBlock(SScalarParam **pInput, int32_t type, void *pVal, int32_t
input->numOfRows = num;
input->columnData->info = createColumnInfo(0, type, bytes);
- colInfoDataEnsureCapacity(input->columnData, 0, num);
+ colInfoDataEnsureCapacity(input->columnData, num);
if (setVal) {
for (int32_t i = 0; i < num; ++i) {
diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6b17cb1066e738e360bd7a8cd2d80c5b0d7def3
--- /dev/null
+++ b/source/libs/scheduler/inc/schInt.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _TD_SCHEDULER_INT_H_
+#define _TD_SCHEDULER_INT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "os.h"
+#include "tarray.h"
+#include "planner.h"
+#include "scheduler.h"
+#include "thash.h"
+#include "trpc.h"
+#include "command.h"
+
+#define SCHEDULE_DEFAULT_MAX_JOB_NUM 1000
+#define SCHEDULE_DEFAULT_MAX_TASK_NUM 1000
+#define SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM 200 // unit is TSDB_TABLE_NUM_UNIT
+
+#define SCH_DEFAULT_TASK_TIMEOUT_USEC 10000000
+#define SCH_MAX_TASK_TIMEOUT_USEC 60000000
+
+#define SCH_MAX_CANDIDATE_EP_NUM TSDB_MAX_REPLICA
+
+enum {
+ SCH_READ = 1,
+ SCH_WRITE,
+};
+
+enum {
+ SCH_EXEC_CB = 1,
+ SCH_FETCH_CB,
+};
+
+typedef enum {
+ SCH_OP_NULL = 0,
+ SCH_OP_EXEC,
+ SCH_OP_FETCH,
+ SCH_OP_GET_STATUS,
+} SCH_OP_TYPE;
+
+typedef struct SSchDebug {
+ bool lockEnable;
+ bool apiEnable;
+} SSchDebug;
+
+typedef struct SSchTrans {
+ void *pTrans;
+ void *pHandle;
+} SSchTrans;
+
+typedef struct SSchHbTrans {
+ SRWLatch lock;
+ int64_t taskNum;
+ SRpcCtx rpcCtx;
+ SSchTrans trans;
+} SSchHbTrans;
+
+typedef struct SSchApiStat {
+
+#if defined(WINDOWS) || defined(_TD_DARWIN_64)
+ size_t avoidCompilationErrors;
+#endif
+
+} SSchApiStat;
+
+typedef struct SSchRuntimeStat {
+
+#if defined(WINDOWS) || defined(_TD_DARWIN_64)
+ size_t avoidCompilationErrors;
+#endif
+
+} SSchRuntimeStat;
+
+typedef struct SSchJobStat {
+
+#if defined(WINDOWS) || defined(_TD_DARWIN_64)
+ size_t avoidCompilationErrors;
+#endif
+
+} SSchJobStat;
+
+typedef struct SSchStat {
+ SSchApiStat api;
+ SSchRuntimeStat runtime;
+ SSchJobStat job;
+} SSchStat;
+
+typedef struct SSchResInfo {
+ SExecResult* execRes;
+ void** fetchRes;
+ schedulerExecFp execFp;
+ schedulerFetchFp fetchFp;
+ void* cbParam;
+} SSchResInfo;
+
+typedef struct SSchOpEvent {
+ SCH_OP_TYPE type;
+ bool begin;
+ SSchedulerReq *pReq;
+} SSchOpEvent;
+
+typedef int32_t (*schStatusEnterFp)(void* pHandle, void* pParam);
+typedef int32_t (*schStatusLeaveFp)(void* pHandle, void* pParam);
+typedef int32_t (*schStatusEventFp)(void* pHandle, void* pParam, void* pEvent);
+
+typedef struct SSchStatusFps {
+ EJobTaskType status;
+ schStatusEnterFp enterFp;
+ schStatusLeaveFp leaveFp;
+ schStatusEventFp eventFp;
+} SSchStatusFps;
+
+typedef struct SSchedulerMgmt {
+ uint64_t taskId; // sequential taksId
+ uint64_t sId; // schedulerId
+ SSchedulerCfg cfg;
+ bool exit;
+ int32_t jobRef;
+ int32_t jobNum;
+ SSchStat stat;
+ SRWLatch hbLock;
+ SHashObj *hbConnections;
+} SSchedulerMgmt;
+
+typedef struct SSchCallbackParamHeader {
+ bool isHbParam;
+} SSchCallbackParamHeader;
+
+typedef struct SSchTaskCallbackParam {
+ SSchCallbackParamHeader head;
+ uint64_t queryId;
+ int64_t refId;
+ uint64_t taskId;
+ int32_t execId;
+ void *pTrans;
+} SSchTaskCallbackParam;
+
+typedef struct SSchHbCallbackParam {
+ SSchCallbackParamHeader head;
+ SQueryNodeEpId nodeEpId;
+ void *pTrans;
+} SSchHbCallbackParam;
+
+typedef struct SSchFlowControl {
+ SRWLatch lock;
+ bool sorted;
+ int32_t tableNumSum;
+ uint32_t execTaskNum;
+ SArray *taskList; // Element is SSchTask*
+} SSchFlowControl;
+
+typedef struct SSchNodeInfo {
+ SQueryNodeAddr addr;
+ void *handle;
+} SSchNodeInfo;
+
+typedef struct SSchLevel {
+ int32_t level;
+ int8_t status;
+ SRWLatch lock;
+ int32_t taskFailed;
+ int32_t taskSucceed;
+ int32_t taskNum;
+ int32_t taskLaunchedNum;
+ int32_t taskDoneNum;
+ SArray *subTasks; // Element is SSchTask
+} SSchLevel;
+
+typedef struct SSchTaskProfile {
+ int64_t startTs;
+ int64_t* execTime;
+ int64_t waitTime;
+ int64_t endTs;
+} SSchTaskProfile;
+
+typedef struct SSchTask {
+ uint64_t taskId; // task id
+ SRWLatch lock; // task reentrant lock
+ int32_t maxExecTimes; // task may exec times
+ int32_t execId; // task current execute try index
+ SSchLevel *level; // level
+ SRWLatch planLock; // task update plan lock
+ SSubplan *plan; // subplan
+ char *msg; // operator tree
+ int32_t msgLen; // msg length
+ int8_t status; // task status
+ int32_t lastMsgType; // last sent msg type
+ int64_t timeoutUsec; // taks timeout useconds before reschedule
+ SQueryNodeAddr succeedAddr; // task executed success node address
+ int8_t candidateIdx; // current try condidation index
+ SArray *candidateAddrs; // condidate node addresses, element is SQueryNodeAddr
+ SHashObj *execNodes; // all tried node for current task, element is SSchNodeInfo
+ SSchTaskProfile profile; // task execution profile
+ int32_t childReady; // child task ready number
+ SArray *children; // the datasource tasks,from which to fetch the result, element is SQueryTask*
+ SArray *parents; // the data destination tasks, get data from current task, element is SQueryTask*
+ void* handle; // task send handle
+ bool registerdHb; // registered in hb
+} SSchTask;
+
+typedef struct SSchJobAttr {
+ EExplainMode explainMode;
+ bool queryJob;
+ bool needFetch;
+ bool needFlowCtrl;
+} SSchJobAttr;
+
+typedef struct {
+ int32_t op;
+ SRWLatch lock;
+ bool syncReq;
+} SSchOpStatus;
+
+typedef struct SSchJob {
+ int64_t refId;
+ uint64_t queryId;
+ SSchJobAttr attr;
+ int32_t levelNum;
+ int32_t taskNum;
+ SRequestConnInfo conn;
+ SArray *nodeList; // qnode/vnode list, SArray
+ SArray *levels; // starting from 0. SArray
+ SQueryPlan *pDag;
+
+ SArray *dataSrcTasks; // SArray
+ int32_t levelIdx;
+ SEpSet dataSrcEps;
+ SHashObj *taskList;
+ SHashObj *execTasks; // executing and executed tasks, key:taskid, value:SQueryTask*
+ SHashObj *flowCtrl; // key is ep, element is SSchFlowControl
+
+ SExplainCtx *explainCtx;
+ int8_t status;
+ SQueryNodeAddr resNode;
+ tsem_t rspSem;
+ SSchOpStatus opStatus;
+ schedulerChkKillFp chkKillFp;
+ void* chkKillParam;
+ SSchTask *fetchTask;
+ int32_t errCode;
+ SRWLatch resLock;
+ SExecResult execRes;
+ void *resData; //TODO free it or not
+ int32_t resNumOfRows;
+ SSchResInfo userRes;
+ const char *sql;
+ SQueryProfileSummary summary;
+} SSchJob;
+
+extern SSchedulerMgmt schMgmt;
+
+#define SCH_TASK_TIMEOUT(_task) ((taosGetTimestampUs() - (_task)->profile.execTime[(_task)->execId % (_task)->maxExecTimes]) > (_task)->timeoutUsec)
+
+#define SCH_TASK_READY_FOR_LAUNCH(readyNum, task) ((readyNum) >= taosArrayGetSize((task)->children))
+
+#define SCH_LOCK_TASK(_task) SCH_LOCK(SCH_WRITE, &(_task)->lock)
+#define SCH_UNLOCK_TASK(_task) SCH_UNLOCK(SCH_WRITE, &(_task)->lock)
+
+#define SCH_TASK_ID(_task) ((_task) ? (_task)->taskId : -1)
+#define SCH_TASK_EID(_task) ((_task) ? (_task)->execId : -1)
+
+#define SCH_IS_DATA_BIND_QRY_TASK(task) ((task)->plan->subplanType == SUBPLAN_TYPE_SCAN)
+#define SCH_IS_DATA_BIND_TASK(task) (((task)->plan->subplanType == SUBPLAN_TYPE_SCAN) || ((task)->plan->subplanType == SUBPLAN_TYPE_MODIFY))
+#define SCH_IS_LEAF_TASK(_job, _task) (((_task)->level->level + 1) == (_job)->levelNum)
+
+#define SCH_SET_TASK_STATUS(task, st) atomic_store_8(&(task)->status, st)
+#define SCH_GET_TASK_STATUS(task) atomic_load_8(&(task)->status)
+#define SCH_GET_TASK_STATUS_STR(task) jobTaskStatusStr(SCH_GET_TASK_STATUS(task))
+
+#define SCH_GET_TASK_HANDLE(_task) ((_task) ? (_task)->handle : NULL)
+#define SCH_SET_TASK_HANDLE(_task, _handle) ((_task)->handle = (_handle))
+
+#define SCH_SET_JOB_STATUS(job, st) atomic_store_8(&(job)->status, st)
+#define SCH_GET_JOB_STATUS(job) atomic_load_8(&(job)->status)
+#define SCH_GET_JOB_STATUS_STR(job) jobTaskStatusStr(SCH_GET_JOB_STATUS(job))
+
+#define SCH_JOB_IN_SYNC_OP(job) ((job)->opStatus.op && (job)->opStatus.syncReq)
+#define SCH_JOB_IN_ASYNC_EXEC_OP(job) ((SCH_OP_EXEC == atomic_val_compare_exchange_32(&(job)->opStatus.op, SCH_OP_EXEC, SCH_OP_NULL)) && (!(job)->opStatus.syncReq))
+#define SCH_JOB_IN_ASYNC_FETCH_OP(job) ((SCH_OP_FETCH == atomic_val_compare_exchange_32(&(job)->opStatus.op, SCH_OP_FETCH, SCH_OP_NULL)) && (!(job)->opStatus.syncReq))
+
+#define SCH_SET_JOB_NEED_FLOW_CTRL(_job) (_job)->attr.needFlowCtrl = true
+#define SCH_JOB_NEED_FLOW_CTRL(_job) ((_job)->attr.needFlowCtrl)
+#define SCH_TASK_NEED_FLOW_CTRL(_job, _task) (SCH_IS_DATA_BIND_QRY_TASK(_task) && SCH_JOB_NEED_FLOW_CTRL(_job) && SCH_IS_LEVEL_UNFINISHED((_task)->level))
+#define SCH_FETCH_TYPE(_pSrcTask) (SCH_IS_DATA_BIND_QRY_TASK(_pSrcTask) ? TDMT_SCH_FETCH : TDMT_SCH_MERGE_FETCH)
+#define SCH_TASK_NEED_FETCH(_task) ((_task)->plan->subplanType != SUBPLAN_TYPE_MODIFY)
+#define SCH_TASK_MAX_EXEC_TIMES(_levelIdx, _levelNum) (SCH_MAX_CANDIDATE_EP_NUM * ((_levelNum) - (_levelIdx)))
+
+#define SCH_SET_JOB_TYPE(_job, type) do { if ((type) != SUBPLAN_TYPE_MODIFY) { (_job)->attr.queryJob = true; } } while (0)
+#define SCH_IS_QUERY_JOB(_job) ((_job)->attr.queryJob)
+#define SCH_JOB_NEED_FETCH(_job) ((_job)->attr.needFetch)
+#define SCH_JOB_NEED_WAIT(_job) (!SCH_IS_QUERY_JOB(_job))
+#define SCH_JOB_NEED_DROP(_job) (SCH_IS_QUERY_JOB(_job))
+#define SCH_IS_EXPLAIN_JOB(_job) (EXPLAIN_MODE_ANALYZE == (_job)->attr.explainMode)
+#define SCH_NETWORK_ERR(_code) ((_code) == TSDB_CODE_RPC_BROKEN_LINK || (_code) == TSDB_CODE_RPC_NETWORK_UNAVAIL)
+#define SCH_MERGE_TASK_NETWORK_ERR(_task, _code, _len) (SCH_NETWORK_ERR(_code) && (((_len) > 0) || (!SCH_IS_DATA_BIND_TASK(_task))))
+#define SCH_REDIRECT_MSGTYPE(_msgType) ((_msgType) == TDMT_SCH_QUERY || (_msgType) == TDMT_SCH_MERGE_QUERY || (_msgType) == TDMT_SCH_FETCH || (_msgType) == TDMT_SCH_MERGE_FETCH)
+#define SCH_TASK_NEED_REDIRECT(_task, _msgType, _code, _rspLen) (SCH_REDIRECT_MSGTYPE(_msgType) && (NEED_SCHEDULER_REDIRECT_ERROR(_code) || SCH_MERGE_TASK_NETWORK_ERR((_task), (_code), (_rspLen))))
+#define SCH_NEED_RETRY(_msgType, _code) ((SCH_NETWORK_ERR(_code) && SCH_REDIRECT_MSGTYPE(_msgType)) || (_code) == TSDB_CODE_SCH_TIMEOUT_ERROR)
+
+#define SCH_IS_LEVEL_UNFINISHED(_level) ((_level)->taskLaunchedNum < (_level)->taskNum)
+#define SCH_GET_CUR_EP(_addr) (&(_addr)->epSet.eps[(_addr)->epSet.inUse])
+#define SCH_SWITCH_EPSET(_addr) ((_addr)->epSet.inUse = ((_addr)->epSet.inUse + 1) % (_addr)->epSet.numOfEps)
+#define SCH_TASK_NUM_OF_EPS(_addr) ((_addr)->epSet.numOfEps)
+
+#define SCH_LOG_TASK_START_TS(_task) \
+ do { \
+ int64_t us = taosGetTimestampUs(); \
+ int32_t idx = (_task)->execId % (_task)->maxExecTimes; \
+ (_task)->profile.execTime[idx] = us; \
+ if (0 == (_task)->execId) { \
+ (_task)->profile.startTs = us; \
+ } \
+ } while (0)
+
+#define SCH_LOG_TASK_WAIT_TS(_task) \
+ do { \
+ int64_t us = taosGetTimestampUs(); \
+ int32_t idx = (_task)->execId % (_task)->maxExecTimes; \
+ (_task)->profile.waitTime += us - (_task)->profile.execTime[idx]; \
+ } while (0)
+
+
+#define SCH_LOG_TASK_END_TS(_task) \
+ do { \
+ int64_t us = taosGetTimestampUs(); \
+ int32_t idx = (_task)->execId % (_task)->maxExecTimes; \
+ (_task)->profile.execTime[idx] = us - (_task)->profile.execTime[idx]; \
+ (_task)->profile.endTs = us; \
+ } while (0)
+
+
+#define SCH_JOB_ELOG(param, ...) qError("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__)
+#define SCH_JOB_DLOG(param, ...) qDebug("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__)
+
+#define SCH_TASK_ELOG(param, ...) \
+ qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_TASK_ID(pTask), SCH_TASK_EID(pTask),__VA_ARGS__)
+#define SCH_TASK_DLOG(param, ...) \
+ qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_TASK_ID(pTask), SCH_TASK_EID(pTask),__VA_ARGS__)
+#define SCH_TASK_DLOGL(param, ...) \
+ qDebugL("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_TASK_ID(pTask), SCH_TASK_EID(pTask),__VA_ARGS__)
+#define SCH_TASK_WLOG(param, ...) \
+ qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_TASK_ID(pTask), SCH_TASK_EID(pTask),__VA_ARGS__)
+
+#define SCH_SET_ERRNO(_err) do { if (TSDB_CODE_SCH_IGNORE_ERROR != (_err)) { terrno = (_err); } } while (0)
+#define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); return _code; } } while (0)
+#define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); } return _code; } while (0)
+#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(code); goto _return; } } while (0)
+
+#define SCH_LOCK_DEBUG(...) do { if (gSCHDebug.lockEnable) { qDebug(__VA_ARGS__); } } while (0)
+
+#define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000
+
+#define SCH_LOCK(type, _lock) do { \
+ if (SCH_READ == (type)) { \
+ assert(atomic_load_32(_lock) >= 0); \
+ SCH_LOCK_DEBUG("SCH RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ taosRLockLatch(_lock); \
+ SCH_LOCK_DEBUG("SCH RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ assert(atomic_load_32(_lock) > 0); \
+ } else { \
+ assert(atomic_load_32(_lock) >= 0); \
+ SCH_LOCK_DEBUG("SCH WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ taosWLockLatch(_lock); \
+ SCH_LOCK_DEBUG("SCH WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ assert(atomic_load_32(_lock) == TD_RWLATCH_WRITE_FLAG_COPY); \
+ } \
+} while (0)
+
+#define SCH_UNLOCK(type, _lock) do { \
+ if (SCH_READ == (type)) { \
+ assert(atomic_load_32((_lock)) > 0); \
+ SCH_LOCK_DEBUG("SCH RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ taosRUnLockLatch(_lock); \
+ SCH_LOCK_DEBUG("SCH RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ assert(atomic_load_32((_lock)) >= 0); \
+ } else { \
+ assert(atomic_load_32((_lock)) & TD_RWLATCH_WRITE_FLAG_COPY); \
+ SCH_LOCK_DEBUG("SCH WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ taosWUnLockLatch(_lock); \
+ SCH_LOCK_DEBUG("SCH WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \
+ assert(atomic_load_32((_lock)) >= 0); \
+ } \
+} while (0)
+
+
+void schDeregisterTaskHb(SSchJob *pJob, SSchTask *pTask);
+void schCleanClusterHb(void* pTrans);
+int32_t schLaunchTask(SSchJob *job, SSchTask *task);
+int32_t schBuildAndSendMsg(SSchJob *job, SSchTask *task, SQueryNodeAddr *addr, int32_t msgType);
+SSchJob *schAcquireJob(int64_t refId);
+int32_t schReleaseJob(int64_t refId);
+void schFreeFlowCtrl(SSchJob *pJob);
+int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel);
+int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask);
+int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough);
+int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask);
+int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask);
+int32_t schLaunchFetchTask(SSchJob *pJob);
+int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode);
+int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray* taskAction);
+int32_t schCloneSMsgSendInfo(void *src, void **dst);
+int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob);
+void schFreeJobImpl(void *job);
+int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx);
+int32_t schEnsureHbConnection(SSchJob *pJob, SSchTask *pTask);
+int32_t schUpdateHbConnection(SQueryNodeEpId *epId, SSchTrans *trans);
+int32_t schHandleHbCallback(void *param, SDataBuf *pMsg, int32_t code);
+void schFreeRpcCtx(SRpcCtx *pCtx);
+int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp);
+bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus);
+int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask);
+int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp);
+int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp);
+void schProcessOnDataFetched(SSchJob *job);
+int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask);
+void schFreeRpcCtxVal(const void *arg);
+int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb);
+int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execId);
+int32_t schExecStaticExplainJob(SSchedulerReq *pReq, int64_t *job, bool sync);
+int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus);
+int32_t schCancelJob(SSchJob *pJob);
+int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode);
+uint64_t schGenTaskId(void);
+void schCloseJobRef(void);
+int32_t schAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob);
+int32_t schJobFetchRows(SSchJob *pJob);
+int32_t schJobFetchRowsA(SSchJob *pJob);
+int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId);
+int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList);
+void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo);
+char* schGetOpStr(SCH_OP_TYPE type);
+int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync);
+int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq);
+int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq);
+int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes);
+int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet);
+int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode);
+void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode);
+int32_t schProcessOnOpBegin(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq);
+void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode);
+int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_t rId, uint64_t tId);
+void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask);
+bool schJobDone(SSchJob *pJob);
+int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask);
+int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask);
+int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param);
+int32_t schHandleOpBeginEvent(int64_t jobId, SSchJob** job, SCH_OP_TYPE type, SSchedulerReq* pReq);
+int32_t schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode);
+int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask);
+void schUpdateJobErrCode(SSchJob *pJob, int32_t errCode);
+int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry);
+int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode);
+int32_t schProcessOnJobPartialSuccess(SSchJob *pJob);
+void schFreeTask(SSchJob *pJob, SSchTask *pTask);
+void schDropTaskInHashList(SSchJob *pJob, SHashObj *list);
+int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level);
+int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask);
+int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel, int32_t levelNum);
+int32_t schSwitchTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask);
+void schDirectPostJobRes(SSchedulerReq* pReq, int32_t errCode);
+bool schChkCurrentOp(SSchJob *pJob, int32_t op, bool sync);
+
+extern SSchDebug gSCHDebug;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_SCHEDULER_INT_H_*/
diff --git a/source/libs/scheduler/inc/schedulerInt.h b/source/libs/scheduler/inc/schedulerInt.h
deleted file mode 100644
index 6b2570c5b70132032c7df84107aa2b294b79233a..0000000000000000000000000000000000000000
--- a/source/libs/scheduler/inc/schedulerInt.h
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _TD_SCHEDULER_INT_H_
-#define _TD_SCHEDULER_INT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "os.h"
-#include "tarray.h"
-#include "planner.h"
-#include "scheduler.h"
-#include "thash.h"
-#include "trpc.h"
-#include "command.h"
-
-#define SCHEDULE_DEFAULT_MAX_JOB_NUM 1000
-#define SCHEDULE_DEFAULT_MAX_TASK_NUM 1000
-#define SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM 200 // unit is TSDB_TABLE_NUM_UNIT
-
-#define SCH_DEFAULT_TASK_TIMEOUT_USEC 10000000
-#define SCH_MAX_TASK_TIMEOUT_USEC 60000000
-
-#define SCH_TASK_MAX_EXEC_TIMES 5
-#define SCH_MAX_CANDIDATE_EP_NUM TSDB_MAX_REPLICA
-
-enum {
- SCH_READ = 1,
- SCH_WRITE,
-};
-
-enum {
- SCH_EXEC_CB = 1,
- SCH_FETCH_CB,
-};
-
-typedef enum {
- SCH_OP_NULL = 0,
- SCH_OP_EXEC,
- SCH_OP_FETCH,
-} SCH_OP_TYPE;
-
-typedef struct SSchTrans {
- void *pTrans;
- void *pHandle;
-} SSchTrans;
-
-typedef struct SSchHbTrans {
- SRWLatch lock;
- int64_t taskNum;
- SRpcCtx rpcCtx;
- SSchTrans trans;
-} SSchHbTrans;
-
-typedef struct SSchApiStat {
-
-#ifdef WINDOWS
- size_t avoidCompilationErrors;
-#endif
-
-} SSchApiStat;
-
-typedef struct SSchRuntimeStat {
-
-#ifdef WINDOWS
- size_t avoidCompilationErrors;
-#endif
-
-} SSchRuntimeStat;
-
-typedef struct SSchJobStat {
-
-#ifdef WINDOWS
- size_t avoidCompilationErrors;
-#endif
-
-} SSchJobStat;
-
-typedef struct SSchStat {
- SSchApiStat api;
- SSchRuntimeStat runtime;
- SSchJobStat job;
-} SSchStat;
-
-typedef struct SSchResInfo {
- SQueryResult* queryRes;
- void** fetchRes;
- schedulerExecCallback execFp;
- schedulerFetchCallback fetchFp;
- void* userParam;
-} SSchResInfo;
-
-typedef struct SSchedulerMgmt {
- uint64_t taskId; // sequential taksId
- uint64_t sId; // schedulerId
- SSchedulerCfg cfg;
- bool exit;
- int32_t jobRef;
- int32_t jobNum;
- SSchStat stat;
- SRWLatch hbLock;
- SHashObj *hbConnections;
-} SSchedulerMgmt;
-
-typedef struct SSchCallbackParamHeader {
- bool isHbParam;
-} SSchCallbackParamHeader;
-
-typedef struct SSchTaskCallbackParam {
- SSchCallbackParamHeader head;
- uint64_t queryId;
- int64_t refId;
- uint64_t taskId;
- int32_t execIdx;
- void *pTrans;
-} SSchTaskCallbackParam;
-
-typedef struct SSchHbCallbackParam {
- SSchCallbackParamHeader head;
- SQueryNodeEpId nodeEpId;
- void *pTrans;
-} SSchHbCallbackParam;
-
-typedef struct SSchFlowControl {
- SRWLatch lock;
- bool sorted;
- int32_t tableNumSum;
- uint32_t execTaskNum;
- SArray *taskList; // Element is SSchTask*
-} SSchFlowControl;
-
-typedef struct SSchNodeInfo {
- SQueryNodeAddr addr;
- void *handle;
-} SSchNodeInfo;
-
-typedef struct SSchLevel {
- int32_t level;
- int8_t status;
- SRWLatch lock;
- int32_t taskFailed;
- int32_t taskSucceed;
- int32_t taskNum;
- int32_t taskLaunchedNum;
- int32_t taskDoneNum;
- SArray *subTasks; // Element is SQueryTask
-} SSchLevel;
-
-typedef struct SSchTaskProfile {
- int64_t startTs;
- int64_t execUseTime[SCH_TASK_MAX_EXEC_TIMES];
- int64_t waitTime;
- int64_t endTs;
-} SSchTaskProfile;
-
-typedef struct SSchTask {
- uint64_t taskId; // task id
- SRWLatch lock; // task lock
- int32_t maxExecTimes; // task may exec times
- int32_t execIdx; // task current execute try index
- SSchLevel *level; // level
- SRWLatch planLock; // task update plan lock
- SSubplan *plan; // subplan
- char *msg; // operator tree
- int32_t msgLen; // msg length
- int8_t status; // task status
- int32_t lastMsgType; // last sent msg type
- int64_t timeoutUsec; // taks timeout useconds before reschedule
- SQueryNodeAddr succeedAddr; // task executed success node address
- int8_t candidateIdx; // current try condidation index
- SArray *candidateAddrs; // condidate node addresses, element is SQueryNodeAddr
- SHashObj *execNodes; // all tried node for current task, element is SSchNodeInfo
- SSchTaskProfile profile; // task execution profile
- int32_t childReady; // child task ready number
- SArray *children; // the datasource tasks,from which to fetch the result, element is SQueryTask*
- SArray *parents; // the data destination tasks, get data from current task, element is SQueryTask*
- void* handle; // task send handle
- bool registerdHb; // registered in hb
-} SSchTask;
-
-typedef struct SSchJobAttr {
- EExplainMode explainMode;
- bool queryJob;
- bool needFlowCtrl;
-} SSchJobAttr;
-
-typedef struct {
- int32_t op;
- bool sync;
-} SSchOpStatus;
-
-typedef struct SSchJob {
- int64_t refId;
- uint64_t queryId;
- SSchJobAttr attr;
- int32_t levelNum;
- int32_t taskNum;
- SRequestConnInfo conn;
- SArray *nodeList; // qnode/vnode list, SArray
- SArray *levels; // starting from 0. SArray
- SNodeList *subPlans; // subplan pointer copied from DAG, no need to free it in scheduler
-
- SArray *dataSrcTasks; // SArray
- int32_t levelIdx;
- SEpSet dataSrcEps;
- SHashObj *taskList;
- SHashObj *execTasks; // executing tasks, key:taskid, value:SQueryTask*
- SHashObj *succTasks; // succeed tasks, key:taskid, value:SQueryTask*
- SHashObj *failTasks; // failed tasks, key:taskid, value:SQueryTask*
- SHashObj *flowCtrl; // key is ep, element is SSchFlowControl
-
- SExplainCtx *explainCtx;
- int8_t status;
- SQueryNodeAddr resNode;
- tsem_t rspSem;
- SSchOpStatus opStatus;
- bool *reqKilled;
- SSchTask *fetchTask;
- int32_t errCode;
- SRWLatch resLock;
- SQueryExecRes execRes;
- void *resData; //TODO free it or not
- int32_t resNumOfRows;
- SSchResInfo userRes;
- const char *sql;
- SQueryProfileSummary summary;
-} SSchJob;
-
-extern SSchedulerMgmt schMgmt;
-
-#define SCH_LOG_TASK_START_TS(_task) \
- do { \
- int64_t us = taosGetTimestampUs(); \
- int32_t idx = (_task)->execIdx % SCH_TASK_MAX_EXEC_TIMES; \
- (_task)->profile.execUseTime[idx] = us; \
- if (0 == (_task)->execIdx) { \
- (_task)->profile.startTs = us; \
- } \
- } while (0)
-
-#define SCH_LOG_TASK_WAIT_TS(_task) \
- do { \
- int64_t us = taosGetTimestampUs(); \
- int32_t idx = (_task)->execIdx % SCH_TASK_MAX_EXEC_TIMES; \
- (_task)->profile.waitTime += us - (_task)->profile.execUseTime[idx]; \
- } while (0)
-
-
-#define SCH_LOG_TASK_END_TS(_task) \
- do { \
- int64_t us = taosGetTimestampUs(); \
- int32_t idx = (_task)->execIdx % SCH_TASK_MAX_EXEC_TIMES; \
- (_task)->profile.execUseTime[idx] = us - (_task)->profile.execUseTime[idx]; \
- (_task)->profile.endTs = us; \
- } while (0)
-
-#define SCH_TASK_TIMEOUT(_task) ((taosGetTimestampUs() - (_task)->profile.execUseTime[(_task)->execIdx % SCH_TASK_MAX_EXEC_TIMES]) > (_task)->timeoutUsec)
-
-#define SCH_TASK_READY_FOR_LAUNCH(readyNum, task) ((readyNum) >= taosArrayGetSize((task)->children))
-
-#define SCH_LOCK_TASK(_task) SCH_LOCK(SCH_WRITE, &(_task)->lock)
-#define SCH_UNLOCK_TASK(_task) SCH_UNLOCK(SCH_WRITE, &(_task)->lock)
-
-#define SCH_TASK_ID(_task) ((_task) ? (_task)->taskId : -1)
-#define SCH_SET_TASK_LASTMSG_TYPE(_task, _type) do { if(_task) { atomic_store_32(&(_task)->lastMsgType, _type); } } while (0)
-#define SCH_GET_TASK_LASTMSG_TYPE(_task) ((_task) ? atomic_load_32(&(_task)->lastMsgType) : -1)
-
-#define SCH_IS_DATA_SRC_QRY_TASK(task) ((task)->plan->subplanType == SUBPLAN_TYPE_SCAN)
-#define SCH_IS_DATA_SRC_TASK(task) (((task)->plan->subplanType == SUBPLAN_TYPE_SCAN) || ((task)->plan->subplanType == SUBPLAN_TYPE_MODIFY))
-#define SCH_IS_LEAF_TASK(_job, _task) (((_task)->level->level + 1) == (_job)->levelNum)
-
-#define SCH_SET_TASK_STATUS(task, st) atomic_store_8(&(task)->status, st)
-#define SCH_GET_TASK_STATUS(task) atomic_load_8(&(task)->status)
-#define SCH_GET_TASK_STATUS_STR(task) jobTaskStatusStr(SCH_GET_TASK_STATUS(task))
-
-#define SCH_GET_TASK_HANDLE(_task) ((_task) ? (_task)->handle : NULL)
-#define SCH_SET_TASK_HANDLE(_task, _handle) ((_task)->handle = (_handle))
-
-#define SCH_SET_JOB_STATUS(job, st) atomic_store_8(&(job)->status, st)
-#define SCH_GET_JOB_STATUS(job) atomic_load_8(&(job)->status)
-#define SCH_GET_JOB_STATUS_STR(job) jobTaskStatusStr(SCH_GET_JOB_STATUS(job))
-
-#define SCH_JOB_IN_SYNC_OP(job) ((job)->opStatus.op && (job)->opStatus.sync)
-#define SCH_JOB_IN_ASYNC_EXEC_OP(job) (((job)->opStatus.op == SCH_OP_EXEC) && (!(job)->opStatus.sync))
-#define SCH_JOB_IN_ASYNC_FETCH_OP(job) (((job)->opStatus.op == SCH_OP_FETCH) && (!(job)->opStatus.sync))
-
-#define SCH_SET_JOB_NEED_FLOW_CTRL(_job) (_job)->attr.needFlowCtrl = true
-#define SCH_JOB_NEED_FLOW_CTRL(_job) ((_job)->attr.needFlowCtrl)
-#define SCH_TASK_NEED_FLOW_CTRL(_job, _task) (SCH_IS_DATA_SRC_QRY_TASK(_task) && SCH_JOB_NEED_FLOW_CTRL(_job) && SCH_IS_LEVEL_UNFINISHED((_task)->level))
-
-#define SCH_SET_JOB_TYPE(_job, type) (_job)->attr.queryJob = ((type) != SUBPLAN_TYPE_MODIFY)
-#define SCH_IS_QUERY_JOB(_job) ((_job)->attr.queryJob)
-#define SCH_JOB_NEED_FETCH(_job) SCH_IS_QUERY_JOB(_job)
-#define SCH_IS_WAIT_ALL_JOB(_job) (!SCH_IS_QUERY_JOB(_job))
-#define SCH_IS_NEED_DROP_JOB(_job) (SCH_IS_QUERY_JOB(_job))
-#define SCH_IS_EXPLAIN_JOB(_job) (EXPLAIN_MODE_ANALYZE == (_job)->attr.explainMode)
-
-#define SCH_IS_LEVEL_UNFINISHED(_level) ((_level)->taskLaunchedNum < (_level)->taskNum)
-#define SCH_GET_CUR_EP(_addr) (&(_addr)->epSet.eps[(_addr)->epSet.inUse])
-#define SCH_SWITCH_EPSET(_addr) ((_addr)->epSet.inUse = ((_addr)->epSet.inUse + 1) % (_addr)->epSet.numOfEps)
-#define SCH_TASK_NUM_OF_EPS(_addr) ((_addr)->epSet.numOfEps)
-
-#define SCH_JOB_ELOG(param, ...) qError("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__)
-#define SCH_JOB_DLOG(param, ...) qDebug("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__)
-
-#define SCH_TASK_ELOG(param, ...) \
- qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__)
-#define SCH_TASK_DLOG(param, ...) \
- qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__)
-#define SCH_TASK_DLOGL(param, ...) \
- qDebugL("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__)
-#define SCH_TASK_WLOG(param, ...) \
- qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__)
-
-#define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0)
-#define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
-#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
-
-#define SCH_LOCK(type, _lock) (SCH_READ == (type) ? taosRLockLatch(_lock) : taosWLockLatch(_lock))
-#define SCH_UNLOCK(type, _lock) (SCH_READ == (type) ? taosRUnLockLatch(_lock) : taosWUnLockLatch(_lock))
-
-
-void schDeregisterTaskHb(SSchJob *pJob, SSchTask *pTask);
-void schCleanClusterHb(void* pTrans);
-int32_t schLaunchTask(SSchJob *job, SSchTask *task);
-int32_t schBuildAndSendMsg(SSchJob *job, SSchTask *task, SQueryNodeAddr *addr, int32_t msgType);
-SSchJob *schAcquireJob(int64_t refId);
-int32_t schReleaseJob(int64_t refId);
-void schFreeFlowCtrl(SSchJob *pJob);
-int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel);
-int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask);
-int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough);
-int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask);
-int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask);
-int32_t schFetchFromRemote(SSchJob *pJob);
-int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode);
-int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray* taskAction);
-int32_t schCloneSMsgSendInfo(void *src, void **dst);
-int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob);
-void schFreeJobImpl(void *job);
-int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx);
-int32_t schEnsureHbConnection(SSchJob *pJob, SSchTask *pTask);
-int32_t schUpdateHbConnection(SQueryNodeEpId *epId, SSchTrans *trans);
-int32_t schHandleHbCallback(void *param, const SDataBuf *pMsg, int32_t code);
-void schFreeRpcCtx(SRpcCtx *pCtx);
-int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp);
-bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus);
-int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask);
-int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp);
-int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp);
-void schProcessOnDataFetched(SSchJob *job);
-int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask);
-void schFreeRpcCtxVal(const void *arg);
-int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb);
-int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execIdx);
-int32_t schExecStaticExplainJob(SSchedulerReq *pReq, int64_t *job, bool sync);
-int32_t schExecJobImpl(SSchedulerReq *pReq, int64_t *job, SQueryResult* pRes, bool sync);
-int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus);
-int32_t schCancelJob(SSchJob *pJob);
-int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode);
-uint64_t schGenTaskId(void);
-void schCloseJobRef(void);
-int32_t schExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes);
-int32_t schAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob);
-int32_t schFetchRows(SSchJob *pJob);
-int32_t schAsyncFetchRows(SSchJob *pJob);
-int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execIdx);
-int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList);
-void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo);
-char* schGetOpStr(SCH_OP_TYPE type);
-int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_TD_SCHEDULER_INT_H_*/
diff --git a/source/libs/scheduler/src/schDbg.c b/source/libs/scheduler/src/schDbg.c
index 5c0c6fbb76974f87e06b5ba1cbcb761b864fd163..a6398522d3358a5867fae171f90a1e5d5fb30077 100644
--- a/source/libs/scheduler/src/schDbg.c
+++ b/source/libs/scheduler/src/schDbg.c
@@ -14,16 +14,17 @@
*/
#include "query.h"
-#include "schedulerInt.h"
+#include "schInt.h"
tsem_t schdRspSem;
+SSchDebug gSCHDebug = {0};
-void schdExecCallback(SQueryResult* pResult, void* param, int32_t code) {
+void schdExecCallback(SExecResult* pResult, void* param, int32_t code) {
if (code) {
pResult->code = code;
}
- *(SQueryResult*)param = *pResult;
+ *(SExecResult*)param = *pResult;
taosMemoryFree(pResult);
diff --git a/source/libs/scheduler/src/schFlowCtrl.c b/source/libs/scheduler/src/schFlowCtrl.c
index 85d205f5f2eba00a2f6bd741b891b26f30488d05..6b34a394b6751b04af22c5c6fbaea314805b86b2 100644
--- a/source/libs/scheduler/src/schFlowCtrl.c
+++ b/source/libs/scheduler/src/schFlowCtrl.c
@@ -13,7 +13,7 @@
* along with this program. If not, see .
*/
-#include "schedulerInt.h"
+#include "schInt.h"
#include "tmsg.h"
#include "query.h"
#include "catalog.h"
diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c
index 72809e1f93f7cc827ce41036ba5ed5dcf8734e86..19bb93249f50d22bb535e25654fc93bbab11a981 100644
--- a/source/libs/scheduler/src/schJob.c
+++ b/source/libs/scheduler/src/schJob.c
@@ -16,146 +16,11 @@
#include "catalog.h"
#include "command.h"
#include "query.h"
-#include "schedulerInt.h"
+#include "schInt.h"
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
-FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { qDebug("sch acquire jobId:0x%"PRIx64, refId); return (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId); }
-
-FORCE_INLINE int32_t schReleaseJob(int64_t refId) { qDebug("sch release jobId:0x%"PRIx64, refId); return taosReleaseRef(schMgmt.jobRef, refId); }
-
-int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel) {
- pTask->plan = pPlan;
- pTask->level = pLevel;
- pTask->execIdx = -1;
- pTask->maxExecTimes = SCH_TASK_MAX_EXEC_TIMES;
- pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC;
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START);
- pTask->taskId = schGenTaskId();
- pTask->execNodes = taosHashInit(SCH_MAX_CANDIDATE_EP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
- if (NULL == pTask->execNodes) {
- SCH_TASK_ELOG("taosHashInit %d execNodes failed", SCH_MAX_CANDIDATE_EP_NUM);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schInitJob(SSchedulerReq *pReq, SSchJob **pSchJob, SQueryResult* pRes, bool syncSchedule) {
- int32_t code = 0;
- int64_t refId = -1;
- SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob));
- if (NULL == pJob) {
- qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob));
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- pJob->attr.explainMode = pReq->pDag->explainInfo.mode;
- pJob->conn = *pReq->pConn;
- pJob->sql = pReq->sql;
- pJob->reqKilled = pReq->reqKilled;
- pJob->userRes.queryRes = pRes;
- pJob->userRes.execFp = pReq->fp;
- pJob->userRes.userParam = pReq->cbParam;
-
- if (pReq->pNodeList != NULL) {
- pJob->nodeList = taosArrayDup(pReq->pNodeList);
- }
-
- pJob->taskList =
- taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
- if (NULL == pJob->taskList) {
- SCH_JOB_ELOG("taosHashInit %d taskList failed", pReq->pDag->numOfSubplans);
- SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- SCH_ERR_JRET(schValidateAndBuildJob(pReq->pDag, pJob));
-
- if (SCH_IS_EXPLAIN_JOB(pJob)) {
- SCH_ERR_JRET(qExecExplainBegin(pReq->pDag, &pJob->explainCtx, pReq->startTs));
- }
-
- pJob->execTasks =
- taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
- if (NULL == pJob->execTasks) {
- SCH_JOB_ELOG("taosHashInit %d execTasks failed", pReq->pDag->numOfSubplans);
- SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- pJob->succTasks =
- taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
- if (NULL == pJob->succTasks) {
- SCH_JOB_ELOG("taosHashInit %d succTasks failed", pReq->pDag->numOfSubplans);
- SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- pJob->failTasks =
- taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
- if (NULL == pJob->failTasks) {
- SCH_JOB_ELOG("taosHashInit %d failTasks failed", pReq->pDag->numOfSubplans);
- SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- tsem_init(&pJob->rspSem, 0, 0);
-
- refId = taosAddRef(schMgmt.jobRef, pJob);
- if (refId < 0) {
- SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno));
- SCH_ERR_JRET(terrno);
- }
-
- atomic_add_fetch_32(&schMgmt.jobNum, 1);
-
- if (NULL == schAcquireJob(refId)) {
- SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId);
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- pJob->refId = refId;
-
- SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId);
-
- schUpdateJobStatus(pJob, JOB_TASK_STATUS_NOT_START);
-
- *pSchJob = pJob;
-
- return TSDB_CODE_SUCCESS;
-
-_return:
-
- if (refId < 0) {
- schFreeJobImpl(pJob);
- } else {
- taosRemoveRef(schMgmt.jobRef, refId);
- }
- SCH_RET(code);
-}
-
-
-void schFreeTask(SSchJob *pJob, SSchTask *pTask) {
- schDeregisterTaskHb(pJob, pTask);
-
- if (pTask->candidateAddrs) {
- taosArrayDestroy(pTask->candidateAddrs);
- }
-
- taosMemoryFreeClear(pTask->msg);
-
- if (pTask->children) {
- taosArrayDestroy(pTask->children);
- }
-
- if (pTask->parents) {
- taosArrayDestroy(pTask->parents);
- }
-
- if (pTask->execNodes) {
- taosHashCleanup(pTask->execNodes);
- }
-}
-
-
void schUpdateJobErrCode(SSchJob *pJob, int32_t errCode) {
if (TSDB_CODE_SUCCESS == errCode) {
return;
@@ -186,7 +51,12 @@ _return:
SCH_JOB_DLOG("job errCode updated to %x - %s", errCode, tstrerror(errCode));
}
-
+bool schJobDone(SSchJob *pJob) {
+ int8_t status = SCH_GET_JOB_STATUS(pJob);
+
+ return (status == JOB_TASK_STATUS_FAIL || status == JOB_TASK_STATUS_DROP ||
+ status == JOB_TASK_STATUS_SUCC);
+}
FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) {
int8_t status = SCH_GET_JOB_STATUS(pJob);
@@ -194,15 +64,16 @@ FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) {
*pStatus = status;
}
- if (*pJob->reqKilled) {
- schUpdateJobStatus(pJob, JOB_TASK_STATUS_DROPPING);
- schUpdateJobErrCode(pJob, TSDB_CODE_TSC_QUERY_KILLED);
+ if (schJobDone(pJob)) {
+ return true;
+ }
+ if ((*pJob->chkKillFp)(pJob->chkKillParam)) {
+ schUpdateJobErrCode(pJob, TSDB_CODE_TSC_QUERY_KILLED);
return true;
- }
+ }
- return (status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_DROPPING ||
- status == JOB_TASK_STATUS_SUCCEED);
+ return false;
}
int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) {
@@ -214,48 +85,44 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) {
oriStatus = SCH_GET_JOB_STATUS(pJob);
if (oriStatus == newStatus) {
- if (newStatus == JOB_TASK_STATUS_DROPPING) {
- SCH_ERR_JRET(TSDB_CODE_SCH_JOB_IS_DROPPING);
- }
-
SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR);
}
switch (oriStatus) {
case JOB_TASK_STATUS_NULL:
- if (newStatus != JOB_TASK_STATUS_NOT_START) {
+ if (newStatus != JOB_TASK_STATUS_INIT) {
SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_NOT_START:
- if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_INIT:
+ if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_DROP) {
SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_EXECUTING:
- if (newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED && newStatus != JOB_TASK_STATUS_FAILED &&
- newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_EXEC:
+ if (newStatus != JOB_TASK_STATUS_PART_SUCC && newStatus != JOB_TASK_STATUS_FAIL &&
+ newStatus != JOB_TASK_STATUS_DROP) {
SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_PARTIAL_SUCCEED:
- if (newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_SUCCEED &&
- newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_PART_SUCC:
+ if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_SUCC &&
+ newStatus != JOB_TASK_STATUS_DROP) {
SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_SUCCEED:
- case JOB_TASK_STATUS_FAILED:
- if (newStatus != JOB_TASK_STATUS_DROPPING) {
+ case JOB_TASK_STATUS_SUCC:
+ case JOB_TASK_STATUS_FAIL:
+ if (newStatus != JOB_TASK_STATUS_DROP) {
SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
}
break;
- case JOB_TASK_STATUS_DROPPING:
+ case JOB_TASK_STATUS_DROP:
SCH_ERR_JRET(TSDB_CODE_QRY_JOB_FREED);
break;
@@ -277,67 +144,11 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) {
_return:
- SCH_JOB_ELOG("invalid job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus));
- SCH_RET(code);
-}
-
-
-void schEndOperation(SSchJob *pJob) {
- int32_t op = atomic_load_32(&pJob->opStatus.op);
- if (SCH_OP_NULL == op) {
- SCH_JOB_DLOG("job already not in any operation, status:%s", jobTaskStatusStr(pJob->status));
- return;
- }
-
- atomic_store_32(&pJob->opStatus.op, SCH_OP_NULL);
-
- SCH_JOB_DLOG("job end %s operation", schGetOpStr(op));
-}
-
-int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync) {
- int32_t code = 0;
- int8_t status = 0;
-
- if (schJobNeedToStop(pJob, &status)) {
- SCH_JOB_ELOG("abort op %s cause of job need to stop", schGetOpStr(type));
- SCH_ERR_JRET(pJob->errCode);
- }
-
- if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) {
- SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op));
- SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR);
- }
-
- SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op));
-
- pJob->opStatus.sync = sync;
-
- switch (type) {
- case SCH_OP_EXEC:
- SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXECUTING));
- break;
- case SCH_OP_FETCH:
- if (!SCH_JOB_NEED_FETCH(pJob)) {
- SCH_JOB_ELOG("no need to fetch data, status:%s", SCH_GET_JOB_STATUS_STR(pJob));
- SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
- }
-
- if (status != JOB_TASK_STATUS_PARTIAL_SUCCEED) {
- SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status));
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
- }
- break;
- default:
- SCH_JOB_ELOG("unknown operation type %d", type);
- SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR);
+ if (TSDB_CODE_SCH_IGNORE_ERROR == code) {
+ SCH_JOB_DLOG("ignore job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus));
+ } else {
+ SCH_JOB_ELOG("invalid job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus));
}
-
- return TSDB_CODE_SUCCESS;
-
-_return:
-
- schEndOperation(pJob);
-
SCH_RET(code);
}
@@ -419,87 +230,24 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) {
}
SSchLevel *pLevel = taosArrayGet(pJob->levels, 0);
- if (SCH_IS_QUERY_JOB(pJob) && pLevel->taskNum > 1) {
- SCH_JOB_ELOG("invalid query plan, level:0, taskNum:%d", pLevel->taskNum);
- SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schRecordTaskSucceedNode(SSchJob *pJob, SSchTask *pTask) {
- SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx);
- if (NULL == addr) {
- SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", pTask->candidateIdx,
- (int32_t)taosArrayGetSize(pTask->candidateAddrs));
- SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
- }
-
- pTask->succeedAddr = *addr;
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execIdx) {
- SSchNodeInfo nodeInfo = {.addr = *addr, .handle = NULL};
-
- if (taosHashPut(pTask->execNodes, &execIdx, sizeof(execIdx), &nodeInfo, sizeof(nodeInfo))) {
- SCH_TASK_ELOG("taosHashPut nodeInfo to execNodes failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- SCH_TASK_DLOG("task execNode added, execIdx:%d", execIdx);
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schDropTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execIdx) {
- if (NULL == pTask->execNodes) {
- return TSDB_CODE_SUCCESS;
- }
-
- if (taosHashRemove(pTask->execNodes, &execIdx, sizeof(execIdx))) {
- SCH_TASK_ELOG("fail to remove execIdx %d from execNodeList", execIdx);
- } else {
- SCH_TASK_DLOG("execIdx %d removed from execNodeList", execIdx);
- }
-
- if (execIdx != pTask->execIdx) { // ignore it
- SCH_TASK_DLOG("execIdx %d is not current execIdx %d", execIdx, pTask->execIdx);
- SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execIdx) {
- if (taosHashGetSize(pTask->execNodes) <= 0) {
- return TSDB_CODE_SUCCESS;
- }
-
- SSchNodeInfo *nodeInfo = taosHashGet(pTask->execNodes, &execIdx, sizeof(execIdx));
- nodeInfo->handle = handle;
-
- SCH_TASK_DLOG("handle updated to %p for execIdx %d", handle, execIdx);
-
- return TSDB_CODE_SUCCESS;
-}
+ if (SCH_IS_QUERY_JOB(pJob)) {
+ if (pLevel->taskNum > 1) {
+ SCH_JOB_ELOG("invalid query plan, level:0, taskNum:%d", pLevel->taskNum);
+ SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
+ }
-int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execIdx) {
- if (dropExecNode) {
- SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execIdx));
+ SSchTask* pTask = taosArrayGet(pLevel->subTasks, 0);
+ if (SUBPLAN_TYPE_MODIFY != pTask->plan->subplanType) {
+ pJob->attr.needFetch = true;
+ }
}
- SCH_SET_TASK_HANDLE(pTask, handle);
-
- schUpdateTaskExecNode(pJob, pTask, handle, execIdx);
-
return TSDB_CODE_SUCCESS;
}
-int32_t schRecordQueryDataSrc(SSchJob *pJob, SSchTask *pTask) {
- if (!SCH_IS_DATA_SRC_QRY_TASK(pTask)) {
+int32_t schAppendJobDataSrc(SSchJob *pJob, SSchTask *pTask) {
+ if (!SCH_IS_DATA_BIND_QRY_TASK(pTask)) {
return TSDB_CODE_SUCCESS;
}
@@ -547,14 +295,12 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) {
pJob->levelNum = levelNum;
pJob->levelIdx = levelNum - 1;
- pJob->subPlans = pDag->pSubplans;
-
SSchLevel level = {0};
SNodeListNode *plans = NULL;
int32_t taskNum = 0;
SSchLevel *pLevel = NULL;
- level.status = JOB_TASK_STATUS_NOT_START;
+ level.status = JOB_TASK_STATUS_INIT;
for (int32_t i = 0; i < levelNum; ++i) {
if (NULL == taosArrayPush(pJob->levels, &level)) {
@@ -591,15 +337,15 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) {
SCH_SET_JOB_TYPE(pJob, plan->subplanType);
SSchTask task = {0};
- SCH_ERR_JRET(schInitTask(pJob, &task, plan, pLevel));
-
SSchTask *pTask = taosArrayPush(pLevel->subTasks, &task);
if (NULL == pTask) {
SCH_TASK_ELOG("taosArrayPush task to level failed, level:%d, taskIdx:%d", pLevel->level, n);
SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- SCH_ERR_JRET(schRecordQueryDataSrc(pJob, pTask));
+ SCH_ERR_JRET(schInitTask(pJob, pTask, plan, pLevel, levelNum));
+
+ SCH_ERR_JRET(schAppendJobDataSrc(pJob, pTask));
if (0 != taosHashPut(planToTask, &plan, POINTER_BYTES, &pTask, POINTER_BYTES)) {
SCH_TASK_ELOG("taosHashPut to planToTaks failed, taskIdx:%d", n);
@@ -628,357 +374,109 @@ _return:
SCH_RET(code);
}
-int32_t schSetAddrsFromNodeList(SSchJob *pJob, SSchTask *pTask) {
- int32_t addNum = 0;
- int32_t nodeNum = 0;
-
- if (pJob->nodeList) {
- nodeNum = taosArrayGetSize(pJob->nodeList);
-
- for (int32_t i = 0; i < nodeNum && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) {
- SQueryNodeLoad *nload = taosArrayGet(pJob->nodeList, i);
- SQueryNodeAddr *naddr = &nload->addr;
-
- if (NULL == taosArrayPush(pTask->candidateAddrs, naddr)) {
- SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, addNum:%d, errno:%d", addNum, errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- SCH_TASK_DLOG("set %dth candidate addr, id %d, fqdn:%s, port:%d", i, naddr->nodeId, SCH_GET_CUR_EP(naddr)->fqdn, SCH_GET_CUR_EP(naddr)->port);
- ++addNum;
- }
- }
+int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes) {
+ pRes->code = atomic_load_32(&pJob->errCode);
+ pRes->numOfRows = pJob->resNumOfRows;
+ pRes->res = pJob->execRes.res;
+ pRes->msgType = pJob->execRes.msgType;
+ pJob->execRes.res = NULL;
- if (addNum <= 0) {
- SCH_TASK_ELOG("no available execNode as candidates, nodeNum:%d", nodeNum);
- SCH_ERR_RET(TSDB_CODE_TSC_NO_EXEC_NODE);
- }
+ SCH_JOB_DLOG("execRes dumped, code: %s", tstrerror(pRes->code));
return TSDB_CODE_SUCCESS;
}
-
-int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) {
- if (NULL != pTask->candidateAddrs) {
- return TSDB_CODE_SUCCESS;
- }
-
- pTask->candidateIdx = 0;
- pTask->candidateAddrs = taosArrayInit(SCH_MAX_CANDIDATE_EP_NUM, sizeof(SQueryNodeAddr));
- if (NULL == pTask->candidateAddrs) {
- SCH_TASK_ELOG("taosArrayInit %d condidate addrs failed", SCH_MAX_CANDIDATE_EP_NUM);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+int32_t schDumpJobFetchRes(SSchJob* pJob, void** pData) {
+ int32_t code = 0;
+ if (pJob->resData && ((SRetrieveTableRsp *)pJob->resData)->completed) {
+ SCH_ERR_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_SUCC, NULL));
}
- if (pTask->plan->execNode.epSet.numOfEps > 0) {
- if (NULL == taosArrayPush(pTask->candidateAddrs, &pTask->plan->execNode)) {
- SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ while (true) {
+ *pData = atomic_load_ptr(&pJob->resData);
+ if (*pData != atomic_val_compare_exchange_ptr(&pJob->resData, *pData, NULL)) {
+ continue;
}
- SCH_TASK_DLOG("use execNode in plan as candidate addr, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps);
-
- return TSDB_CODE_SUCCESS;
+ break;
}
- SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask));
-
- /*
- for (int32_t i = 0; i < job->dataSrcEps.numOfEps && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) {
- strncpy(epSet->fqdn[epSet->numOfEps], job->dataSrcEps.fqdn[i], sizeof(job->dataSrcEps.fqdn[i]));
- epSet->port[epSet->numOfEps] = job->dataSrcEps.port[i];
-
- ++epSet->numOfEps;
+ if (NULL == *pData) {
+ SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)taosMemoryCalloc(1, sizeof(SRetrieveTableRsp));
+ if (rsp) {
+ rsp->completed = 1;
}
- */
-
- return TSDB_CODE_SUCCESS;
-}
-int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask) {
- int32_t code = taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId));
- if (code) {
- SCH_TASK_ELOG("task failed to rm from execTask list, code:%x", code);
- SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
+ *pData = rsp;
+ SCH_JOB_DLOG("empty res and set query complete, code:%x", code);
}
+ SCH_JOB_DLOG("fetch done, totalRows:%d", pJob->resNumOfRows);
+
return TSDB_CODE_SUCCESS;
}
-
-int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) {
- int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
- if (0 != code) {
- if (HASH_NODE_EXIST(code)) {
- SCH_TASK_ELOG("task already in execTask list, code:%x", code);
- SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
- }
-
- SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+int32_t schNotifyUserExecRes(SSchJob* pJob) {
+ SExecResult* pRes = taosMemoryCalloc(1, sizeof(SExecResult));
+ if (pRes) {
+ schDumpJobExecRes(pJob, pRes);
}
- SCH_TASK_DLOG("task added to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
+ SCH_JOB_DLOG("sch start to invoke exec cb, code: %s", tstrerror(pJob->errCode));
+ (*pJob->userRes.execFp)(pRes, pJob->userRes.cbParam, atomic_load_32(&pJob->errCode));
+ SCH_JOB_DLOG("sch end from exec cb, code: %s", tstrerror(pJob->errCode));
return TSDB_CODE_SUCCESS;
}
-int32_t schMoveTaskToSuccList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
- if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) {
- SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- } else {
- SCH_TASK_DLOG("task removed from execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
- }
-
- int32_t code = taosHashPut(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
- if (0 != code) {
- if (HASH_NODE_EXIST(code)) {
- *moved = true;
- SCH_TASK_ELOG("task already in succTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- SCH_TASK_ELOG("taosHashPut task to succTask list failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- *moved = true;
+int32_t schNotifyUserFetchRes(SSchJob* pJob) {
+ void* pRes = NULL;
+
+ schDumpJobFetchRes(pJob, &pRes);
- SCH_TASK_DLOG("task moved to succTask list, numOfTasks:%d", taosHashGetSize(pJob->succTasks));
+ SCH_JOB_DLOG("sch start to invoke fetch cb, code: %s", tstrerror(pJob->errCode));
+ (*pJob->userRes.fetchFp)(pRes, pJob->userRes.cbParam, atomic_load_32(&pJob->errCode));
+ SCH_JOB_DLOG("sch end from fetch cb, code: %s", tstrerror(pJob->errCode));
return TSDB_CODE_SUCCESS;
}
-int32_t schMoveTaskToFailList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
- *moved = false;
-
- if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) {
- SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- }
-
- int32_t code = taosHashPut(pJob->failTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
- if (0 != code) {
- if (HASH_NODE_EXIST(code)) {
- *moved = true;
-
- SCH_TASK_WLOG("task already in failTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- SCH_TASK_ELOG("taosHashPut task to failTask list failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- *moved = true;
-
- SCH_TASK_DLOG("task moved to failTask list, numOfTasks:%d", taosHashGetSize(pJob->failTasks));
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
- if (0 != taosHashRemove(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId))) {
- SCH_TASK_WLOG("remove task from succTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- }
-
- int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
- if (0 != code) {
- if (HASH_NODE_EXIST(code)) {
- *moved = true;
-
- SCH_TASK_ELOG("task already in execTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno);
- SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- *moved = true;
-
- SCH_TASK_DLOG("task moved to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) {
- int8_t status = 0;
-
- if (schJobNeedToStop(pJob, &status)) {
- *needRetry = false;
- SCH_TASK_DLOG("task no more retry cause of job status, job status:%s", jobTaskStatusStr(status));
- return TSDB_CODE_SUCCESS;
- }
-
- if (TSDB_CODE_SCH_TIMEOUT_ERROR == errCode) {
- pTask->maxExecTimes++;
- if (pTask->timeoutUsec < SCH_MAX_TASK_TIMEOUT_USEC) {
- pTask->timeoutUsec *= 2;
- if (pTask->timeoutUsec > SCH_MAX_TASK_TIMEOUT_USEC) {
- pTask->timeoutUsec = SCH_MAX_TASK_TIMEOUT_USEC;
- }
- }
- }
-
- if ((pTask->execIdx + 1) >= pTask->maxExecTimes) {
- *needRetry = false;
- SCH_TASK_DLOG("task no more retry since reach max try times, execIdx:%d", pTask->execIdx);
- return TSDB_CODE_SUCCESS;
- }
-
- if (!NEED_SCHEDULER_RETRY_ERROR(errCode)) {
- *needRetry = false;
- SCH_TASK_DLOG("task no more retry cause of errCode, errCode:%x - %s", errCode, tstrerror(errCode));
- return TSDB_CODE_SUCCESS;
- }
-
- // TODO CHECK epList/condidateList
- if (SCH_IS_DATA_SRC_TASK(pTask)) {
- if ((pTask->execIdx + 1) >= SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)) {
- *needRetry = false;
- SCH_TASK_DLOG("task no more retry since all ep tried, execIdx:%d, epNum:%d", pTask->execIdx,
- SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode));
- return TSDB_CODE_SUCCESS;
- }
- } else {
- int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs);
-
- if ((pTask->candidateIdx + 1) >= candidateNum && (TSDB_CODE_SCH_TIMEOUT_ERROR != errCode)) {
- *needRetry = false;
- SCH_TASK_DLOG("task no more retry since all candiates tried, candidateIdx:%d, candidateNum:%d",
- pTask->candidateIdx, candidateNum);
- return TSDB_CODE_SUCCESS;
- }
- }
-
- *needRetry = true;
- SCH_TASK_DLOG("task need the %dth retry, errCode:%x - %s", pTask->execIdx + 1, errCode, tstrerror(errCode));
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) {
- atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1);
-
- SCH_ERR_RET(schRemoveTaskFromExecList(pJob, pTask));
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START);
-
- if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) {
- SCH_ERR_RET(schDecTaskFlowQuota(pJob, pTask));
- SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask));
- }
-
- schDeregisterTaskHb(pJob, pTask);
-
- if (SCH_IS_DATA_SRC_TASK(pTask)) {
- SCH_SWITCH_EPSET(&pTask->plan->execNode);
- } else {
- int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs);
- if (++pTask->candidateIdx >= candidateNum) {
- pTask->candidateIdx = 0;
- }
- }
-
- SCH_ERR_RET(schLaunchTask(pJob, pTask));
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes) {
- pRes->code = atomic_load_32(&pJob->errCode);
- pRes->numOfRows = pJob->resNumOfRows;
- pRes->res = pJob->execRes;
- pJob->execRes.res = NULL;
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schSetJobFetchRes(SSchJob* pJob, void** pData) {
- int32_t code = 0;
- if (pJob->resData && ((SRetrieveTableRsp *)pJob->resData)->completed) {
- SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_SUCCEED));
- }
-
- while (true) {
- *pData = atomic_load_ptr(&pJob->resData);
- if (*pData != atomic_val_compare_exchange_ptr(&pJob->resData, *pData, NULL)) {
- continue;
- }
-
- break;
- }
-
- if (NULL == *pData) {
- SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)taosMemoryCalloc(1, sizeof(SRetrieveTableRsp));
- if (rsp) {
- rsp->completed = 1;
- }
-
- *pData = rsp;
- SCH_JOB_DLOG("empty res and set query complete, code:%x", code);
- }
-
- SCH_JOB_DLOG("fetch done, totalRows:%d", pJob->resNumOfRows);
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schNotifyUserExecRes(SSchJob* pJob) {
- SQueryResult* pRes = taosMemoryCalloc(1, sizeof(SQueryResult));
- if (pRes) {
- schSetJobQueryRes(pJob, pRes);
- }
-
- schEndOperation(pJob);
-
- SCH_JOB_DLOG("sch start to invoke exec cb, code: %s", tstrerror(pJob->errCode));
- (*pJob->userRes.execFp)(pRes, pJob->userRes.userParam, atomic_load_32(&pJob->errCode));
- SCH_JOB_DLOG("sch end from query cb, code: %s", tstrerror(pJob->errCode));
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schNotifyUserFetchRes(SSchJob* pJob) {
- void* pRes = NULL;
-
- schSetJobFetchRes(pJob, &pRes);
-
- schEndOperation(pJob);
-
- SCH_JOB_DLOG("sch start to invoke fetch cb, code: %s", tstrerror(pJob->errCode));
- (*pJob->userRes.fetchFp)(pRes, pJob->userRes.userParam, atomic_load_32(&pJob->errCode));
- SCH_JOB_DLOG("sch end from fetch cb, code: %s", tstrerror(pJob->errCode));
-
- return TSDB_CODE_SUCCESS;
-}
-
-void schPostJobRes(SSchJob *pJob, SCH_OP_TYPE op) {
- if (SCH_OP_NULL == pJob->opStatus.op) {
- SCH_JOB_DLOG("job not in any op, no need to post job res, status:%s", jobTaskStatusStr(pJob->status));
- return;
+void schPostJobRes(SSchJob *pJob, SCH_OP_TYPE op) {
+ SCH_LOCK(SCH_WRITE, &pJob->opStatus.lock);
+
+ if (SCH_OP_NULL == pJob->opStatus.op) {
+ SCH_JOB_DLOG("job not in any operation, no need to post job res, status:%s", jobTaskStatusStr(pJob->status));
+ goto _return;
}
if (op && pJob->opStatus.op != op) {
- SCH_JOB_ELOG("job in op %s mis-match with expected %s", schGetOpStr(pJob->opStatus.op), schGetOpStr(op));
- return;
+ SCH_JOB_ELOG("job in operation %s mis-match with expected %s", schGetOpStr(pJob->opStatus.op), schGetOpStr(op));
+ goto _return;
}
if (SCH_JOB_IN_SYNC_OP(pJob)) {
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
tsem_post(&pJob->rspSem);
} else if (SCH_JOB_IN_ASYNC_EXEC_OP(pJob)) {
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
schNotifyUserExecRes(pJob);
} else if (SCH_JOB_IN_ASYNC_FETCH_OP(pJob)) {
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
schNotifyUserFetchRes(pJob);
} else {
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
SCH_JOB_ELOG("job not in any operation, status:%s", jobTaskStatusStr(pJob->status));
}
+
+ return;
+
+_return:
+
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
}
int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCode) {
- // if already FAILED, no more processing
- SCH_ERR_RET(schUpdateJobStatus(pJob, status));
-
schUpdateJobErrCode(pJob, errCode);
int32_t code = atomic_load_32(&pJob->errCode);
@@ -988,333 +486,81 @@ int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCod
schPostJobRes(pJob, 0);
- SCH_RET(code);
+ SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR);
}
// Note: no more task error processing, handled in function internal
int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) {
- SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAILED, errCode));
+ if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) {
+ return TSDB_CODE_SCH_IGNORE_ERROR;
+ }
+
+ schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAIL, errCode);
+ return TSDB_CODE_SCH_IGNORE_ERROR;
}
// Note: no more error processing, handled in function internal
int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode) {
- SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_DROPPING, errCode));
+ SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_DROP, errCode));
}
-// Note: no more task error processing, handled in function internal
int32_t schProcessOnJobPartialSuccess(SSchJob *pJob) {
- int32_t code = 0;
-
- SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_PARTIAL_SUCCEED));
-
schPostJobRes(pJob, SCH_OP_EXEC);
return TSDB_CODE_SUCCESS;
-
-_return:
-
- SCH_RET(schProcessOnJobFailure(pJob, code));
}
void schProcessOnDataFetched(SSchJob *pJob) {
schPostJobRes(pJob, SCH_OP_FETCH);
}
-// Note: no more task error processing, handled in function internal
-int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) {
- int8_t status = 0;
-
- if (errCode == TSDB_CODE_SCH_TIMEOUT_ERROR) {
- SCH_LOG_TASK_WAIT_TS(pTask);
- } else {
- SCH_LOG_TASK_END_TS(pTask);
- }
-
- if (schJobNeedToStop(pJob, &status)) {
- SCH_TASK_DLOG("task failed not processed cause of job status, job status:%s", jobTaskStatusStr(status));
- SCH_RET(atomic_load_32(&pJob->errCode));
- }
-
- bool needRetry = false;
- bool moved = false;
- int32_t taskDone = 0;
- int32_t code = 0;
-
- SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode));
-
- SCH_ERR_JRET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry));
-
- if (!needRetry) {
- SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode));
-
- if (SCH_GET_TASK_STATUS(pTask) == JOB_TASK_STATUS_EXECUTING) {
- SCH_ERR_JRET(schMoveTaskToFailList(pJob, pTask, &moved));
- } else {
- SCH_TASK_ELOG("task not in executing list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAILED);
-
- if (SCH_IS_WAIT_ALL_JOB(pJob)) {
- SCH_LOCK(SCH_WRITE, &pTask->level->lock);
- pTask->level->taskFailed++;
- taskDone = pTask->level->taskSucceed + pTask->level->taskFailed;
- SCH_UNLOCK(SCH_WRITE, &pTask->level->lock);
-
- schUpdateJobErrCode(pJob, errCode);
-
- if (taskDone < pTask->level->taskNum) {
- SCH_TASK_DLOG("need to wait other tasks, doneNum:%d, allNum:%d", taskDone, pTask->level->taskNum);
- SCH_RET(errCode);
- }
- }
- } else {
- SCH_ERR_JRET(schHandleTaskRetry(pJob, pTask));
-
- return TSDB_CODE_SUCCESS;
- }
-
-_return:
-
- SCH_RET(schProcessOnJobFailure(pJob, errCode));
-}
-
-int32_t schLaunchNextLevelTasks(SSchJob *pJob, SSchTask *pTask) {
- if (!SCH_IS_QUERY_JOB(pJob)) {
- return TSDB_CODE_SUCCESS;
- }
-
- SSchLevel *pLevel = pTask->level;
- int32_t doneNum = atomic_add_fetch_32(&pLevel->taskDoneNum, 1);
- if (doneNum == pLevel->taskNum) {
- pJob->levelIdx--;
-
- pLevel = taosArrayGet(pJob->levels, pJob->levelIdx);
- for (int32_t i = 0; i < pLevel->taskNum; ++i) {
- SSchTask *pTask = taosArrayGet(pLevel->subTasks, i);
-
- if (pTask->children && taosArrayGetSize(pTask->children) > 0) {
- continue;
- }
-
- SCH_ERR_RET(schLaunchTask(pJob, pTask));
- }
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-
-// Note: no more task error processing, handled in function internal
-int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) {
- bool moved = false;
- int32_t code = 0;
-
- SCH_TASK_DLOG("taskOnSuccess, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
-
- SCH_LOG_TASK_END_TS(pTask);
-
- SCH_ERR_JRET(schMoveTaskToSuccList(pJob, pTask, &moved));
-
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PARTIAL_SUCCEED);
-
- SCH_ERR_JRET(schRecordTaskSucceedNode(pJob, pTask));
-
- SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask));
-
- int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0;
- if (parentNum == 0) {
- int32_t taskDone = 0;
- if (SCH_IS_WAIT_ALL_JOB(pJob)) {
- SCH_LOCK(SCH_WRITE, &pTask->level->lock);
- pTask->level->taskSucceed++;
- taskDone = pTask->level->taskSucceed + pTask->level->taskFailed;
- SCH_UNLOCK(SCH_WRITE, &pTask->level->lock);
-
- if (taskDone < pTask->level->taskNum) {
- SCH_TASK_DLOG("wait all tasks, done:%d, all:%d", taskDone, pTask->level->taskNum);
- return TSDB_CODE_SUCCESS;
- } else if (taskDone > pTask->level->taskNum) {
- SCH_TASK_ELOG("taskDone number invalid, done:%d, total:%d", taskDone, pTask->level->taskNum);
- }
-
- if (pTask->level->taskFailed > 0) {
- SCH_RET(schProcessOnJobFailure(pJob, 0));
- } else {
- SCH_RET(schProcessOnJobPartialSuccess(pJob));
- }
- } else {
- pJob->resNode = pTask->succeedAddr;
- }
-
- pJob->fetchTask = pTask;
-
- SCH_ERR_JRET(schMoveTaskToExecList(pJob, pTask, &moved));
-
- SCH_RET(schProcessOnJobPartialSuccess(pJob));
- }
-
- /*
- if (SCH_IS_DATA_SRC_TASK(task) && job->dataSrcEps.numOfEps < SCH_MAX_CANDIDATE_EP_NUM) {
- strncpy(job->dataSrcEps.fqdn[job->dataSrcEps.numOfEps], task->execAddr.fqdn, sizeof(task->execAddr.fqdn));
- job->dataSrcEps.port[job->dataSrcEps.numOfEps] = task->execAddr.port;
-
- ++job->dataSrcEps.numOfEps;
- }
- */
-
- for (int32_t i = 0; i < parentNum; ++i) {
- SSchTask *parent = *(SSchTask **)taosArrayGet(pTask->parents, i);
- int32_t readyNum = atomic_add_fetch_32(&parent->childReady, 1);
-
- SCH_LOCK(SCH_WRITE, &parent->lock);
- SDownstreamSourceNode source = {.type = QUERY_NODE_DOWNSTREAM_SOURCE,
- .taskId = pTask->taskId,
- .schedId = schMgmt.sId,
- .addr = pTask->succeedAddr};
- qSetSubplanExecutionNode(parent->plan, pTask->plan->id.groupId, &source);
- SCH_UNLOCK(SCH_WRITE, &parent->lock);
-
- if (SCH_TASK_READY_FOR_LAUNCH(readyNum, parent)) {
- SCH_TASK_DLOG("all %d children task done, start to launch parent task 0x%" PRIx64, readyNum, parent->taskId);
- SCH_ERR_RET(schLaunchTask(pJob, parent));
- }
- }
-
- SCH_ERR_RET(schLaunchNextLevelTasks(pJob, pTask));
-
- return TSDB_CODE_SUCCESS;
-
-_return:
-
- SCH_RET(schProcessOnJobFailure(pJob, code));
-}
-
-// Note: no more error processing, handled in function internal
-int32_t schFetchFromRemote(SSchJob *pJob) {
- int32_t code = 0;
-
- void *resData = atomic_load_ptr(&pJob->resData);
- if (resData) {
- SCH_JOB_DLOG("res already fetched, res:%p", resData);
- return TSDB_CODE_SUCCESS;
- }
-
- SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, TDMT_VND_FETCH));
-
- return TSDB_CODE_SUCCESS;
-
-_return:
-
- SCH_RET(schProcessOnTaskFailure(pJob, pJob->fetchTask, code));
-}
-
int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp) {
SCH_TASK_DLOG("got explain rsp, rows:%d, complete:%d", htonl(pRsp->numOfRows), pRsp->completed);
atomic_store_32(&pJob->resNumOfRows, htonl(pRsp->numOfRows));
atomic_store_ptr(&pJob->resData, pRsp);
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCCEED);
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCC);
schProcessOnDataFetched(pJob);
return TSDB_CODE_SUCCESS;
}
-void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask) {
- if (NULL == pTask->execNodes) {
- SCH_TASK_DLOG("no exec address, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- return;
- }
-
- int32_t size = (int32_t)taosHashGetSize(pTask->execNodes);
-
- if (size <= 0) {
- SCH_TASK_DLOG("task has no execNodes, no need to drop it, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
- return;
- }
-
- SSchNodeInfo *nodeInfo = taosHashIterate(pTask->execNodes, NULL);
- while (nodeInfo) {
- SCH_SET_TASK_HANDLE(pTask, nodeInfo->handle);
-
- schBuildAndSendMsg(pJob, pTask, &nodeInfo->addr, TDMT_VND_DROP_TASK);
-
- nodeInfo = taosHashIterate(pTask->execNodes, nodeInfo);
- }
- SCH_TASK_DLOG("task has been dropped on %d exec nodes", size);
-}
-
-
-int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) {
- if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) {
+int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask) {
+ if (!SCH_IS_QUERY_JOB(pJob)) {
return TSDB_CODE_SUCCESS;
}
- SCH_LOCK_TASK(pTask);
- if (JOB_TASK_STATUS_EXECUTING == pTask->status && pJob->fetchTask != pTask && taosArrayGetSize(pTask->candidateAddrs) > 1) {
- SCH_TASK_DLOG("task execIdx %d will be rescheduled now", pTask->execIdx);
- schDropTaskOnExecNode(pJob, pTask);
- taosHashClear(pTask->execNodes);
- schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR);
- }
- SCH_UNLOCK_TASK(pTask);
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList) {
- int32_t taskNum = (int32_t)taosArrayGetSize(pStatusList);
- SSchTask *pTask = NULL;
-
- qDebug("%d task status in hb rsp from nodeId:%d, fqdn:%s, port:%d", taskNum, pEpId->nodeId, pEpId->ep.fqdn, pEpId->ep.port);
-
- for (int32_t i = 0; i < taskNum; ++i) {
- STaskStatus *taskStatus = taosArrayGet(pStatusList, i);
-
- SSchJob *pJob = schAcquireJob(taskStatus->refId);
- if (NULL == pJob) {
- qWarn("job not found, refId:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64, taskStatus->refId,
- taskStatus->queryId, taskStatus->taskId);
- // TODO DROP TASK FROM SERVER!!!!
- continue;
- }
-
- SCH_JOB_DLOG("TID:0x%" PRIx64 " task status in server: %s", taskStatus->taskId, jobTaskStatusStr(taskStatus->status));
-
- pTask = NULL;
- schGetTaskInJob(pJob, taskStatus->taskId, &pTask);
- if (NULL == pTask) {
- // TODO DROP TASK FROM SERVER!!!!
- schReleaseJob(taskStatus->refId);
- continue;
- }
-
- if (taskStatus->status == JOB_TASK_STATUS_FAILED) {
- // RECORD AND HANDLE ERROR!!!!
- schReleaseJob(taskStatus->refId);
- continue;
- }
+ SSchLevel *pLevel = pTask->level;
+ int32_t doneNum = atomic_add_fetch_32(&pLevel->taskDoneNum, 1);
+ if (doneNum == pLevel->taskNum) {
+ pJob->levelIdx--;
- if (taskStatus->status == JOB_TASK_STATUS_NOT_START && SCH_TASK_TIMEOUT(pTask)) {
- schRescheduleTask(pJob, pTask);
- }
+ pLevel = taosArrayGet(pJob->levels, pJob->levelIdx);
+ for (int32_t i = 0; i < pLevel->taskNum; ++i) {
+ SSchTask *pTask = taosArrayGet(pLevel->subTasks, i);
- schReleaseJob(taskStatus->refId);
+ if (pTask->children && taosArrayGetSize(pTask->children) > 0) {
+ continue;
+ }
+
+ SCH_ERR_RET(schLaunchTask(pJob, pTask));
+ }
}
return TSDB_CODE_SUCCESS;
}
-
int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp) {
if (rsp->tbFName[0]) {
+ SCH_LOCK(SCH_WRITE, &pJob->resLock);
+
if (NULL == pJob->execRes.res) {
pJob->execRes.res = taosArrayInit(pJob->taskNum, sizeof(STbVerInfo));
if (NULL == pJob->execRes.res) {
+ SCH_UNLOCK(SCH_WRITE, &pJob->resLock);
SCH_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
}
}
@@ -1325,25 +571,11 @@ int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp) {
tbInfo.tversion = rsp->tversion;
taosArrayPush((SArray *)pJob->execRes.res, &tbInfo);
- pJob->execRes.msgType = TDMT_VND_QUERY;
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) {
- int32_t s = taosHashGetSize(pTaskList);
- if (s <= 0) {
- return TSDB_CODE_SUCCESS;
- }
+ pJob->execRes.msgType = TDMT_SCH_QUERY;
- SSchTask **task = taosHashGet(pTaskList, &taskId, sizeof(taskId));
- if (NULL == task || NULL == (*task)) {
- return TSDB_CODE_SUCCESS;
+ SCH_UNLOCK(SCH_WRITE, &pJob->resLock);
}
- *pTask = *task;
-
return TSDB_CODE_SUCCESS;
}
@@ -1357,123 +589,24 @@ int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask) {
return TSDB_CODE_SUCCESS;
}
-int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) {
- int8_t status = 0;
- int32_t code = 0;
-
- atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1);
- pTask->execIdx++;
-
- SCH_TASK_DLOG("start to launch task's %dth exec", pTask->execIdx);
-
- SCH_LOG_TASK_START_TS(pTask);
-
- if (schJobNeedToStop(pJob, &status)) {
- SCH_TASK_DLOG("no need to launch task cause of job status, job status:%s", jobTaskStatusStr(status));
-
- SCH_RET(atomic_load_32(&pJob->errCode));
- }
-
- // NOTE: race condition: the task should be put into the hash table before send msg to server
- if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXECUTING) {
- SCH_ERR_RET(schPushTaskToExecList(pJob, pTask));
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXECUTING);
- }
-
- SSubplan *plan = pTask->plan;
-
- if (NULL == pTask->msg) { // TODO add more detailed reason for failure
- code = qSubPlanToString(plan, &pTask->msg, &pTask->msgLen);
- if (TSDB_CODE_SUCCESS != code) {
- SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg,
- pTask->msgLen);
- SCH_ERR_RET(code);
- } else {
- SCH_TASK_DLOGL("physical plan len:%d, %s", pTask->msgLen, pTask->msg);
- }
- }
-
- SCH_ERR_RET(schSetTaskCandidateAddrs(pJob, pTask));
-
- if (SCH_IS_QUERY_JOB(pJob)) {
- SCH_ERR_RET(schEnsureHbConnection(pJob, pTask));
- }
-
- SCH_ERR_RET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType));
-
- return TSDB_CODE_SUCCESS;
-}
-
-// Note: no more error processing, handled in function internal
-int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) {
- bool enough = false;
- int32_t code = 0;
-
- SCH_SET_TASK_HANDLE(pTask, NULL);
- if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) {
- SCH_ERR_JRET(schCheckIncTaskFlowQuota(pJob, pTask, &enough));
-
- if (enough) {
- SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask));
- }
+int32_t schLaunchJob(SSchJob *pJob) {
+ if (EXPLAIN_MODE_STATIC == pJob->attr.explainMode) {
+ SCH_ERR_RET(qExecStaticExplain(pJob->pDag, (SRetrieveTableRsp **)&pJob->resData));
+ SCH_ERR_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL));
} else {
- SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask));
- }
-
- return TSDB_CODE_SUCCESS;
-
-_return:
-
- SCH_RET(schProcessOnTaskFailure(pJob, pTask, code));
-}
-
-int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) {
- for (int32_t i = 0; i < level->taskNum; ++i) {
- SSchTask *pTask = taosArrayGet(level->subTasks, i);
-
- SCH_ERR_RET(schLaunchTask(pJob, pTask));
+ SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx);
+ SCH_ERR_RET(schLaunchLevelTasks(pJob, level));
}
return TSDB_CODE_SUCCESS;
}
-int32_t schLaunchJob(SSchJob *pJob) {
- SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx);
-
- SCH_ERR_RET(schChkJobNeedFlowCtrl(pJob, level));
-
- SCH_ERR_RET(schLaunchLevelTasks(pJob, level));
-
- return TSDB_CODE_SUCCESS;
-}
-
-
-void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) {
- if (!SCH_IS_NEED_DROP_JOB(pJob)) {
- return;
- }
-
- void *pIter = taosHashIterate(list, NULL);
- while (pIter) {
- SSchTask *pTask = *(SSchTask **)pIter;
-
- schDropTaskOnExecNode(pJob, pTask);
-
- pIter = taosHashIterate(list, pIter);
- }
-}
void schDropJobAllTasks(SSchJob *pJob) {
schDropTaskInHashList(pJob, pJob->execTasks);
- schDropTaskInHashList(pJob, pJob->succTasks);
- schDropTaskInHashList(pJob, pJob->failTasks);
-}
-
-int32_t schCancelJob(SSchJob *pJob) {
- // TODO
- return TSDB_CODE_SUCCESS;
- // TODO MOVE ALL TASKS FROM EXEC LIST TO FAIL LIST
+// schDropTaskInHashList(pJob, pJob->succTasks);
+// schDropTaskInHashList(pJob, pJob->failTasks);
}
void schFreeJobImpl(void *job) {
@@ -1485,14 +618,10 @@ void schFreeJobImpl(void *job) {
uint64_t queryId = pJob->queryId;
int64_t refId = pJob->refId;
- if (pJob->status == JOB_TASK_STATUS_EXECUTING) {
- schCancelJob(pJob);
- }
+ qDebug("QID:0x%" PRIx64 " begin to free sch job, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob);
schDropJobAllTasks(pJob);
- pJob->subPlans = NULL; // it is a reference to pDag->pSubplans
-
int32_t numOfLevels = taosArrayGetSize(pJob->levels);
for (int32_t i = 0; i < numOfLevels; ++i) {
SSchLevel *pLevel = taosArrayGet(pJob->levels, i);
@@ -1509,8 +638,8 @@ void schFreeJobImpl(void *job) {
schFreeFlowCtrl(pJob);
taosHashCleanup(pJob->execTasks);
- taosHashCleanup(pJob->failTasks);
- taosHashCleanup(pJob->succTasks);
+// taosHashCleanup(pJob->failTasks);
+// taosHashCleanup(pJob->succTasks);
taosHashCleanup(pJob->taskList);
taosArrayDestroy(pJob->levels);
@@ -1521,197 +650,307 @@ void schFreeJobImpl(void *job) {
destroyQueryExecRes(&pJob->execRes);
- taosMemoryFreeClear(pJob->userRes.queryRes);
+ qDestroyQueryPlan(pJob->pDag);
+
+ taosMemoryFreeClear(pJob->userRes.execRes);
taosMemoryFreeClear(pJob->resData);
taosMemoryFree(pJob);
- qDebug("QID:0x%" PRIx64 " sch job freed, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob);
-
int32_t jobNum = atomic_sub_fetch_32(&schMgmt.jobNum, 1);
if (jobNum == 0) {
schCloseJobRef();
}
-}
-int32_t schExecJobImpl(SSchedulerReq *pReq, int64_t *job, SQueryResult* pRes, bool sync) {
- if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) {
- qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId);
- }
+ qDebug("QID:0x%" PRIx64 " sch job freed, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob);
+}
+int32_t schJobFetchRows(SSchJob *pJob) {
int32_t code = 0;
- SSchJob *pJob = NULL;
- SCH_ERR_JRET(schInitJob(pReq, &pJob, pRes, sync));
-
- qDebug("QID:0x%" PRIx64 " sch job refId 0x%"PRIx64 " started", pReq->pDag->queryId, pJob->refId);
- *job = pJob->refId;
- SCH_ERR_JRET(schBeginOperation(pJob, SCH_OP_EXEC, sync));
+ if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC)) {
+ SCH_ERR_RET(schLaunchFetchTask(pJob));
+
+ if (schChkCurrentOp(pJob, SCH_OP_FETCH, true)) {
+ SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob));
+ tsem_wait(&pJob->rspSem);
+ SCH_RET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes));
+ }
+ } else {
+ if (schChkCurrentOp(pJob, SCH_OP_FETCH, true)) {
+ SCH_RET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes));
+ } else {
+ schPostJobRes(pJob, SCH_OP_FETCH);
+ }
+ }
- code = schLaunchJob(pJob);
+ SCH_RET(code);
+}
- if (sync) {
- SCH_JOB_DLOG("will wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob));
- tsem_wait(&pJob->rspSem);
-
- schEndOperation(pJob);
- } else if (code) {
- schPostJobRes(pJob, SCH_OP_EXEC);
+int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq) {
+ int32_t code = 0;
+ int64_t refId = -1;
+ SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob));
+ if (NULL == pJob) {
+ qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob));
+ SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- SCH_JOB_DLOG("job exec done, job status:%s, jobId:0x%" PRIx64, SCH_GET_JOB_STATUS_STR(pJob), pJob->refId);
+ pJob->attr.explainMode = pReq->pDag->explainInfo.mode;
+ pJob->conn = *pReq->pConn;
+ pJob->sql = pReq->sql;
+ pJob->pDag = pReq->pDag;
+ pJob->chkKillFp = pReq->chkKillFp;
+ pJob->chkKillParam = pReq->chkKillParam;
+ pJob->userRes.execFp = pReq->execFp;
+ pJob->userRes.cbParam = pReq->cbParam;
- schReleaseJob(pJob->refId);
+ if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) {
+ qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId);
+ } else {
+ pJob->nodeList = taosArrayDup(pReq->pNodeList);
+ }
- SCH_RET(code);
+ pJob->taskList =
+ taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
+ if (NULL == pJob->taskList) {
+ SCH_JOB_ELOG("taosHashInit %d taskList failed", pReq->pDag->numOfSubplans);
+ SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
-_return:
+ SCH_ERR_JRET(schValidateAndBuildJob(pReq->pDag, pJob));
- if (!sync) {
- pReq->fp(NULL, pReq->cbParam, code);
+ if (SCH_IS_EXPLAIN_JOB(pJob)) {
+ SCH_ERR_JRET(qExecExplainBegin(pReq->pDag, &pJob->explainCtx, pReq->startTs));
}
- schReleaseJob(pJob->refId);
-
- SCH_RET(code);
-}
-
-int32_t schExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes) {
- int32_t code = 0;
-
- *pJob = 0;
-
- if (EXPLAIN_MODE_STATIC == pReq->pDag->explainInfo.mode) {
- SCH_ERR_JRET(schExecStaticExplainJob(pReq, pJob, true));
- } else {
- SCH_ERR_JRET(schExecJobImpl(pReq, pJob, NULL, true));
+ pJob->execTasks =
+ taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK);
+ if (NULL == pJob->execTasks) {
+ SCH_JOB_ELOG("taosHashInit %d execTasks failed", pReq->pDag->numOfSubplans);
+ SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
-_return:
+ tsem_init(&pJob->rspSem, 0, 0);
- if (*pJob) {
- SSchJob *job = schAcquireJob(*pJob);
- schSetJobQueryRes(job, pRes);
- schReleaseJob(*pJob);
+ pJob->refId = taosAddRef(schMgmt.jobRef, pJob);
+ if (pJob->refId < 0) {
+ SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno));
+ SCH_ERR_JRET(terrno);
}
- return code;
-}
+ atomic_add_fetch_32(&schMgmt.jobNum, 1);
-int32_t schAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob) {
- int32_t code = 0;
+ *pJobId = pJob->refId;
+
+ SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId);
- *pJob = 0;
+ return TSDB_CODE_SUCCESS;
+
+_return:
- if (EXPLAIN_MODE_STATIC == pReq->pDag->explainInfo.mode) {
- SCH_RET(schExecStaticExplainJob(pReq, pJob, false));
+ if (NULL == pJob) {
+ qDestroyQueryPlan(pReq->pDag);
+ } else if (pJob->refId < 0) {
+ schFreeJobImpl(pJob);
+ } else {
+ taosRemoveRef(schMgmt.jobRef, pJob->refId);
}
- SCH_ERR_RET(schExecJobImpl(pReq, pJob, NULL, false));
-
- return code;
+ SCH_RET(code);
}
-int32_t schExecStaticExplainJob(SSchedulerReq *pReq, int64_t *job, bool sync) {
- qDebug("QID:0x%" PRIx64 " job started", pReq->pDag->queryId);
+int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) {
+ int32_t code = 0;
+ qDebug("QID:0x%" PRIx64 " sch job refId 0x%"PRIx64 " started", pReq->pDag->queryId, pJob->refId);
- int32_t code = 0;
- SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob));
- if (NULL == pJob) {
- qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob));
- code = TSDB_CODE_QRY_OUT_OF_MEMORY;
- pReq->fp(NULL, pReq->cbParam, code);
- SCH_ERR_RET(code);
+ SCH_ERR_RET(schLaunchJob(pJob));
+
+ if (pReq->syncReq) {
+ SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob));
+ tsem_wait(&pJob->rspSem);
}
- pJob->sql = pReq->sql;
- pJob->reqKilled = pReq->reqKilled;
- pJob->attr.queryJob = true;
- pJob->attr.explainMode = pReq->pDag->explainInfo.mode;
- pJob->queryId = pReq->pDag->queryId;
- pJob->subPlans = pReq->pDag->pSubplans;
- pJob->userRes.execFp = pReq->fp;
- pJob->userRes.userParam = pReq->cbParam;
+ SCH_JOB_DLOG("job exec done, job status:%s, jobId:0x%" PRIx64, SCH_GET_JOB_STATUS_STR(pJob), pJob->refId);
- schUpdateJobStatus(pJob, JOB_TASK_STATUS_NOT_START);
+ return TSDB_CODE_SUCCESS;
+}
- code = schBeginOperation(pJob, SCH_OP_EXEC, sync);
- if (code) {
- pReq->fp(NULL, pReq->cbParam, code);
- SCH_ERR_RET(code);
+void schDirectPostJobRes(SSchedulerReq* pReq, int32_t errCode) {
+ if (NULL == pReq || pReq->syncReq) {
+ return;
}
- SCH_ERR_JRET(qExecStaticExplain(pReq->pDag, (SRetrieveTableRsp **)&pJob->resData));
+ if (pReq->execFp) {
+ (*pReq->execFp)(NULL, pReq->cbParam, errCode);
+ } else if (pReq->fetchFp) {
+ (*pReq->fetchFp)(NULL, pReq->cbParam, errCode);
+ }
+}
- int64_t refId = taosAddRef(schMgmt.jobRef, pJob);
- if (refId < 0) {
- SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno));
- SCH_ERR_JRET(terrno);
+bool schChkCurrentOp(SSchJob *pJob, int32_t op, bool sync) {
+ SCH_LOCK(SCH_READ, &pJob->opStatus.lock);
+ bool r = (pJob->opStatus.op == op) && (pJob->opStatus.syncReq == sync);
+ SCH_UNLOCK(SCH_READ, &pJob->opStatus.lock);
+
+ return r;
+}
+
+void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) {
+ int32_t op = 0;
+
+ switch (type) {
+ case SCH_OP_EXEC:
+ if (pReq && pReq->syncReq) {
+ SCH_LOCK(SCH_WRITE, &pJob->opStatus.lock);
+ op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL);
+ if (SCH_OP_NULL == op || op != type) {
+ SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status));
+ }
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+ schDumpJobExecRes(pJob, pReq->pExecRes);
+ }
+ break;
+ case SCH_OP_FETCH:
+ if (pReq && pReq->syncReq) {
+ SCH_LOCK(SCH_WRITE, &pJob->opStatus.lock);
+ op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL);
+ if (SCH_OP_NULL == op || op != type) {
+ SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status));
+ }
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+ }
+ break;
+ case SCH_OP_GET_STATUS:
+ errCode = TSDB_CODE_SUCCESS;
+ break;
+ default:
+ break;
}
- if (NULL == schAcquireJob(refId)) {
- SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId);
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
+ if (errCode) {
+ schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)&errCode);
}
- pJob->refId = refId;
+ SCH_JOB_DLOG("job end %s operation with code %s", schGetOpStr(type), tstrerror(errCode));
+}
- SCH_JOB_DLOG("job refId:0x%" PRIx64, pJob->refId);
+int32_t schProcessOnOpBegin(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq) {
+ int32_t code = 0;
+ int8_t status = SCH_GET_JOB_STATUS(pJob);
+
+ switch (type) {
+ case SCH_OP_EXEC:
+ SCH_LOCK(SCH_WRITE, &pJob->opStatus.lock);
+ if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) {
+ SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op));
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+ schDirectPostJobRes(pReq, TSDB_CODE_TSC_APP_ERROR);
+ SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR);
+ }
+
+ SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op));
+
+ pJob->opStatus.syncReq = pReq->syncReq;
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+ break;
+ case SCH_OP_FETCH:
+ SCH_LOCK(SCH_WRITE, &pJob->opStatus.lock);
+ if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) {
+ SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op));
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+ schDirectPostJobRes(pReq, TSDB_CODE_TSC_APP_ERROR);
+ SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR);
+ }
+
+ SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op));
+
+ pJob->userRes.fetchRes = pReq->pFetchRes;
+ pJob->userRes.fetchFp = pReq->fetchFp;
+ pJob->userRes.cbParam = pReq->cbParam;
+
+ pJob->opStatus.syncReq = pReq->syncReq;
+ SCH_UNLOCK(SCH_WRITE, &pJob->opStatus.lock);
+
+ if (!SCH_JOB_NEED_FETCH(pJob)) {
+ SCH_JOB_ELOG("no need to fetch data, status:%s", SCH_GET_JOB_STATUS_STR(pJob));
+ SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
+ }
- pJob->status = JOB_TASK_STATUS_PARTIAL_SUCCEED;
-
- *job = pJob->refId;
- SCH_JOB_DLOG("job exec done, job status:%s", SCH_GET_JOB_STATUS_STR(pJob));
-
- if (!sync) {
- schPostJobRes(pJob, SCH_OP_EXEC);
- } else {
- schEndOperation(pJob);
+ if (status != JOB_TASK_STATUS_PART_SUCC) {
+ SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status));
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ break;
+ case SCH_OP_GET_STATUS:
+ if (pJob->status < JOB_TASK_STATUS_INIT || pJob->levelNum <= 0 || NULL == pJob->levels) {
+ qDebug("job not initialized or not executable job, refId:0x%" PRIx64, pJob->refId);
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+ break;
+ default:
+ SCH_JOB_ELOG("unknown operation type %d", type);
+ SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR);
}
- schReleaseJob(pJob->refId);
+ if (schJobNeedToStop(pJob, &status)) {
+ SCH_JOB_ELOG("abort op %s cause of job need to stop, status:%s", schGetOpStr(type), jobTaskStatusStr(status));
+ SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR);
+ }
- SCH_RET(code);
+ return TSDB_CODE_SUCCESS;
+}
-_return:
+void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode) {
+ if (pTask) {
+ SCH_UNLOCK_TASK(pTask);
+ }
- schEndOperation(pJob);
- if (!sync) {
- pReq->fp(NULL, pReq->cbParam, code);
+ if (errCode) {
+ schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)&errCode);
}
- schFreeJobImpl(pJob);
-
- SCH_RET(code);
+ if (pJob) {
+ schReleaseJob(pJob->refId);
+ }
}
-int32_t schFetchRows(SSchJob *pJob) {
- int32_t code = 0;
+int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_t rId, uint64_t tId) {
+ int32_t code = 0;
+ int8_t status = 0;
- if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC)) {
- SCH_ERR_JRET(schFetchFromRemote(pJob));
- tsem_wait(&pJob->rspSem);
+ SSchTask *pTask = NULL;
+ SSchJob *pJob = schAcquireJob(rId);
+ if (NULL == pJob) {
+ qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 "job no exist, may be dropped, refId:0x%" PRIx64, qId, tId, rId);
+ SCH_ERR_RET(TSDB_CODE_QRY_JOB_NOT_EXIST);
+ }
+
+ if (schJobNeedToStop(pJob, &status)) {
+ SCH_TASK_DLOG("will not do further processing cause of job status %s", jobTaskStatusStr(status));
+ SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR);
}
- SCH_ERR_JRET(schSetJobFetchRes(pJob, pJob->userRes.fetchRes));
+ SCH_ERR_JRET(schGetTaskInJob(pJob, tId, &pTask));
-_return:
+ SCH_LOCK_TASK(pTask);
- schEndOperation(pJob);
+ *job = pJob;
+ *task = pTask;
- SCH_RET(code);
-}
+ return TSDB_CODE_SUCCESS;
-int32_t schAsyncFetchRows(SSchJob *pJob) {
- int32_t code = 0;
+_return:
- if (pJob->attr.explainMode == EXPLAIN_MODE_STATIC) {
- schPostJobRes(pJob, SCH_OP_FETCH);
- return TSDB_CODE_SUCCESS;
+ if (pTask) {
+ SCH_UNLOCK_TASK(pTask);
+ }
+ if (pJob) {
+ schReleaseJob(rId);
}
- SCH_ERR_RET(schFetchFromRemote(pJob));
-
- return TSDB_CODE_SUCCESS;
+ SCH_RET(code);
}
+
diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c
index 0bd747785cb162ed6ad10b7c7fc6f5f77ab28d9e..1b893739bd846f8e94911c03bbd562d13d6a0370 100644
--- a/source/libs/scheduler/src/schRemote.c
+++ b/source/libs/scheduler/src/schRemote.c
@@ -16,53 +16,41 @@
#include "catalog.h"
#include "command.h"
#include "query.h"
-#include "schedulerInt.h"
+#include "schInt.h"
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
-
-int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) {
- int32_t lastMsgType = SCH_GET_TASK_LASTMSG_TYPE(pTask);
+int32_t schValidateRspMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) {
+ int32_t lastMsgType = pTask->lastMsgType;
int32_t taskStatus = SCH_GET_TASK_STATUS(pTask);
- int32_t reqMsgType = msgType - 1;
+ int32_t reqMsgType = (msgType & 1U) ? msgType : (msgType - 1);
switch (msgType) {
case TDMT_SCH_LINK_BROKEN:
- case TDMT_VND_EXPLAIN_RSP:
- return TSDB_CODE_SUCCESS;
- case TDMT_VND_QUERY_RSP: // query_rsp may be processed later than ready_rsp
- if (lastMsgType != reqMsgType && -1 != lastMsgType) {
- SCH_TASK_DLOG("rsp msg type mis-match, last sent msgType:%s, rspType:%s", TMSG_INFO(lastMsgType),
- TMSG_INFO(msgType));
- }
-
- if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) {
- SCH_TASK_DLOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus),
- TMSG_INFO(msgType));
- }
-
- SCH_SET_TASK_LASTMSG_TYPE(pTask, -1);
+ case TDMT_SCH_EXPLAIN_RSP:
return TSDB_CODE_SUCCESS;
- case TDMT_VND_FETCH_RSP:
- if (lastMsgType != reqMsgType && -1 != lastMsgType) {
+ case TDMT_SCH_FETCH_RSP:
+ case TDMT_SCH_MERGE_FETCH_RSP:
+ if (lastMsgType != reqMsgType) {
SCH_TASK_ELOG("rsp msg type mis-match, last sent msgType:%s, rspType:%s", TMSG_INFO(lastMsgType),
TMSG_INFO(msgType));
SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
}
-
- if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) {
+ if (taskStatus != JOB_TASK_STATUS_PART_SUCC) {
SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus),
TMSG_INFO(msgType));
SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
}
- SCH_SET_TASK_LASTMSG_TYPE(pTask, -1);
return TSDB_CODE_SUCCESS;
+ case TDMT_SCH_MERGE_QUERY_RSP:
+ case TDMT_SCH_QUERY_RSP:
case TDMT_VND_CREATE_TABLE_RSP:
case TDMT_VND_DROP_TABLE_RSP:
case TDMT_VND_ALTER_TABLE_RSP:
case TDMT_VND_SUBMIT_RSP:
case TDMT_VND_DELETE_RSP:
+ case TDMT_VND_COMMIT_RSP:
break;
default:
SCH_TASK_ELOG("unknown rsp msg, type:%s, status:%s", TMSG_INFO(msgType), jobTaskStatusStr(taskStatus));
@@ -75,32 +63,38 @@ int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgTy
SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
}
- if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) {
+ if (taskStatus != JOB_TASK_STATUS_EXEC) {
SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus),
TMSG_INFO(msgType));
SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
}
- SCH_SET_TASK_LASTMSG_TYPE(pTask, -1);
-
return TSDB_CODE_SUCCESS;
}
// Note: no more task error processing, handled in function internal
-int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, char *msg, int32_t msgSize,
- int32_t rspCode) {
+int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) {
int32_t code = 0;
- int8_t status = 0;
+ char *msg = pMsg->pData;
+ int32_t msgSize = pMsg->len;
+ int32_t msgType = pMsg->msgType;
- if (schJobNeedToStop(pJob, &status)) {
- SCH_TASK_ELOG("rsp not processed cause of job status, job status:%s, rspCode:0x%x", jobTaskStatusStr(status), rspCode);
- taosMemoryFreeClear(msg);
- SCH_RET(atomic_load_32(&pJob->errCode));
- }
+ bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode));
+ SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, execId));
+
+ SCH_ERR_JRET(schValidateRspMsgType(pJob, pTask, msgType));
- SCH_ERR_JRET(schValidateReceivedMsgType(pJob, pTask, msgType));
+ int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1);
+ if (SCH_TASK_NEED_REDIRECT(pTask, reqType, rspCode, pMsg->len)) {
+ SCH_RET(schHandleRedirect(pJob, pTask, (SDataBuf *)pMsg, rspCode));
+ }
switch (msgType) {
+ case TDMT_VND_COMMIT_RSP: {
+ SCH_ERR_JRET(rspCode);
+ SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
+ break;
+ }
case TDMT_VND_CREATE_TABLE_RSP: {
SVCreateTbBatchRsp batchRsp = {0};
if (msg) {
@@ -122,8 +116,8 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
}
SCH_ERR_JRET(rspCode);
- taosMemoryFreeClear(msg);
-
+ taosMemoryFreeClear(msg);
+
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
break;
}
@@ -148,8 +142,8 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
}
SCH_ERR_JRET(rspCode);
- taosMemoryFreeClear(msg);
-
+ taosMemoryFreeClear(msg);
+
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
break;
}
@@ -162,7 +156,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
tDecoderClear(&coder);
SCH_ERR_JRET(code);
SCH_ERR_JRET(rsp.code);
-
+
pJob->execRes.res = rsp.pMeta;
pJob->execRes.msgType = TDMT_VND_ALTER_TABLE;
}
@@ -173,8 +167,8 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
}
- taosMemoryFreeClear(msg);
-
+ taosMemoryFreeClear(msg);
+
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
break;
}
@@ -222,7 +216,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
SCH_UNLOCK(SCH_WRITE, &pJob->resLock);
}
- taosMemoryFreeClear(msg);
+ taosMemoryFreeClear(msg);
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
@@ -232,7 +226,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
SCH_ERR_JRET(rspCode);
if (msg) {
- SDecoder coder = {0};
+ SDecoder coder = {0};
SVDeleteRsp rsp = {0};
tDecoderInit(&coder, msg, msgSize);
tDecodeSVDeleteRsp(&coder, &rsp);
@@ -246,25 +240,33 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
break;
- }
- case TDMT_VND_QUERY_RSP: {
- SQueryTableRsp *rsp = (SQueryTableRsp *)msg;
-
+ }
+ case TDMT_SCH_QUERY_RSP:
+ case TDMT_SCH_MERGE_QUERY_RSP: {
SCH_ERR_JRET(rspCode);
if (NULL == msg) {
SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
}
+
+ SQueryTableRsp *rsp = (SQueryTableRsp *)msg;
+ rsp->code = ntohl(rsp->code);
+ rsp->sversion = ntohl(rsp->sversion);
+ rsp->tversion = ntohl(rsp->tversion);
+ rsp->affectedRows = be64toh(rsp->affectedRows);
+
SCH_ERR_JRET(rsp->code);
SCH_ERR_JRET(schSaveJobQueryRes(pJob, rsp));
- taosMemoryFreeClear(msg);
-
+ atomic_add_fetch_32(&pJob->resNumOfRows, rsp->affectedRows);
+
+ taosMemoryFreeClear(msg);
+
SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask));
break;
}
- case TDMT_VND_EXPLAIN_RSP: {
+ case TDMT_SCH_EXPLAIN_RSP: {
SCH_ERR_JRET(rspCode);
if (NULL == msg) {
SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
@@ -294,7 +296,8 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
}
break;
}
- case TDMT_VND_FETCH_RSP: {
+ case TDMT_SCH_FETCH_RSP:
+ case TDMT_SCH_MERGE_FETCH_RSP: {
SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)msg;
SCH_ERR_JRET(rspCode);
@@ -310,14 +313,14 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
SCH_ERR_JRET(schProcessOnExplainDone(pJob, pTask, pRsp));
}
- taosMemoryFreeClear(msg);
+ taosMemoryFreeClear(msg);
return TSDB_CODE_SUCCESS;
}
- SCH_ERR_JRET(schFetchFromRemote(pJob));
+ SCH_ERR_JRET(schLaunchFetchTask(pJob));
- taosMemoryFreeClear(msg);
+ taosMemoryFreeClear(msg);
return TSDB_CODE_SUCCESS;
}
@@ -332,18 +335,18 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch
atomic_add_fetch_32(&pJob->resNumOfRows, htonl(rsp->numOfRows));
if (rsp->completed) {
- SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCCEED);
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCC);
}
SCH_TASK_DLOG("got fetch rsp, rows:%d, complete:%d", htonl(rsp->numOfRows), rsp->completed);
- msg = NULL;
+ msg = NULL;
schProcessOnDataFetched(pJob);
break;
}
- case TDMT_VND_DROP_TASK_RSP: {
- // SHOULD NEVER REACH HERE
+ case TDMT_SCH_DROP_TASK_RSP: {
+ // NEVER REACH HERE
SCH_TASK_ELOG("invalid status to handle drop task rsp, refId:0x%" PRIx64, pJob->refId);
SCH_ERR_JRET(TSDB_CODE_SCH_INTERNAL_ERROR);
break;
@@ -366,89 +369,40 @@ _return:
SCH_RET(schProcessOnTaskFailure(pJob, pTask, code));
}
-
-int32_t schHandleCallback(void *param, const SDataBuf *pMsg, int32_t msgType, int32_t rspCode) {
+int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) {
int32_t code = 0;
SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param;
SSchTask *pTask = NULL;
+ SSchJob *pJob = NULL;
- SSchJob *pJob = schAcquireJob(pParam->refId);
- if (NULL == pJob) {
- qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 "taosAcquireRef job failed, may be dropped, refId:0x%" PRIx64,
- pParam->queryId, pParam->taskId, pParam->refId);
- SCH_ERR_JRET(TSDB_CODE_QRY_JOB_FREED);
- }
-
- SCH_ERR_JRET(schGetTaskInJob(pJob, pParam->taskId, &pTask));
-
- SCH_LOCK_TASK(pTask);
-
- SCH_TASK_DLOG("rsp msg received, type:%s, handle:%p, code:%s", TMSG_INFO(msgType), pMsg->handle, tstrerror(rspCode));
-
- if (pParam->execIdx != pTask->execIdx) {
- SCH_TASK_DLOG("execIdx %d mis-match current execIdx %d", pParam->execIdx, pTask->execIdx);
- goto _return;
- }
+ qDebug("begin to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle,
+ tstrerror(rspCode));
- bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || rspCode == TSDB_CODE_RPC_NETWORK_UNAVAIL);
- SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, pParam->execIdx));
-
- SCH_ERR_JRET(schHandleResponseMsg(pJob, pTask, msgType, pMsg->pData, pMsg->len, rspCode));
+ SCH_ERR_RET(schProcessOnCbBegin(&pJob, &pTask, pParam->queryId, pParam->refId, pParam->taskId));
-_return:
+ code = schHandleResponseMsg(pJob, pTask, pParam->execId, pMsg, rspCode);
+ pMsg->pData = NULL;
- if (pTask) {
- SCH_UNLOCK_TASK(pTask);
- }
-
- if (pJob) {
- schReleaseJob(pParam->refId);
- }
+ schProcessOnCbEnd(pJob, pTask, code);
+ taosMemoryFreeClear(pMsg->pData);
taosMemoryFreeClear(param);
- SCH_RET(code);
-}
-int32_t schHandleSubmitCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_SUBMIT_RSP, code);
-}
-
-int32_t schHandleCreateTbCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_CREATE_TABLE_RSP, code);
-}
-
-int32_t schHandleDropTbCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_DROP_TABLE_RSP, code);
-}
-
-int32_t schHandleAlterTbCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_ALTER_TABLE_RSP, code);
-}
+ qDebug("end to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle,
+ tstrerror(rspCode));
-int32_t schHandleQueryCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_QUERY_RSP, code);
-}
-
-int32_t schHandleDeleteCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_DELETE_RSP, code);
-}
-
-int32_t schHandleFetchCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_FETCH_RSP, code);
-}
-
-int32_t schHandleExplainCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- return schHandleCallback(param, pMsg, TDMT_VND_EXPLAIN_RSP, code);
+ SCH_RET(code);
}
-int32_t schHandleDropCallback(void *param, const SDataBuf *pMsg, int32_t code) {
+int32_t schHandleDropCallback(void *param, SDataBuf *pMsg, int32_t code) {
SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param;
- qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " drop task rsp received, code:0x%x", pParam->queryId, pParam->taskId, code);
+ qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " drop task rsp received, code:0x%x", pParam->queryId, pParam->taskId,
+ code);
taosMemoryFreeClear(param);
return TSDB_CODE_SUCCESS;
}
-int32_t schHandleLinkBrokenCallback(void *param, const SDataBuf *pMsg, int32_t code) {
+int32_t schHandleLinkBrokenCallback(void *param, SDataBuf *pMsg, int32_t code) {
SSchCallbackParamHeader *head = (SSchCallbackParamHeader *)param;
rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT);
@@ -461,26 +415,60 @@ int32_t schHandleLinkBrokenCallback(void *param, const SDataBuf *pMsg, int32_t c
SCH_ERR_RET(schBuildAndSendHbMsg(&hbParam->nodeEpId, NULL));
} else {
- SCH_ERR_RET(schHandleCallback(param, pMsg, TDMT_SCH_LINK_BROKEN, code));
+ SCH_ERR_RET(schHandleCallback(param, pMsg, code));
}
return TSDB_CODE_SUCCESS;
}
+int32_t schHandleCommitCallback(void *param, SDataBuf *pMsg, int32_t code) {
+ return schHandleCallback(param, pMsg, code);
+}
+
+int32_t schHandleHbCallback(void *param, SDataBuf *pMsg, int32_t code) {
+ SSchedulerHbRsp rsp = {0};
+ SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param;
-int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bool isHb, SSchTrans *trans, void **pParam) {
+ if (code) {
+ qError("hb rsp error:%s", tstrerror(code));
+ SCH_ERR_JRET(code);
+ }
+
+ if (tDeserializeSSchedulerHbRsp(pMsg->pData, pMsg->len, &rsp)) {
+ qError("invalid hb rsp msg, size:%d", pMsg->len);
+ SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
+ }
+
+ SSchTrans trans = {0};
+ trans.pTrans = pParam->pTrans;
+ trans.pHandle = pMsg->handle;
+
+ SCH_ERR_JRET(schUpdateHbConnection(&rsp.epId, &trans));
+
+ SCH_ERR_JRET(schProcessOnTaskStatusRsp(&rsp.epId, rsp.taskStatus));
+
+_return:
+
+ tFreeSSchedulerHbRsp(&rsp);
+ taosMemoryFree(param);
+
+ SCH_RET(code);
+}
+
+int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bool isHb, SSchTrans *trans,
+ void **pParam) {
if (!isHb) {
SSchTaskCallbackParam *param = taosMemoryCalloc(1, sizeof(SSchTaskCallbackParam));
if (NULL == param) {
SCH_TASK_ELOG("calloc %d failed", (int32_t)sizeof(SSchTaskCallbackParam));
SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
-
+
param->queryId = pJob->queryId;
param->refId = pJob->refId;
param->taskId = SCH_TASK_ID(pTask);
param->pTrans = pJob->conn.pTrans;
- param->execIdx = pTask->execIdx;
+ param->execId = pTask->execId;
*pParam = param;
return TSDB_CODE_SUCCESS;
@@ -492,19 +480,19 @@ int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bo
SCH_TASK_ELOG("calloc %d failed", (int32_t)sizeof(SSchHbCallbackParam));
SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
-
+
param->head.isHbParam = true;
-
+
SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx);
param->nodeEpId.nodeId = addr->nodeId;
- SEp* pEp = SCH_GET_CUR_EP(addr);
+ SEp *pEp = SCH_GET_CUR_EP(addr);
strcpy(param->nodeEpId.ep.fqdn, pEp->fqdn);
param->nodeEpId.ep.port = pEp->port;
param->pTrans = trans->pTrans;
*pParam = param;
return TSDB_CODE_SUCCESS;
- }
+ }
// hb msg
SSchTaskCallbackParam *param = taosMemoryCalloc(1, sizeof(SSchTaskCallbackParam));
@@ -512,14 +500,15 @@ int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bo
qError("calloc SSchTaskCallbackParam failed");
SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
-
+
param->pTrans = trans->pTrans;
*pParam = param;
return TSDB_CODE_SUCCESS;
}
-int32_t schGenerateCallBackInfo(SSchJob *pJob, SSchTask *pTask, void* msg, uint32_t msgSize, int32_t msgType, SSchTrans *trans, bool isHb, SMsgSendInfo **pMsgSendInfo) {
+int32_t schGenerateCallBackInfo(SSchJob *pJob, SSchTask *pTask, void *msg, uint32_t msgSize, int32_t msgType,
+ SSchTrans *trans, bool isHb, SMsgSendInfo **pMsgSendInfo) {
int32_t code = 0;
SMsgSendInfo *msgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
if (NULL == msgSendInfo) {
@@ -534,7 +523,7 @@ int32_t schGenerateCallBackInfo(SSchJob *pJob, SSchTask *pTask, void* msg, uint3
msgSendInfo->requestId = pJob->conn.requestId;
msgSendInfo->requestObjRefId = pJob->conn.requestObjRefId;
}
-
+
if (TDMT_SCH_LINK_BROKEN != msgType) {
msgSendInfo->msgInfo.pData = msg;
msgSendInfo->msgInfo.len = msgSize;
@@ -553,39 +542,29 @@ _return:
SCH_RET(code);
}
-
int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp) {
switch (msgType) {
case TDMT_VND_CREATE_TABLE:
- *fp = schHandleCreateTbCallback;
- break;
case TDMT_VND_DROP_TABLE:
- *fp = schHandleDropTbCallback;
- break;
case TDMT_VND_ALTER_TABLE:
- *fp = schHandleAlterTbCallback;
- break;
case TDMT_VND_SUBMIT:
- *fp = schHandleSubmitCallback;
- break;
- case TDMT_VND_QUERY:
- *fp = schHandleQueryCallback;
- break;
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY:
case TDMT_VND_DELETE:
- *fp = schHandleDeleteCallback;
- break;
- case TDMT_VND_EXPLAIN:
- *fp = schHandleExplainCallback;
+ case TDMT_SCH_EXPLAIN:
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH:
+ *fp = schHandleCallback;
break;
- case TDMT_VND_FETCH:
- *fp = schHandleFetchCallback;
- break;
- case TDMT_VND_DROP_TASK:
+ case TDMT_SCH_DROP_TASK:
*fp = schHandleDropCallback;
break;
- case TDMT_VND_QUERY_HEARTBEAT:
+ case TDMT_SCH_QUERY_HEARTBEAT:
*fp = schHandleHbCallback;
break;
+ case TDMT_VND_COMMIT:
+ *fp = schHandleCommitCallback;
+ break;
case TDMT_SCH_LINK_BROKEN:
*fp = schHandleLinkBrokenCallback;
break;
@@ -663,7 +642,6 @@ _return:
SCH_RET(code);
}
-
int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx) {
int32_t code = 0;
SSchHbCallbackParam *param = NULL;
@@ -692,9 +670,9 @@ int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx) {
SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- int32_t msgType = TDMT_VND_QUERY_HEARTBEAT_RSP;
+ int32_t msgType = TDMT_SCH_QUERY_HEARTBEAT_RSP;
__async_send_cb_fn_t fp = NULL;
- SCH_ERR_JRET(schGetCallbackFp(TDMT_VND_QUERY_HEARTBEAT, &fp));
+ SCH_ERR_JRET(schGetCallbackFp(TDMT_SCH_QUERY_HEARTBEAT, &fp));
param->nodeEpId = epId;
param->pTrans = pJob->conn.pTrans;
@@ -722,40 +700,10 @@ _return:
SCH_RET(code);
}
-int32_t schHandleHbCallback(void *param, const SDataBuf *pMsg, int32_t code) {
- SSchedulerHbRsp rsp = {0};
- SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param;
-
- if (code) {
- qError("hb rsp error:%s", tstrerror(code));
- SCH_ERR_JRET(code);
- }
-
- if (tDeserializeSSchedulerHbRsp(pMsg->pData, pMsg->len, &rsp)) {
- qError("invalid hb rsp msg, size:%d", pMsg->len);
- SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
- }
-
- SSchTrans trans = {0};
- trans.pTrans = pParam->pTrans;
- trans.pHandle = pMsg->handle;
-
- SCH_ERR_JRET(schUpdateHbConnection(&rsp.epId, &trans));
-
- SCH_ERR_JRET(schProcessOnTaskStatusRsp(&rsp.epId, rsp.taskStatus));
-
-_return:
-
- tFreeSSchedulerHbRsp(&rsp);
- taosMemoryFree(param);
-
- SCH_RET(code);
-}
-
int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb) {
- int32_t code = 0;
- int32_t msgType = TDMT_SCH_LINK_BROKEN;
- SSchTrans trans = {.pTrans = pJob->conn.pTrans};
+ int32_t code = 0;
+ int32_t msgType = TDMT_SCH_LINK_BROKEN;
+ SSchTrans trans = {.pTrans = pJob->conn.pTrans};
SMsgSendInfo *pMsgSendInfo = NULL;
SCH_ERR_JRET(schGenerateCallBackInfo(pJob, pTask, NULL, 0, msgType, &trans, isHb, &pMsgSendInfo));
@@ -784,9 +732,9 @@ int32_t schMakeQueryRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx) {
}
SSchTrans trans = {.pTrans = pJob->conn.pTrans, .pHandle = SCH_GET_TASK_HANDLE(pTask)};
- SCH_ERR_JRET(schGenerateCallBackInfo(pJob, pTask, NULL, 0, TDMT_VND_EXPLAIN, &trans, false, &pExplainMsgSendInfo));
+ SCH_ERR_JRET(schGenerateCallBackInfo(pJob, pTask, NULL, 0, TDMT_SCH_EXPLAIN, &trans, false, &pExplainMsgSendInfo));
- int32_t msgType = TDMT_VND_EXPLAIN_RSP;
+ int32_t msgType = TDMT_SCH_EXPLAIN_RSP;
SRpcCtxVal ctxVal = {.val = pExplainMsgSendInfo, .clone = schCloneSMsgSendInfo};
if (taosHashPut(pCtx->args, &msgType, sizeof(msgType), &ctxVal, sizeof(ctxVal))) {
SCH_TASK_ELOG("taosHashPut msg %d to rpcCtx failed", msgType);
@@ -876,20 +824,22 @@ int32_t schUpdateSendTargetInfo(SMsgSendInfo *pMsgSendInfo, SQueryNodeAddr *addr
return TSDB_CODE_SUCCESS;
}
-int32_t schAsyncSendMsg(SSchJob *pJob, SSchTask *pTask, SSchTrans *trans, SQueryNodeAddr *addr, int32_t msgType, void *msg,
- uint32_t msgSize, bool persistHandle, SRpcCtx *ctx) {
+int32_t schAsyncSendMsg(SSchJob *pJob, SSchTask *pTask, SSchTrans *trans, SQueryNodeAddr *addr, int32_t msgType,
+ void *msg, uint32_t msgSize, bool persistHandle, SRpcCtx *ctx) {
int32_t code = 0;
SEpSet *epSet = &addr->epSet;
SMsgSendInfo *pMsgSendInfo = NULL;
- bool isHb = (TDMT_VND_QUERY_HEARTBEAT == msgType);
+ bool isHb = (TDMT_SCH_QUERY_HEARTBEAT == msgType);
SCH_ERR_JRET(schGenerateCallBackInfo(pJob, pTask, msg, msgSize, msgType, trans, isHb, &pMsgSendInfo));
- SCH_ERR_JRET(schUpdateSendTargetInfo(pMsgSendInfo, addr, pTask));
+ SCH_ERR_JRET(schUpdateSendTargetInfo(pMsgSendInfo, addr, pTask));
- qDebug("start to send %s msg to node[%d,%s,%d], pTrans:%p, pHandle:%p", TMSG_INFO(msgType),
- addr->nodeId, epSet->eps[epSet->inUse].fqdn, epSet->eps[epSet->inUse].port,
- trans->pTrans, trans->pHandle);
+ qDebug("start to send %s msg to node[%d,%s,%d], pTrans:%p, pHandle:%p", TMSG_INFO(msgType), addr->nodeId,
+ epSet->eps[epSet->inUse].fqdn, epSet->eps[epSet->inUse].port, trans->pTrans, trans->pHandle);
+ if (pTask) {
+ pTask->lastMsgType = msgType;
+ }
int64_t transporterId = 0;
code = asyncSendMsgToServerExt(trans->pTrans, epSet, &transporterId, pMsgSendInfo, persistHandle, ctx);
@@ -920,13 +870,12 @@ _return:
SCH_RET(code);
}
-
-int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray* taskAction) {
+int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray *taskAction) {
SSchedulerHbReq req = {0};
int32_t code = 0;
SRpcCtx rpcCtx = {0};
SSchTrans trans = {0};
- int32_t msgType = TDMT_VND_QUERY_HEARTBEAT;
+ int32_t msgType = TDMT_SCH_QUERY_HEARTBEAT;
req.header.vgId = nodeEpId->nodeId;
req.sId = schMgmt.sId;
@@ -965,7 +914,7 @@ int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray* taskAction) {
SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- int64_t transporterId = 0;
+ int64_t transporterId = 0;
SQueryNodeAddr addr = {.nodeId = nodeEpId->nodeId};
addr.epSet.inUse = 0;
addr.epSet.numOfEps = 1;
@@ -993,14 +942,16 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
if (NULL == addr) {
addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx);
isCandidateAddr = true;
- SCH_TASK_DLOG("target candidateIdx %d", pTask->candidateIdx);
+ SCH_TASK_DLOG("target candidateIdx %d, epInUse %d/%d", pTask->candidateIdx, addr->epSet.inUse,
+ addr->epSet.numOfEps);
}
switch (msgType) {
case TDMT_VND_CREATE_TABLE:
case TDMT_VND_DROP_TABLE:
case TDMT_VND_ALTER_TABLE:
- case TDMT_VND_SUBMIT: {
+ case TDMT_VND_SUBMIT:
+ case TDMT_VND_COMMIT: {
msgSize = pTask->msgLen;
msg = taosMemoryCalloc(1, msgSize);
if (NULL == msg) {
@@ -1020,7 +971,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
req.taskId = pTask->taskId;
req.phyLen = pTask->msgLen;
req.sqlLen = strlen(pJob->sql);
- req.sql = (char*)pJob->sql;
+ req.sql = (char *)pJob->sql;
req.msg = pTask->msg;
msgSize = tSerializeSVDeleteReq(NULL, 0, &req);
msg = taosMemoryCalloc(1, msgSize);
@@ -1032,7 +983,8 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
tSerializeSVDeleteReq(msg, msgSize, &req);
break;
}
- case TDMT_VND_QUERY: {
+ case TDMT_SCH_QUERY:
+ case TDMT_SCH_MERGE_QUERY: {
SCH_ERR_RET(schMakeQueryRpcCtx(pJob, pTask, &rpcCtx));
uint32_t len = strlen(pJob->sql);
@@ -1049,8 +1001,10 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
pMsg->queryId = htobe64(pJob->queryId);
pMsg->taskId = htobe64(pTask->taskId);
pMsg->refId = htobe64(pJob->refId);
+ pMsg->execId = htonl(pTask->execId);
pMsg->taskType = TASK_TYPE_TEMP;
pMsg->explain = SCH_IS_EXPLAIN_JOB(pJob);
+ pMsg->needFetch = SCH_TASK_NEED_FETCH(pTask);
pMsg->phyLen = htonl(pTask->msgLen);
pMsg->sqlLen = htonl(len);
@@ -1060,7 +1014,8 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
persistHandle = true;
break;
}
- case TDMT_VND_FETCH: {
+ case TDMT_SCH_FETCH:
+ case TDMT_SCH_MERGE_FETCH: {
msgSize = sizeof(SResFetchReq);
msg = taosMemoryCalloc(1, msgSize);
if (NULL == msg) {
@@ -1075,10 +1030,11 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
pMsg->sId = htobe64(schMgmt.sId);
pMsg->queryId = htobe64(pJob->queryId);
pMsg->taskId = htobe64(pTask->taskId);
+ pMsg->execId = htonl(pTask->execId);
break;
}
- case TDMT_VND_DROP_TASK: {
+ case TDMT_SCH_DROP_TASK: {
msgSize = sizeof(STaskDropReq);
msg = taosMemoryCalloc(1, msgSize);
if (NULL == msg) {
@@ -1094,9 +1050,10 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
pMsg->queryId = htobe64(pJob->queryId);
pMsg->taskId = htobe64(pTask->taskId);
pMsg->refId = htobe64(pJob->refId);
+ pMsg->execId = htonl(pTask->execId);
break;
}
- case TDMT_VND_QUERY_HEARTBEAT: {
+ case TDMT_SCH_QUERY_HEARTBEAT: {
SCH_ERR_RET(schMakeHbRpcCtx(pJob, pTask, &rpcCtx));
SSchedulerHbReq req = {0};
@@ -1129,26 +1086,21 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
break;
}
- SCH_SET_TASK_LASTMSG_TYPE(pTask, msgType);
-
SSchTrans trans = {.pTrans = pJob->conn.pTrans, .pHandle = SCH_GET_TASK_HANDLE(pTask)};
- SCH_ERR_JRET(schAsyncSendMsg(pJob, pTask, &trans, addr, msgType, msg, msgSize, persistHandle,
- (rpcCtx.args ? &rpcCtx : NULL)));
+ SCH_ERR_JRET(
+ schAsyncSendMsg(pJob, pTask, &trans, addr, msgType, msg, msgSize, persistHandle, (rpcCtx.args ? &rpcCtx : NULL)));
- if (msgType == TDMT_VND_QUERY) {
- SCH_ERR_RET(schAppendTaskExecNode(pJob, pTask, addr, pTask->execIdx));
+ if (msgType == TDMT_SCH_QUERY || msgType == TDMT_SCH_MERGE_QUERY) {
+ SCH_ERR_RET(schAppendTaskExecNode(pJob, pTask, addr, pTask->execId));
}
return TSDB_CODE_SUCCESS;
_return:
- SCH_SET_TASK_LASTMSG_TYPE(pTask, -1);
+ pTask->lastMsgType = -1;
schFreeRpcCtx(&rpcCtx);
taosMemoryFreeClear(msg);
SCH_RET(code);
}
-
-
-
diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c
new file mode 100644
index 0000000000000000000000000000000000000000..a4fa4f283913c785dca72944b2b3178e4ce5d84f
--- /dev/null
+++ b/source/libs/scheduler/src/schStatus.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "catalog.h"
+#include "command.h"
+#include "query.h"
+#include "schInt.h"
+#include "tmsg.h"
+#include "tref.h"
+#include "trpc.h"
+
+int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param) {
+ int32_t code = 0;
+ SCH_ERR_JRET(schUpdateJobStatus(pJob, status));
+
+ switch (status) {
+ case JOB_TASK_STATUS_INIT:
+ break;
+ case JOB_TASK_STATUS_EXEC:
+ SCH_ERR_JRET(schExecJob(pJob, (SSchedulerReq*)param));
+ break;
+ case JOB_TASK_STATUS_PART_SUCC:
+ SCH_ERR_JRET(schProcessOnJobPartialSuccess(pJob));
+ break;
+ case JOB_TASK_STATUS_SUCC:
+ break;
+ case JOB_TASK_STATUS_FAIL:
+ SCH_RET(schProcessOnJobFailure(pJob, (param ? *(int32_t*)param : 0)));
+ break;
+ case JOB_TASK_STATUS_DROP:
+ schProcessOnJobDropped(pJob, *(int32_t*)param);
+
+ if (taosRemoveRef(schMgmt.jobRef, pJob->refId)) {
+ SCH_JOB_ELOG("remove job from job list failed, refId:0x%" PRIx64, pJob->refId);
+ } else {
+ SCH_JOB_DLOG("job removed from jobRef list, refId:0x%" PRIx64, pJob->refId);
+ }
+ break;
+ default: {
+ SCH_JOB_ELOG("unknown job status %d", status);
+ SCH_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ SCH_RET(schProcessOnJobFailure(pJob, code));
+}
+
+int32_t schHandleOpBeginEvent(int64_t jobId, SSchJob** job, SCH_OP_TYPE type, SSchedulerReq* pReq) {
+ SSchJob *pJob = schAcquireJob(jobId);
+ if (NULL == pJob) {
+ qError("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, jobId);
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ *job = pJob;
+
+ SCH_RET(schProcessOnOpBegin(pJob, type, pReq));
+}
+
+int32_t schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) {
+ int32_t code = errCode;
+
+ if (NULL == pJob) {
+ schDirectPostJobRes(pReq, errCode);
+ SCH_RET(code);
+ }
+
+ schProcessOnOpEnd(pJob, type, pReq, errCode);
+
+ if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) {
+ code = pJob->errCode;
+ }
+
+ schReleaseJob(pJob->refId);
+
+ return code;
+}
+
+
diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c
new file mode 100644
index 0000000000000000000000000000000000000000..236257666b23b93d174f8f1126497f061dfd90c9
--- /dev/null
+++ b/source/libs/scheduler/src/schTask.c
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "catalog.h"
+#include "command.h"
+#include "query.h"
+#include "schInt.h"
+#include "tmsg.h"
+#include "tref.h"
+#include "trpc.h"
+
+void schFreeTask(SSchJob *pJob, SSchTask *pTask) {
+ schDeregisterTaskHb(pJob, pTask);
+
+ if (pTask->candidateAddrs) {
+ taosArrayDestroy(pTask->candidateAddrs);
+ }
+
+ taosMemoryFreeClear(pTask->msg);
+
+ if (pTask->children) {
+ taosArrayDestroy(pTask->children);
+ }
+
+ if (pTask->parents) {
+ taosArrayDestroy(pTask->parents);
+ }
+
+ if (pTask->execNodes) {
+ taosHashCleanup(pTask->execNodes);
+ }
+
+ taosMemoryFree(pTask->profile.execTime);
+}
+
+int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel, int32_t levelNum) {
+ int32_t code = 0;
+
+ pTask->plan = pPlan;
+ pTask->level = pLevel;
+ pTask->execId = -1;
+ pTask->maxExecTimes = SCH_TASK_MAX_EXEC_TIMES(pLevel->level, levelNum);
+ pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC;
+ pTask->taskId = schGenTaskId();
+ pTask->execNodes =
+ taosHashInit(SCH_MAX_CANDIDATE_EP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
+ pTask->profile.execTime = taosMemoryCalloc(pTask->maxExecTimes, sizeof(int64_t));
+ if (NULL == pTask->execNodes || NULL == pTask->profile.execTime) {
+ SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT);
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ taosMemoryFreeClear(pTask->profile.execTime);
+ taosHashCleanup(pTask->execNodes);
+
+ SCH_RET(code);
+}
+
+int32_t schRecordTaskSucceedNode(SSchJob *pJob, SSchTask *pTask) {
+ SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx);
+ if (NULL == addr) {
+ SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", pTask->candidateIdx,
+ (int32_t)taosArrayGetSize(pTask->candidateAddrs));
+ SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
+ }
+
+ pTask->succeedAddr = *addr;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execId) {
+ SSchNodeInfo nodeInfo = {.addr = *addr, .handle = NULL};
+
+ if (taosHashPut(pTask->execNodes, &execId, sizeof(execId), &nodeInfo, sizeof(nodeInfo))) {
+ SCH_TASK_ELOG("taosHashPut nodeInfo to execNodes failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ SCH_TASK_DLOG("task execNode added, execId:%d", execId);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schDropTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) {
+ if (NULL == pTask->execNodes) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (taosHashRemove(pTask->execNodes, &execId, sizeof(execId))) {
+ SCH_TASK_ELOG("fail to remove execId %d from execNodeList", execId);
+ } else {
+ SCH_TASK_DLOG("execId %d removed from execNodeList", execId);
+ }
+
+ if (execId != pTask->execId) { // ignore it
+ SCH_TASK_DLOG("execId %d is not current execId %d", execId, pTask->execId);
+ SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) {
+ if (taosHashGetSize(pTask->execNodes) <= 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SSchNodeInfo *nodeInfo = taosHashGet(pTask->execNodes, &execId, sizeof(execId));
+ nodeInfo->handle = handle;
+
+ SCH_TASK_DLOG("handle updated to %p for execId %d", handle, execId);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId) {
+ if (dropExecNode) {
+ SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execId));
+ }
+
+ SCH_SET_TASK_HANDLE(pTask, handle);
+
+ schUpdateTaskExecNode(pJob, pTask, handle, execId);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+// Note: no more task error processing, handled in function internal
+int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) {
+ if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) {
+ return TSDB_CODE_SCH_IGNORE_ERROR;
+ }
+
+ int8_t status = 0;
+ if (schJobNeedToStop(pJob, &status)) {
+ SCH_TASK_DLOG("no more task failure processing cause of job status %s", jobTaskStatusStr(status));
+ SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR);
+ }
+
+ if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) {
+ SCH_TASK_ELOG("task already not in EXEC status, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ if (errCode == TSDB_CODE_SCH_TIMEOUT_ERROR) {
+ SCH_LOG_TASK_WAIT_TS(pTask);
+ } else {
+ SCH_LOG_TASK_END_TS(pTask);
+ }
+
+ bool needRetry = false;
+ bool moved = false;
+ int32_t taskDone = 0;
+
+ SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode));
+
+ SCH_ERR_RET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry));
+
+ if (!needRetry) {
+ SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode));
+
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAIL);
+
+ if (SCH_JOB_NEED_WAIT(pJob)) {
+ SCH_LOCK(SCH_WRITE, &pTask->level->lock);
+ pTask->level->taskFailed++;
+ taskDone = pTask->level->taskSucceed + pTask->level->taskFailed;
+ SCH_UNLOCK(SCH_WRITE, &pTask->level->lock);
+
+ schUpdateJobErrCode(pJob, errCode);
+
+ if (taskDone < pTask->level->taskNum) {
+ SCH_TASK_DLOG("need to wait other tasks, doneNum:%d, allNum:%d", taskDone, pTask->level->taskNum);
+ SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR);
+ }
+
+ SCH_RET(atomic_load_32(&pJob->errCode));
+ }
+ } else {
+ SCH_ERR_RET(schHandleTaskRetry(pJob, pTask));
+
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SCH_RET(errCode);
+}
+
+// Note: no more task error processing, handled in function internal
+int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) {
+ bool moved = false;
+ int32_t code = 0;
+
+ SCH_TASK_DLOG("taskOnSuccess, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+
+ SCH_LOG_TASK_END_TS(pTask);
+
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PART_SUCC);
+
+ SCH_ERR_RET(schRecordTaskSucceedNode(pJob, pTask));
+
+ SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask));
+
+ int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0;
+ if (parentNum == 0) {
+ int32_t taskDone = 0;
+ if (SCH_JOB_NEED_WAIT(pJob)) {
+ SCH_LOCK(SCH_WRITE, &pTask->level->lock);
+ pTask->level->taskSucceed++;
+ taskDone = pTask->level->taskSucceed + pTask->level->taskFailed;
+ SCH_UNLOCK(SCH_WRITE, &pTask->level->lock);
+
+ if (taskDone < pTask->level->taskNum) {
+ SCH_TASK_DLOG("wait all tasks, done:%d, all:%d", taskDone, pTask->level->taskNum);
+ return TSDB_CODE_SUCCESS;
+ } else if (taskDone > pTask->level->taskNum) {
+ SCH_TASK_ELOG("taskDone number invalid, done:%d, total:%d", taskDone, pTask->level->taskNum);
+ }
+
+ if (pTask->level->taskFailed > 0) {
+ SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, NULL));
+ } else {
+ SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL));
+ }
+ } else {
+ pJob->resNode = pTask->succeedAddr;
+ }
+
+ pJob->fetchTask = pTask;
+
+ SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL));
+ }
+
+ /*
+ if (SCH_IS_DATA_SRC_TASK(task) && job->dataSrcEps.numOfEps < SCH_MAX_CANDIDATE_EP_NUM) {
+ strncpy(job->dataSrcEps.fqdn[job->dataSrcEps.numOfEps], task->execAddr.fqdn, sizeof(task->execAddr.fqdn));
+ job->dataSrcEps.port[job->dataSrcEps.numOfEps] = task->execAddr.port;
+
+ ++job->dataSrcEps.numOfEps;
+ }
+ */
+
+ for (int32_t i = 0; i < parentNum; ++i) {
+ SSchTask *parent = *(SSchTask **)taosArrayGet(pTask->parents, i);
+ int32_t readyNum = atomic_add_fetch_32(&parent->childReady, 1);
+
+ SCH_LOCK(SCH_WRITE, &parent->planLock);
+ SDownstreamSourceNode source = {
+ .type = QUERY_NODE_DOWNSTREAM_SOURCE,
+ .taskId = pTask->taskId,
+ .schedId = schMgmt.sId,
+ .execId = pTask->execId,
+ .addr = pTask->succeedAddr,
+ .fetchMsgType = SCH_FETCH_TYPE(pTask),
+ };
+ qSetSubplanExecutionNode(parent->plan, pTask->plan->id.groupId, &source);
+ SCH_UNLOCK(SCH_WRITE, &parent->planLock);
+
+ if (SCH_TASK_READY_FOR_LAUNCH(readyNum, parent)) {
+ SCH_TASK_DLOG("all %d children task done, start to launch parent task 0x%" PRIx64, readyNum, parent->taskId);
+ SCH_ERR_RET(schLaunchTask(pJob, parent));
+ }
+ }
+
+ SCH_ERR_RET(schLaunchJobLowerLevel(pJob, pTask));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) {
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (SCH_TASK_TIMEOUT(pTask) && JOB_TASK_STATUS_EXEC == pTask->status && pJob->fetchTask != pTask &&
+ taosArrayGetSize(pTask->candidateAddrs) > 1) {
+ SCH_TASK_DLOG("task execId %d will be rescheduled now", pTask->execId);
+ schDropTaskOnExecNode(pJob, pTask);
+ taosHashClear(pTask->execNodes);
+
+ SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR));
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) {
+ int32_t code = 0;
+
+ if ((pTask->execId + 1) >= pTask->maxExecTimes) {
+ SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId);
+ schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void *)&rspCode);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SCH_TASK_DLOG("task will be redirected now, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+
+ schDropTaskOnExecNode(pJob, pTask);
+ taosHashClear(pTask->execNodes);
+ SCH_ERR_JRET(schRemoveTaskFromExecList(pJob, pTask));
+ schDeregisterTaskHb(pJob, pTask);
+ atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1);
+ taosMemoryFreeClear(pTask->msg);
+ pTask->msgLen = 0;
+ pTask->lastMsgType = 0;
+ memset(&pTask->succeedAddr, 0, sizeof(pTask->succeedAddr));
+
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ if (pData) {
+ SCH_ERR_JRET(schUpdateTaskCandidateAddr(pJob, pTask, pData->pEpSet));
+ }
+
+ if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) {
+ if (JOB_TASK_STATUS_EXEC == SCH_GET_TASK_STATUS(pTask)) {
+ SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask));
+ }
+ }
+
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT);
+
+ SCH_ERR_JRET(schLaunchTask(pJob, pTask));
+
+ return TSDB_CODE_SUCCESS;
+ }
+
+ // merge plan
+
+ pTask->childReady = 0;
+
+ qClearSubplanExecutionNode(pTask->plan);
+
+ // Note: current error task and upper level merge task
+ if ((pData && 0 == pData->len) || NULL == pData) {
+ SCH_ERR_JRET(schSwitchTaskCandidateAddr(pJob, pTask));
+ }
+
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT);
+
+ int32_t childrenNum = taosArrayGetSize(pTask->children);
+ for (int32_t i = 0; i < childrenNum; ++i) {
+ SSchTask *pChild = taosArrayGetP(pTask->children, i);
+ SCH_LOCK_TASK(pChild);
+ schDoTaskRedirect(pJob, pChild, NULL, rspCode);
+ SCH_UNLOCK_TASK(pChild);
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ SCH_RET(schProcessOnTaskFailure(pJob, pTask, code));
+}
+
+int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) {
+ int32_t code = 0;
+
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ if (NULL == pData->pEpSet) {
+ SCH_TASK_ELOG("no epset updated while got error %s", tstrerror(rspCode));
+ SCH_ERR_JRET(rspCode);
+ }
+ }
+
+ SCH_RET(schDoTaskRedirect(pJob, pTask, pData, rspCode));
+
+_return:
+
+ SCH_RET(schProcessOnTaskFailure(pJob, pTask, code));
+}
+
+int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) {
+ int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
+ if (0 != code) {
+ if (HASH_NODE_EXIST(code)) {
+ SCH_TASK_ELOG("task already in execTask list, code:%x", code);
+ SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
+ }
+
+ SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ SCH_TASK_DLOG("task added to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+/*
+int32_t schMoveTaskToSuccList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
+ if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) {
+ SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ } else {
+ SCH_TASK_DLOG("task removed from execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
+ }
+
+ int32_t code = taosHashPut(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
+ if (0 != code) {
+ if (HASH_NODE_EXIST(code)) {
+ *moved = true;
+ SCH_TASK_ELOG("task already in succTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ SCH_TASK_ELOG("taosHashPut task to succTask list failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ *moved = true;
+
+ SCH_TASK_DLOG("task moved to succTask list, numOfTasks:%d", taosHashGetSize(pJob->succTasks));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schMoveTaskToFailList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
+ *moved = false;
+
+ if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) {
+ SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ }
+
+ int32_t code = taosHashPut(pJob->failTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
+ if (0 != code) {
+ if (HASH_NODE_EXIST(code)) {
+ *moved = true;
+
+ SCH_TASK_WLOG("task already in failTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ SCH_TASK_ELOG("taosHashPut task to failTask list failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ *moved = true;
+
+ SCH_TASK_DLOG("task moved to failTask list, numOfTasks:%d", taosHashGetSize(pJob->failTasks));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) {
+ if (0 != taosHashRemove(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId))) {
+ SCH_TASK_WLOG("remove task from succTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ }
+
+ int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES);
+ if (0 != code) {
+ if (HASH_NODE_EXIST(code)) {
+ *moved = true;
+
+ SCH_TASK_ELOG("task already in execTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
+ }
+
+ SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ *moved = true;
+
+ SCH_TASK_DLOG("task moved to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks));
+
+ return TSDB_CODE_SUCCESS;
+}
+*/
+
+int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) {
+ if (TSDB_CODE_SCH_TIMEOUT_ERROR == errCode) {
+ pTask->maxExecTimes++;
+ if (pTask->timeoutUsec < SCH_MAX_TASK_TIMEOUT_USEC) {
+ pTask->timeoutUsec *= 2;
+ if (pTask->timeoutUsec > SCH_MAX_TASK_TIMEOUT_USEC) {
+ pTask->timeoutUsec = SCH_MAX_TASK_TIMEOUT_USEC;
+ }
+ }
+ }
+
+ if ((pTask->execId + 1) >= pTask->maxExecTimes) {
+ *needRetry = false;
+ SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (!SCH_NEED_RETRY(pTask->lastMsgType, errCode)) {
+ *needRetry = false;
+ SCH_TASK_DLOG("task no more retry cause of errCode, errCode:%x - %s", errCode, tstrerror(errCode));
+ return TSDB_CODE_SUCCESS;
+ }
+
+/*
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ if ((pTask->execId + 1) >= SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)) {
+ *needRetry = false;
+ SCH_TASK_DLOG("task no more retry since all ep tried, execId:%d, epNum:%d", pTask->execId,
+ SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode));
+ return TSDB_CODE_SUCCESS;
+ }
+ } else {
+ int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs);
+
+ if ((pTask->candidateIdx + 1) >= candidateNum && (TSDB_CODE_SCH_TIMEOUT_ERROR != errCode)) {
+ *needRetry = false;
+ SCH_TASK_DLOG("task no more retry since all candiates tried, candidateIdx:%d, candidateNum:%d",
+ pTask->candidateIdx, candidateNum);
+ return TSDB_CODE_SUCCESS;
+ }
+ }
+*/
+
+ *needRetry = true;
+ SCH_TASK_DLOG("task need the %dth retry, errCode:%x - %s", pTask->execId + 1, errCode, tstrerror(errCode));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) {
+ atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1);
+
+ SCH_ERR_RET(schRemoveTaskFromExecList(pJob, pTask));
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT);
+
+ if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) {
+ SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask));
+ }
+
+ schDeregisterTaskHb(pJob, pTask);
+
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx);
+ SCH_SWITCH_EPSET(addr);
+ } else {
+ SCH_ERR_RET(schSwitchTaskCandidateAddr(pJob, pTask));
+ }
+
+ SCH_ERR_RET(schLaunchTask(pJob, pTask));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schSetAddrsFromNodeList(SSchJob *pJob, SSchTask *pTask) {
+ int32_t addNum = 0;
+ int32_t nodeNum = 0;
+
+ if (pJob->nodeList) {
+ nodeNum = taosArrayGetSize(pJob->nodeList);
+
+ for (int32_t i = 0; i < nodeNum && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) {
+ SQueryNodeLoad *nload = taosArrayGet(pJob->nodeList, i);
+ SQueryNodeAddr *naddr = &nload->addr;
+
+ if (NULL == taosArrayPush(pTask->candidateAddrs, naddr)) {
+ SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, addNum:%d, errno:%d", addNum, errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ SCH_TASK_DLOG("set %dth candidate addr, id %d, fqdn:%s, port:%d", i, naddr->nodeId, SCH_GET_CUR_EP(naddr)->fqdn,
+ SCH_GET_CUR_EP(naddr)->port);
+
+ ++addNum;
+ }
+ }
+
+ if (addNum <= 0) {
+ SCH_TASK_ELOG("no available execNode as candidates, nodeNum:%d", nodeNum);
+ SCH_ERR_RET(TSDB_CODE_TSC_NO_EXEC_NODE);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) {
+ if (NULL != pTask->candidateAddrs) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ pTask->candidateIdx = 0;
+ pTask->candidateAddrs = taosArrayInit(SCH_MAX_CANDIDATE_EP_NUM, sizeof(SQueryNodeAddr));
+ if (NULL == pTask->candidateAddrs) {
+ SCH_TASK_ELOG("taosArrayInit %d condidate addrs failed", SCH_MAX_CANDIDATE_EP_NUM);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ if (pTask->plan->execNode.epSet.numOfEps > 0) {
+ if (NULL == taosArrayPush(pTask->candidateAddrs, &pTask->plan->execNode)) {
+ SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, errno:%d", errno);
+ SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ SCH_TASK_DLOG("use execNode in plan as candidate addr, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps);
+
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (SCH_IS_DATA_BIND_TASK(pTask)) {
+ SCH_TASK_ELOG("no execNode specifed for data src task, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps);
+ SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
+ }
+
+ SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask));
+
+ /*
+ for (int32_t i = 0; i < job->dataSrcEps.numOfEps && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) {
+ strncpy(epSet->fqdn[epSet->numOfEps], job->dataSrcEps.fqdn[i], sizeof(job->dataSrcEps.fqdn[i]));
+ epSet->port[epSet->numOfEps] = job->dataSrcEps.port[i];
+
+ ++epSet->numOfEps;
+ }
+ */
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet *pEpSet) {
+ if (NULL == pTask->candidateAddrs || 1 != taosArrayGetSize(pTask->candidateAddrs)) {
+ SCH_TASK_ELOG("not able to update cndidate addr, addr num %d",
+ (int32_t)(pTask->candidateAddrs ? taosArrayGetSize(pTask->candidateAddrs) : 0));
+ SCH_ERR_RET(TSDB_CODE_APP_ERROR);
+ }
+
+ SQueryNodeAddr *pAddr = taosArrayGet(pTask->candidateAddrs, 0);
+
+ SEp *pOld = &pAddr->epSet.eps[pAddr->epSet.inUse];
+ SEp *pNew = &pEpSet->eps[pEpSet->inUse];
+
+ SCH_TASK_DLOG("update task ep from %s:%d to %s:%d", pOld->fqdn, pOld->port, pNew->fqdn, pNew->port);
+
+ memcpy(&pAddr->epSet, pEpSet, sizeof(pAddr->epSet));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schSwitchTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask) {
+ int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs);
+ if (++pTask->candidateIdx >= candidateNum) {
+ pTask->candidateIdx = 0;
+ }
+ SCH_TASK_DLOG("switch task candiateIdx to %d", pTask->candidateIdx);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask) {
+ int32_t code = taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId));
+ if (code) {
+ SCH_TASK_ELOG("task failed to rm from execTask list, code:%x", code);
+ SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask) {
+ if (NULL == pTask->execNodes) {
+ SCH_TASK_DLOG("no exec address, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ return;
+ }
+
+ int32_t size = (int32_t)taosHashGetSize(pTask->execNodes);
+
+ if (size <= 0) {
+ SCH_TASK_DLOG("task has no execNodes, no need to drop it, status:%s", SCH_GET_TASK_STATUS_STR(pTask));
+ return;
+ }
+
+ SSchNodeInfo *nodeInfo = taosHashIterate(pTask->execNodes, NULL);
+ while (nodeInfo) {
+ SCH_SET_TASK_HANDLE(pTask, nodeInfo->handle);
+
+ schBuildAndSendMsg(pJob, pTask, &nodeInfo->addr, TDMT_SCH_DROP_TASK);
+
+ nodeInfo = taosHashIterate(pTask->execNodes, nodeInfo);
+ }
+
+ SCH_TASK_DLOG("task has been dropped on %d exec nodes", size);
+}
+
+int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId *pEpId, SArray *pStatusList) {
+ int32_t taskNum = (int32_t)taosArrayGetSize(pStatusList);
+ SSchTask *pTask = NULL;
+ SSchJob *pJob = NULL;
+
+ qDebug("%d task status in hb rsp from nodeId:%d, fqdn:%s, port:%d", taskNum, pEpId->nodeId, pEpId->ep.fqdn,
+ pEpId->ep.port);
+
+ for (int32_t i = 0; i < taskNum; ++i) {
+ STaskStatus *pStatus = taosArrayGet(pStatusList, i);
+ int32_t code = 0;
+
+ qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d task status in server: %s", pStatus->queryId, pStatus->taskId,
+ pStatus->execId, jobTaskStatusStr(pStatus->status));
+
+ if (schProcessOnCbBegin(&pJob, &pTask, pStatus->queryId, pStatus->refId, pStatus->taskId)) {
+ continue;
+ }
+
+ if (pStatus->execId != pTask->execId) {
+ // TODO
+ SCH_TASK_DLOG("execId %d mis-match current execId %d", pStatus->execId, pTask->execId);
+ schProcessOnCbEnd(pJob, pTask, 0);
+ continue;
+ }
+
+ if (pStatus->status == JOB_TASK_STATUS_FAIL) {
+ // RECORD AND HANDLE ERROR!!!!
+ schProcessOnCbEnd(pJob, pTask, 0);
+ continue;
+ }
+
+ if (pStatus->status == JOB_TASK_STATUS_INIT) {
+ code = schRescheduleTask(pJob, pTask);
+ }
+
+ schProcessOnCbEnd(pJob, pTask, code);
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) {
+ int8_t status = 0;
+ int32_t code = 0;
+
+ atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1);
+ pTask->execId++;
+
+ SCH_TASK_DLOG("start to launch task's %dth exec", pTask->execId);
+
+ SCH_LOG_TASK_START_TS(pTask);
+
+ if (schJobNeedToStop(pJob, &status)) {
+ SCH_TASK_DLOG("no need to launch task cause of job status %s", jobTaskStatusStr(status));
+ SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR);
+ }
+
+ // NOTE: race condition: the task should be put into the hash table before send msg to server
+ if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) {
+ SCH_ERR_RET(schPushTaskToExecList(pJob, pTask));
+ SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXEC);
+ }
+
+ SSubplan *plan = pTask->plan;
+
+ if (NULL == pTask->msg) { // TODO add more detailed reason for failure
+ code = qSubPlanToString(plan, &pTask->msg, &pTask->msgLen);
+ if (TSDB_CODE_SUCCESS != code) {
+ SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg,
+ pTask->msgLen);
+ SCH_ERR_RET(code);
+ } else {
+ SCH_TASK_DLOGL("physical plan len:%d, %s", pTask->msgLen, pTask->msg);
+ }
+ }
+
+ SCH_ERR_RET(schSetTaskCandidateAddrs(pJob, pTask));
+
+ if (SCH_IS_QUERY_JOB(pJob)) {
+ SCH_ERR_RET(schEnsureHbConnection(pJob, pTask));
+ }
+
+ SCH_ERR_RET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType));
+
+ return TSDB_CODE_SUCCESS;
+}
+
+// Note: no more error processing, handled in function internal
+int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) {
+ bool enough = false;
+ int32_t code = 0;
+
+ SCH_SET_TASK_HANDLE(pTask, NULL);
+
+ if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) {
+ SCH_ERR_JRET(schCheckIncTaskFlowQuota(pJob, pTask, &enough));
+
+ if (enough) {
+ SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask));
+ }
+ } else {
+ SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask));
+ }
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ SCH_RET(schProcessOnTaskFailure(pJob, pTask, code));
+}
+
+int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) {
+ SCH_ERR_RET(schChkJobNeedFlowCtrl(pJob, level));
+
+ for (int32_t i = 0; i < level->taskNum; ++i) {
+ SSchTask *pTask = taosArrayGet(level->subTasks, i);
+
+ SCH_ERR_RET(schLaunchTask(pJob, pTask));
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) {
+ if (!SCH_JOB_NEED_DROP(pJob)) {
+ return;
+ }
+
+ void *pIter = taosHashIterate(list, NULL);
+ while (pIter) {
+ SSchTask *pTask = *(SSchTask **)pIter;
+
+ schDropTaskOnExecNode(pJob, pTask);
+
+ pIter = taosHashIterate(list, pIter);
+ }
+}
+
+// Note: no more error processing, handled in function internal
+int32_t schLaunchFetchTask(SSchJob *pJob) {
+ int32_t code = 0;
+
+ void *resData = atomic_load_ptr(&pJob->resData);
+ if (resData) {
+ SCH_JOB_DLOG("res already fetched, res:%p", resData);
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, SCH_FETCH_TYPE(pJob->fetchTask)));
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ SCH_RET(schProcessOnTaskFailure(pJob, pJob->fetchTask, code));
+}
diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c
index 73077cbf0f6632e0a7a7b9979e0b6d17baf90fd3..f848dfa2101f7f5ab23c860f8e34f788fe8054cb 100644
--- a/source/libs/scheduler/src/schUtil.c
+++ b/source/libs/scheduler/src/schUtil.c
@@ -16,11 +16,25 @@
#include "catalog.h"
#include "command.h"
#include "query.h"
-#include "schedulerInt.h"
+#include "schInt.h"
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
+FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) {
+ qDebug("sch acquire jobId:0x%"PRIx64, refId);
+ return (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId);
+}
+
+FORCE_INLINE int32_t schReleaseJob(int64_t refId) {
+ if (0 == refId) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ qDebug("sch release jobId:0x%"PRIx64, refId);
+ return taosReleaseRef(schMgmt.jobRef, refId);
+}
+
char* schGetOpStr(SCH_OP_TYPE type) {
switch (type) {
case SCH_OP_NULL:
@@ -29,6 +43,8 @@ char* schGetOpStr(SCH_OP_TYPE type) {
return "EXEC";
case SCH_OP_FETCH:
return "FETCH";
+ case SCH_OP_GET_STATUS:
+ return "GET STATUS";
default:
return "UNKNOWN";
}
@@ -283,3 +299,20 @@ void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo) {
taosMemoryFree(msgSendInfo);
}
+int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) {
+ int32_t s = taosHashGetSize(pTaskList);
+ if (s <= 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ SSchTask **task = taosHashGet(pTaskList, &taskId, sizeof(taskId));
+ if (NULL == task || NULL == (*task)) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ *pTask = *task;
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c
index 57a405ffa3ffd524e7203a2935a4135ec3bd5208..39465f3064e9b117ca97c345223b17ce83e95a3d 100644
--- a/source/libs/scheduler/src/scheduler.c
+++ b/source/libs/scheduler/src/scheduler.c
@@ -13,13 +13,10 @@
* along with this program. If not, see .
*/
-#include "catalog.h"
-#include "command.h"
#include "query.h"
-#include "schedulerInt.h"
+#include "schInt.h"
#include "tmsg.h"
#include "tref.h"
-#include "trpc.h"
SSchedulerMgmt schMgmt = {
.jobRef = -1,
@@ -67,101 +64,45 @@ int32_t schedulerInit(SSchedulerCfg *cfg) {
return TSDB_CODE_SUCCESS;
}
-int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes) {
- qDebug("scheduler sync exec job start");
-
- if (NULL == pReq || NULL == pJob || NULL == pRes) {
- SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
- }
+int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId) {
+ qDebug("scheduler %s exec job start", pReq->syncReq ? "SYNC" : "ASYNC");
- SCH_RET(schExecJob(pReq, pJob, pRes));
-}
+ int32_t code = 0;
+ SSchJob *pJob = NULL;
-int32_t schedulerAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob) {
- qDebug("scheduler async exec job start");
+ SCH_ERR_JRET(schInitJob(pJobId, pReq));
- int32_t code = 0;
- if (NULL == pReq || NULL == pJob) {
- SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
- }
-
- schAsyncExecJob(pReq, pJob);
+ SCH_ERR_JRET(schHandleOpBeginEvent(*pJobId, &pJob, SCH_OP_EXEC, pReq));
-_return:
+ SCH_ERR_JRET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_INIT, pReq));
- if (code != TSDB_CODE_SUCCESS) {
- pReq->fp(NULL, pReq->cbParam, code);
- }
+ SCH_ERR_JRET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_EXEC, pReq));
- SCH_RET(code);
+_return:
+
+ SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_EXEC, pReq, code));
}
-int32_t schedulerFetchRows(int64_t job, void **pData) {
- qDebug("scheduler sync fetch rows start");
-
- if (NULL == pData) {
- SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
- }
+int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq *pReq) {
+ qDebug("scheduler %s fetch rows start", pReq->syncReq ? "SYNC" : "ASYNC");
int32_t code = 0;
- SSchJob *pJob = schAcquireJob(job);
- if (NULL == pJob) {
- qError("acquire job from jobRef list failed, may be dropped, jobId:0x%" PRIx64, job);
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- SCH_ERR_RET(schBeginOperation(pJob, SCH_OP_FETCH, true));
+ SSchJob *pJob = NULL;
- pJob->userRes.fetchRes = pData;
- code = schFetchRows(pJob);
-
- schReleaseJob(job);
-
- SCH_RET(code);
-}
-
-void schedulerAsyncFetchRows(int64_t job, schedulerFetchCallback fp, void* param) {
- qDebug("scheduler async fetch rows start");
-
- int32_t code = 0;
- if (NULL == fp || NULL == param) {
- SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
- }
-
- SSchJob *pJob = schAcquireJob(job);
- if (NULL == pJob) {
- qError("acquire sch job from job list failed, may be dropped, jobId:0x%" PRIx64, job);
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
- }
+ SCH_ERR_JRET(schHandleOpBeginEvent(jobId, &pJob, SCH_OP_FETCH, pReq));
- SCH_ERR_JRET(schBeginOperation(pJob, SCH_OP_FETCH, false));
-
- pJob->userRes.fetchFp = fp;
- pJob->userRes.userParam = param;
-
- SCH_ERR_JRET(schAsyncFetchRows(pJob));
+ SCH_ERR_JRET(schJobFetchRows(pJob));
_return:
- if (code) {
- fp(NULL, param, code);
- }
-
- schReleaseJob(job);
+ SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_FETCH, pReq, code));
}
-int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub) {
+int32_t schedulerGetTasksStatus(int64_t jobId, SArray *pSub) {
int32_t code = 0;
- SSchJob *pJob = schAcquireJob(job);
- if (NULL == pJob) {
- qDebug("acquire job from jobRef list failed, may not started or dropped, refId:0x%" PRIx64, job);
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
+ SSchJob *pJob = NULL;
- if (pJob->status < JOB_TASK_STATUS_NOT_START || pJob->levelNum <= 0 || NULL == pJob->levels) {
- qDebug("job not initialized or not executable job, refId:0x%" PRIx64, job);
- SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR);
- }
+ SCH_ERR_JRET(schHandleOpBeginEvent(jobId, &pJob, SCH_OP_GET_STATUS, NULL));
for (int32_t i = pJob->levelNum - 1; i >= 0; --i) {
SSchLevel *pLevel = taosArrayGet(pJob->levels, i);
@@ -178,23 +119,7 @@ int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub) {
_return:
- schReleaseJob(job);
-
- SCH_RET(code);
-}
-
-int32_t scheduleCancelJob(int64_t job) {
- SSchJob *pJob = schAcquireJob(job);
- if (NULL == pJob) {
- qError("acquire job from jobRef list failed, may be dropped, jobId:0x%" PRIx64, job);
- SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR);
- }
-
- int32_t code = schCancelJob(pJob);
-
- schReleaseJob(job);
-
- SCH_RET(code);
+ SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_GET_STATUS, NULL, code));
}
void schedulerStopQueryHb(void *pTrans) {
@@ -205,26 +130,21 @@ void schedulerStopQueryHb(void *pTrans) {
schCleanClusterHb(pTrans);
}
-void schedulerFreeJob(int64_t job, int32_t errCode) {
- SSchJob *pJob = schAcquireJob(job);
- if (NULL == pJob) {
- qError("acquire job from jobRef list failed, may be dropped, jobId:0x%" PRIx64, job);
+void schedulerFreeJob(int64_t* jobId, int32_t errCode) {
+ if (0 == *jobId) {
return;
}
- int32_t code = schProcessOnJobDropped(pJob, errCode);
- if (TSDB_CODE_SCH_JOB_IS_DROPPING == code) {
- SCH_JOB_DLOG("sch job is already dropping, refId:0x%" PRIx64, job);
+ SSchJob *pJob = schAcquireJob(*jobId);
+ if (NULL == pJob) {
+ qError("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, *jobId);
return;
}
- SCH_JOB_DLOG("start to remove job from jobRef list, refId:0x%" PRIx64, job);
-
- if (taosRemoveRef(schMgmt.jobRef, job)) {
- SCH_JOB_ELOG("remove job from job list failed, refId:0x%" PRIx64, job);
- }
-
- schReleaseJob(job);
+ schSwitchJobStatus(pJob, JOB_TASK_STATUS_DROP, (void*)&errCode);
+
+ schReleaseJob(*jobId);
+ *jobId = 0;
}
void schedulerDestroy(void) {
diff --git a/source/libs/scheduler/test/CMakeLists.txt b/source/libs/scheduler/test/CMakeLists.txt
index 0b0aafebb91f4a87f7a1428e5a68b649b229ffac..ce928862215d3efe7dc14c1c50e581416cb18777 100644
--- a/source/libs/scheduler/test/CMakeLists.txt
+++ b/source/libs/scheduler/test/CMakeLists.txt
@@ -1,18 +1,20 @@
MESSAGE(STATUS "build scheduler unit test")
-# GoogleTest requires at least C++11
-SET(CMAKE_CXX_STANDARD 11)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
+IF(NOT TD_DARWIN)
+ # GoogleTest requires at least C++11
+ SET(CMAKE_CXX_STANDARD 11)
+ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
-ADD_EXECUTABLE(schedulerTest ${SOURCE_LIST})
-TARGET_LINK_LIBRARIES(
- schedulerTest
- PUBLIC os util common catalog transport gtest qcom taos_static planner scheduler
-)
+ ADD_EXECUTABLE(schedulerTest ${SOURCE_LIST})
+ TARGET_LINK_LIBRARIES(
+ schedulerTest
+ PUBLIC os util common catalog transport gtest qcom taos_static planner scheduler
+ )
-TARGET_INCLUDE_DIRECTORIES(
- schedulerTest
- PUBLIC "${TD_SOURCE_DIR}/include/libs/scheduler/"
- PRIVATE "${TD_SOURCE_DIR}/source/libs/scheduler/inc"
-)
+ TARGET_INCLUDE_DIRECTORIES(
+ schedulerTest
+ PUBLIC "${TD_SOURCE_DIR}/include/libs/scheduler/"
+ PRIVATE "${TD_SOURCE_DIR}/source/libs/scheduler/inc"
+ )
+ENDIF()
\ No newline at end of file
diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp
index e5cc3cd48188f51ad9431c3e21027292998213ad..d6b1baf978bdc823b3337e80830ec89f5de4e790 100644
--- a/source/libs/scheduler/test/schedulerTests.cpp
+++ b/source/libs/scheduler/test/schedulerTests.cpp
@@ -50,7 +50,7 @@
#pragma GCC diagnostic ignored "-Wreturn-type"
#pragma GCC diagnostic ignored "-Wformat"
-#include "schedulerInt.h"
+#include "schInt.h"
#include "stub.h"
#include "tref.h"
@@ -87,7 +87,7 @@ void schtInitLogFile() {
}
-void schtQueryCb(SQueryResult* pResult, void* param, int32_t code) {
+void schtQueryCb(SExecResult* pResult, void* param, int32_t code) {
assert(TSDB_CODE_SUCCESS == code);
*(int32_t*)param = 1;
}
@@ -118,7 +118,7 @@ void schtBuildQueryDag(SQueryPlan *dag) {
scanPlan->level = 1;
scanPlan->pParents = nodesMakeList();
scanPlan->pNode = (SPhysiNode*)taosMemoryCalloc(1, sizeof(SPhysiNode));
- scanPlan->msgType = TDMT_VND_QUERY;
+ scanPlan->msgType = TDMT_SCH_QUERY;
mergePlan->id.queryId = qId;
mergePlan->id.groupId = schtMergeTemplateId;
@@ -130,7 +130,7 @@ void schtBuildQueryDag(SQueryPlan *dag) {
mergePlan->pChildren = nodesMakeList();
mergePlan->pParents = NULL;
mergePlan->pNode = (SPhysiNode*)taosMemoryCalloc(1, sizeof(SPhysiNode));
- mergePlan->msgType = TDMT_VND_QUERY;
+ mergePlan->msgType = TDMT_SCH_QUERY;
merge->pNodeList = nodesMakeList();
scan->pNodeList = nodesMakeList();
@@ -181,7 +181,7 @@ void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) {
scanPlan[i].level = 1;
scanPlan[i].pParents = nodesMakeList();
scanPlan[i].pNode = (SPhysiNode*)taosMemoryCalloc(1, sizeof(SPhysiNode));
- scanPlan[i].msgType = TDMT_VND_QUERY;
+ scanPlan[i].msgType = TDMT_SCH_QUERY;
nodesListAppend(scanPlan[i].pParents, (SNode*)mergePlan);
nodesListAppend(mergePlan->pChildren, (SNode*)(scanPlan + i));
@@ -198,7 +198,7 @@ void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) {
mergePlan->pParents = NULL;
mergePlan->pNode = (SPhysiNode*)taosMemoryCalloc(1, sizeof(SPhysiNode));
- mergePlan->msgType = TDMT_VND_QUERY;
+ mergePlan->msgType = TDMT_SCH_QUERY;
nodesListAppend(merge->pNodeList, (SNode*)mergePlan);
@@ -412,7 +412,7 @@ void *schtCreateFetchRspThread(void *param) {
rsp->completed = 1;
rsp->numOfRows = 10;
- code = schHandleResponseMsg(pJob, pJob->fetchTask, TDMT_VND_FETCH_RSP, (char *)rsp, sizeof(*rsp), 0);
+ code = schHandleResponseMsg(pJob, pJob->fetchTask, TDMT_SCH_FETCH_RSP, (char *)rsp, sizeof(*rsp), 0);
schReleaseJob(job);
@@ -445,7 +445,7 @@ void *schtFetchRspThread(void *aa) {
dataBuf.pData = rsp;
dataBuf.len = sizeof(*rsp);
- code = schHandleCallback(param, &dataBuf, TDMT_VND_FETCH_RSP, 0);
+ code = schHandleCallback(param, &dataBuf, TDMT_SCH_FETCH_RSP, 0);
assert(code == 0 || code);
}
@@ -457,7 +457,7 @@ void schtFreeQueryJob(int32_t freeThread) {
int64_t job = queryJobRefId;
if (job && atomic_val_compare_exchange_64(&queryJobRefId, job, 0)) {
- schedulerFreeJob(job, 0);
+ schedulerFreeJob(&job, 0);
if (freeThread) {
if (++freeNum % schtTestPrintNum == 0) {
printf("FreeNum:%d\n", freeNum);
@@ -507,14 +507,15 @@ void* schtRunJobThread(void *aa) {
SRequestConnInfo conn = {0};
conn.pTrans = mockPointer;
SSchedulerReq req = {0};
+ req.syncReq = false;
req.pConn = &conn;
req.pNodeList = qnodeList;
req.pDag = &dag;
req.sql = "select * from tb";
- req.fp = schtQueryCb;
+ req.execFp = schtQueryCb;
req.cbParam = &queryDone;
- code = schedulerAsyncExecJob(&req, &queryJobRefId);
+ code = schedulerExecJob(&req, &queryJobRefId);
assert(code == 0);
pJob = schAcquireJob(queryJobRefId);
@@ -547,7 +548,7 @@ void* schtRunJobThread(void *aa) {
dataBuf.pData = &rsp;
dataBuf.len = sizeof(rsp);
- code = schHandleCallback(param, &dataBuf, TDMT_VND_QUERY_RSP, 0);
+ code = schHandleCallback(param, &dataBuf, TDMT_SCH_QUERY_RSP, 0);
assert(code == 0 || code);
pIter = taosHashIterate(execTasks, pIter);
@@ -566,7 +567,7 @@ void* schtRunJobThread(void *aa) {
dataBuf.pData = &rsp;
dataBuf.len = sizeof(rsp);
- code = schHandleCallback(param, &dataBuf, TDMT_VND_QUERY_RSP, 0);
+ code = schHandleCallback(param, &dataBuf, TDMT_SCH_QUERY_RSP, 0);
assert(code == 0 || code);
pIter = taosHashIterate(execTasks, pIter);
@@ -584,7 +585,10 @@ void* schtRunJobThread(void *aa) {
atomic_store_32(&schtStartFetch, 1);
void *data = NULL;
- code = schedulerFetchRows(queryJobRefId, &data);
+ req.syncReq = true;
+ req.pFetchRes = &data;
+
+ code = schedulerFetchRows(queryJobRefId, &req);
assert(code == 0 || code);
if (0 == code) {
@@ -594,7 +598,7 @@ void* schtRunJobThread(void *aa) {
}
data = NULL;
- code = schedulerFetchRows(queryJobRefId, &data);
+ code = schedulerFetchRows(queryJobRefId, &req);
assert(code == 0 || code);
schtFreeQueryJob(0);
@@ -658,15 +662,15 @@ TEST(queryTest, normalCase) {
SRequestConnInfo conn = {0};
conn.pTrans = mockPointer;
- SSchedulerReq req = {0};
+ SSchedulerReq req = {0};
req.pConn = &conn;
req.pNodeList = qnodeList;
req.pDag = &dag;
req.sql = "select * from tb";
- req.fp = schtQueryCb;
+ req.execFp = schtQueryCb;
req.cbParam = &queryDone;
- code = schedulerAsyncExecJob(&req, &job);
+ code = schedulerExecJob(&req, &job);
ASSERT_EQ(code, 0);
@@ -677,7 +681,7 @@ TEST(queryTest, normalCase) {
SSchTask *task = *(SSchTask **)pIter;
SQueryTableRsp rsp = {0};
- code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
+ code = schHandleResponseMsg(pJob, task, TDMT_SCH_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
ASSERT_EQ(code, 0);
pIter = taosHashIterate(pJob->execTasks, pIter);
@@ -688,7 +692,7 @@ TEST(queryTest, normalCase) {
SSchTask *task = *(SSchTask **)pIter;
SQueryTableRsp rsp = {0};
- code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
+ code = schHandleResponseMsg(pJob, task, TDMT_SCH_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
ASSERT_EQ(code, 0);
pIter = taosHashIterate(pJob->execTasks, pIter);
@@ -709,7 +713,10 @@ TEST(queryTest, normalCase) {
taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job);
void *data = NULL;
- code = schedulerFetchRows(job, &data);
+ req.syncReq = true;
+ req.pFetchRes = &data;
+
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data;
@@ -718,13 +725,13 @@ TEST(queryTest, normalCase) {
taosMemoryFreeClear(data);
data = NULL;
- code = schedulerFetchRows(job, &data);
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
ASSERT_TRUE(data == NULL);
schReleaseJob(job);
- schedulerFreeJob(job, 0);
+ schedulerFreeJob(&job, 0);
schtFreeQueryDag(&dag);
@@ -767,9 +774,9 @@ TEST(queryTest, readyFirstCase) {
req.pNodeList = qnodeList;
req.pDag = &dag;
req.sql = "select * from tb";
- req.fp = schtQueryCb;
+ req.execFp = schtQueryCb;
req.cbParam = &queryDone;
- code = schedulerAsyncExecJob(&req, &job);
+ code = schedulerExecJob(&req, &job);
ASSERT_EQ(code, 0);
@@ -780,7 +787,7 @@ TEST(queryTest, readyFirstCase) {
SSchTask *task = *(SSchTask **)pIter;
SQueryTableRsp rsp = {0};
- code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
+ code = schHandleResponseMsg(pJob, task, TDMT_SCH_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
ASSERT_EQ(code, 0);
pIter = taosHashIterate(pJob->execTasks, pIter);
@@ -791,7 +798,7 @@ TEST(queryTest, readyFirstCase) {
SSchTask *task = *(SSchTask **)pIter;
SQueryTableRsp rsp = {0};
- code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
+ code = schHandleResponseMsg(pJob, task, TDMT_SCH_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
ASSERT_EQ(code, 0);
pIter = taosHashIterate(pJob->execTasks, pIter);
@@ -813,7 +820,9 @@ TEST(queryTest, readyFirstCase) {
taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job);
void *data = NULL;
- code = schedulerFetchRows(job, &data);
+ req.syncReq = true;
+ req.pFetchRes = &data;
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data;
@@ -822,13 +831,13 @@ TEST(queryTest, readyFirstCase) {
taosMemoryFreeClear(data);
data = NULL;
- code = schedulerFetchRows(job, &data);
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
ASSERT_TRUE(data == NULL);
schReleaseJob(job);
- schedulerFreeJob(job, 0);
+ schedulerFreeJob(&job, 0);
schtFreeQueryDag(&dag);
@@ -874,10 +883,10 @@ TEST(queryTest, flowCtrlCase) {
req.pNodeList = qnodeList;
req.pDag = &dag;
req.sql = "select * from tb";
- req.fp = schtQueryCb;
+ req.execFp = schtQueryCb;
req.cbParam = &queryDone;
- code = schedulerAsyncExecJob(&req, &job);
+ code = schedulerExecJob(&req, &job);
ASSERT_EQ(code, 0);
@@ -896,9 +905,9 @@ TEST(queryTest, flowCtrlCase) {
taosHashCancelIterate(pJob->execTasks, pIter);
- if (task->lastMsgType == TDMT_VND_QUERY) {
+ if (task->lastMsgType == TDMT_SCH_QUERY) {
SQueryTableRsp rsp = {0};
- code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
+ code = schHandleResponseMsg(pJob, task, TDMT_SCH_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0);
ASSERT_EQ(code, 0);
} else {
@@ -925,7 +934,9 @@ TEST(queryTest, flowCtrlCase) {
taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job);
void *data = NULL;
- code = schedulerFetchRows(job, &data);
+ req.syncReq = true;
+ req.pFetchRes = &data;
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data;
@@ -934,13 +945,13 @@ TEST(queryTest, flowCtrlCase) {
taosMemoryFreeClear(data);
data = NULL;
- code = schedulerFetchRows(job, &data);
+ code = schedulerFetchRows(job, &req);
ASSERT_EQ(code, 0);
ASSERT_TRUE(data == NULL);
schReleaseJob(job);
- schedulerFreeJob(job, 0);
+ schedulerFreeJob(&job, 0);
schtFreeQueryDag(&dag);
@@ -978,7 +989,7 @@ TEST(insertTest, normalCase) {
TdThread thread1;
taosThreadCreate(&(thread1), &thattr, schtSendRsp, &insertJobRefId);
- SQueryResult res = {0};
+ SExecResult res = {0};
SRequestConnInfo conn = {0};
conn.pTrans = mockPointer;
@@ -987,14 +998,14 @@ TEST(insertTest, normalCase) {
req.pNodeList = qnodeList;
req.pDag = &dag;
req.sql = "insert into tb values(now,1)";
- req.fp = schtQueryCb;
+ req.execFp = schtQueryCb;
req.cbParam = NULL;
- code = schedulerExecJob(&req, &insertJobRefId, &res);
+ code = schedulerExecJob(&req, &insertJobRefId);
ASSERT_EQ(code, 0);
ASSERT_EQ(res.numOfRows, 20);
- schedulerFreeJob(insertJobRefId, 0);
+ schedulerFreeJob(&insertJobRefId, 0);
schedulerDestroy();
}
diff --git a/source/libs/stream/inc/streamInc.h b/source/libs/stream/inc/streamInc.h
index 8aaf4953def5d8fcb1fe354124c28f595649d8e1..f9f4e6277424f3f1be7a24b3f2f71412406fd661 100644
--- a/source/libs/stream/inc/streamInc.h
+++ b/source/libs/stream/inc/streamInc.h
@@ -17,6 +17,7 @@
#define _STREAM_INC_H_
#include "executor.h"
+#include "tref.h"
#include "tstream.h"
#ifdef __cplusplus
@@ -24,8 +25,9 @@ extern "C" {
#endif
typedef struct {
- int8_t inited;
- void* timer;
+ int8_t inited;
+ int32_t refPool;
+ void* timer;
} SStreamGlobalEnv;
static SStreamGlobalEnv streamEnv;
@@ -33,7 +35,15 @@ static SStreamGlobalEnv streamEnv;
int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb);
int32_t streamDispatch(SStreamTask* pTask, SMsgCb* pMsgCb);
int32_t streamDispatchReqToData(const SStreamDispatchReq* pReq, SStreamDataBlock* pData);
-int32_t streamBuildDispatchMsg(SStreamTask* pTask, SStreamDataBlock* data, SRpcMsg* pMsg, SEpSet** ppEpSet);
+int32_t streamRetrieveReqToData(const SStreamRetrieveReq* pReq, SStreamDataBlock* pData);
+int32_t streamBuildDispatchMsg(SStreamTask* pTask, const SStreamDataBlock* data, SRpcMsg* pMsg, SEpSet** ppEpSet);
+
+int32_t streamBroadcastToChildren(SStreamTask* pTask, const SSDataBlock* pBlock);
+
+int32_t tEncodeStreamRetrieveReq(SEncoder* pEncoder, const SStreamRetrieveReq* pReq);
+
+int32_t streamAppendQueueItem(SStreamQueueItem* dst, SStreamQueueItem* elem);
+void streamFreeQitem(SStreamQueueItem* data);
#ifdef __cplusplus
}
diff --git a/source/libs/stream/src/stream.c b/source/libs/stream/src/stream.c
index 38a1ad14b1b4abf124a3badf905f2b30a15a0f80..566d9209a84e123840a5b0abb68c6583b9f4eb93 100644
--- a/source/libs/stream/src/stream.c
+++ b/source/libs/stream/src/stream.c
@@ -50,6 +50,10 @@ void streamCleanUp() {
void streamTriggerByTimer(void* param, void* tmrId) {
SStreamTask* pTask = (void*)param;
+ if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) {
+ return;
+ }
+
if (atomic_load_8(&pTask->triggerStatus) == TASK_TRIGGER_STATUS__ACTIVE) {
SStreamTrigger* trigger = taosAllocateQitem(sizeof(SStreamTrigger), DEF_QITEM);
if (trigger == NULL) return;
@@ -72,9 +76,6 @@ void streamTriggerByTimer(void* param, void* tmrId) {
int32_t streamSetupTrigger(SStreamTask* pTask) {
if (pTask->triggerParam != 0) {
- if (streamInit() < 0) {
- return -1;
- }
pTask->timer = taosTmrStart(streamTriggerByTimer, (int32_t)pTask->triggerParam, pTask, streamEnv.timer);
pTask->triggerStatus = TASK_TRIGGER_STATUS__IN_ACTIVE;
}
@@ -82,8 +83,8 @@ int32_t streamSetupTrigger(SStreamTask* pTask) {
}
int32_t streamLaunchByWrite(SStreamTask* pTask, int32_t vgId) {
- int8_t execStatus = atomic_load_8(&pTask->status);
- if (execStatus == TASK_STATUS__IDLE || execStatus == TASK_STATUS__CLOSING) {
+ int8_t execStatus = atomic_load_8(&pTask->execStatus);
+ if (execStatus == TASK_EXEC_STATUS__IDLE || execStatus == TASK_EXEC_STATUS__CLOSING) {
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
if (pRunReq == NULL) return -1;
@@ -96,7 +97,7 @@ int32_t streamLaunchByWrite(SStreamTask* pTask, int32_t vgId) {
.pCont = pRunReq,
.contLen = sizeof(SStreamTaskRunReq),
};
- tmsgPutToQueue(pTask->pMsgCb, FETCH_QUEUE, &msg);
+ tmsgPutToQueue(pTask->pMsgCb, STREAM_QUEUE, &msg);
}
return 0;
}
@@ -107,8 +108,8 @@ int32_t streamTaskEnqueue(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg*
// enqueue
if (pData != NULL) {
- pData->type = STREAM_DATA_TYPE_SSDATA_BLOCK;
- pData->sourceVg = pReq->sourceVg;
+ pData->type = STREAM_INPUT__DATA_BLOCK;
+ pData->srcVgId = pReq->dataSrcVgId;
// decode
/*pData->blocks = pReq->data;*/
/*pBlock->sourceVer = pReq->sourceVer;*/
@@ -129,15 +130,51 @@ int32_t streamTaskEnqueue(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg*
SStreamDispatchRsp* pCont = POINTER_SHIFT(buf, sizeof(SMsgHead));
pCont->inputStatus = status;
pCont->streamId = pReq->streamId;
- pCont->taskId = pReq->sourceTaskId;
+ pCont->taskId = pReq->upstreamTaskId;
pRsp->pCont = buf;
pRsp->contLen = sizeof(SMsgHead) + sizeof(SStreamDispatchRsp);
tmsgSendRsp(pRsp);
return status == TASK_INPUT_STATUS__NORMAL ? 0 : -1;
}
+int32_t streamTaskEnqueueRetrieve(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pRsp) {
+ SStreamDataBlock* pData = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
+ int8_t status = TASK_INPUT_STATUS__NORMAL;
+
+ // enqueue
+ if (pData != NULL) {
+ pData->type = STREAM_INPUT__DATA_RETRIEVE;
+ pData->srcVgId = 0;
+ // decode
+ /*pData->blocks = pReq->data;*/
+ /*pBlock->sourceVer = pReq->sourceVer;*/
+ streamRetrieveReqToData(pReq, pData);
+ if (streamTaskInput(pTask, (SStreamQueueItem*)pData) == 0) {
+ status = TASK_INPUT_STATUS__NORMAL;
+ } else {
+ status = TASK_INPUT_STATUS__FAILED;
+ }
+ } else {
+ /*streamTaskInputFail(pTask);*/
+ /*status = TASK_INPUT_STATUS__FAILED;*/
+ }
+
+ // rsp by input status
+ void* buf = rpcMallocCont(sizeof(SMsgHead) + sizeof(SStreamRetrieveRsp));
+ ((SMsgHead*)buf)->vgId = htonl(pReq->srcNodeId);
+ SStreamRetrieveRsp* pCont = POINTER_SHIFT(buf, sizeof(SMsgHead));
+ pCont->streamId = pReq->streamId;
+ pCont->rspToTaskId = pReq->srcTaskId;
+ pCont->rspFromTaskId = pReq->dstTaskId;
+ pRsp->pCont = buf;
+ pRsp->contLen = sizeof(SMsgHead) + sizeof(SStreamRetrieveRsp);
+ tmsgSendRsp(pRsp);
+ return status == TASK_INPUT_STATUS__NORMAL ? 0 : -1;
+}
+
int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pRsp) {
- qInfo("task %d receive dispatch req from node %d task %d", pTask->taskId, pReq->upstreamNodeId, pReq->sourceTaskId);
+ qDebug("task %d receive dispatch req from node %d task %d", pTask->taskId, pReq->upstreamNodeId,
+ pReq->upstreamTaskId);
// 1. handle input
streamTaskEnqueue(pTask, pReq, pRsp);
@@ -172,7 +209,7 @@ int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, S
int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp) {
ASSERT(pRsp->inputStatus == TASK_OUTPUT_STATUS__NORMAL || pRsp->inputStatus == TASK_OUTPUT_STATUS__BLOCKED);
- qInfo("task %d receive dispatch rsp", pTask->taskId);
+ qDebug("task %d receive dispatch rsp", pTask->taskId);
int8_t old = atomic_exchange_8(&pTask->outputStatus, pRsp->inputStatus);
ASSERT(old == TASK_OUTPUT_STATUS__WAIT);
@@ -188,6 +225,7 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp) {
int32_t streamProcessRunReq(SStreamTask* pTask) {
streamExec(pTask, pTask->pMsgCb);
+
if (pTask->dispatchType != TASK_DISPATCH__NONE) {
streamDispatch(pTask, pTask->pMsgCb);
}
@@ -203,3 +241,22 @@ int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp)
//
return 0;
}
+
+int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pRsp) {
+ qDebug("task %d receive retrieve req from node %d task %d", pTask->taskId, pReq->srcNodeId, pReq->srcTaskId);
+
+ streamTaskEnqueueRetrieve(pTask, pReq, pRsp);
+
+ ASSERT(pTask->execType != TASK_EXEC__NONE);
+ streamExec(pTask, pTask->pMsgCb);
+
+ ASSERT(pTask->dispatchType != TASK_DISPATCH__NONE);
+ streamDispatch(pTask, pTask->pMsgCb);
+
+ return 0;
+}
+
+int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp) {
+ //
+ return 0;
+}
diff --git a/source/libs/stream/src/streamData.c b/source/libs/stream/src/streamData.c
index 6699e86b1e6137cd9f7a5f873d207c23a0cc09f9..8e16b23e56e9506c1110afcbee0dfb251c7e4cc8 100644
--- a/source/libs/stream/src/streamData.c
+++ b/source/libs/stream/src/streamData.c
@@ -15,27 +15,6 @@
#include "streamInc.h"
-#if 0
-int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput) {
- int32_t tlen = 0;
- tlen += taosEncodeFixedI8(buf, pOutput->type);
- tlen += taosEncodeFixedI32(buf, pOutput->sourceVg);
- tlen += taosEncodeFixedI64(buf, pOutput->sourceVer);
- ASSERT(pOutput->type == STREAM_INPUT__DATA_BLOCK);
- tlen += tEncodeDataBlocks(buf, pOutput->blocks);
- return tlen;
-}
-
-void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput) {
- buf = taosDecodeFixedI8(buf, &pInput->type);
- buf = taosDecodeFixedI32(buf, &pInput->sourceVg);
- buf = taosDecodeFixedI64(buf, &pInput->sourceVer);
- ASSERT(pInput->type == STREAM_INPUT__DATA_BLOCK);
- buf = tDecodeDataBlocks(buf, &pInput->blocks);
- return (void*)buf;
-}
-#endif
-
int32_t streamDispatchReqToData(const SStreamDispatchReq* pReq, SStreamDataBlock* pData) {
int32_t blockNum = pReq->blockNum;
SArray* pArray = taosArrayInit(blockNum, sizeof(SSDataBlock));
@@ -48,14 +27,36 @@ int32_t streamDispatchReqToData(const SStreamDispatchReq* pReq, SStreamDataBlock
ASSERT(pReq->blockNum == taosArrayGetSize(pReq->dataLen));
for (int32_t i = 0; i < blockNum; i++) {
- int32_t len = *(int32_t*)taosArrayGet(pReq->dataLen, i);
+ /*int32_t len = *(int32_t*)taosArrayGet(pReq->dataLen, i);*/
SRetrieveTableRsp* pRetrieve = taosArrayGetP(pReq->data, i);
SSDataBlock* pDataBlock = taosArrayGet(pArray, i);
- blockCompressDecode(pDataBlock, htonl(pRetrieve->numOfCols), htonl(pRetrieve->numOfRows), pRetrieve->data);
+ blockDecode(pDataBlock, htonl(pRetrieve->numOfCols), htonl(pRetrieve->numOfRows), pRetrieve->data);
// TODO: refactor
+ pDataBlock->info.window.skey = be64toh(pRetrieve->skey);
+ pDataBlock->info.window.ekey = be64toh(pRetrieve->ekey);
+
pDataBlock->info.type = pRetrieve->streamBlockType;
- pDataBlock->info.childId = pReq->sourceChildId;
+ pDataBlock->info.childId = pReq->upstreamChildId;
+ }
+ pData->blocks = pArray;
+ return 0;
+}
+
+int32_t streamRetrieveReqToData(const SStreamRetrieveReq* pReq, SStreamDataBlock* pData) {
+ SArray* pArray = taosArrayInit(1, sizeof(SSDataBlock));
+ if (pArray == NULL) {
+ return -1;
}
+ taosArraySetSize(pArray, 1);
+ SRetrieveTableRsp* pRetrieve = pReq->pRetrieve;
+ SSDataBlock* pDataBlock = taosArrayGet(pArray, 0);
+ blockDecode(pDataBlock, htonl(pRetrieve->numOfCols), htonl(pRetrieve->numOfRows), pRetrieve->data);
+ // TODO: refactor
+ pDataBlock->info.window.skey = be64toh(pRetrieve->skey);
+ pDataBlock->info.window.ekey = be64toh(pRetrieve->ekey);
+
+ pDataBlock->info.type = pRetrieve->streamBlockType;
+
pData->blocks = pArray;
return 0;
}
@@ -87,3 +88,38 @@ SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit) {
memcpy(pSubmitClone, pSubmit, sizeof(SStreamDataSubmit));
return pSubmitClone;
}
+
+void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit) {
+ int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1);
+ ASSERT(ref >= 0);
+ if (ref == 0) {
+ taosMemoryFree(pDataSubmit->data);
+ taosMemoryFree(pDataSubmit->dataRef);
+ }
+}
+
+int32_t streamAppendQueueItem(SStreamQueueItem* dst, SStreamQueueItem* elem) {
+ ASSERT(elem);
+ if (dst->type == elem->type && dst->type == STREAM_INPUT__DATA_BLOCK) {
+ SStreamDataBlock* pBlock = (SStreamDataBlock*)dst;
+ SStreamDataBlock* pBlockSrc = (SStreamDataBlock*)elem;
+ taosArrayAddAll(pBlock->blocks, pBlockSrc->blocks);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+void streamFreeQitem(SStreamQueueItem* data) {
+ int8_t type = data->type;
+ if (type == STREAM_INPUT__TRIGGER) {
+ blockDataDestroy(((SStreamTrigger*)data)->pBlock);
+ taosFreeQitem(data);
+ } else if (type == STREAM_INPUT__DATA_BLOCK || type == STREAM_INPUT__DATA_RETRIEVE) {
+ taosArrayDestroyEx(((SStreamDataBlock*)data)->blocks, (FDelete)blockDataFreeRes);
+ taosFreeQitem(data);
+ } else if (type == STREAM_INPUT__DATA_SUBMIT) {
+ streamDataSubmitRefDec((SStreamDataSubmit*)data);
+ taosFreeQitem(data);
+ }
+}
diff --git a/source/libs/stream/src/streamDispatch.c b/source/libs/stream/src/streamDispatch.c
index 1894f697c01d550fd4877d2dc533d527b4d51eb4..e2faf28abe2e0e6fa2e61abe7fbd9b1f00a8ff9e 100644
--- a/source/libs/stream/src/streamDispatch.c
+++ b/source/libs/stream/src/streamDispatch.c
@@ -19,9 +19,9 @@ int32_t tEncodeStreamDispatchReq(SEncoder* pEncoder, const SStreamDispatchReq* p
if (tStartEncode(pEncoder) < 0) return -1;
if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
if (tEncodeI32(pEncoder, pReq->taskId) < 0) return -1;
- if (tEncodeI32(pEncoder, pReq->sourceTaskId) < 0) return -1;
- if (tEncodeI32(pEncoder, pReq->sourceVg) < 0) return -1;
- if (tEncodeI32(pEncoder, pReq->sourceChildId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->upstreamTaskId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->dataSrcVgId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->upstreamChildId) < 0) return -1;
if (tEncodeI32(pEncoder, pReq->upstreamNodeId) < 0) return -1;
if (tEncodeI32(pEncoder, pReq->blockNum) < 0) return -1;
ASSERT(taosArrayGetSize(pReq->data) == pReq->blockNum);
@@ -40,9 +40,9 @@ int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq) {
if (tStartDecode(pDecoder) < 0) return -1;
if (tDecodeI64(pDecoder, &pReq->streamId) < 0) return -1;
if (tDecodeI32(pDecoder, &pReq->taskId) < 0) return -1;
- if (tDecodeI32(pDecoder, &pReq->sourceTaskId) < 0) return -1;
- if (tDecodeI32(pDecoder, &pReq->sourceVg) < 0) return -1;
- if (tDecodeI32(pDecoder, &pReq->sourceChildId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->upstreamTaskId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->dataSrcVgId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->upstreamChildId) < 0) return -1;
if (tDecodeI32(pDecoder, &pReq->upstreamNodeId) < 0) return -1;
if (tDecodeI32(pDecoder, &pReq->blockNum) < 0) return -1;
ASSERT(pReq->blockNum > 0);
@@ -62,6 +62,106 @@ int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq) {
return 0;
}
+int32_t tEncodeStreamRetrieveReq(SEncoder* pEncoder, const SStreamRetrieveReq* pReq) {
+ if (tStartEncode(pEncoder) < 0) return -1;
+ if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->dstNodeId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->dstTaskId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->srcNodeId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pReq->srcTaskId) < 0) return -1;
+ if (tEncodeBinary(pEncoder, (const uint8_t*)pReq->pRetrieve, pReq->retrieveLen) < 0) return -1;
+ tEndEncode(pEncoder);
+ return pEncoder->pos;
+}
+
+int32_t tDecodeStreamRetrieveReq(SDecoder* pDecoder, SStreamRetrieveReq* pReq) {
+ if (tStartDecode(pDecoder) < 0) return -1;
+ if (tDecodeI64(pDecoder, &pReq->streamId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->dstNodeId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->dstTaskId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->srcNodeId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pReq->srcTaskId) < 0) return -1;
+ uint64_t len = 0;
+ if (tDecodeBinaryAlloc(pDecoder, (void**)&pReq->pRetrieve, &len) < 0) return -1;
+ pReq->retrieveLen = (int32_t)len;
+ tEndDecode(pDecoder);
+ return 0;
+}
+
+int32_t streamBroadcastToChildren(SStreamTask* pTask, const SSDataBlock* pBlock) {
+ SRetrieveTableRsp* pRetrieve = NULL;
+ void* buf = NULL;
+ int32_t dataStrLen = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
+
+ pRetrieve = taosMemoryCalloc(1, dataStrLen);
+ if (pRetrieve == NULL) return -1;
+
+ int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
+ pRetrieve->useconds = 0;
+ pRetrieve->precision = TSDB_DEFAULT_PRECISION;
+ pRetrieve->compressed = 0;
+ pRetrieve->completed = 1;
+ pRetrieve->streamBlockType = pBlock->info.type;
+ pRetrieve->numOfRows = htonl(pBlock->info.rows);
+ pRetrieve->numOfCols = htonl(numOfCols);
+ pRetrieve->skey = htobe64(pBlock->info.window.skey);
+ pRetrieve->ekey = htobe64(pBlock->info.window.ekey);
+
+ int32_t actualLen = 0;
+ blockEncode(pBlock, pRetrieve->data, &actualLen, numOfCols, false);
+
+ SStreamRetrieveReq req = {
+ .streamId = pTask->streamId,
+ .srcNodeId = pTask->nodeId,
+ .srcTaskId = pTask->taskId,
+ .pRetrieve = pRetrieve,
+ .retrieveLen = dataStrLen,
+ };
+
+ int32_t sz = taosArrayGetSize(pTask->childEpInfo);
+ ASSERT(sz > 0);
+ for (int32_t i = 0; i < sz; i++) {
+ SStreamChildEpInfo* pEpInfo = taosArrayGetP(pTask->childEpInfo, i);
+ req.dstNodeId = pEpInfo->nodeId;
+ req.dstTaskId = pEpInfo->taskId;
+ int32_t code;
+ int32_t len;
+ tEncodeSize(tEncodeStreamRetrieveReq, &req, len, code);
+ if (code < 0) {
+ ASSERT(0);
+ return -1;
+ }
+
+ buf = rpcMallocCont(sizeof(SMsgHead) + len);
+ if (buf == NULL) {
+ goto FAIL;
+ }
+
+ ((SMsgHead*)buf)->vgId = htonl(pEpInfo->nodeId);
+ void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
+ SEncoder encoder;
+ tEncoderInit(&encoder, abuf, len);
+ tEncodeStreamRetrieveReq(&encoder, &req);
+
+ SRpcMsg rpcMsg = {
+ .code = 0,
+ .msgType = TDMT_STREAM_RETRIEVE,
+ .pCont = buf,
+ .contLen = sizeof(SMsgHead) + len,
+ };
+
+ if (tmsgSendReq(&pEpInfo->epSet, &rpcMsg) < 0) {
+ ASSERT(0);
+ return -1;
+ }
+ }
+ return 0;
+FAIL:
+ if (pRetrieve) taosMemoryFree(pRetrieve);
+ if (buf) taosMemoryFree(buf);
+ return -1;
+}
+
static int32_t streamAddBlockToDispatchMsg(const SSDataBlock* pBlock, SStreamDispatchReq* pReq) {
int32_t dataStrLen = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock);
void* buf = taosMemoryCalloc(1, dataStrLen);
@@ -74,10 +174,14 @@ static int32_t streamAddBlockToDispatchMsg(const SSDataBlock* pBlock, SStreamDis
pRetrieve->completed = 1;
pRetrieve->streamBlockType = pBlock->info.type;
pRetrieve->numOfRows = htonl(pBlock->info.rows);
- pRetrieve->numOfCols = htonl(pBlock->info.numOfCols);
+ pRetrieve->skey = htobe64(pBlock->info.window.skey);
+ pRetrieve->ekey = htobe64(pBlock->info.window.ekey);
+
+ int32_t numOfCols = (int32_t)taosArrayGetSize(pBlock->pDataBlock);
+ pRetrieve->numOfCols = htonl(numOfCols);
int32_t actualLen = 0;
- blockCompressEncode(pBlock, pRetrieve->data, &actualLen, pBlock->info.numOfCols, false);
+ blockEncode(pBlock, pRetrieve->data, &actualLen, numOfCols, false);
actualLen += sizeof(SRetrieveTableRsp);
ASSERT(actualLen <= dataStrLen);
taosArrayPush(pReq->dataLen, &actualLen);
@@ -86,7 +190,7 @@ static int32_t streamAddBlockToDispatchMsg(const SSDataBlock* pBlock, SStreamDis
return 0;
}
-int32_t streamBuildDispatchMsg(SStreamTask* pTask, SStreamDataBlock* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
+int32_t streamBuildDispatchMsg(SStreamTask* pTask, const SStreamDataBlock* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
void* buf = NULL;
int32_t code = -1;
int32_t blockNum = taosArrayGetSize(data->blocks);
@@ -94,9 +198,9 @@ int32_t streamBuildDispatchMsg(SStreamTask* pTask, SStreamDataBlock* data, SRpcM
SStreamDispatchReq req = {
.streamId = pTask->streamId,
- .sourceTaskId = pTask->taskId,
- .sourceVg = data->sourceVg,
- .sourceChildId = pTask->childId,
+ .dataSrcVgId = data->srcVgId,
+ .upstreamTaskId = pTask->taskId,
+ .upstreamChildId = pTask->selfChildId,
.upstreamNodeId = pTask->nodeId,
.blockNum = blockNum,
};
@@ -147,8 +251,8 @@ int32_t streamBuildDispatchMsg(SStreamTask* pTask, SStreamDataBlock* data, SRpcM
ASSERT(vgId > 0 || vgId == SNODE_HANDLE);
req.taskId = downstreamTaskId;
- qInfo("dispatch from task %d (child id %d) to down stream task %d in vnode %d", pTask->taskId, pTask->childId,
- downstreamTaskId, vgId);
+ qDebug("dispatch from task %d (child id %d) to down stream task %d in vnode %d", pTask->taskId, pTask->selfChildId,
+ downstreamTaskId, vgId);
// serialize
int32_t tlen;
@@ -194,12 +298,13 @@ int32_t streamDispatch(SStreamTask* pTask, SMsgCb* pMsgCb) {
SStreamDataBlock* pBlock = streamQueueNextItem(pTask->outputQueue);
if (pBlock == NULL) {
+ qDebug("stream stop dispatching since no output: task %d", pTask->taskId);
atomic_store_8(&pTask->outputStatus, TASK_OUTPUT_STATUS__NORMAL);
return 0;
}
- ASSERT(pBlock->type == STREAM_DATA_TYPE_SSDATA_BLOCK);
+ ASSERT(pBlock->type == STREAM_INPUT__DATA_BLOCK);
- qInfo("stream continue dispatching: task %d", pTask->taskId);
+ qDebug("stream continue dispatching: task %d", pTask->taskId);
SRpcMsg dispatchMsg = {0};
SEpSet* pEpSet = NULL;
@@ -208,6 +313,8 @@ int32_t streamDispatch(SStreamTask* pTask, SMsgCb* pMsgCb) {
atomic_store_8(&pTask->outputStatus, TASK_OUTPUT_STATUS__NORMAL);
return -1;
}
+ taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes);
+ taosFreeQitem(pBlock);
tmsgSendReq(pEpSet, &dispatchMsg);
return 0;
diff --git a/source/libs/stream/src/streamExec.c b/source/libs/stream/src/streamExec.c
index 5a71fccab886f56ddc5c9de178879a0f1feb145a..023c092028bf4ec22196844bb3d42c2c7ad45409 100644
--- a/source/libs/stream/src/streamExec.c
+++ b/source/libs/stream/src/streamExec.c
@@ -13,8 +13,7 @@
* along with this program. If not, see .
*/
-#include "executor.h"
-#include "tstream.h"
+#include "streamInc.h"
static int32_t streamTaskExecImpl(SStreamTask* pTask, void* data, SArray* pRes) {
void* exec = pTask->exec.executor;
@@ -23,16 +22,20 @@ static int32_t streamTaskExecImpl(SStreamTask* pTask, void* data, SArray* pRes)
SStreamQueueItem* pItem = (SStreamQueueItem*)data;
if (pItem->type == STREAM_INPUT__TRIGGER) {
SStreamTrigger* pTrigger = (SStreamTrigger*)data;
- qSetMultiStreamInput(exec, pTrigger->pBlock, 1, STREAM_DATA_TYPE_SSDATA_BLOCK, false);
+ qSetMultiStreamInput(exec, pTrigger->pBlock, 1, STREAM_INPUT__DATA_BLOCK, false);
} else if (pItem->type == STREAM_INPUT__DATA_SUBMIT) {
+ ASSERT(pTask->isDataScan);
SStreamDataSubmit* pSubmit = (SStreamDataSubmit*)data;
- ASSERT(pTask->inputType == STREAM_INPUT__DATA_SUBMIT);
- qSetStreamInput(exec, pSubmit->data, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
- } else if (pItem->type == STREAM_INPUT__DATA_BLOCK) {
+ qDebug("task %d %p set submit input %p %p %d", pTask->taskId, pTask, pSubmit, pSubmit->data, *pSubmit->dataRef);
+ qSetStreamInput(exec, pSubmit->data, STREAM_INPUT__DATA_SUBMIT, false);
+ } else if (pItem->type == STREAM_INPUT__DATA_BLOCK || pItem->type == STREAM_INPUT__DATA_RETRIEVE) {
SStreamDataBlock* pBlock = (SStreamDataBlock*)data;
- ASSERT(pTask->inputType == STREAM_INPUT__DATA_BLOCK);
- SArray* blocks = pBlock->blocks;
- qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_DATA_TYPE_SSDATA_BLOCK, false);
+ SArray* blocks = pBlock->blocks;
+ qDebug("task %d %p set ssdata input", pTask->taskId, pTask);
+ qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_INPUT__DATA_BLOCK, false);
+ } else if (pItem->type == STREAM_INPUT__DROP) {
+ // TODO exec drop
+ return 0;
}
// exec
@@ -42,21 +45,70 @@ static int32_t streamTaskExecImpl(SStreamTask* pTask, void* data, SArray* pRes)
if (qExecTask(exec, &output, &ts) < 0) {
ASSERT(false);
}
- if (output == NULL) break;
- // TODO: do we need free memory?
- SSDataBlock* outputCopy = createOneDataBlock(output, true);
- outputCopy->info.childId = pTask->childId;
- taosArrayPush(pRes, outputCopy);
+ if (output == NULL) {
+ if (pItem->type == STREAM_INPUT__DATA_RETRIEVE) {
+ SSDataBlock block = {0};
+ SStreamDataBlock* pRetrieveBlock = (SStreamDataBlock*)data;
+ ASSERT(taosArrayGetSize(pRetrieveBlock->blocks) == 1);
+ assignOneDataBlock(&block, taosArrayGet(pRetrieveBlock->blocks, 0));
+ block.info.type = STREAM_PULL_OVER;
+ block.info.childId = pTask->selfChildId;
+ taosArrayPush(pRes, &block);
+ }
+ break;
+ }
+
+ if (output->info.type == STREAM_RETRIEVE) {
+ if (streamBroadcastToChildren(pTask, output) < 0) {
+ // TODO
+ }
+ continue;
+ }
+
+ SSDataBlock block = {0};
+ assignOneDataBlock(&block, output);
+ block.info.childId = pTask->selfChildId;
+ taosArrayPush(pRes, &block);
}
return 0;
}
static SArray* streamExecForQall(SStreamTask* pTask, SArray* pRes) {
while (1) {
- void* data = streamQueueNextItem(pTask->inputQueue);
+ int32_t cnt = 0;
+ void* data = NULL;
+ while (1) {
+ SStreamQueueItem* qItem = streamQueueNextItem(pTask->inputQueue);
+ if (qItem == NULL) {
+ qDebug("stream exec over, queue empty");
+ break;
+ }
+ if (data == NULL) {
+ data = qItem;
+ streamQueueProcessSuccess(pTask->inputQueue);
+ continue;
+ } else {
+ if (streamAppendQueueItem(data, qItem) < 0) {
+ streamQueueProcessFail(pTask->inputQueue);
+ break;
+ } else {
+ cnt++;
+ streamQueueProcessSuccess(pTask->inputQueue);
+ taosArrayDestroy(((SStreamDataBlock*)qItem)->blocks);
+ taosFreeQitem(qItem);
+ }
+ }
+ }
if (data == NULL) break;
+ qDebug("stream task %d exec begin, batch msg: %d", pTask->taskId, cnt);
streamTaskExecImpl(pTask, data, pRes);
+ qDebug("stream task %d exec end", pTask->taskId);
+
+ if (pTask->taskStatus == TASK_STATUS__DROPPING) {
+ taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes);
+ return NULL;
+ }
if (taosArrayGetSize(pRes) != 0) {
SStreamDataBlock* qRes = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
@@ -67,24 +119,17 @@ static SArray* streamExecForQall(SStreamTask* pTask, SArray* pRes) {
}
qRes->type = STREAM_INPUT__DATA_BLOCK;
qRes->blocks = pRes;
- /*qRes->sourceVg = pTask->nodeId;*/
if (streamTaskOutput(pTask, qRes) < 0) {
- streamQueueProcessFail(pTask->inputQueue);
- taosArrayDestroy(pRes);
+ /*streamQueueProcessFail(pTask->inputQueue);*/
+ taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes);
taosFreeQitem(qRes);
return NULL;
}
-
- if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
- streamDataSubmitRefDec((SStreamDataSubmit*)data);
- taosFreeQitem(data);
- } else {
- taosArrayDestroyEx(((SStreamDataBlock*)data)->blocks, (FDelete)tDeleteSSDataBlock);
- taosFreeQitem(data);
- }
- streamQueueProcessSuccess(pTask->inputQueue);
- return taosArrayInit(0, sizeof(SSDataBlock));
+ /*streamQueueProcessSuccess(pTask->inputQueue);*/
+ pRes = taosArrayInit(0, sizeof(SSDataBlock));
}
+
+ streamFreeQitem(data);
}
return pRes;
}
@@ -94,27 +139,31 @@ int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb) {
SArray* pRes = taosArrayInit(0, sizeof(SSDataBlock));
if (pRes == NULL) return -1;
while (1) {
- int8_t execStatus = atomic_val_compare_exchange_8(&pTask->status, TASK_STATUS__IDLE, TASK_STATUS__EXECUTING);
- if (execStatus == TASK_STATUS__IDLE) {
+ int8_t execStatus =
+ atomic_val_compare_exchange_8(&pTask->execStatus, TASK_EXEC_STATUS__IDLE, TASK_EXEC_STATUS__EXECUTING);
+ if (execStatus == TASK_EXEC_STATUS__IDLE) {
// first run
+ qDebug("stream exec, enter exec status");
pRes = streamExecForQall(pTask, pRes);
if (pRes == NULL) goto FAIL;
// set status closing
- atomic_store_8(&pTask->status, TASK_STATUS__CLOSING);
+ atomic_store_8(&pTask->execStatus, TASK_EXEC_STATUS__CLOSING);
// second run, make sure inputQ and qall are cleared
+ qDebug("stream exec, enter closing status");
pRes = streamExecForQall(pTask, pRes);
if (pRes == NULL) goto FAIL;
- taosArrayDestroy(pRes);
- atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
+ taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes);
+ atomic_store_8(&pTask->execStatus, TASK_EXEC_STATUS__IDLE);
+ qDebug("stream exec, return result");
return 0;
- } else if (execStatus == TASK_STATUS__CLOSING) {
+ } else if (execStatus == TASK_EXEC_STATUS__CLOSING) {
continue;
- } else if (execStatus == TASK_STATUS__EXECUTING) {
+ } else if (execStatus == TASK_EXEC_STATUS__EXECUTING) {
ASSERT(taosArrayGetSize(pRes) == 0);
- taosArrayDestroy(pRes);
+ taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes);
return 0;
} else {
ASSERT(0);
@@ -122,7 +171,6 @@ int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb) {
}
FAIL:
if (pRes) taosArrayDestroy(pRes);
- atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
+ atomic_store_8(&pTask->execStatus, TASK_EXEC_STATUS__IDLE);
return -1;
}
-
diff --git a/source/libs/stream/src/streamQueue.c b/source/libs/stream/src/streamQueue.c
index d5a4da60f56b08a9be47406280b6a812701c3870..f82ef1b42fff735e92106eee97731a2c14b1d380 100644
--- a/source/libs/stream/src/streamQueue.c
+++ b/source/libs/stream/src/streamQueue.c
@@ -41,12 +41,3 @@ void streamQueueClose(SStreamQueue* queue) {
return;
}
}
-
-void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit) {
- int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1);
- ASSERT(ref >= 0);
- if (ref == 0) {
- taosMemoryFree(pDataSubmit->data);
- taosMemoryFree(pDataSubmit->dataRef);
- }
-}
diff --git a/source/libs/stream/src/streamTask.c b/source/libs/stream/src/streamTask.c
index b5a63d937ae6be238406839921ba8a514568001a..97aa182dc96eeb402316bb9d54df576312d461e3 100644
--- a/source/libs/stream/src/streamTask.c
+++ b/source/libs/stream/src/streamTask.c
@@ -23,29 +23,53 @@ SStreamTask* tNewSStreamTask(int64_t streamId) {
}
pTask->taskId = tGenIdPI32();
pTask->streamId = streamId;
- pTask->status = TASK_STATUS__IDLE;
+ pTask->execStatus = TASK_EXEC_STATUS__IDLE;
pTask->inputStatus = TASK_INPUT_STATUS__NORMAL;
pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL;
return pTask;
}
+int32_t tEncodeStreamEpInfo(SEncoder* pEncoder, const SStreamChildEpInfo* pInfo) {
+ if (tEncodeI32(pEncoder, pInfo->taskId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pInfo->nodeId) < 0) return -1;
+ if (tEncodeI32(pEncoder, pInfo->childId) < 0) return -1;
+ if (tEncodeSEpSet(pEncoder, &pInfo->epSet) < 0) return -1;
+ return 0;
+}
+
+int32_t tDecodeStreamEpInfo(SDecoder* pDecoder, SStreamChildEpInfo* pInfo) {
+ if (tDecodeI32(pDecoder, &pInfo->taskId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pInfo->nodeId) < 0) return -1;
+ if (tDecodeI32(pDecoder, &pInfo->childId) < 0) return -1;
+ if (tDecodeSEpSet(pDecoder, &pInfo->epSet) < 0) return -1;
+ return 0;
+}
+
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) {
/*if (tStartEncode(pEncoder) < 0) return -1;*/
if (tEncodeI64(pEncoder, pTask->streamId) < 0) return -1;
if (tEncodeI32(pEncoder, pTask->taskId) < 0) return -1;
- if (tEncodeI8(pEncoder, pTask->inputType) < 0) return -1;
- if (tEncodeI8(pEncoder, pTask->status) < 0) return -1;
+ if (tEncodeI8(pEncoder, pTask->isDataScan) < 0) return -1;
if (tEncodeI8(pEncoder, pTask->execType) < 0) return -1;
if (tEncodeI8(pEncoder, pTask->sinkType) < 0) return -1;
if (tEncodeI8(pEncoder, pTask->dispatchType) < 0) return -1;
if (tEncodeI16(pEncoder, pTask->dispatchMsgType) < 0) return -1;
- if (tEncodeI8(pEncoder, pTask->dataScan) < 0) return -1;
- if (tEncodeI32(pEncoder, pTask->childId) < 0) return -1;
+ if (tEncodeI8(pEncoder, pTask->taskStatus) < 0) return -1;
+ if (tEncodeI8(pEncoder, pTask->execStatus) < 0) return -1;
+
+ if (tEncodeI32(pEncoder, pTask->selfChildId) < 0) return -1;
if (tEncodeI32(pEncoder, pTask->nodeId) < 0) return -1;
if (tEncodeSEpSet(pEncoder, &pTask->epSet) < 0) return -1;
+ int32_t epSz = taosArrayGetSize(pTask->childEpInfo);
+ if (tEncodeI32(pEncoder, epSz) < 0) return -1;
+ for (int32_t i = 0; i < epSz; i++) {
+ SStreamChildEpInfo* pInfo = taosArrayGetP(pTask->childEpInfo, i);
+ if (tEncodeStreamEpInfo(pEncoder, pInfo) < 0) return -1;
+ }
+
if (pTask->execType != TASK_EXEC__NONE) {
if (tEncodeCStr(pEncoder, pTask->exec.qmsg) < 0) return -1;
}
@@ -62,9 +86,7 @@ int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) {
ASSERT(pTask->sinkType == TASK_SINK__NONE);
}
- if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
- if (tEncodeI32(pEncoder, pTask->inplaceDispatcher.taskId) < 0) return -1;
- } else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
+ if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.taskId) < 0) return -1;
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.nodeId) < 0) return -1;
if (tEncodeSEpSet(pEncoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
@@ -82,18 +104,29 @@ int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) {
/*if (tStartDecode(pDecoder) < 0) return -1;*/
if (tDecodeI64(pDecoder, &pTask->streamId) < 0) return -1;
if (tDecodeI32(pDecoder, &pTask->taskId) < 0) return -1;
- if (tDecodeI8(pDecoder, &pTask->inputType) < 0) return -1;
- if (tDecodeI8(pDecoder, &pTask->status) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pTask->isDataScan) < 0) return -1;
if (tDecodeI8(pDecoder, &pTask->execType) < 0) return -1;
if (tDecodeI8(pDecoder, &pTask->sinkType) < 0) return -1;
if (tDecodeI8(pDecoder, &pTask->dispatchType) < 0) return -1;
if (tDecodeI16(pDecoder, &pTask->dispatchMsgType) < 0) return -1;
- if (tDecodeI8(pDecoder, &pTask->dataScan) < 0) return -1;
- if (tDecodeI32(pDecoder, &pTask->childId) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pTask->taskStatus) < 0) return -1;
+ if (tDecodeI8(pDecoder, &pTask->execStatus) < 0) return -1;
+
+ if (tDecodeI32(pDecoder, &pTask->selfChildId) < 0) return -1;
if (tDecodeI32(pDecoder, &pTask->nodeId) < 0) return -1;
if (tDecodeSEpSet(pDecoder, &pTask->epSet) < 0) return -1;
+ int32_t epSz;
+ if (tDecodeI32(pDecoder, &epSz) < 0) return -1;
+ pTask->childEpInfo = taosArrayInit(epSz, sizeof(void*));
+ for (int32_t i = 0; i < epSz; i++) {
+ SStreamChildEpInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamChildEpInfo));
+ if (pInfo == NULL) return -1;
+ if (tDecodeStreamEpInfo(pDecoder, pInfo) < 0) return -1;
+ taosArrayPush(pTask->childEpInfo, &pInfo);
+ }
+
if (pTask->execType != TASK_EXEC__NONE) {
if (tDecodeCStrAlloc(pDecoder, &pTask->exec.qmsg) < 0) return -1;
}
@@ -112,9 +145,7 @@ int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) {
ASSERT(pTask->sinkType == TASK_SINK__NONE);
}
- if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
- if (tDecodeI32(pDecoder, &pTask->inplaceDispatcher.taskId) < 0) return -1;
- } else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
+ if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.taskId) < 0) return -1;
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.nodeId) < 0) return -1;
if (tDecodeSEpSet(pDecoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
diff --git a/source/libs/stream/src/streamUpdate.c b/source/libs/stream/src/streamUpdate.c
index ada391b40a76af148e07789375a756a6590648b3..d0fb9c22e19527ee9352245596663877a6ba29c7 100644
--- a/source/libs/stream/src/streamUpdate.c
+++ b/source/libs/stream/src/streamUpdate.c
@@ -17,7 +17,7 @@
#include "ttime.h"
#define DEFAULT_FALSE_POSITIVE 0.01
-#define DEFAULT_BUCKET_SIZE 1024
+#define DEFAULT_BUCKET_SIZE 131072
#define ROWS_PER_MILLISECOND 1
#define MAX_NUM_SCALABLE_BF 100000
#define MIN_NUM_SCALABLE_BF 10
@@ -119,6 +119,7 @@ SUpdateInfo *updateInfoInit(int64_t interval, int32_t precision, int64_t waterma
taosArrayPush(pInfo->pTsBuckets, &dumy);
}
pInfo->numBuckets = DEFAULT_BUCKET_SIZE;
+ pInfo->pCloseWinSBF = NULL;
return pInfo;
}
@@ -154,6 +155,9 @@ bool updateInfoIsUpdated(SUpdateInfo *pInfo, tb_uid_t tableId, TSKEY ts) {
TSKEY maxTs = *(TSKEY *)taosArrayGet(pInfo->pTsBuckets, index);
if (ts < maxTs - pInfo->watermark) {
// this window has been closed.
+ if (pInfo->pCloseWinSBF) {
+ return tScalableBfPut(pInfo->pCloseWinSBF, &ts, sizeof(TSKEY));
+ }
return true;
}
@@ -193,3 +197,19 @@ void updateInfoDestroy(SUpdateInfo *pInfo) {
taosArrayDestroy(pInfo->pTsSBFs);
taosMemoryFree(pInfo);
}
+
+void updateInfoAddCloseWindowSBF(SUpdateInfo *pInfo) {
+ if (pInfo->pCloseWinSBF) {
+ return;
+ }
+ int64_t rows = adjustExpEntries(pInfo->interval * ROWS_PER_MILLISECOND);
+ pInfo->pCloseWinSBF = tScalableBfInit(rows, DEFAULT_FALSE_POSITIVE);
+}
+
+void updateInfoDestoryColseWinSBF(SUpdateInfo *pInfo) {
+ if (!pInfo || !pInfo->pCloseWinSBF) {
+ return;
+ }
+ tScalableBfDestroy(pInfo->pCloseWinSBF);
+ pInfo->pCloseWinSBF = NULL;
+}
diff --git a/source/libs/sync/inc/syncAppendEntries.h b/source/libs/sync/inc/syncAppendEntries.h
index 98df22d51b9a73f99aad6cd550bc6214a58d30a2..e15c85d73bfda288bfb249c366a020997f1202c1 100644
--- a/source/libs/sync/inc/syncAppendEntries.h
+++ b/source/libs/sync/inc/syncAppendEntries.h
@@ -94,6 +94,7 @@ extern "C" {
//
int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg);
int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMsg);
+int32_t syncNodeOnAppendEntriesSnapshot2Cb(SSyncNode* ths, SyncAppendEntriesBatch* pMsg);
#ifdef __cplusplus
}
diff --git a/source/libs/sync/inc/syncAppendEntriesReply.h b/source/libs/sync/inc/syncAppendEntriesReply.h
index e509a50dc4c215ad678d4d66b93d37102167a8e7..03148252fba36d8264123a5e169cb18a065d5de4 100644
--- a/source/libs/sync/inc/syncAppendEntriesReply.h
+++ b/source/libs/sync/inc/syncAppendEntriesReply.h
@@ -42,6 +42,7 @@ extern "C" {
//
int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg);
int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg);
+int32_t syncNodeOnAppendEntriesReplySnapshot2Cb(SSyncNode* ths, SyncAppendEntriesReply* pMsg);
#ifdef __cplusplus
}
diff --git a/source/libs/sync/inc/syncEnv.h b/source/libs/sync/inc/syncEnv.h
index 4f91990ccf29a93cdd7b9d4fd4f2e16bfc3df480..dd032f148177eaf9d4773fcd698cdffedc67887b 100644
--- a/source/libs/sync/inc/syncEnv.h
+++ b/source/libs/sync/inc/syncEnv.h
@@ -30,11 +30,11 @@ extern "C" {
#define TIMER_MAX_MS 0x7FFFFFFF
#define ENV_TICK_TIMER_MS 1000
-#define PING_TIMER_MS 1000
-#define ELECT_TIMER_MS_MIN 500
+#define PING_TIMER_MS 5000
+#define ELECT_TIMER_MS_MIN 1300
#define ELECT_TIMER_MS_MAX (ELECT_TIMER_MS_MIN * 2)
#define ELECT_TIMER_MS_RANGE (ELECT_TIMER_MS_MAX - ELECT_TIMER_MS_MIN)
-#define HEARTBEAT_TIMER_MS 100
+#define HEARTBEAT_TIMER_MS 900
#define EMPTY_RAFT_ID ((SRaftId){.addr = 0, .vgId = 0})
diff --git a/source/libs/sync/inc/syncIO.h b/source/libs/sync/inc/syncIO.h
index 88d3065375a007c367b5301679cb84a697045922..f3064e668df575d51dbd1efc333e373543522de1 100644
--- a/source/libs/sync/inc/syncIO.h
+++ b/source/libs/sync/inc/syncIO.h
@@ -50,7 +50,7 @@ typedef struct SSyncIO {
void *pSyncNode;
int32_t (*FpOnSyncPing)(SSyncNode *pSyncNode, SyncPing *pMsg);
int32_t (*FpOnSyncPingReply)(SSyncNode *pSyncNode, SyncPingReply *pMsg);
- int32_t (*FpOnSyncClientRequest)(SSyncNode *pSyncNode, SyncClientRequest *pMsg);
+ int32_t (*FpOnSyncClientRequest)(SSyncNode *pSyncNode, SyncClientRequest *pMsg, SyncIndex *pRetIndex);
int32_t (*FpOnSyncRequestVote)(SSyncNode *pSyncNode, SyncRequestVote *pMsg);
int32_t (*FpOnSyncRequestVoteReply)(SSyncNode *pSyncNode, SyncRequestVoteReply *pMsg);
int32_t (*FpOnSyncAppendEntries)(SSyncNode *pSyncNode, SyncAppendEntries *pMsg);
diff --git a/source/libs/sync/inc/syncInt.h b/source/libs/sync/inc/syncInt.h
index 63db395425c23d2c4ac50fda93b88b974c4787ab..e361c8021cf166818d4ffefd5888ffa6afce06b2 100644
--- a/source/libs/sync/inc/syncInt.h
+++ b/source/libs/sync/inc/syncInt.h
@@ -169,11 +169,13 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo);
void syncNodeStart(SSyncNode* pSyncNode);
void syncNodeStartStandBy(SSyncNode* pSyncNode);
void syncNodeClose(SSyncNode* pSyncNode);
-int32_t syncNodePropose(SSyncNode* pSyncNode, const SRpcMsg* pMsg, bool isWeak);
+int32_t syncNodePropose(SSyncNode* pSyncNode, SRpcMsg* pMsg, bool isWeak);
+int32_t syncNodeProposeBatch(SSyncNode* pSyncNode, SRpcMsg* pMsgArr, bool* pIsWeakArr, int32_t arrSize);
// option
-bool syncNodeSnapshotEnable(SSyncNode* pSyncNode);
-SyncIndex syncNodeGetSnapshotConfigIndex(SSyncNode* pSyncNode, SyncIndex snapshotLastApplyIndex);
+bool syncNodeSnapshotEnable(SSyncNode* pSyncNode);
+ESyncStrategy syncNodeStrategy(SSyncNode* pSyncNode);
+SyncIndex syncNodeGetSnapshotConfigIndex(SSyncNode* pSyncNode, SyncIndex snapshotLastApplyIndex);
// ping --------------
int32_t syncNodePing(SSyncNode* pSyncNode, const SRaftId* destRaftId, SyncPing* pMsg);
@@ -197,6 +199,7 @@ int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, S
cJSON* syncNode2Json(const SSyncNode* pSyncNode);
char* syncNode2Str(const SSyncNode* pSyncNode);
void syncNodeEventLog(const SSyncNode* pSyncNode, char* str);
+void syncNodeErrorLog(const SSyncNode* pSyncNode, char* str);
char* syncNode2SimpleStr(const SSyncNode* pSyncNode);
bool syncNodeInConfig(SSyncNode* pSyncNode, const SSyncCfg* config);
void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* newConfig, SyncIndex lastConfigChangeIndex);
@@ -220,7 +223,6 @@ void syncNodeVoteForSelf(SSyncNode* pSyncNode);
// snapshot --------------
bool syncNodeHasSnapshot(SSyncNode* pSyncNode);
-bool syncNodeIsIndexInSnapshot(SSyncNode* pSyncNode, SyncIndex index);
SyncIndex syncNodeGetLastIndex(SSyncNode* pSyncNode);
SyncTerm syncNodeGetLastTerm(SSyncNode* pSyncNode);
@@ -232,6 +234,7 @@ SyncIndex syncNodeGetPreIndex(SSyncNode* pSyncNode, SyncIndex index);
SyncTerm syncNodeGetPreTerm(SSyncNode* pSyncNode, SyncIndex index);
int32_t syncNodeGetPreIndexTerm(SSyncNode* pSyncNode, SyncIndex index, SyncIndex* pPreIndex, SyncTerm* pPreTerm);
+bool syncNodeIsOptimizedOneReplica(SSyncNode* ths, SRpcMsg* pMsg);
int32_t syncNodeCommit(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex, uint64_t flag);
int32_t syncNodeUpdateNewConfigIndex(SSyncNode* ths, SSyncCfg* pNewCfg);
@@ -248,11 +251,15 @@ void syncStartStandBy(int64_t rid);
bool syncNodeCanChange(SSyncNode* pSyncNode);
bool syncNodeCheckNewConfig(SSyncNode* pSyncNode, const SSyncCfg* pNewCfg);
+int32_t syncNodeLeaderTransfer(SSyncNode* pSyncNode);
+int32_t syncNodeLeaderTransferTo(SSyncNode* pSyncNode, SNodeInfo newLeader);
+
// for debug --------------
void syncNodePrint(SSyncNode* pObj);
void syncNodePrint2(char* s, SSyncNode* pObj);
void syncNodeLog(SSyncNode* pObj);
void syncNodeLog2(char* s, SSyncNode* pObj);
+void syncNodeLog3(char* s, SSyncNode* pObj);
#ifdef __cplusplus
}
diff --git a/source/libs/sync/inc/syncOnMessage.h b/source/libs/sync/inc/syncOnMessage.h
deleted file mode 100644
index 2f8856e652a84332a9455fb1f6bc26bf8a975e89..0000000000000000000000000000000000000000
--- a/source/libs/sync/inc/syncOnMessage.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _TD_LIBS_SYNC_ON_MESSAGE_H
-#define _TD_LIBS_SYNC_ON_MESSAGE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include
-#include
-#include
-#include "taosdef.h"
-
-// TLA+ Spec
-// Receive(m) ==
-// LET i == m.mdest
-// j == m.msource
-// IN \* Any RPC with a newer term causes the recipient to advance
-// \* its term first. Responses with stale terms are ignored.
-// \/ UpdateTerm(i, j, m)
-// \/ /\ m.mtype = RequestVoteRequest
-// /\ HandleRequestVoteRequest(i, j, m)
-// \/ /\ m.mtype = RequestVoteResponse
-// /\ \/ DropStaleResponse(i, j, m)
-// \/ HandleRequestVoteResponse(i, j, m)
-// \/ /\ m.mtype = AppendEntriesRequest
-// /\ HandleAppendEntriesRequest(i, j, m)
-// \/ /\ m.mtype = AppendEntriesResponse
-// /\ \/ DropStaleResponse(i, j, m)
-// \/ HandleAppendEntriesResponse(i, j, m)
-
-// DuplicateMessage(m) ==
-// /\ Send(m)
-// /\ UNCHANGED <>
-
-// DropMessage(m) ==
-// /\ Discard(m)
-// /\ UNCHANGED <>
-
-// Next == /\ \/ \E i \in Server : Restart(i)
-// \/ \E i \in Server : Timeout(i)
-// \/ \E i,j \in Server : RequestVote(i, j)
-// \/ \E i \in Server : BecomeLeader(i)
-// \/ \E i \in Server, v \in Value : ClientRequest(i, v)
-// \/ \E i \in Server : AdvanceCommitIndex(i)
-// \/ \E i,j \in Server : AppendEntries(i, j)
-// \/ \E m \in DOMAIN messages : Receive(m)
-// \/ \E m \in DOMAIN messages : DuplicateMessage(m)
-// \/ \E m \in DOMAIN messages : DropMessage(m)
-// \* History variable that tracks every log ever:
-// /\ allLogs' = allLogs \cup {log[i] : i \in Server}
-//
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_TD_LIBS_SYNC_ON_MESSAGE_H*/
diff --git a/source/libs/sync/inc/syncRaftCfg.h b/source/libs/sync/inc/syncRaftCfg.h
index 7f45276e9f2bb5891e96b22650fd3eddd37a338b..fead7cdc762b46b4d3e26a2af0d5f370eb19c6cf 100644
--- a/source/libs/sync/inc/syncRaftCfg.h
+++ b/source/libs/sync/inc/syncRaftCfg.h
@@ -27,7 +27,7 @@ extern "C" {
#include "syncInt.h"
#include "taosdef.h"
-#define CONFIG_FILE_LEN 1024
+#define CONFIG_FILE_LEN 2048
#define MAX_CONFIG_INDEX_COUNT 512
@@ -36,7 +36,8 @@ typedef struct SRaftCfg {
TdFilePtr pFile;
char path[TSDB_FILENAME_LEN * 2];
int8_t isStandBy;
- int8_t snapshotEnable;
+ int32_t batchSize;
+ int8_t snapshotStrategy;
SyncIndex lastConfigIndex;
SyncIndex configIndexArr[MAX_CONFIG_INDEX_COUNT];
@@ -62,7 +63,8 @@ int32_t raftCfgFromStr(const char *s, SRaftCfg *pRaftCfg);
typedef struct SRaftCfgMeta {
int8_t isStandBy;
- int8_t snapshotEnable;
+ int32_t batchSize;
+ int8_t snapshotStrategy;
SyncIndex lastConfigIndex;
} SRaftCfgMeta;
diff --git a/source/libs/sync/inc/syncRaftEntry.h b/source/libs/sync/inc/syncRaftEntry.h
index b13018651666760bd1b9904067784c23aa736ac4..fdfabf12a3820d332b2404592a2f104a90fb76b6 100644
--- a/source/libs/sync/inc/syncRaftEntry.h
+++ b/source/libs/sync/inc/syncRaftEntry.h
@@ -26,22 +26,24 @@ extern "C" {
#include "syncInt.h"
#include "syncMessage.h"
#include "taosdef.h"
+#include "tskiplist.h"
typedef struct SSyncRaftEntry {
uint32_t bytes;
- uint32_t msgType; // SyncClientRequest msgType
- uint32_t originalRpcType; // user RpcMsg msgType
+ uint32_t msgType; // TDMT_SYNC_CLIENT_REQUEST
+ uint32_t originalRpcType; // origin RpcMsg msgType
uint64_t seqNum;
bool isWeak;
SyncTerm term;
SyncIndex index;
- uint32_t dataLen; // user RpcMsg.contLen
- char data[]; // user RpcMsg.pCont
+ uint32_t dataLen; // origin RpcMsg.contLen
+ char data[]; // origin RpcMsg.pCont
} SSyncRaftEntry;
SSyncRaftEntry* syncEntryBuild(uint32_t dataLen);
SSyncRaftEntry* syncEntryBuild2(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index); // step 4
SSyncRaftEntry* syncEntryBuild3(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index);
+SSyncRaftEntry* syncEntryBuild4(SRpcMsg* pOriginalMsg, SyncTerm term, SyncIndex index);
SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId);
void syncEntryDestory(SSyncRaftEntry* pEntry);
char* syncEntrySerialize(const SSyncRaftEntry* pEntry, uint32_t* len); // step 5
@@ -56,6 +58,54 @@ void syncEntryPrint2(char* s, const SSyncRaftEntry* pObj);
void syncEntryLog(const SSyncRaftEntry* pObj);
void syncEntryLog2(char* s, const SSyncRaftEntry* pObj);
+//-----------------------------------
+typedef struct SRaftEntryHashCache {
+ SHashObj* pEntryHash;
+ int32_t maxCount;
+ int32_t currentCount;
+ TdThreadMutex mutex;
+ SSyncNode* pSyncNode;
+} SRaftEntryHashCache;
+
+SRaftEntryHashCache* raftCacheCreate(SSyncNode* pSyncNode, int32_t maxCount);
+void raftCacheDestroy(SRaftEntryHashCache* pCache);
+int32_t raftCachePutEntry(struct SRaftEntryHashCache* pCache, SSyncRaftEntry* pEntry);
+int32_t raftCacheGetEntry(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry);
+int32_t raftCacheGetEntryP(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry);
+int32_t raftCacheDelEntry(struct SRaftEntryHashCache* pCache, SyncIndex index);
+int32_t raftCacheGetAndDel(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry);
+int32_t raftCacheClear(struct SRaftEntryHashCache* pCache);
+
+cJSON* raftCache2Json(SRaftEntryHashCache* pObj);
+char* raftCache2Str(SRaftEntryHashCache* pObj);
+void raftCachePrint(SRaftEntryHashCache* pObj);
+void raftCachePrint2(char* s, SRaftEntryHashCache* pObj);
+void raftCacheLog(SRaftEntryHashCache* pObj);
+void raftCacheLog2(char* s, SRaftEntryHashCache* pObj);
+
+//-----------------------------------
+typedef struct SRaftEntryCache {
+ SSkipList* pSkipList;
+ int32_t maxCount;
+ int32_t currentCount;
+ TdThreadMutex mutex;
+ SSyncNode* pSyncNode;
+} SRaftEntryCache;
+
+SRaftEntryCache* raftEntryCacheCreate(SSyncNode* pSyncNode, int32_t maxCount);
+void raftEntryCacheDestroy(SRaftEntryCache* pCache);
+int32_t raftEntryCachePutEntry(struct SRaftEntryCache* pCache, SSyncRaftEntry* pEntry);
+int32_t raftEntryCacheGetEntry(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry);
+int32_t raftEntryCacheGetEntryP(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry);
+int32_t raftEntryCacheClear(struct SRaftEntryCache* pCache, int32_t count);
+
+cJSON* raftEntryCache2Json(SRaftEntryCache* pObj);
+char* raftEntryCache2Str(SRaftEntryCache* pObj);
+void raftEntryCachePrint(SRaftEntryCache* pObj);
+void raftEntryCachePrint2(char* s, SRaftEntryCache* pObj);
+void raftEntryCacheLog(SRaftEntryCache* pObj);
+void raftEntryCacheLog2(char* s, SRaftEntryCache* pObj);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/libs/sync/inc/syncRaftLog.h b/source/libs/sync/inc/syncRaftLog.h
index aec1f77b420b595b0d0393e02f472de7f6eda101..65ec77e38ff10ff77de1d4000515439ad7844ef9 100644
--- a/source/libs/sync/inc/syncRaftLog.h
+++ b/source/libs/sync/inc/syncRaftLog.h
@@ -26,11 +26,16 @@ extern "C" {
#include "syncInt.h"
#include "syncRaftEntry.h"
#include "taosdef.h"
+#include "wal.h"
typedef struct SSyncLogStoreData {
SSyncNode* pSyncNode;
SWal* pWal;
- SyncIndex beginIndex; // valid begin index, default 0, may be set beginIndex > 0
+
+ TdThreadMutex mutex;
+ SWalReader* pWalHandle;
+
+ // SyncIndex beginIndex; // valid begin index, default 0, may be set beginIndex > 0
} SSyncLogStoreData;
SSyncLogStore* logStoreCreate(SSyncNode* pSyncNode);
diff --git a/source/libs/sync/inc/syncReplication.h b/source/libs/sync/inc/syncReplication.h
index 4b1f5b46387413ff8a92df0bfe2a37bc6376ee55..dad7d9b5ec56abb14daea35a73dde2384dd54d8f 100644
--- a/source/libs/sync/inc/syncReplication.h
+++ b/source/libs/sync/inc/syncReplication.h
@@ -53,8 +53,11 @@ extern "C" {
//
int32_t syncNodeAppendEntriesPeers(SSyncNode* pSyncNode);
int32_t syncNodeAppendEntriesPeersSnapshot(SSyncNode* pSyncNode);
+int32_t syncNodeAppendEntriesPeersSnapshot2(SSyncNode* pSyncNode);
+
int32_t syncNodeReplicate(SSyncNode* pSyncNode);
int32_t syncNodeAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncAppendEntries* pMsg);
+int32_t syncNodeAppendEntriesBatch(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncAppendEntriesBatch* pMsg);
#ifdef __cplusplus
}
diff --git a/source/libs/sync/inc/syncSnapshot.h b/source/libs/sync/inc/syncSnapshot.h
index 069154fb93416c3b90840ed81ea8ac2bebf2d8b3..0dc67cf15077cee2558b582b33b358583b9e8aab 100644
--- a/source/libs/sync/inc/syncSnapshot.h
+++ b/source/libs/sync/inc/syncSnapshot.h
@@ -35,57 +35,64 @@ extern "C" {
#define SYNC_SNAPSHOT_RETRY_MS 5000
+//---------------------------------------------------
typedef struct SSyncSnapshotSender {
- bool start;
- int32_t seq;
- int32_t ack;
- void *pReader;
- void *pCurrentBlock;
- int32_t blockLen;
- SSnapshot snapshot;
- SSyncCfg lastConfig;
- int64_t sendingMS;
- SSyncNode *pSyncNode;
- int32_t replicaIndex;
- SyncTerm term;
- SyncTerm privateTerm;
- bool finish;
+ bool start;
+ int32_t seq;
+ int32_t ack;
+ void * pReader;
+ void * pCurrentBlock;
+ int32_t blockLen;
+ SSnapshotParam snapshotParam;
+ SSnapshot snapshot;
+ SSyncCfg lastConfig;
+ int64_t sendingMS;
+ SSyncNode * pSyncNode;
+ int32_t replicaIndex;
+ SyncTerm term;
+ SyncTerm privateTerm;
+ bool finish;
} SSyncSnapshotSender;
SSyncSnapshotSender *snapshotSenderCreate(SSyncNode *pSyncNode, int32_t replicaIndex);
void snapshotSenderDestroy(SSyncSnapshotSender *pSender);
bool snapshotSenderIsStart(SSyncSnapshotSender *pSender);
-void snapshotSenderStart(SSyncSnapshotSender *pSender);
-void snapshotSenderStop(SSyncSnapshotSender *pSender);
+int32_t snapshotSenderStart(SSyncSnapshotSender *pSender, SSnapshotParam snapshotParam, SSnapshot snapshot,
+ void *pReader);
+int32_t snapshotSenderStop(SSyncSnapshotSender *pSender, bool finish);
int32_t snapshotSend(SSyncSnapshotSender *pSender);
int32_t snapshotReSend(SSyncSnapshotSender *pSender);
-cJSON *snapshotSender2Json(SSyncSnapshotSender *pSender);
-char *snapshotSender2Str(SSyncSnapshotSender *pSender);
-char *snapshotSender2SimpleStr(SSyncSnapshotSender *pSender, char *event);
-typedef struct SSyncSnapshotReceiver {
- bool start;
-
- int32_t ack;
- void *pWriter;
- SyncTerm term;
- SyncTerm privateTerm;
- SSnapshot snapshot;
+cJSON *snapshotSender2Json(SSyncSnapshotSender *pSender);
+char * snapshotSender2Str(SSyncSnapshotSender *pSender);
+char * snapshotSender2SimpleStr(SSyncSnapshotSender *pSender, char *event);
- SSyncNode *pSyncNode;
- SRaftId fromId;
+//---------------------------------------------------
+typedef struct SSyncSnapshotReceiver {
+ bool start;
+ int32_t ack;
+ void * pWriter;
+ SyncTerm term;
+ SyncTerm privateTerm;
+ SSnapshotParam snapshotParam;
+ SSnapshot snapshot;
+ SRaftId fromId;
+ SSyncNode * pSyncNode;
} SSyncSnapshotReceiver;
SSyncSnapshotReceiver *snapshotReceiverCreate(SSyncNode *pSyncNode, SRaftId fromId);
void snapshotReceiverDestroy(SSyncSnapshotReceiver *pReceiver);
-void snapshotReceiverStart(SSyncSnapshotReceiver *pReceiver, SyncTerm privateTerm, SyncSnapshotSend *pBeginMsg);
-bool snapshotReceiverIsStart(SSyncSnapshotReceiver *pReceiver);
-void snapshotReceiverStop(SSyncSnapshotReceiver *pReceiver, bool apply);
+int32_t snapshotReceiverStart(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pBeginMsg);
+int32_t snapshotReceiverStop(SSyncSnapshotReceiver *pReceiver);
+bool snapshotReceiverIsStart(SSyncSnapshotReceiver *pReceiver);
+
cJSON *snapshotReceiver2Json(SSyncSnapshotReceiver *pReceiver);
-char *snapshotReceiver2Str(SSyncSnapshotReceiver *pReceiver);
-char *snapshotReceiver2SimpleStr(SSyncSnapshotReceiver *pReceiver, char *event);
+char * snapshotReceiver2Str(SSyncSnapshotReceiver *pReceiver);
+char * snapshotReceiver2SimpleStr(SSyncSnapshotReceiver *pReceiver, char *event);
+//---------------------------------------------------
+// on message
int32_t syncNodeOnSnapshotSendCb(SSyncNode *ths, SyncSnapshotSend *pMsg);
int32_t syncNodeOnSnapshotRspCb(SSyncNode *ths, SyncSnapshotRsp *pMsg);
diff --git a/source/libs/sync/src/syncAppendEntries.c b/source/libs/sync/src/syncAppendEntries.c
index d2726201cceb50c910e0cebfff23322c6747a1ef..8409e1c71137e856304fd6a304ae3d9f031451fe 100644
--- a/source/libs/sync/src/syncAppendEntries.c
+++ b/source/libs/sync/src/syncAppendEntries.c
@@ -92,26 +92,50 @@
int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
int32_t ret = 0;
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "==syncNodeOnAppendEntriesCb== term:%lu", ths->pRaftStore->currentTerm);
- syncAppendEntriesLog2(logBuf, pMsg);
+ // print log
+ syncAppendEntriesLog2("==syncNodeOnAppendEntriesCb==", pMsg);
+
+ // if already drop replica, do not process
+ if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
+ syncNodeEventLog(ths, "recv sync-append-entries, maybe replica already dropped");
+ return ret;
+ }
+ // maybe update term
if (pMsg->term > ths->pRaftStore->currentTerm) {
syncNodeUpdateTerm(ths, pMsg->term);
}
- assert(pMsg->term <= ths->pRaftStore->currentTerm);
+ ASSERT(pMsg->term <= ths->pRaftStore->currentTerm);
// reset elect timer
if (pMsg->term == ths->pRaftStore->currentTerm) {
ths->leaderCache = pMsg->srcId;
syncNodeResetElectTimer(ths);
}
- assert(pMsg->dataLen >= 0);
+ ASSERT(pMsg->dataLen >= 0);
+
+ do {
+ // return to follower state
+ if (pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_CANDIDATE) {
+ syncNodeEventLog(ths, "recv sync-append-entries, candidate to follower");
+
+ syncNodeBecomeFollower(ths, "from candidate by append entries");
+
+ // ret or reply?
+ return ret;
+ }
+ } while (0);
SyncTerm localPreLogTerm = 0;
if (pMsg->prevLogIndex >= SYNC_INDEX_BEGIN && pMsg->prevLogIndex <= ths->pLogStore->getLastIndex(ths->pLogStore)) {
SSyncRaftEntry* pEntry = ths->pLogStore->getEntry(ths->pLogStore, pMsg->prevLogIndex);
- assert(pEntry != NULL);
+ if (pEntry == NULL) {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "getEntry error, index:%" PRId64 ", since %s", pMsg->prevLogIndex, terrstr());
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
+ }
+
localPreLogTerm = pEntry->term;
syncEntryDestory(pEntry);
}
@@ -124,10 +148,13 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
// reject request
if ((pMsg->term < ths->pRaftStore->currentTerm) ||
((pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) && !logOK)) {
- sTrace(
- "syncNodeOnAppendEntriesCb --> reject, pMsg->term:%lu, ths->pRaftStore->currentTerm:%lu, ths->state:%d, "
- "logOK:%d",
- pMsg->term, ths->pRaftStore->currentTerm, ths->state, logOK);
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries, reject, pre-index:%" PRId64 ", pre-term:%" PRIu64 ", datalen:%d",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
pReply->srcId = ths->myRaftId;
@@ -136,6 +163,16 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
pReply->success = false;
pReply->matchIndex = SYNC_INDEX_INVALID;
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
SRpcMsg rpcMsg;
syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
@@ -144,23 +181,10 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
return ret;
}
- // return to follower state
- if (pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_CANDIDATE) {
- sTrace(
- "syncNodeOnAppendEntriesCb --> return to follower, pMsg->term:%lu, ths->pRaftStore->currentTerm:%lu, "
- "ths->state:%d, logOK:%d",
- pMsg->term, ths->pRaftStore->currentTerm, ths->state, logOK);
-
- syncNodeBecomeFollower(ths, "from candidate by append entries");
-
- // ret or reply?
- return ret;
- }
-
// accept request
if (pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_FOLLOWER && logOK) {
// preIndex = -1, or has preIndex entry in local log
- assert(pMsg->prevLogIndex <= ths->pLogStore->getLastIndex(ths->pLogStore));
+ ASSERT(pMsg->prevLogIndex <= ths->pLogStore->getLastIndex(ths->pLogStore));
// has extra entries (> preIndex) in local log
bool hasExtraEntries = pMsg->prevLogIndex < ths->pLogStore->getLastIndex(ths->pLogStore);
@@ -168,10 +192,13 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
// has entries in SyncAppendEntries msg
bool hasAppendEntries = pMsg->dataLen > 0;
- sTrace(
- "syncNodeOnAppendEntriesCb --> accept, pMsg->term:%lu, ths->pRaftStore->currentTerm:%lu, ths->state:%d, "
- "logOK:%d, hasExtraEntries:%d, hasAppendEntries:%d",
- pMsg->term, ths->pRaftStore->currentTerm, ths->state, logOK, hasExtraEntries, hasAppendEntries);
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries, accept, pre-index:%" PRId64 ", pre-term:%" PRIu64 ", datalen:%d",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
if (hasExtraEntries && hasAppendEntries) {
// not conflict by default
@@ -179,13 +206,21 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
SyncIndex extraIndex = pMsg->prevLogIndex + 1;
SSyncRaftEntry* pExtraEntry = ths->pLogStore->getEntry(ths->pLogStore, extraIndex);
- assert(pExtraEntry != NULL);
+ if (pExtraEntry == NULL) {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "getEntry error2, index:%" PRId64 ", since %s", extraIndex, terrstr());
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
+ }
SSyncRaftEntry* pAppendEntry = syncEntryDeserialize(pMsg->data, pMsg->dataLen);
- assert(pAppendEntry != NULL);
+ if (pAppendEntry == NULL) {
+ syncNodeErrorLog(ths, "syncEntryDeserialize pAppendEntry error");
+ return -1;
+ }
// log not match, conflict
- assert(extraIndex == pAppendEntry->index);
+ ASSERT(extraIndex == pAppendEntry->index);
if (pExtraEntry->term != pAppendEntry->term) {
conflict = true;
}
@@ -195,13 +230,19 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
SyncIndex delBegin = ths->pLogStore->getLastIndex(ths->pLogStore);
SyncIndex delEnd = extraIndex;
- sTrace("syncNodeOnAppendEntriesCb --> conflict:%d, delBegin:%ld, delEnd:%ld", conflict, delBegin, delEnd);
+ sTrace("syncNodeOnAppendEntriesCb --> conflict:%d, delBegin:%" PRId64 ", delEnd:%" PRId64, conflict, delBegin,
+ delEnd);
// notice! reverse roll back!
for (SyncIndex index = delEnd; index >= delBegin; --index) {
if (ths->pFsm->FpRollBackCb != NULL) {
SSyncRaftEntry* pRollBackEntry = ths->pLogStore->getEntry(ths->pLogStore, index);
- assert(pRollBackEntry != NULL);
+ if (pRollBackEntry == NULL) {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "getEntry error3, index:%" PRId64 ", since %s", index, terrstr());
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
+ }
// if (pRollBackEntry->msgType != TDMT_SYNC_NOOP) {
if (syncUtilUserRollback(pRollBackEntry->msgType)) {
@@ -257,7 +298,10 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
} else if (!hasExtraEntries && hasAppendEntries) {
SSyncRaftEntry* pAppendEntry = syncEntryDeserialize(pMsg->data, pMsg->dataLen);
- assert(pAppendEntry != NULL);
+ if (pAppendEntry == NULL) {
+ syncNodeErrorLog(ths, "syncEntryDeserialize pAppendEntry2 error");
+ return -1;
+ }
// append new entries
ths->pLogStore->appendEntry(ths->pLogStore, pAppendEntry);
@@ -287,7 +331,8 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
// do nothing
} else {
- assert(0);
+ syncNodeLog3("", ths);
+ ASSERT(0);
}
SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
@@ -302,6 +347,16 @@ int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
pReply->matchIndex = pMsg->prevLogIndex;
}
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
SRpcMsg rpcMsg;
syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
@@ -367,7 +422,52 @@ static int32_t syncNodeMakeLogSame(SSyncNode* ths, SyncAppendEntries* pMsg) {
ASSERT(code == 0);
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "log truncate, from %ld to %ld", delBegin, delEnd);
+ snprintf(eventLog, sizeof(eventLog), "log truncate, from %" PRId64 " to %" PRId64, delBegin, delEnd);
+ syncNodeEventLog(ths, eventLog);
+ logStoreSimpleLog2("after syncNodeMakeLogSame", ths->pLogStore);
+
+ return code;
+}
+
+static int32_t syncNodeDoMakeLogSame(SSyncNode* ths, SyncIndex FromIndex) {
+ int32_t code;
+
+ SyncIndex delBegin = FromIndex;
+ SyncIndex delEnd = ths->pLogStore->syncLogLastIndex(ths->pLogStore);
+
+ // invert roll back!
+ for (SyncIndex index = delEnd; index >= delBegin; --index) {
+ if (ths->pFsm->FpRollBackCb != NULL) {
+ SSyncRaftEntry* pRollBackEntry;
+ code = ths->pLogStore->syncLogGetEntry(ths->pLogStore, index, &pRollBackEntry);
+ ASSERT(code == 0);
+ ASSERT(pRollBackEntry != NULL);
+
+ if (syncUtilUserRollback(pRollBackEntry->msgType)) {
+ SRpcMsg rpcMsg;
+ syncEntry2OriginalRpc(pRollBackEntry, &rpcMsg);
+
+ SFsmCbMeta cbMeta = {0};
+ cbMeta.index = pRollBackEntry->index;
+ cbMeta.lastConfigIndex = syncNodeGetSnapshotConfigIndex(ths, cbMeta.index);
+ cbMeta.isWeak = pRollBackEntry->isWeak;
+ cbMeta.code = 0;
+ cbMeta.state = ths->state;
+ cbMeta.seqNum = pRollBackEntry->seqNum;
+ ths->pFsm->FpRollBackCb(ths->pFsm, &rpcMsg, cbMeta);
+ rpcFreeCont(rpcMsg.pCont);
+ }
+
+ syncEntryDestory(pRollBackEntry);
+ }
+ }
+
+ // delete confict entries
+ code = ths->pLogStore->syncLogTruncate(ths->pLogStore, delBegin);
+ ASSERT(code == 0);
+
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "log truncate, from %" PRId64 " to %" PRId64, delBegin, delEnd);
syncNodeEventLog(ths, eventLog);
logStoreSimpleLog2("after syncNodeMakeLogSame", ths->pLogStore);
@@ -393,44 +493,363 @@ static int32_t syncNodePreCommit(SSyncNode* ths, SSyncRaftEntry* pEntry) {
return 0;
}
+static bool syncNodeOnAppendEntriesBatchLogOK(SSyncNode* pSyncNode, SyncAppendEntriesBatch* pMsg) {
+ if (pMsg->prevLogIndex == SYNC_INDEX_INVALID) {
+ return true;
+ }
+
+ SyncIndex myLastIndex = syncNodeGetLastIndex(pSyncNode);
+ if (pMsg->prevLogIndex > myLastIndex) {
+ sDebug("vgId:%d sync log not ok, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
+ return false;
+ }
+
+ SyncTerm myPreLogTerm = syncNodeGetPreTerm(pSyncNode, pMsg->prevLogIndex + 1);
+ if (myPreLogTerm == SYNC_TERM_INVALID) {
+ sDebug("vgId:%d sync log not ok2, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
+ return false;
+ }
+
+ if (pMsg->prevLogIndex <= myLastIndex && pMsg->prevLogTerm == myPreLogTerm) {
+ return true;
+ }
+
+ sDebug("vgId:%d sync log not ok3, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
+ return false;
+}
+
// really pre log match
// prevLogIndex == -1
static bool syncNodeOnAppendEntriesLogOK(SSyncNode* pSyncNode, SyncAppendEntries* pMsg) {
if (pMsg->prevLogIndex == SYNC_INDEX_INVALID) {
- if (gRaftDetailLog) {
- sTrace("syncNodeOnAppendEntriesLogOK true, pMsg->prevLogIndex:%ld", pMsg->prevLogIndex);
- }
return true;
}
SyncIndex myLastIndex = syncNodeGetLastIndex(pSyncNode);
if (pMsg->prevLogIndex > myLastIndex) {
- if (gRaftDetailLog) {
- sTrace("syncNodeOnAppendEntriesLogOK false, pMsg->prevLogIndex:%ld, myLastIndex:%ld", pMsg->prevLogIndex,
- myLastIndex);
- }
+ sDebug("vgId:%d sync log not ok, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
return false;
}
SyncTerm myPreLogTerm = syncNodeGetPreTerm(pSyncNode, pMsg->prevLogIndex + 1);
+ if (myPreLogTerm == SYNC_TERM_INVALID) {
+ sDebug("vgId:%d sync log not ok2, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
+ return false;
+ }
+
if (pMsg->prevLogIndex <= myLastIndex && pMsg->prevLogTerm == myPreLogTerm) {
- if (gRaftDetailLog) {
- sTrace(
- "syncNodeOnAppendEntriesLogOK true, pMsg->prevLogIndex:%ld, myLastIndex:%ld, pMsg->prevLogTerm:%lu, "
- "myPreLogTerm:%lu",
- pMsg->prevLogIndex, myLastIndex, pMsg->prevLogTerm, myPreLogTerm);
- }
return true;
}
- if (gRaftDetailLog) {
- sTrace(
- "syncNodeOnAppendEntriesLogOK false, pMsg->prevLogIndex:%ld, myLastIndex:%ld, pMsg->prevLogTerm:%lu, "
- "myPreLogTerm:%lu",
- pMsg->prevLogIndex, myLastIndex, pMsg->prevLogTerm, myPreLogTerm);
+ sDebug("vgId:%d sync log not ok3, preindex:%" PRId64, pSyncNode->vgId, pMsg->prevLogIndex);
+ return false;
+}
+
+int32_t syncNodeOnAppendEntriesSnapshot2Cb(SSyncNode* ths, SyncAppendEntriesBatch* pMsg) {
+ int32_t ret = 0;
+ int32_t code = 0;
+
+ // if already drop replica, do not process
+ if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
+ syncNodeEventLog(ths, "recv sync-append-entries-batch, maybe replica already dropped");
+ return ret;
}
- return false;
+ // maybe update term
+ if (pMsg->term > ths->pRaftStore->currentTerm) {
+ syncNodeUpdateTerm(ths, pMsg->term);
+ }
+ ASSERT(pMsg->term <= ths->pRaftStore->currentTerm);
+
+ // reset elect timer
+ if (pMsg->term == ths->pRaftStore->currentTerm) {
+ ths->leaderCache = pMsg->srcId;
+ syncNodeResetElectTimer(ths);
+ }
+ ASSERT(pMsg->dataLen >= 0);
+
+ // candidate to follower
+ //
+ // operation:
+ // to follower
+ do {
+ bool condition = pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_CANDIDATE;
+ if (condition) {
+ syncNodeEventLog(ths, "recv sync-append-entries-batch, candidate to follower");
+
+ syncNodeBecomeFollower(ths, "from candidate by append entries");
+ // do not reply?
+ return ret;
+ }
+ } while (0);
+
+ // fake match2
+ //
+ // condition1:
+ // preIndex <= my commit index
+ //
+ // operation:
+ // if hasAppendEntries && pMsg->prevLogIndex == ths->commitIndex, append entry
+ // match my-commit-index or my-commit-index + batchSize
+ do {
+ bool condition = (pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) &&
+ (pMsg->prevLogIndex <= ths->commitIndex);
+ if (condition) {
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries-batch, fake match2, {pre-index:%" PRId64 ", pre-term:%" PRIu64
+ ", datalen:%d, datacount:%d}",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen, pMsg->dataCount);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
+
+ SyncIndex matchIndex = ths->commitIndex;
+ bool hasAppendEntries = pMsg->dataLen > 0;
+ SOffsetAndContLen* metaTableArr = syncAppendEntriesBatchMetaTableArray(pMsg);
+
+ if (hasAppendEntries && pMsg->prevLogIndex == ths->commitIndex) {
+ // make log same
+ do {
+ SyncIndex logLastIndex = ths->pLogStore->syncLogLastIndex(ths->pLogStore);
+ bool hasExtraEntries = logLastIndex > pMsg->prevLogIndex;
+
+ if (hasExtraEntries) {
+ // make log same, rollback deleted entries
+ code = syncNodeDoMakeLogSame(ths, pMsg->prevLogIndex + 1);
+ ASSERT(code == 0);
+ }
+
+ } while (0);
+
+ // append entry batch
+ for (int32_t i = 0; i < pMsg->dataCount; ++i) {
+ SSyncRaftEntry* pAppendEntry = (SSyncRaftEntry*)(pMsg->data + metaTableArr[i].offset);
+ code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pAppendEntry);
+ if (code != 0) {
+ return -1;
+ }
+
+ code = syncNodePreCommit(ths, pAppendEntry);
+ ASSERT(code == 0);
+
+ // syncEntryDestory(pAppendEntry);
+ }
+
+ // fsync once
+ SSyncLogStoreData* pData = ths->pLogStore->data;
+ SWal* pWal = pData->pWal;
+ walFsync(pWal, true);
+
+ // update match index
+ matchIndex = pMsg->prevLogIndex + pMsg->dataCount;
+ }
+
+ // prepare response msg
+ SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
+ pReply->srcId = ths->myRaftId;
+ pReply->destId = pMsg->srcId;
+ pReply->term = ths->pRaftStore->currentTerm;
+ pReply->privateTerm = ths->pNewNodeReceiver->privateTerm;
+ pReply->success = true;
+ pReply->matchIndex = matchIndex;
+
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
+ // send response
+ SRpcMsg rpcMsg;
+ syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
+ syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
+ syncAppendEntriesReplyDestroy(pReply);
+
+ return 0;
+ }
+ } while (0);
+
+ // calculate logOK here, before will coredump, due to fake match
+ bool logOK = syncNodeOnAppendEntriesBatchLogOK(ths, pMsg);
+
+ // not match
+ //
+ // condition1:
+ // term < myTerm
+ //
+ // condition2:
+ // !logOK
+ //
+ // operation:
+ // not match
+ // no operation on log
+ do {
+ bool condition1 = pMsg->term < ths->pRaftStore->currentTerm;
+ bool condition2 =
+ (pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) && !logOK;
+ bool condition = condition1 || condition2;
+
+ if (condition) {
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries-batch, not match, {pre-index:%" PRId64 ", pre-term:%" PRIu64
+ ", datalen:%d, datacount:%d}",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen, pMsg->dataCount);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
+
+ // prepare response msg
+ SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
+ pReply->srcId = ths->myRaftId;
+ pReply->destId = pMsg->srcId;
+ pReply->term = ths->pRaftStore->currentTerm;
+ pReply->privateTerm = ths->pNewNodeReceiver->privateTerm;
+ pReply->success = false;
+ pReply->matchIndex = SYNC_INDEX_INVALID;
+
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
+ // send response
+ SRpcMsg rpcMsg;
+ syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
+ syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
+ syncAppendEntriesReplyDestroy(pReply);
+
+ return 0;
+ }
+ } while (0);
+
+ // really match
+ //
+ // condition:
+ // logOK
+ //
+ // operation:
+ // match
+ // make log same
+ do {
+ bool condition = (pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) && logOK;
+ if (condition) {
+ // has extra entries (> preIndex) in local log
+ SyncIndex myLastIndex = syncNodeGetLastIndex(ths);
+ bool hasExtraEntries = myLastIndex > pMsg->prevLogIndex;
+
+ // has entries in SyncAppendEntries msg
+ bool hasAppendEntries = pMsg->dataLen > 0;
+ SOffsetAndContLen* metaTableArr = syncAppendEntriesBatchMetaTableArray(pMsg);
+
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries-batch, match, {pre-index:%" PRId64 ", pre-term:%" PRIu64
+ ", datalen:%d, datacount:%d}",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen, pMsg->dataCount);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
+
+ if (hasExtraEntries) {
+ // make log same, rollback deleted entries
+ code = syncNodeDoMakeLogSame(ths, pMsg->prevLogIndex + 1);
+ ASSERT(code == 0);
+ }
+
+ if (hasAppendEntries) {
+ // append entry batch
+ for (int32_t i = 0; i < pMsg->dataCount; ++i) {
+ SSyncRaftEntry* pAppendEntry = (SSyncRaftEntry*)(pMsg->data + metaTableArr[i].offset);
+ code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pAppendEntry);
+ if (code != 0) {
+ return -1;
+ }
+
+ code = syncNodePreCommit(ths, pAppendEntry);
+ ASSERT(code == 0);
+
+ // syncEntryDestory(pAppendEntry);
+ }
+
+ // fsync once
+ SSyncLogStoreData* pData = ths->pLogStore->data;
+ SWal* pWal = pData->pWal;
+ walFsync(pWal, true);
+ }
+
+ // prepare response msg
+ SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
+ pReply->srcId = ths->myRaftId;
+ pReply->destId = pMsg->srcId;
+ pReply->term = ths->pRaftStore->currentTerm;
+ pReply->privateTerm = ths->pNewNodeReceiver->privateTerm;
+ pReply->success = true;
+ pReply->matchIndex = hasAppendEntries ? pMsg->prevLogIndex + pMsg->dataCount : pMsg->prevLogIndex;
+
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
+ // send response
+ SRpcMsg rpcMsg;
+ syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
+ syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg);
+ syncAppendEntriesReplyDestroy(pReply);
+
+ // maybe update commit index, leader notice me
+ if (pMsg->commitIndex > ths->commitIndex) {
+ // has commit entry in local
+ if (pMsg->commitIndex <= ths->pLogStore->syncLogLastIndex(ths->pLogStore)) {
+ // advance commit index to sanpshot first
+ SSnapshot snapshot;
+ ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &snapshot);
+ if (snapshot.lastApplyIndex >= 0 && snapshot.lastApplyIndex > ths->commitIndex) {
+ SyncIndex commitBegin = ths->commitIndex;
+ SyncIndex commitEnd = snapshot.lastApplyIndex;
+ ths->commitIndex = snapshot.lastApplyIndex;
+
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "commit by snapshot from index:%" PRId64 " to index:%" PRId64,
+ commitBegin, commitEnd);
+ syncNodeEventLog(ths, eventLog);
+ }
+
+ SyncIndex beginIndex = ths->commitIndex + 1;
+ SyncIndex endIndex = pMsg->commitIndex;
+
+ // update commit index
+ ths->commitIndex = pMsg->commitIndex;
+
+ // call back Wal
+ code = ths->pLogStore->updateCommitIndex(ths->pLogStore, ths->commitIndex);
+ ASSERT(code == 0);
+
+ code = syncNodeCommit(ths, beginIndex, endIndex, ths->state);
+ ASSERT(code == 0);
+ }
+ }
+ return 0;
+ }
+ } while (0);
+
+ return 0;
}
int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMsg) {
@@ -438,14 +857,11 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
int32_t code = 0;
// print log
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "recv SyncAppendEntries, vgId:%d, term:%lu", ths->vgId,
- ths->pRaftStore->currentTerm);
- syncAppendEntriesLog2(logBuf, pMsg);
+ syncAppendEntriesLog2("==syncNodeOnAppendEntriesSnapshotCb==", pMsg);
// if already drop replica, do not process
if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
- sInfo("recv SyncAppendEntries maybe replica already dropped");
+ syncNodeEventLog(ths, "recv sync-append-entries, maybe replica already dropped");
return ret;
}
@@ -469,7 +885,7 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
do {
bool condition = pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_CANDIDATE;
if (condition) {
- sTrace("recv SyncAppendEntries, candidate to follower");
+ syncNodeEventLog(ths, "recv sync-append-entries, candidate to follower");
syncNodeBecomeFollower(ths, "from candidate by append entries");
// do not reply?
@@ -477,6 +893,7 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
}
} while (0);
+#if 0
// fake match
//
// condition1:
@@ -502,7 +919,7 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
bool condition0 = (pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) &&
syncNodeHasSnapshot(ths);
bool condition1 =
- condition0 && (ths->pLogStore->syncLogEntryCount(ths->pLogStore) == 0) && (pMsg->prevLogIndex > myLastIndex);
+ condition0 && (ths->pLogStore->syncLogEntryCount(ths->pLogStore) == 0) && (pMsg->prevLogIndex > myLastIndex); // donot use syncLogEntryCount!!! use isEmpty
bool condition2 = condition0 && (ths->pLogStore->syncLogLastIndex(ths->pLogStore) <= snapshot.lastApplyIndex) &&
(pMsg->prevLogIndex > myLastIndex);
bool condition3 = condition0 && (pMsg->prevLogIndex < snapshot.lastApplyIndex);
@@ -510,11 +927,10 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
bool condition = condition1 || condition2 || condition3 || condition4;
if (condition) {
- sTrace(
- "recv SyncAppendEntries, fake match, myLastIndex:%ld, syncLogBeginIndex:%ld, syncLogEndIndex:%ld, "
- "condition1:%d, condition2:%d, condition3:%d, condition4:%d",
- myLastIndex, ths->pLogStore->syncLogBeginIndex(ths->pLogStore),
- ths->pLogStore->syncLogEndIndex(ths->pLogStore), condition1, condition2, condition3, condition4);
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries, fake match, pre-index:%" PRId64 ", pre-term:%" PRIu64,
+ pMsg->prevLogIndex, pMsg->prevLogTerm);
+ syncNodeEventLog(ths, logBuf);
// prepare response msg
SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
@@ -534,6 +950,7 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
return ret;
}
} while (0);
+#endif
// fake match2
//
@@ -548,8 +965,13 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
bool condition = (pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) &&
(pMsg->prevLogIndex <= ths->commitIndex);
if (condition) {
- sTrace("recv SyncAppendEntries, fake match2, msg-prevLogIndex:%ld, my-commitIndex:%ld", pMsg->prevLogIndex,
- ths->commitIndex);
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries, fake match2, pre-index:%" PRId64 ", pre-term:%" PRIu64 ", datalen:%d",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
SyncIndex matchIndex = ths->commitIndex;
bool hasAppendEntries = pMsg->dataLen > 0;
@@ -571,12 +993,15 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
}
code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pAppendEntry);
- ASSERT(code == 0);
+ if (code != 0) {
+ return -1;
+ }
// pre commit
code = syncNodePreCommit(ths, pAppendEntry);
ASSERT(code == 0);
+ // update match index
matchIndex = pMsg->prevLogIndex + 1;
syncEntryDestory(pAppendEntry);
@@ -591,6 +1016,16 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
pReply->success = true;
pReply->matchIndex = matchIndex;
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
// send response
SRpcMsg rpcMsg;
syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
@@ -622,11 +1057,11 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
bool condition = condition1 || condition2;
if (condition) {
- sTrace(
- "recv SyncAppendEntries, not match, syncLogBeginIndex:%ld, syncLogEndIndex:%ld, condition1:%d, "
- "condition2:%d, logOK:%d",
- ths->pLogStore->syncLogBeginIndex(ths->pLogStore), ths->pLogStore->syncLogEndIndex(ths->pLogStore),
- condition1, condition2, logOK);
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries, not match, pre-index:%" PRId64 ", pre-term:%" PRIu64 ", datalen:%d",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen);
+ syncNodeEventLog(ths, logBuf);
// prepare response msg
SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(ths->vgId);
@@ -637,6 +1072,16 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
pReply->success = false;
pReply->matchIndex = SYNC_INDEX_INVALID;
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
// send response
SRpcMsg rpcMsg;
syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
@@ -665,8 +1110,11 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
// has entries in SyncAppendEntries msg
bool hasAppendEntries = pMsg->dataLen > 0;
- sTrace("recv SyncAppendEntries, match, myLastIndex:%ld, hasExtraEntries:%d, hasAppendEntries:%d", myLastIndex,
- hasExtraEntries, hasAppendEntries);
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "recv sync-append-entries, match, pre-index:%" PRId64 ", pre-term:%" PRIu64 ", datalen:%d",
+ pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen);
+ syncNodeEventLog(ths, logBuf);
if (hasExtraEntries) {
// make log same, rollback deleted entries
@@ -680,7 +1128,9 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
ASSERT(pAppendEntry != NULL);
code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pAppendEntry);
- ASSERT(code == 0);
+ if (code != 0) {
+ return -1;
+ }
// pre commit
code = syncNodePreCommit(ths, pAppendEntry);
@@ -698,6 +1148,16 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
pReply->success = true;
pReply->matchIndex = hasAppendEntries ? pMsg->prevLogIndex + 1 : pMsg->prevLogIndex;
+ // msg event log
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pReply->destId.addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-append-entries-reply to %s:%d, {term:%" PRIu64 ", pterm:%" PRIu64
+ ", success:%d, match-index:%" PRId64 "}",
+ ths->vgId, host, port, pReply->term, pReply->privateTerm, pReply->success, pReply->matchIndex);
+ } while (0);
+
// send response
SRpcMsg rpcMsg;
syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg);
@@ -717,8 +1177,8 @@ int32_t syncNodeOnAppendEntriesSnapshotCb(SSyncNode* ths, SyncAppendEntries* pMs
ths->commitIndex = snapshot.lastApplyIndex;
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "commit by snapshot from index:%ld to index:%ld", commitBegin,
- commitEnd);
+ snprintf(eventLog, sizeof(eventLog), "commit by snapshot from index:%" PRId64 " to index:%" PRId64,
+ commitBegin, commitEnd);
syncNodeEventLog(ths, eventLog);
}
diff --git a/source/libs/sync/src/syncAppendEntriesReply.c b/source/libs/sync/src/syncAppendEntriesReply.c
index 47fd23baaef98add632cfbdd65d7ea73ef6efdfb..c18c2b4d381a19bea0e2460a60f5fa1f76f1b5d8 100644
--- a/source/libs/sync/src/syncAppendEntriesReply.c
+++ b/source/libs/sync/src/syncAppendEntriesReply.c
@@ -40,16 +40,27 @@
int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg) {
int32_t ret = 0;
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "==syncNodeOnAppendEntriesReplyCb== term:%lu", ths->pRaftStore->currentTerm);
- syncAppendEntriesReplyLog2(logBuf, pMsg);
+ // print log
+ syncAppendEntriesReplyLog2("==syncNodeOnAppendEntriesReplyCb==", pMsg);
+
+ // if already drop replica, do not process
+ if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, maybe replica already dropped");
+ return 0;
+ }
+ // drop stale response
if (pMsg->term < ths->pRaftStore->currentTerm) {
- sTrace("DropStaleResponse, receive term:%" PRIu64 ", current term:%" PRIu64 "", pMsg->term,
- ths->pRaftStore->currentTerm);
- return ret;
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, recv-term:%" PRIu64 ", drop stale response",
+ pMsg->term);
+ syncNodeEventLog(ths, logBuf);
+ return 0;
}
+ if (gRaftDetailLog) {
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, before");
+ }
syncIndexMgrLog2("==syncNodeOnAppendEntriesReplyCb== before pNextIndex", ths->pNextIndex);
syncIndexMgrLog2("==syncNodeOnAppendEntriesReplyCb== before pMatchIndex", ths->pMatchIndex);
@@ -59,15 +70,13 @@ int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* p
// }
if (pMsg->term > ths->pRaftStore->currentTerm) {
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "syncNodeOnAppendEntriesReplyCb error term, receive:%lu current:%lu", pMsg->term,
- ths->pRaftStore->currentTerm);
- syncNodeLog2(logBuf, ths);
- sError("%s", logBuf);
- return ret;
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, error term, recv-term:%" PRIu64, pMsg->term);
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
}
- assert(pMsg->term == ths->pRaftStore->currentTerm);
+ ASSERT(pMsg->term == ths->pRaftStore->currentTerm);
if (pMsg->success) {
// nextIndex' = [nextIndex EXCEPT ![i][j] = m.mmatchIndex + 1]
@@ -91,42 +100,207 @@ int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* p
syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), nextIndex);
}
+ if (gRaftDetailLog) {
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, after");
+ }
syncIndexMgrLog2("==syncNodeOnAppendEntriesReplyCb== after pNextIndex", ths->pNextIndex);
syncIndexMgrLog2("==syncNodeOnAppendEntriesReplyCb== after pMatchIndex", ths->pMatchIndex);
return ret;
}
+// only start once
+static void syncNodeStartSnapshotOnce(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex, SyncTerm lastApplyTerm,
+ SyncAppendEntriesReply* pMsg) {
+ // get sender
+ SSyncSnapshotSender* pSender = syncNodeGetSnapshotSender(ths, &(pMsg->srcId));
+ ASSERT(pSender != NULL);
+
+ if (snapshotSenderIsStart(pSender)) {
+ do {
+ char* eventLog = snapshotSender2SimpleStr(pSender, "snapshot sender already start");
+ syncNodeErrorLog(ths, eventLog);
+ taosMemoryFree(eventLog);
+ } while (0);
+
+ return;
+ }
+
+ SSnapshot snapshot = {
+ .data = NULL, .lastApplyIndex = endIndex, .lastApplyTerm = lastApplyTerm, .lastConfigIndex = SYNC_INDEX_INVALID};
+ void* pReader = NULL;
+ SSnapshotParam readerParam = {.start = beginIndex, .end = endIndex};
+ int32_t code = ths->pFsm->FpSnapshotStartRead(ths->pFsm, &readerParam, &pReader);
+ ASSERT(code == 0);
+
+ if (pMsg->privateTerm < pSender->privateTerm) {
+ ASSERT(pReader != NULL);
+ snapshotSenderStart(pSender, readerParam, snapshot, pReader);
+
+ } else {
+ if (pReader != NULL) {
+ ths->pFsm->FpSnapshotStopRead(ths->pFsm, pReader);
+ }
+ }
+}
+
+int32_t syncNodeOnAppendEntriesReplySnapshot2Cb(SSyncNode* ths, SyncAppendEntriesReply* pMsg) {
+ int32_t ret = 0;
+
+ // if already drop replica, do not process
+ if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, maybe replica already dropped");
+ return -1;
+ }
+
+ // drop stale response
+ if (pMsg->term < ths->pRaftStore->currentTerm) {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, recv-term:%" PRIu64 ", drop stale response",
+ pMsg->term);
+ syncNodeEventLog(ths, logBuf);
+ return -1;
+ }
+
+ // error term
+ if (pMsg->term > ths->pRaftStore->currentTerm) {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, error term, recv-term:%" PRIu64, pMsg->term);
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
+ }
+
+ ASSERT(pMsg->term == ths->pRaftStore->currentTerm);
+
+ if (pMsg->success) {
+ SyncIndex newNextIndex = pMsg->matchIndex + 1;
+ SyncIndex newMatchIndex = pMsg->matchIndex;
+
+ bool needStartSnapshot = false;
+ if (newMatchIndex >= SYNC_INDEX_BEGIN && !ths->pLogStore->syncLogExist(ths->pLogStore, newMatchIndex)) {
+ needStartSnapshot = true;
+ }
+
+ if (!needStartSnapshot) {
+ // update next-index, match-index
+ syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), newNextIndex);
+ syncIndexMgrSetIndex(ths->pMatchIndex, &(pMsg->srcId), newMatchIndex);
+
+ // maybe commit
+ if (ths->state == TAOS_SYNC_STATE_LEADER) {
+ syncMaybeAdvanceCommitIndex(ths);
+ }
+
+ } else {
+ // start snapshot
+ SSnapshot oldSnapshot;
+ ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &oldSnapshot);
+ if (oldSnapshot.lastApplyIndex > newMatchIndex) {
+ syncNodeStartSnapshotOnce(ths, newMatchIndex + 1, oldSnapshot.lastApplyIndex, oldSnapshot.lastApplyTerm,
+ pMsg); // term maybe not ok?
+ }
+
+ syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), oldSnapshot.lastApplyIndex + 1);
+ syncIndexMgrSetIndex(ths->pMatchIndex, &(pMsg->srcId), newMatchIndex);
+ }
+
+ // event log, update next-index
+ do {
+ char host[64];
+ int16_t port;
+ syncUtilU642Addr(pMsg->srcId.addr, host, sizeof(host), &port);
+
+ char logBuf[256];
+ snprintf(logBuf, sizeof(logBuf), "reset next-index:%" PRId64 ", match-index:%" PRId64 " for %s:%d", newNextIndex,
+ newMatchIndex, host, port);
+ syncNodeEventLog(ths, logBuf);
+
+ } while (0);
+
+ } else {
+ SyncIndex nextIndex = syncIndexMgrGetIndex(ths->pNextIndex, &(pMsg->srcId));
+
+ if (nextIndex > SYNC_INDEX_BEGIN) {
+ --nextIndex;
+
+ bool needStartSnapshot = false;
+ if (nextIndex >= SYNC_INDEX_BEGIN && !ths->pLogStore->syncLogExist(ths->pLogStore, nextIndex)) {
+ needStartSnapshot = true;
+ }
+ if (nextIndex - 1 >= SYNC_INDEX_BEGIN && !ths->pLogStore->syncLogExist(ths->pLogStore, nextIndex - 1)) {
+ needStartSnapshot = true;
+ }
+
+ if (!needStartSnapshot) {
+ // do nothing
+
+ } else {
+ SSnapshot oldSnapshot;
+ ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &oldSnapshot);
+ SyncTerm newSnapshotTerm = oldSnapshot.lastApplyTerm;
+ syncNodeStartSnapshotOnce(ths, SYNC_INDEX_BEGIN, nextIndex, newSnapshotTerm, pMsg);
+
+ // get sender
+ SSyncSnapshotSender* pSender = syncNodeGetSnapshotSender(ths, &(pMsg->srcId));
+ ASSERT(pSender != NULL);
+ SyncIndex sentryIndex = pSender->snapshot.lastApplyIndex + 1;
+
+ // update nextIndex to sentryIndex
+ if (nextIndex <= sentryIndex) {
+ nextIndex = sentryIndex;
+ }
+ }
+
+ } else {
+ nextIndex = SYNC_INDEX_BEGIN;
+ }
+ syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), nextIndex);
+
+ // event log, update next-index
+ do {
+ char host[64];
+ int16_t port;
+ syncUtilU642Addr(pMsg->srcId.addr, host, sizeof(host), &port);
+
+ SyncIndex newNextIndex = nextIndex;
+ SyncIndex newMatchIndex = syncIndexMgrGetIndex(ths->pMatchIndex, &(pMsg->srcId));
+ char logBuf[256];
+ snprintf(logBuf, sizeof(logBuf), "reset2 next-index:%" PRId64 ", match-index:%" PRId64 " for %s:%d", newNextIndex,
+ newMatchIndex, host, port);
+ syncNodeEventLog(ths, logBuf);
+
+ } while (0);
+ }
+
+ return 0;
+}
+
int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg) {
int32_t ret = 0;
// print log
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "recv SyncAppendEntriesReply, vgId:%d, term:%lu", ths->vgId,
- ths->pRaftStore->currentTerm);
- syncAppendEntriesReplyLog2(logBuf, pMsg);
+ syncAppendEntriesReplyLog2("==syncNodeOnAppendEntriesReplySnapshotCb==", pMsg);
// if already drop replica, do not process
if (!syncNodeInRaftGroup(ths, &(pMsg->srcId)) && !ths->pRaftCfg->isStandBy) {
- sInfo("recv SyncAppendEntriesReply, maybe replica already dropped");
- return ret;
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, maybe replica already dropped");
+ return 0;
}
// drop stale response
if (pMsg->term < ths->pRaftStore->currentTerm) {
- sTrace("recv SyncAppendEntriesReply, drop stale response, receive_term:%lu current_term:%lu", pMsg->term,
- ths->pRaftStore->currentTerm);
- return ret;
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, recv-term:%" PRIu64 ", drop stale response",
+ pMsg->term);
+ syncNodeEventLog(ths, logBuf);
+ return 0;
}
- syncIndexMgrLog2("recv SyncAppendEntriesReply, before pNextIndex:", ths->pNextIndex);
- syncIndexMgrLog2("recv SyncAppendEntriesReply, before pMatchIndex:", ths->pMatchIndex);
if (gRaftDetailLog) {
- SSnapshot snapshot;
- ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &snapshot);
- sTrace("recv SyncAppendEntriesReply, before snapshot.lastApplyIndex:%ld, snapshot.lastApplyTerm:%lu",
- snapshot.lastApplyIndex, snapshot.lastApplyTerm);
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, before");
}
+ syncIndexMgrLog2("recv sync-append-entries-reply, before pNextIndex:", ths->pNextIndex);
+ syncIndexMgrLog2("recv sync-append-entries-reply, before pMatchIndex:", ths->pMatchIndex);
// no need this code, because if I receive reply.term, then I must have sent for that term.
// if (pMsg->term > ths->pRaftStore->currentTerm) {
@@ -134,12 +308,10 @@ int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntries
// }
if (pMsg->term > ths->pRaftStore->currentTerm) {
- char logBuf[128] = {0};
- snprintf(logBuf, sizeof(logBuf), "recv SyncAppendEntriesReply, error term, receive_term:%lu current_term:%lu",
- pMsg->term, ths->pRaftStore->currentTerm);
- syncNodeLog2(logBuf, ths);
- sError("%s", logBuf);
- return ret;
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "recv sync-append-entries-reply, error term, recv-term:%" PRIu64, pMsg->term);
+ syncNodeErrorLog(ths, logBuf);
+ return -1;
}
ASSERT(pMsg->term == ths->pRaftStore->currentTerm);
@@ -149,7 +321,7 @@ int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntries
syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), pMsg->matchIndex + 1);
if (gRaftDetailLog) {
- sTrace("update next match, index:%ld, success:%d", pMsg->matchIndex + 1, pMsg->success);
+ sTrace("update next match, index:%" PRId64 ", success:%d", pMsg->matchIndex + 1, pMsg->success);
}
// matchIndex' = [matchIndex EXCEPT ![i][j] = m.mmatchIndex]
@@ -163,7 +335,7 @@ int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntries
} else {
SyncIndex nextIndex = syncIndexMgrGetIndex(ths->pNextIndex, &(pMsg->srcId));
if (gRaftDetailLog) {
- sTrace("update next index not match, begin, index:%ld, success:%d", nextIndex, pMsg->success);
+ sTrace("update next index not match, begin, index:%" PRId64 ", success:%d", nextIndex, pMsg->success);
}
// notice! int64, uint64
@@ -173,19 +345,25 @@ int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntries
// get sender
SSyncSnapshotSender* pSender = syncNodeGetSnapshotSender(ths, &(pMsg->srcId));
ASSERT(pSender != NULL);
- bool hasSnapshot = syncNodeHasSnapshot(ths);
- SSnapshot snapshot;
- ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &snapshot);
-
- // start sending snapshot first time
- // start here, stop by receiver
- if (hasSnapshot && nextIndex <= snapshot.lastApplyIndex + 1 && !snapshotSenderIsStart(pSender) &&
- pMsg->privateTerm < pSender->privateTerm) {
- snapshotSenderStart(pSender);
-
- char* eventLog = snapshotSender2SimpleStr(pSender, "snapshot sender start");
- syncNodeEventLog(ths, eventLog);
- taosMemoryFree(eventLog);
+
+ SSnapshot snapshot = {.data = NULL,
+ .lastApplyIndex = SYNC_INDEX_INVALID,
+ .lastApplyTerm = 0,
+ .lastConfigIndex = SYNC_INDEX_INVALID};
+ void* pReader = NULL;
+ ths->pFsm->FpGetSnapshot(ths->pFsm, &snapshot, NULL, &pReader);
+ if (snapshot.lastApplyIndex >= SYNC_INDEX_BEGIN && nextIndex <= snapshot.lastApplyIndex + 1 &&
+ !snapshotSenderIsStart(pSender) && pMsg->privateTerm < pSender->privateTerm) {
+ // has snapshot
+ ASSERT(pReader != NULL);
+ SSnapshotParam readerParam = {.start = 0, .end = snapshot.lastApplyIndex};
+ snapshotSenderStart(pSender, readerParam, snapshot, pReader);
+
+ } else {
+ // no snapshot
+ if (pReader != NULL) {
+ ths->pFsm->FpSnapshotStopRead(ths->pFsm, pReader);
+ }
}
SyncIndex sentryIndex = pSender->snapshot.lastApplyIndex + 1;
@@ -201,18 +379,15 @@ int32_t syncNodeOnAppendEntriesReplySnapshotCb(SSyncNode* ths, SyncAppendEntries
syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), nextIndex);
if (gRaftDetailLog) {
- sTrace("update next index not match, end, index:%ld, success:%d", nextIndex, pMsg->success);
+ sTrace("update next index not match, end, index:%" PRId64 ", success:%d", nextIndex, pMsg->success);
}
}
- syncIndexMgrLog2("recv SyncAppendEntriesReply, after pNextIndex:", ths->pNextIndex);
- syncIndexMgrLog2("recv SyncAppendEntriesReply, after pMatchIndex:", ths->pMatchIndex);
if (gRaftDetailLog) {
- SSnapshot snapshot;
- ths->pFsm->FpGetSnapshotInfo(ths->pFsm, &snapshot);
- sTrace("recv SyncAppendEntriesReply, after snapshot.lastApplyIndex:%ld, snapshot.lastApplyTerm:%lu",
- snapshot.lastApplyIndex, snapshot.lastApplyTerm);
+ syncNodeEventLog(ths, "recv sync-append-entries-reply, after");
}
+ syncIndexMgrLog2("recv sync-append-entries-reply, after pNextIndex:", ths->pNextIndex);
+ syncIndexMgrLog2("recv sync-append-entries-reply, after pMatchIndex:", ths->pMatchIndex);
- return ret;
+ return 0;
}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncCommit.c b/source/libs/sync/src/syncCommit.c
index ec3e1ab2baf94deb6153f3f0b69b067e05f33a92..b3cdd079a49c6a13bc2b74c9d00f92e235d39ce8 100644
--- a/source/libs/sync/src/syncCommit.c
+++ b/source/libs/sync/src/syncCommit.c
@@ -57,8 +57,8 @@ void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {
pSyncNode->commitIndex = snapshot.lastApplyIndex;
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "commit by snapshot from index:%ld to index:%ld", pSyncNode->commitIndex,
- snapshot.lastApplyIndex);
+ snprintf(eventLog, sizeof(eventLog), "commit by snapshot from index:%" PRId64 " to index:%" PRId64, commitBegin,
+ commitEnd);
syncNodeEventLog(pSyncNode, eventLog);
}
@@ -68,14 +68,14 @@ void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {
bool agree = syncAgree(pSyncNode, index);
if (gRaftDetailLog) {
- sTrace("syncMaybeAdvanceCommitIndex syncAgree:%d, index:%ld, pSyncNode->commitIndex:%ld", agree, index,
- pSyncNode->commitIndex);
+ sTrace("syncMaybeAdvanceCommitIndex syncAgree:%d, index:%" PRId64 ", pSyncNode->commitIndex:%" PRId64, agree,
+ index, pSyncNode->commitIndex);
}
if (agree) {
// term
SSyncRaftEntry* pEntry = pSyncNode->pLogStore->getEntry(pSyncNode->pLogStore, index);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
// cannot commit, even if quorum agree. need check term!
if (pEntry->term == pSyncNode->pRaftStore->currentTerm) {
@@ -83,7 +83,8 @@ void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {
newCommitIndex = index;
if (gRaftDetailLog) {
- sTrace("syncMaybeAdvanceCommitIndex maybe to update, newCommitIndex:%ld commit, pSyncNode->commitIndex:%ld",
+ sTrace("syncMaybeAdvanceCommitIndex maybe to update, newCommitIndex:%" PRId64
+ " commit, pSyncNode->commitIndex:%" PRId64,
newCommitIndex, pSyncNode->commitIndex);
}
@@ -91,10 +92,9 @@ void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {
break;
} else {
if (gRaftDetailLog) {
- sTrace(
- "syncMaybeAdvanceCommitIndex can not commit due to term not equal, pEntry->term:%lu, "
- "pSyncNode->pRaftStore->currentTerm:%lu",
- pEntry->term, pSyncNode->pRaftStore->currentTerm);
+ sTrace("syncMaybeAdvanceCommitIndex can not commit due to term not equal, pEntry->term:%" PRIu64
+ ", pSyncNode->pRaftStore->currentTerm:%" PRIu64,
+ pEntry->term, pSyncNode->pRaftStore->currentTerm);
}
}
@@ -102,12 +102,13 @@ void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {
}
}
+ // maybe execute fsm
if (newCommitIndex > pSyncNode->commitIndex) {
SyncIndex beginIndex = pSyncNode->commitIndex + 1;
SyncIndex endIndex = newCommitIndex;
if (gRaftDetailLog) {
- sTrace("syncMaybeAdvanceCommitIndex sync commit %ld", newCommitIndex);
+ sTrace("syncMaybeAdvanceCommitIndex sync commit %" PRId64, newCommitIndex);
}
// update commit index
diff --git a/source/libs/sync/src/syncElection.c b/source/libs/sync/src/syncElection.c
index fdebbe3990f32efed4b5e63a07dcc50ad2666fd8..6dcbb598aeffa16c859dac20550450253ef8ffeb 100644
--- a/source/libs/sync/src/syncElection.c
+++ b/source/libs/sync/src/syncElection.c
@@ -32,7 +32,7 @@
// /\ UNCHANGED <>
//
int32_t syncNodeRequestVotePeers(SSyncNode* pSyncNode) {
- assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
+ ASSERT(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
int32_t ret = 0;
for (int i = 0; i < pSyncNode->peersNum; ++i) {
@@ -44,7 +44,7 @@ int32_t syncNodeRequestVotePeers(SSyncNode* pSyncNode) {
pMsg->lastLogTerm = pSyncNode->pLogStore->getLastTerm(pSyncNode->pLogStore);
ret = syncNodeRequestVote(pSyncNode, &pSyncNode->peersId[i], pMsg);
- assert(ret == 0);
+ ASSERT(ret == 0);
syncRequestVoteDestroy(pMsg);
}
return ret;
@@ -75,7 +75,11 @@ int32_t syncNodeElect(SSyncNode* pSyncNode) {
if (pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER) {
syncNodeFollower2Candidate(pSyncNode);
}
- assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
+
+ if (pSyncNode->state != TAOS_SYNC_STATE_CANDIDATE) {
+ syncNodeErrorLog(pSyncNode, "not candidate, can not elect");
+ return -1;
+ }
// start election
raftStoreNextTerm(pSyncNode->pRaftStore);
@@ -86,28 +90,44 @@ int32_t syncNodeElect(SSyncNode* pSyncNode) {
syncNodeVoteForSelf(pSyncNode);
if (voteGrantedMajority(pSyncNode->pVotesGranted)) {
// only myself, to leader
- assert(!pSyncNode->pVotesGranted->toLeader);
+ ASSERT(!pSyncNode->pVotesGranted->toLeader);
syncNodeCandidate2Leader(pSyncNode);
pSyncNode->pVotesGranted->toLeader = true;
return ret;
}
- if (pSyncNode->pRaftCfg->snapshotEnable) {
- ret = syncNodeRequestVotePeersSnapshot(pSyncNode);
- } else {
- ret = syncNodeRequestVotePeers(pSyncNode);
- }
+ switch (pSyncNode->pRaftCfg->snapshotStrategy) {
+ case SYNC_STRATEGY_NO_SNAPSHOT:
+ ret = syncNodeRequestVotePeers(pSyncNode);
+ break;
+
+ case SYNC_STRATEGY_STANDARD_SNAPSHOT:
+ case SYNC_STRATEGY_WAL_FIRST:
+ ret = syncNodeRequestVotePeersSnapshot(pSyncNode);
+ break;
- assert(ret == 0);
+ default:
+ ret = syncNodeRequestVotePeers(pSyncNode);
+ break;
+ }
+ ASSERT(ret == 0);
syncNodeResetElectTimer(pSyncNode);
return ret;
}
int32_t syncNodeRequestVote(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncRequestVote* pMsg) {
- sTrace("syncNodeRequestVote pSyncNode:%p ", pSyncNode);
int32_t ret = 0;
+ do {
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(destRaftId->addr, host, sizeof(host), &port);
+ sDebug("vgId:%d, send sync-request-vote to %s:%d, {term:%" PRIu64 ", last-index:%" PRId64 ", last-term:%" PRIu64
+ "}",
+ pSyncNode->vgId, host, port, pMsg->term, pMsg->lastLogTerm, pMsg->lastLogIndex);
+ } while (0);
+
SRpcMsg rpcMsg;
syncRequestVote2RpcMsg(pMsg, &rpcMsg);
syncNodeSendMsgById(destRaftId, pSyncNode, &rpcMsg);
diff --git a/source/libs/sync/src/syncEnv.c b/source/libs/sync/src/syncEnv.c
index e67439f8feae8601e75e0c8df2dcc82aced32a86..fb0bfb8bef318c2f8d2d53f12cfabcfa4fb30ef2 100644
--- a/source/libs/sync/src/syncEnv.c
+++ b/source/libs/sync/src/syncEnv.c
@@ -14,7 +14,7 @@
*/
#include "syncEnv.h"
-// #include
+// #include
SSyncEnv *gSyncEnv = NULL;
@@ -35,11 +35,12 @@ bool syncEnvIsStart() {
}
int32_t syncEnvStart() {
- int32_t ret = 0;
- taosSeedRand(taosGetTimestampSec());
+ int32_t ret = 0;
+ uint32_t seed = (uint32_t)(taosGetTimestampNs() & 0x00000000FFFFFFFF);
+ taosSeedRand(seed);
// gSyncEnv = doSyncEnvStart(gSyncEnv);
gSyncEnv = doSyncEnvStart();
- assert(gSyncEnv != NULL);
+ ASSERT(gSyncEnv != NULL);
sTrace("sync env start ok");
return ret;
}
@@ -85,7 +86,7 @@ static void syncEnvTick(void *param, void *tmrId) {
static SSyncEnv *doSyncEnvStart() {
SSyncEnv *pSyncEnv = (SSyncEnv *)taosMemoryMalloc(sizeof(SSyncEnv));
- assert(pSyncEnv != NULL);
+ ASSERT(pSyncEnv != NULL);
memset(pSyncEnv, 0, sizeof(SSyncEnv));
pSyncEnv->envTickTimerCounter = 0;
@@ -102,7 +103,7 @@ static SSyncEnv *doSyncEnvStart() {
}
static int32_t doSyncEnvStop(SSyncEnv *pSyncEnv) {
- assert(pSyncEnv == gSyncEnv);
+ ASSERT(pSyncEnv == gSyncEnv);
if (pSyncEnv != NULL) {
atomic_store_8(&(pSyncEnv->isStart), 0);
taosTmrCleanUp(pSyncEnv->pTimerManager);
diff --git a/source/libs/sync/src/syncIO.c b/source/libs/sync/src/syncIO.c
index 0b5a9685c0e86de847fbf2d4e6cc180650872ab1..d9f11ba80f925ad2b73e443169968a54d10209f3 100644
--- a/source/libs/sync/src/syncIO.c
+++ b/source/libs/sync/src/syncIO.c
@@ -47,11 +47,11 @@ static void syncIOTickPing(void *param, void *tmrId);
int32_t syncIOStart(char *host, uint16_t port) {
int32_t ret = 0;
gSyncIO = syncIOCreate(host, port);
- assert(gSyncIO != NULL);
+ ASSERT(gSyncIO != NULL);
taosSeedRand(taosGetTimestampSec());
ret = syncIOStartInternal(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
sTrace("syncIOStart ok, gSyncIO:%p", gSyncIO);
return ret;
@@ -59,16 +59,16 @@ int32_t syncIOStart(char *host, uint16_t port) {
int32_t syncIOStop() {
int32_t ret = syncIOStopInternal(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
ret = syncIODestroy(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
return ret;
}
int32_t syncIOSendMsg(const SEpSet *pEpSet, SRpcMsg *pMsg) {
- assert(pEpSet->inUse == 0);
- assert(pEpSet->numOfEps == 1);
+ ASSERT(pEpSet->inUse == 0);
+ ASSERT(pEpSet->numOfEps == 1);
int32_t ret = 0;
{
@@ -107,25 +107,25 @@ int32_t syncIOEqMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) {
int32_t syncIOQTimerStart() {
int32_t ret = syncIOStartQ(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
return ret;
}
int32_t syncIOQTimerStop() {
int32_t ret = syncIOStopQ(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
return ret;
}
int32_t syncIOPingTimerStart() {
int32_t ret = syncIOStartPing(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
return ret;
}
int32_t syncIOPingTimerStop() {
int32_t ret = syncIOStopPing(gSyncIO);
- assert(ret == 0);
+ ASSERT(ret == 0);
return ret;
}
@@ -151,7 +151,7 @@ static SSyncIO *syncIOCreate(char *host, uint16_t port) {
static int32_t syncIODestroy(SSyncIO *io) {
int32_t ret = 0;
int8_t start = atomic_load_8(&io->isStart);
- assert(start == 0);
+ ASSERT(start == 0);
if (io->serverRpc != NULL) {
rpcClose(io->serverRpc);
@@ -242,13 +242,13 @@ static int32_t syncIOStopInternal(SSyncIO *io) {
}
static void *syncIOConsumerFunc(void *param) {
- SSyncIO * io = param;
- STaosQall *qall;
- SRpcMsg * pRpcMsg, rpcMsg;
- qall = taosAllocateQall();
+ SSyncIO *io = param;
+ STaosQall *qall = taosAllocateQall();
+ SRpcMsg *pRpcMsg, rpcMsg;
+ SQueueInfo qinfo = {0};
while (1) {
- int numOfMsgs = taosReadAllQitemsFromQset(io->pQset, qall, NULL, NULL);
+ int numOfMsgs = taosReadAllQitemsFromQset(io->pQset, qall, &qinfo);
sTrace("syncIOConsumerFunc %d msgs are received", numOfMsgs);
if (numOfMsgs <= 0) {
break;
@@ -264,7 +264,7 @@ static void *syncIOConsumerFunc(void *param) {
if (pRpcMsg->msgType == TDMT_SYNC_PING) {
if (io->FpOnSyncPing != NULL) {
SyncPing *pSyncMsg = syncPingFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncPing(io->pSyncNode, pSyncMsg);
syncPingDestroy(pSyncMsg);
}
@@ -272,7 +272,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_PING_REPLY) {
if (io->FpOnSyncPingReply != NULL) {
SyncPingReply *pSyncMsg = syncPingReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncPingReply(io->pSyncNode, pSyncMsg);
syncPingReplyDestroy(pSyncMsg);
}
@@ -280,15 +280,15 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) {
if (io->FpOnSyncClientRequest != NULL) {
SyncClientRequest *pSyncMsg = syncClientRequestFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
- io->FpOnSyncClientRequest(io->pSyncNode, pSyncMsg);
+ ASSERT(pSyncMsg != NULL);
+ io->FpOnSyncClientRequest(io->pSyncNode, pSyncMsg, NULL);
syncClientRequestDestroy(pSyncMsg);
}
} else if (pRpcMsg->msgType == TDMT_SYNC_REQUEST_VOTE) {
if (io->FpOnSyncRequestVote != NULL) {
SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncRequestVote(io->pSyncNode, pSyncMsg);
syncRequestVoteDestroy(pSyncMsg);
}
@@ -296,7 +296,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_REQUEST_VOTE_REPLY) {
if (io->FpOnSyncRequestVoteReply != NULL) {
SyncRequestVoteReply *pSyncMsg = syncRequestVoteReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncRequestVoteReply(io->pSyncNode, pSyncMsg);
syncRequestVoteReplyDestroy(pSyncMsg);
}
@@ -304,7 +304,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_APPEND_ENTRIES) {
if (io->FpOnSyncAppendEntries != NULL) {
SyncAppendEntries *pSyncMsg = syncAppendEntriesFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncAppendEntries(io->pSyncNode, pSyncMsg);
syncAppendEntriesDestroy(pSyncMsg);
}
@@ -312,7 +312,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_APPEND_ENTRIES_REPLY) {
if (io->FpOnSyncAppendEntriesReply != NULL) {
SyncAppendEntriesReply *pSyncMsg = syncAppendEntriesReplyFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncAppendEntriesReply(io->pSyncNode, pSyncMsg);
syncAppendEntriesReplyDestroy(pSyncMsg);
}
@@ -320,7 +320,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_TIMEOUT) {
if (io->FpOnSyncTimeout != NULL) {
SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncTimeout(io->pSyncNode, pSyncMsg);
syncTimeoutDestroy(pSyncMsg);
}
@@ -328,7 +328,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_SNAPSHOT_SEND) {
if (io->FpOnSyncSnapshotSend != NULL) {
SyncSnapshotSend *pSyncMsg = syncSnapshotSendFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncSnapshotSend(io->pSyncNode, pSyncMsg);
syncSnapshotSendDestroy(pSyncMsg);
}
@@ -336,7 +336,7 @@ static void *syncIOConsumerFunc(void *param) {
} else if (pRpcMsg->msgType == TDMT_SYNC_SNAPSHOT_RSP) {
if (io->FpOnSyncSnapshotRsp != NULL) {
SyncSnapshotRsp *pSyncMsg = syncSnapshotRspFromRpcMsg2(pRpcMsg);
- assert(pSyncMsg != NULL);
+ ASSERT(pSyncMsg != NULL);
io->FpOnSyncSnapshotRsp(io->pSyncNode, pSyncMsg);
syncSnapshotRspDestroy(pSyncMsg);
}
@@ -369,6 +369,8 @@ static void *syncIOConsumerFunc(void *param) {
taosFreeQitem(pRpcMsg);
}
+
+ taosUpdateItemSize(qinfo.queue, numOfMsgs);
}
taosFreeQall(qall);
diff --git a/source/libs/sync/src/syncIndexMgr.c b/source/libs/sync/src/syncIndexMgr.c
index 18cb55b417411b46e9482409b40fc5dc477513f7..a9c1147fc1bdf3e7bd1a640da23a963224edefc2 100644
--- a/source/libs/sync/src/syncIndexMgr.c
+++ b/source/libs/sync/src/syncIndexMgr.c
@@ -20,7 +20,7 @@
SSyncIndexMgr *syncIndexMgrCreate(SSyncNode *pSyncNode) {
SSyncIndexMgr *pSyncIndexMgr = taosMemoryMalloc(sizeof(SSyncIndexMgr));
- assert(pSyncIndexMgr != NULL);
+ ASSERT(pSyncIndexMgr != NULL);
memset(pSyncIndexMgr, 0, sizeof(SSyncIndexMgr));
pSyncIndexMgr->replicas = &(pSyncNode->replicasId);
@@ -63,7 +63,12 @@ void syncIndexMgrSetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId,
}
// maybe config change
- assert(0);
+ // ASSERT(0);
+
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pRaftId->addr, host, sizeof(host), &port);
+ sError("vgId:%d index mgr set for %s:%d, index:%" PRId64 " error", pSyncIndexMgr->pSyncNode->vgId, host, port, index);
}
SyncIndex syncIndexMgrGetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId) {
@@ -73,7 +78,9 @@ SyncIndex syncIndexMgrGetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaf
return idx;
}
}
- assert(0);
+
+ syncNodeLog3("syncIndexMgrGetIndex", pSyncIndexMgr->pSyncNode);
+ ASSERT(0);
}
cJSON *syncIndexMgr2Json(SSyncIndexMgr *pSyncIndexMgr) {
@@ -127,28 +134,28 @@ char *syncIndexMgr2Str(SSyncIndexMgr *pSyncIndexMgr) {
// for debug -------------------
void syncIndexMgrPrint(SSyncIndexMgr *pObj) {
char *serialized = syncIndexMgr2Str(pObj);
- printf("syncIndexMgrPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncIndexMgrPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncIndexMgrPrint2(char *s, SSyncIndexMgr *pObj) {
char *serialized = syncIndexMgr2Str(pObj);
- printf("syncIndexMgrPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncIndexMgrPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncIndexMgrLog(SSyncIndexMgr *pObj) {
char *serialized = syncIndexMgr2Str(pObj);
- sTrace("syncIndexMgrLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncIndexMgrLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncIndexMgrLog2(char *s, SSyncIndexMgr *pObj) {
if (gRaftDetailLog) {
char *serialized = syncIndexMgr2Str(pObj);
- sTrace("syncIndexMgrLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncIndexMgrLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -162,7 +169,11 @@ void syncIndexMgrSetTerm(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId, S
}
// maybe config change
- assert(0);
+ // ASSERT(0);
+ char host[128];
+ uint16_t port;
+ syncUtilU642Addr(pRaftId->addr, host, sizeof(host), &port);
+ sError("vgId:%d index mgr set for %s:%d, term:%" PRIu64 " error", pSyncIndexMgr->pSyncNode->vgId, host, port, term);
}
SyncTerm syncIndexMgrGetTerm(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId) {
@@ -172,5 +183,5 @@ SyncTerm syncIndexMgrGetTerm(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftI
return term;
}
}
- assert(0);
+ ASSERT(0);
}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c
index 33e7a8241f92f2865e5d1e1a209237dac8c54693..b7e6c1e142adbc0929eaf18f3686bbf0ceb08278 100644
--- a/source/libs/sync/src/syncMain.c
+++ b/source/libs/sync/src/syncMain.c
@@ -50,7 +50,6 @@ static int32_t syncNodeAppendNoop(SSyncNode* ths);
// process message ----
int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg);
int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg);
-int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg);
// life cycle
static void syncFreeNode(void* param);
@@ -66,6 +65,7 @@ int32_t syncInit() {
syncCleanUp();
ret = -1;
} else {
+ sDebug("sync rsetId:%" PRId64 " is open", tsNodeRefId);
ret = syncEnvStart();
}
}
@@ -75,9 +75,10 @@ int32_t syncInit() {
void syncCleanUp() {
int32_t ret = syncEnvStop();
- assert(ret == 0);
+ ASSERT(ret == 0);
if (tsNodeRefId != -1) {
+ sDebug("sync rsetId:%" PRId64 " is closed", tsNodeRefId);
taosCloseRef(tsNodeRefId);
tsNodeRefId = -1;
}
@@ -85,7 +86,7 @@ void syncCleanUp() {
int64_t syncOpen(const SSyncInfo* pSyncInfo) {
SSyncNode* pSyncNode = syncNodeOpen(pSyncInfo);
- assert(pSyncNode != NULL);
+ ASSERT(pSyncNode != NULL);
if (gRaftDetailLog) {
syncNodeLog2("syncNodeOpen open success", pSyncNode);
@@ -97,6 +98,7 @@ int64_t syncOpen(const SSyncInfo* pSyncInfo) {
return -1;
}
+ sDebug("vgId:%d, rid:%" PRId64 " is added to rsetId:%" PRId64, pSyncInfo->vgId, pSyncNode->rid, tsNodeRefId);
return pSyncNode->rid;
}
@@ -137,13 +139,14 @@ void syncStartStandBy(int64_t rid) {
void syncStop(int64_t rid) {
SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
- if (pSyncNode == NULL) {
- return;
- }
+ if (pSyncNode == NULL) return;
+
+ int32_t vgId = pSyncNode->vgId;
syncNodeClose(pSyncNode);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
taosRemoveRef(tsNodeRefId, rid);
+ sDebug("vgId:%d, rid:%" PRId64 " is removed from rsetId:%" PRId64, vgId, rid, tsNodeRefId);
}
int32_t syncSetStandby(int64_t rid) {
@@ -155,9 +158,13 @@ int32_t syncSetStandby(int64_t rid) {
}
if (pSyncNode->state != TAOS_SYNC_STATE_FOLLOWER) {
+ if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) {
+ terrno = TSDB_CODE_SYN_IS_LEADER;
+ } else {
+ terrno = TSDB_CODE_SYN_STANDBY_NOT_READY;
+ }
+ sError("failed to set standby since it is not follower, state:%s rid:%" PRId64, syncStr(pSyncNode->state), rid);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
- terrno = TSDB_CODE_SYN_IS_LEADER;
- sError("failed to set standby since it is not follower, rid:%" PRId64, rid);
return -1;
}
@@ -266,16 +273,8 @@ int32_t syncLeaderTransfer(int64_t rid) {
}
ASSERT(rid == pSyncNode->rid);
- if (pSyncNode->peersNum == 0) {
- taosReleaseRef(tsNodeRefId, pSyncNode->rid);
- terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
- return -1;
- }
-
- SNodeInfo newLeader = (pSyncNode->peersNodeInfo)[0];
+ int32_t ret = syncNodeLeaderTransfer(pSyncNode);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
-
- int32_t ret = syncLeaderTransferTo(rid, newLeader);
return ret;
}
@@ -286,15 +285,39 @@ int32_t syncLeaderTransferTo(int64_t rid, SNodeInfo newLeader) {
return -1;
}
ASSERT(rid == pSyncNode->rid);
+
+ int32_t ret = syncNodeLeaderTransferTo(pSyncNode, newLeader);
+ taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+ return ret;
+}
+
+int32_t syncNodeLeaderTransfer(SSyncNode* pSyncNode) {
+ if (pSyncNode->peersNum == 0) {
+ sDebug("only one replica, cannot leader transfer");
+ terrno = TSDB_CODE_SYN_ONE_REPLICA;
+ return -1;
+ }
+
+ SNodeInfo newLeader = (pSyncNode->peersNodeInfo)[0];
+ int32_t ret = syncNodeLeaderTransferTo(pSyncNode, newLeader);
+ return ret;
+}
+
+int32_t syncNodeLeaderTransferTo(SSyncNode* pSyncNode, SNodeInfo newLeader) {
int32_t ret = 0;
if (pSyncNode->replicaNum == 1) {
- sError("only one replica, cannot drop leader");
- taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+ sDebug("only one replica, cannot leader transfer");
terrno = TSDB_CODE_SYN_ONE_REPLICA;
return -1;
}
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "begin leader transfer to %s:%u", newLeader.nodeFqdn, newLeader.nodePort);
+ syncNodeEventLog(pSyncNode, logBuf);
+ } while (0);
+
SyncLeaderTransfer* pMsg = syncLeaderTransferBuild(pSyncNode->vgId);
pMsg->newLeaderId.addr = syncUtilAddr2U64(newLeader.nodeFqdn, newLeader.nodePort);
pMsg->newLeaderId.vgId = pSyncNode->vgId;
@@ -305,7 +328,6 @@ int32_t syncLeaderTransferTo(int64_t rid, SNodeInfo newLeader) {
syncLeaderTransferDestroy(pMsg);
ret = syncNodePropose(pSyncNode, &rpcMsg, false);
- taosReleaseRef(tsNodeRefId, pSyncNode->rid);
return ret;
}
@@ -314,7 +336,7 @@ bool syncCanLeaderTransfer(int64_t rid) {
if (pSyncNode == NULL) {
return false;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
if (pSyncNode->replicaNum == 1) {
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -341,7 +363,7 @@ bool syncCanLeaderTransfer(int64_t rid) {
return matchOK;
}
-int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pMsg, bool isWeak) {
+int32_t syncForwardToPeer(int64_t rid, SRpcMsg* pMsg, bool isWeak) {
int32_t ret = syncPropose(rid, pMsg, isWeak);
return ret;
}
@@ -351,7 +373,7 @@ ESyncState syncGetMyRole(int64_t rid) {
if (pSyncNode == NULL) {
return TAOS_SYNC_STATE_ERROR;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
ESyncState state = pSyncNode->state;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -363,9 +385,18 @@ bool syncIsReady(int64_t rid) {
if (pSyncNode == NULL) {
return false;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
bool b = (pSyncNode->state == TAOS_SYNC_STATE_LEADER) && pSyncNode->restoreFinish;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+
+ // if false, set error code
+ if (false == b) {
+ if (pSyncNode->state != TAOS_SYNC_STATE_LEADER) {
+ terrno = TSDB_CODE_SYN_NOT_LEADER;
+ } else {
+ terrno = TSDB_CODE_APP_NOT_READY;
+ }
+ }
return b;
}
@@ -374,19 +405,51 @@ bool syncIsRestoreFinish(int64_t rid) {
if (pSyncNode == NULL) {
return false;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
bool b = pSyncNode->restoreFinish;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
return b;
}
+int32_t syncGetSnapshotByIndex(int64_t rid, SyncIndex index, SSnapshot* pSnapshot) {
+ if (index < SYNC_INDEX_BEGIN) {
+ return -1;
+ }
+
+ SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
+ if (pSyncNode == NULL) {
+ return -1;
+ }
+ ASSERT(rid == pSyncNode->rid);
+
+ SSyncRaftEntry* pEntry = NULL;
+ int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, index, &pEntry);
+ if (code != 0) {
+ if (pEntry != NULL) {
+ syncEntryDestory(pEntry);
+ }
+ taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+ return -1;
+ }
+ ASSERT(pEntry != NULL);
+
+ pSnapshot->data = NULL;
+ pSnapshot->lastApplyIndex = index;
+ pSnapshot->lastApplyTerm = pEntry->term;
+ pSnapshot->lastConfigIndex = syncNodeGetSnapshotConfigIndex(pSyncNode, index);
+
+ syncEntryDestory(pEntry);
+ taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+ return 0;
+}
+
int32_t syncGetSnapshotMeta(int64_t rid, struct SSnapshotMeta* sMeta) {
SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
if (pSyncNode == NULL) {
return -1;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
sMeta->lastConfigIndex = pSyncNode->pRaftCfg->lastConfigIndex;
sTrace("vgId:%d, get snapshot meta, lastConfigIndex:%" PRId64, pSyncNode->vgId, pSyncNode->pRaftCfg->lastConfigIndex);
@@ -400,7 +463,7 @@ int32_t syncGetSnapshotMetaByIndex(int64_t rid, SyncIndex snapshotIndex, struct
if (pSyncNode == NULL) {
return -1;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
ASSERT(pSyncNode->pRaftCfg->configIndexCount >= 1);
SyncIndex lastIndex = (pSyncNode->pRaftCfg->configIndexArr)[0];
@@ -412,7 +475,7 @@ int32_t syncGetSnapshotMetaByIndex(int64_t rid, SyncIndex snapshotIndex, struct
}
}
sMeta->lastConfigIndex = lastIndex;
- sTrace("vgId:%d, get snapshot meta by index:%" PRId64 " lastConfigIndex:%" PRId64, pSyncNode->vgId, snapshotIndex,
+ sTrace("vgId:%d, get snapshot meta by index:%" PRId64 " lcindex:%" PRId64, pSyncNode->vgId, snapshotIndex,
sMeta->lastConfigIndex);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -429,8 +492,9 @@ SyncIndex syncNodeGetSnapshotConfigIndex(SSyncNode* pSyncNode, SyncIndex snapsho
lastIndex = (pSyncNode->pRaftCfg->configIndexArr)[i];
}
}
+ sTrace("vgId:%d, sync get snapshot last config index, index:%" PRId64 " lcindex:%" PRId64, pSyncNode->vgId,
+ snapshotLastApplyIndex, lastIndex);
- sTrace("sync syncNodeGetSnapshotConfigIndex index:%ld lastConfigIndex:%ld", snapshotLastApplyIndex, lastIndex);
return lastIndex;
}
@@ -444,7 +508,7 @@ SyncTerm syncGetMyTerm(int64_t rid) {
if (pSyncNode == NULL) {
return TAOS_SYNC_STATE_ERROR;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
SyncTerm term = pSyncNode->pRaftStore->currentTerm;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -456,7 +520,7 @@ SyncGroupId syncGetVgId(int64_t rid) {
if (pSyncNode == NULL) {
return TAOS_SYNC_STATE_ERROR;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
SyncGroupId vgId = pSyncNode->vgId;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -469,18 +533,36 @@ void syncGetEpSet(int64_t rid, SEpSet* pEpSet) {
memset(pEpSet, 0, sizeof(*pEpSet));
return;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
pEpSet->numOfEps = 0;
for (int i = 0; i < pSyncNode->pRaftCfg->cfg.replicaNum; ++i) {
snprintf(pEpSet->eps[i].fqdn, sizeof(pEpSet->eps[i].fqdn), "%s", (pSyncNode->pRaftCfg->cfg.nodeInfo)[i].nodeFqdn);
pEpSet->eps[i].port = (pSyncNode->pRaftCfg->cfg.nodeInfo)[i].nodePort;
(pEpSet->numOfEps)++;
-
- sInfo("syncGetEpSet index:%d %s:%d", i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
+ sInfo("vgId:%d sync get epset: index:%d %s:%d", pSyncNode->vgId, i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
}
pEpSet->inUse = pSyncNode->pRaftCfg->cfg.myIndex;
+ sInfo("vgId:%d sync get epset in-use:%d", pSyncNode->vgId, pEpSet->inUse);
+
+ taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+}
- sInfo("syncGetEpSet pEpSet->inUse:%d ", pEpSet->inUse);
+void syncGetRetryEpSet(int64_t rid, SEpSet* pEpSet) {
+ SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
+ if (pSyncNode == NULL) {
+ memset(pEpSet, 0, sizeof(*pEpSet));
+ return;
+ }
+ ASSERT(rid == pSyncNode->rid);
+ pEpSet->numOfEps = 0;
+ for (int i = 0; i < pSyncNode->pRaftCfg->cfg.replicaNum; ++i) {
+ snprintf(pEpSet->eps[i].fqdn, sizeof(pEpSet->eps[i].fqdn), "%s", (pSyncNode->pRaftCfg->cfg.nodeInfo)[i].nodeFqdn);
+ pEpSet->eps[i].port = (pSyncNode->pRaftCfg->cfg.nodeInfo)[i].nodePort;
+ (pEpSet->numOfEps)++;
+ sInfo("vgId:%d sync get retry epset: index:%d %s:%d", pSyncNode->vgId, i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
+ }
+ pEpSet->inUse = (pSyncNode->pRaftCfg->cfg.myIndex + 1) % pEpSet->numOfEps;
+ sInfo("vgId:%d sync get retry epset in-use:%d", pSyncNode->vgId, pEpSet->inUse);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
}
@@ -490,7 +572,7 @@ int32_t syncGetRespRpc(int64_t rid, uint64_t index, SRpcMsg* msg) {
if (pSyncNode == NULL) {
return TAOS_SYNC_STATE_ERROR;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
SRespStub stub;
int32_t ret = syncRespMgrGet(pSyncNode->pSyncRespMgr, index, &stub);
@@ -507,7 +589,7 @@ int32_t syncGetAndDelRespRpc(int64_t rid, uint64_t index, SRpcHandleInfo* pInfo)
if (pSyncNode == NULL) {
return TAOS_SYNC_STATE_ERROR;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
SRespStub stub;
int32_t ret = syncRespMgrGetAndDel(pSyncNode->pSyncRespMgr, index, &stub);
@@ -523,10 +605,10 @@ int32_t syncGetAndDelRespRpc(int64_t rid, uint64_t index, SRpcHandleInfo* pInfo)
void syncSetMsgCb(int64_t rid, const SMsgCb* msgcb) {
SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
if (pSyncNode == NULL) {
- sTrace("syncSetQ get pSyncNode is NULL, rid:%ld", rid);
+ sTrace("syncSetQ get pSyncNode is NULL, rid:%" PRId64, rid);
return;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
pSyncNode->msgcb = msgcb;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -535,10 +617,10 @@ void syncSetMsgCb(int64_t rid, const SMsgCb* msgcb) {
char* sync2SimpleStr(int64_t rid) {
SSyncNode* pSyncNode = (SSyncNode*)taosAcquireRef(tsNodeRefId, rid);
if (pSyncNode == NULL) {
- sTrace("syncSetRpc get pSyncNode is NULL, rid:%ld", rid);
+ sTrace("syncSetRpc get pSyncNode is NULL, rid:%" PRId64, rid);
return NULL;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
char* s = syncNode2SimpleStr(pSyncNode);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -550,7 +632,7 @@ void setPingTimerMS(int64_t rid, int32_t pingTimerMS) {
if (pSyncNode == NULL) {
return;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
pSyncNode->pingBaseLine = pingTimerMS;
pSyncNode->pingTimerMS = pingTimerMS;
@@ -562,7 +644,7 @@ void setElectTimerMS(int64_t rid, int32_t electTimerMS) {
if (pSyncNode == NULL) {
return;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
pSyncNode->electBaseLine = electTimerMS;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
@@ -573,29 +655,138 @@ void setHeartbeatTimerMS(int64_t rid, int32_t hbTimerMS) {
if (pSyncNode == NULL) {
return;
}
- assert(rid == pSyncNode->rid);
+ ASSERT(rid == pSyncNode->rid);
pSyncNode->hbBaseLine = hbTimerMS;
pSyncNode->heartbeatTimerMS = hbTimerMS;
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
}
-int32_t syncPropose(int64_t rid, const SRpcMsg* pMsg, bool isWeak) {
- int32_t ret = 0;
+int32_t syncPropose(int64_t rid, SRpcMsg* pMsg, bool isWeak) {
+ SSyncNode* pSyncNode = taosAcquireRef(tsNodeRefId, rid);
+ if (pSyncNode == NULL) {
+ taosReleaseRef(tsNodeRefId, rid);
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
+ ASSERT(rid == pSyncNode->rid);
+
+ int32_t ret = syncNodePropose(pSyncNode, pMsg, isWeak);
+ taosReleaseRef(tsNodeRefId, pSyncNode->rid);
+ return ret;
+}
+
+int32_t syncProposeBatch(int64_t rid, SRpcMsg* pMsgArr, bool* pIsWeakArr, int32_t arrSize) {
+ if (arrSize < 0) {
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
SSyncNode* pSyncNode = taosAcquireRef(tsNodeRefId, rid);
if (pSyncNode == NULL) {
terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
return -1;
}
- assert(rid == pSyncNode->rid);
- ret = syncNodePropose(pSyncNode, pMsg, isWeak);
+ ASSERT(rid == pSyncNode->rid);
+ int32_t ret = syncNodeProposeBatch(pSyncNode, pMsgArr, pIsWeakArr, arrSize);
taosReleaseRef(tsNodeRefId, pSyncNode->rid);
return ret;
}
-int32_t syncNodePropose(SSyncNode* pSyncNode, const SRpcMsg* pMsg, bool isWeak) {
+static bool syncNodeBatchOK(SRpcMsg* pMsgArr, int32_t arrSize) {
+ for (int32_t i = 0; i < arrSize; ++i) {
+ if (pMsgArr[i].msgType == TDMT_SYNC_CONFIG_CHANGE) {
+ return false;
+ }
+
+ if (pMsgArr[i].msgType == TDMT_SYNC_CONFIG_CHANGE_FINISH) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int32_t syncNodeProposeBatch(SSyncNode* pSyncNode, SRpcMsg* pMsgArr, bool* pIsWeakArr, int32_t arrSize) {
+ if (!syncNodeBatchOK(pMsgArr, arrSize)) {
+ syncNodeErrorLog(pSyncNode, "sync propose batch error");
+ terrno = TSDB_CODE_SYN_BATCH_ERROR;
+ return -1;
+ }
+
+ if (arrSize > SYNC_MAX_BATCH_SIZE) {
+ syncNodeErrorLog(pSyncNode, "sync propose batch error");
+ terrno = TSDB_CODE_SYN_BATCH_ERROR;
+ return -1;
+ }
+
+ if (pSyncNode->state != TAOS_SYNC_STATE_LEADER) {
+ syncNodeErrorLog(pSyncNode, "sync propose not leader");
+ terrno = TSDB_CODE_SYN_NOT_LEADER;
+ return -1;
+ }
+
+ if (pSyncNode->changing) {
+ syncNodeErrorLog(pSyncNode, "sync propose not ready");
+ terrno = TSDB_CODE_SYN_PROPOSE_NOT_READY;
+ return -1;
+ }
+
+ SRaftMeta raftArr[SYNC_MAX_BATCH_SIZE];
+ for (int i = 0; i < arrSize; ++i) {
+ SRespStub stub;
+ stub.createTime = taosGetTimestampMs();
+ stub.rpcMsg = pMsgArr[i];
+ uint64_t seqNum = syncRespMgrAdd(pSyncNode->pSyncRespMgr, &stub);
+
+ raftArr[i].isWeak = pIsWeakArr[i];
+ raftArr[i].seqNum = seqNum;
+ }
+
+ SyncClientRequestBatch* pSyncMsg = syncClientRequestBatchBuild(pMsgArr, raftArr, arrSize, pSyncNode->vgId);
+ ASSERT(pSyncMsg != NULL);
+
+ SRpcMsg rpcMsg;
+ syncClientRequestBatch2RpcMsg(pSyncMsg, &rpcMsg);
+ taosMemoryFree(pSyncMsg); // only free msg body, do not free rpc msg content
+
+ if (pSyncNode->replicaNum == 1 && pSyncNode->vgId != 1) {
+ int32_t code = syncNodeOnClientRequestBatchCb(pSyncNode, pSyncMsg);
+ if (code == 0) {
+ // update rpc msg applyIndex
+ SRpcMsg* msgArr = syncClientRequestBatchRpcMsgArr(pSyncMsg);
+ ASSERT(arrSize == pSyncMsg->dataCount);
+ for (int i = 0; i < arrSize; ++i) {
+ pMsgArr[i].info.conn.applyIndex = msgArr[i].info.conn.applyIndex;
+ syncRespMgrDel(pSyncNode->pSyncRespMgr, raftArr[i].seqNum);
+ }
+
+ rpcFreeCont(rpcMsg.pCont);
+ terrno = 0;
+ return 1;
+
+ } else {
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
+
+ } else {
+ if (pSyncNode->FpEqMsg != NULL && (*pSyncNode->FpEqMsg)(pSyncNode->msgcb, &rpcMsg) == 0) {
+ // enqueue msg ok
+ return 0;
+
+ } else {
+ sError("vgId:%d, enqueue msg error, FpEqMsg is NULL", pSyncNode->vgId);
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int32_t syncNodePropose(SSyncNode* pSyncNode, SRpcMsg* pMsg, bool isWeak) {
int32_t ret = 0;
char eventLog[128];
@@ -606,7 +797,7 @@ int32_t syncNodePropose(SSyncNode* pSyncNode, const SRpcMsg* pMsg, bool isWeak)
if (pSyncNode->changing && pMsg->msgType != TDMT_SYNC_CONFIG_CHANGE_FINISH) {
ret = -1;
terrno = TSDB_CODE_SYN_PROPOSE_NOT_READY;
- sError("sync propose not ready, type:%s,%d", TMSG_INFO(pMsg->msgType), pMsg->msgType);
+ sError("vgId:%d, sync propose not ready, type:%s,%d", pSyncNode->vgId, TMSG_INFO(pMsg->msgType), pMsg->msgType);
goto _END;
}
@@ -615,7 +806,8 @@ int32_t syncNodePropose(SSyncNode* pSyncNode, const SRpcMsg* pMsg, bool isWeak)
if (!syncNodeCanChange(pSyncNode)) {
ret = -1;
terrno = TSDB_CODE_SYN_RECONFIG_NOT_READY;
- sError("sync reconfig not ready, type:%s,%d", TMSG_INFO(pMsg->msgType), pMsg->msgType);
+ sError("vgId:%d, sync reconfig not ready, type:%s,%d", pSyncNode->vgId, TMSG_INFO(pMsg->msgType),
+ pMsg->msgType);
goto _END;
}
@@ -632,20 +824,42 @@ int32_t syncNodePropose(SSyncNode* pSyncNode, const SRpcMsg* pMsg, bool isWeak)
SRpcMsg rpcMsg;
syncClientRequest2RpcMsg(pSyncMsg, &rpcMsg);
- if (pSyncNode->FpEqMsg != NULL && (*pSyncNode->FpEqMsg)(pSyncNode->msgcb, &rpcMsg) == 0) {
- ret = 0;
+ // optimized one replica
+ if (syncNodeIsOptimizedOneReplica(pSyncNode, pMsg)) {
+ SyncIndex retIndex;
+ int32_t code = syncNodeOnClientRequestCb(pSyncNode, pSyncMsg, &retIndex);
+ if (code == 0) {
+ pMsg->info.conn.applyIndex = retIndex;
+ pMsg->info.conn.applyTerm = pSyncNode->pRaftStore->currentTerm;
+ rpcFreeCont(rpcMsg.pCont);
+ syncRespMgrDel(pSyncNode->pSyncRespMgr, seqNum);
+ ret = 1;
+ sDebug("vgId:%d optimized index:%" PRId64 " success, msgtype:%s,%d", pSyncNode->vgId, retIndex,
+ TMSG_INFO(pMsg->msgType), pMsg->msgType);
+ } else {
+ ret = -1;
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ sError("vgId:%d optimized index:%" PRId64 " error, msgtype:%s,%d", pSyncNode->vgId, retIndex,
+ TMSG_INFO(pMsg->msgType), pMsg->msgType);
+ }
+
} else {
- ret = -1;
- terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
- sError("syncPropose pSyncNode->FpEqMsg is NULL");
+ if (pSyncNode->FpEqMsg != NULL && (*pSyncNode->FpEqMsg)(pSyncNode->msgcb, &rpcMsg) == 0) {
+ ret = 0;
+ } else {
+ ret = -1;
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ sError("vgId:%d, enqueue msg error, FpEqMsg is NULL", pSyncNode->vgId);
+ }
}
+
syncClientRequestDestroy(pSyncMsg);
goto _END;
} else {
ret = -1;
terrno = TSDB_CODE_SYN_NOT_LEADER;
- sError("syncPropose not leader, %s", syncUtilState2String(pSyncNode->state));
+ sError("vgId:%d, sync propose not leader, %s", pSyncNode->vgId, syncUtilState2String(pSyncNode->state));
goto _END;
}
@@ -658,7 +872,7 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
SSyncInfo* pSyncInfo = (SSyncInfo*)pOldSyncInfo;
SSyncNode* pSyncNode = (SSyncNode*)taosMemoryMalloc(sizeof(SSyncNode));
- assert(pSyncNode != NULL);
+ ASSERT(pSyncNode != NULL);
memset(pSyncNode, 0, sizeof(SSyncNode));
int32_t ret = 0;
@@ -675,15 +889,16 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
// create a new raft config file
SRaftCfgMeta meta;
meta.isStandBy = pSyncInfo->isStandBy;
- meta.snapshotEnable = pSyncInfo->snapshotEnable;
+ meta.snapshotStrategy = pSyncInfo->snapshotStrategy;
meta.lastConfigIndex = SYNC_INDEX_INVALID;
+ meta.batchSize = pSyncInfo->batchSize;
ret = raftCfgCreateFile((SSyncCfg*)&(pSyncInfo->syncCfg), meta, pSyncNode->configPath);
- assert(ret == 0);
+ ASSERT(ret == 0);
} else {
// update syncCfg by raft_config.json
pSyncNode->pRaftCfg = raftCfgOpen(pSyncNode->configPath);
- assert(pSyncNode->pRaftCfg != NULL);
+ ASSERT(pSyncNode->pRaftCfg != NULL);
pSyncInfo->syncCfg = pSyncNode->pRaftCfg->cfg;
if (gRaftDetailLog) {
@@ -708,7 +923,7 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
// init raft config
pSyncNode->pRaftCfg = raftCfgOpen(pSyncNode->configPath);
- assert(pSyncNode->pRaftCfg != NULL);
+ ASSERT(pSyncNode->pRaftCfg != NULL);
// init internal
pSyncNode->myNodeInfo = pSyncNode->pRaftCfg->cfg.nodeInfo[pSyncNode->pRaftCfg->cfg.myIndex];
@@ -767,23 +982,23 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
// init TLA+ server vars
pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER;
pSyncNode->pRaftStore = raftStoreOpen(pSyncNode->raftStorePath);
- assert(pSyncNode->pRaftStore != NULL);
+ ASSERT(pSyncNode->pRaftStore != NULL);
// init TLA+ candidate vars
pSyncNode->pVotesGranted = voteGrantedCreate(pSyncNode);
- assert(pSyncNode->pVotesGranted != NULL);
+ ASSERT(pSyncNode->pVotesGranted != NULL);
pSyncNode->pVotesRespond = votesRespondCreate(pSyncNode);
- assert(pSyncNode->pVotesRespond != NULL);
+ ASSERT(pSyncNode->pVotesRespond != NULL);
// init TLA+ leader vars
pSyncNode->pNextIndex = syncIndexMgrCreate(pSyncNode);
- assert(pSyncNode->pNextIndex != NULL);
+ ASSERT(pSyncNode->pNextIndex != NULL);
pSyncNode->pMatchIndex = syncIndexMgrCreate(pSyncNode);
- assert(pSyncNode->pMatchIndex != NULL);
+ ASSERT(pSyncNode->pMatchIndex != NULL);
// init TLA+ log vars
pSyncNode->pLogStore = logStoreCreate(pSyncNode);
- assert(pSyncNode->pLogStore != NULL);
+ ASSERT(pSyncNode->pLogStore != NULL);
pSyncNode->commitIndex = SYNC_INDEX_INVALID;
// timer ms init
@@ -824,15 +1039,15 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
pSyncNode->FpOnSnapshotSend = syncNodeOnSnapshotSendCb;
pSyncNode->FpOnSnapshotRsp = syncNodeOnSnapshotRspCb;
- if (pSyncNode->pRaftCfg->snapshotEnable) {
- sInfo("sync node use snapshot");
+ if (pSyncNode->pRaftCfg->snapshotStrategy) {
+ sInfo("vgId:%d, sync node use snapshot", pSyncNode->vgId);
pSyncNode->FpOnRequestVote = syncNodeOnRequestVoteSnapshotCb;
pSyncNode->FpOnRequestVoteReply = syncNodeOnRequestVoteReplySnapshotCb;
pSyncNode->FpOnAppendEntries = syncNodeOnAppendEntriesSnapshotCb;
pSyncNode->FpOnAppendEntriesReply = syncNodeOnAppendEntriesReplySnapshotCb;
} else {
- sInfo("sync node do not use snapshot");
+ sInfo("vgId:%d, sync node do not use snapshot", pSyncNode->vgId);
pSyncNode->FpOnRequestVote = syncNodeOnRequestVoteCb;
pSyncNode->FpOnRequestVoteReply = syncNodeOnRequestVoteReplyCb;
pSyncNode->FpOnAppendEntries = syncNodeOnAppendEntriesCb;
@@ -840,19 +1055,12 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pOldSyncInfo) {
}
// tools
- pSyncNode->pSyncRespMgr = syncRespMgrCreate(pSyncNode, 0);
- assert(pSyncNode->pSyncRespMgr != NULL);
+ pSyncNode->pSyncRespMgr = syncRespMgrCreate(pSyncNode, SYNC_RESP_TTL_MS);
+ ASSERT(pSyncNode->pSyncRespMgr != NULL);
// restore state
pSyncNode->restoreFinish = false;
- // pSyncNode->pSnapshot = NULL;
- // if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
- // pSyncNode->pSnapshot = taosMemoryMalloc(sizeof(SSnapshot));
- // pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, pSyncNode->pSnapshot);
- // }
- // tsem_init(&(pSyncNode->restoreSem), 0, 0);
-
// snapshot senders
for (int i = 0; i < TSDB_MAX_REPLICA; ++i) {
SSyncSnapshotSender* pSender = snapshotSenderCreate(pSyncNode, i);
@@ -882,18 +1090,15 @@ void syncNodeStart(SSyncNode* pSyncNode) {
syncNodeBecomeLeader(pSyncNode, "one replica start");
// Raft 3.6.2 Committing entries from previous terms
- return;
+ syncNodeAppendNoop(pSyncNode);
+ syncMaybeAdvanceCommitIndex(pSyncNode);
+ } else {
+ syncNodeBecomeFollower(pSyncNode, "first start");
}
- syncNodeBecomeFollower(pSyncNode, "first start");
-
- // int32_t ret = 0;
- // ret = syncNodeStartPingTimer(pSyncNode);
- // assert(ret == 0);
-
- if (gRaftDetailLog) {
- syncNodeLog2("==state change become leader immediately==", pSyncNode);
- }
+ int32_t ret = 0;
+ ret = syncNodeStartPingTimer(pSyncNode);
+ ASSERT(ret == 0);
}
void syncNodeStartStandBy(SSyncNode* pSyncNode) {
@@ -911,10 +1116,10 @@ void syncNodeClose(SSyncNode* pSyncNode) {
syncNodeEventLog(pSyncNode, "sync close");
int32_t ret;
- assert(pSyncNode != NULL);
+ ASSERT(pSyncNode != NULL);
ret = raftStoreClose(pSyncNode->pRaftStore);
- assert(ret == 0);
+ ASSERT(ret == 0);
syncRespMgrDestroy(pSyncNode->pSyncRespMgr);
voteGrantedDestroy(pSyncNode->pVotesGranted);
@@ -944,20 +1149,14 @@ void syncNodeClose(SSyncNode* pSyncNode) {
pSyncNode->pNewNodeReceiver = NULL;
}
- /*
- if (pSyncNode->pSnapshot != NULL) {
- taosMemoryFree(pSyncNode->pSnapshot);
- }
- */
-
- // tsem_destroy(&pSyncNode->restoreSem);
-
// free memory in syncFreeNode
// taosMemoryFree(pSyncNode);
}
// option
-bool syncNodeSnapshotEnable(SSyncNode* pSyncNode) { return pSyncNode->pRaftCfg->snapshotEnable; }
+// bool syncNodeSnapshotEnable(SSyncNode* pSyncNode) { return pSyncNode->pRaftCfg->snapshotEnable; }
+
+ESyncStrategy syncNodeStrategy(SSyncNode* pSyncNode) { return pSyncNode->pRaftCfg->snapshotStrategy; }
// ping --------------
int32_t syncNodePing(SSyncNode* pSyncNode, const SRaftId* destRaftId, SyncPing* pMsg) {
@@ -976,7 +1175,7 @@ int32_t syncNodePingSelf(SSyncNode* pSyncNode) {
int32_t ret = 0;
SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, &pSyncNode->myRaftId, pSyncNode->vgId);
ret = syncNodePing(pSyncNode, &pMsg->destId, pMsg);
- assert(ret == 0);
+ ASSERT(ret == 0);
syncPingDestroy(pMsg);
return ret;
@@ -988,7 +1187,7 @@ int32_t syncNodePingPeers(SSyncNode* pSyncNode) {
SRaftId* destId = &(pSyncNode->peersId[i]);
SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, destId, pSyncNode->vgId);
ret = syncNodePing(pSyncNode, destId, pMsg);
- assert(ret == 0);
+ ASSERT(ret == 0);
syncPingDestroy(pMsg);
}
return ret;
@@ -1000,7 +1199,7 @@ int32_t syncNodePingAll(SSyncNode* pSyncNode) {
SRaftId* destId = &(pSyncNode->replicasId[i]);
SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, destId, pSyncNode->vgId);
ret = syncNodePing(pSyncNode, destId, pMsg);
- assert(ret == 0);
+ ASSERT(ret == 0);
syncPingDestroy(pMsg);
}
return ret;
@@ -1014,7 +1213,7 @@ int32_t syncNodeStartPingTimer(SSyncNode* pSyncNode) {
&pSyncNode->pPingTimer);
atomic_store_64(&pSyncNode->pingTimerLogicClock, pSyncNode->pingTimerLogicClockUser);
} else {
- sError("sync env is stop, syncNodeStartPingTimer");
+ sError("vgId:%d, start ping timer error, sync env is stop", pSyncNode->vgId);
}
return ret;
}
@@ -1035,7 +1234,7 @@ int32_t syncNodeStartElectTimer(SSyncNode* pSyncNode, int32_t ms) {
&pSyncNode->pElectTimer);
atomic_store_64(&pSyncNode->electTimerLogicClock, pSyncNode->electTimerLogicClockUser);
} else {
- sError("sync env is stop, syncNodeStartElectTimer");
+ sError("vgId:%d, start elect timer error, sync env is stop", pSyncNode->vgId);
}
return ret;
}
@@ -1075,7 +1274,7 @@ int32_t syncNodeStartHeartbeatTimer(SSyncNode* pSyncNode) {
&pSyncNode->pHeartbeatTimer);
atomic_store_64(&pSyncNode->heartbeatTimerLogicClock, pSyncNode->heartbeatTimerLogicClockUser);
} else {
- sError("sync env is stop, syncNodeStartHeartbeatTimer");
+ sError("vgId:%d, start heartbeat timer error, sync env is stop", pSyncNode->vgId);
}
return ret;
}
@@ -1106,8 +1305,10 @@ int32_t syncNodeSendMsgById(const SRaftId* destRaftId, SSyncNode* pSyncNode, SRp
pMsg->info.noResp = 1;
pSyncNode->FpSendMsg(&epSet, pMsg);
} else {
- sTrace("syncNodeSendMsgById pSyncNode->FpSendMsg is NULL");
+ sError("vgId:%d, sync send msg by id error, fp-send-msg is null", pSyncNode->vgId);
+ return -1;
}
+
return 0;
}
@@ -1121,7 +1322,7 @@ int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, S
pMsg->info.noResp = 1;
pSyncNode->FpSendMsg(&epSet, pMsg);
} else {
- sTrace("syncNodeSendMsgByInfo pSyncNode->FpSendMsg is NULL");
+ sError("vgId:%d, sync send msg by info error, fp-send-msg is null", pSyncNode->vgId);
}
return 0;
}
@@ -1184,7 +1385,7 @@ cJSON* syncNode2Json(const SSyncNode* pSyncNode) {
cJSON_AddItemToObject(pRoot, "leaderCache", pLaderCache);
// life cycle
- snprintf(u64buf, sizeof(u64buf), "%ld", pSyncNode->rid);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pSyncNode->rid);
cJSON_AddStringToObject(pRoot, "rid", u64buf);
// tla+ server vars
@@ -1202,7 +1403,7 @@ cJSON* syncNode2Json(const SSyncNode* pSyncNode) {
// tla+ log vars
cJSON_AddItemToObject(pRoot, "pLogStore", logStore2Json(pSyncNode->pLogStore));
- snprintf(u64buf, sizeof(u64buf), "%" PRId64 "", pSyncNode->commitIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pSyncNode->commitIndex);
cJSON_AddStringToObject(pRoot, "commitIndex", u64buf);
// timer ms init
@@ -1214,39 +1415,39 @@ cJSON* syncNode2Json(const SSyncNode* pSyncNode) {
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pPingTimer);
cJSON_AddStringToObject(pRoot, "pPingTimer", u64buf);
cJSON_AddNumberToObject(pRoot, "pingTimerMS", pSyncNode->pingTimerMS);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->pingTimerLogicClock);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->pingTimerLogicClock);
cJSON_AddStringToObject(pRoot, "pingTimerLogicClock", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->pingTimerLogicClockUser);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->pingTimerLogicClockUser);
cJSON_AddStringToObject(pRoot, "pingTimerLogicClockUser", u64buf);
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpPingTimerCB);
cJSON_AddStringToObject(pRoot, "FpPingTimerCB", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->pingTimerCounter);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->pingTimerCounter);
cJSON_AddStringToObject(pRoot, "pingTimerCounter", u64buf);
// elect timer
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pElectTimer);
cJSON_AddStringToObject(pRoot, "pElectTimer", u64buf);
cJSON_AddNumberToObject(pRoot, "electTimerMS", pSyncNode->electTimerMS);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->electTimerLogicClock);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->electTimerLogicClock);
cJSON_AddStringToObject(pRoot, "electTimerLogicClock", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->electTimerLogicClockUser);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->electTimerLogicClockUser);
cJSON_AddStringToObject(pRoot, "electTimerLogicClockUser", u64buf);
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpElectTimerCB);
cJSON_AddStringToObject(pRoot, "FpElectTimerCB", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->electTimerCounter);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->electTimerCounter);
cJSON_AddStringToObject(pRoot, "electTimerCounter", u64buf);
// heartbeat timer
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pHeartbeatTimer);
cJSON_AddStringToObject(pRoot, "pHeartbeatTimer", u64buf);
cJSON_AddNumberToObject(pRoot, "heartbeatTimerMS", pSyncNode->heartbeatTimerMS);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->heartbeatTimerLogicClock);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->heartbeatTimerLogicClock);
cJSON_AddStringToObject(pRoot, "heartbeatTimerLogicClock", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->heartbeatTimerLogicClockUser);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->heartbeatTimerLogicClockUser);
cJSON_AddStringToObject(pRoot, "heartbeatTimerLogicClockUser", u64buf);
snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpHeartbeatTimerCB);
cJSON_AddStringToObject(pRoot, "FpHeartbeatTimerCB", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%" PRIu64 "", pSyncNode->heartbeatTimerCounter);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pSyncNode->heartbeatTimerCounter);
cJSON_AddStringToObject(pRoot, "heartbeatTimerCounter", u64buf);
// callback
@@ -1278,6 +1479,9 @@ cJSON* syncNode2Json(const SSyncNode* pSyncNode) {
// snapshot receivers
cJSON* pReceivers = cJSON_CreateArray();
cJSON_AddItemToObject(pRoot, "receiver", snapshotReceiver2Json(pSyncNode->pNewNodeReceiver));
+
+ // changing
+ cJSON_AddNumberToObject(pRoot, "changing", pSyncNode->changing);
}
cJSON* pJson = cJSON_CreateObject();
@@ -1296,46 +1500,153 @@ void syncNodeEventLog(const SSyncNode* pSyncNode, char* str) {
int32_t userStrLen = strlen(str);
SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
- if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
+ if (pSyncNode->pFsm != NULL && pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
}
- SyncIndex logLastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore);
+
+ SyncIndex logLastIndex = SYNC_INDEX_INVALID;
+ SyncIndex logBeginIndex = SYNC_INDEX_INVALID;
+ if (pSyncNode->pLogStore != NULL) {
+ logLastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore);
+ logBeginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore);
+ }
+
+ char* pCfgStr = syncCfg2SimpleStr(&(pSyncNode->pRaftCfg->cfg));
+ char* printStr = "";
+ if (pCfgStr != NULL) {
+ printStr = pCfgStr;
+ }
if (userStrLen < 256) {
- char logBuf[128 + 256];
- snprintf(logBuf, sizeof(logBuf),
- "vgId:%d, sync %s %s, term:%lu, commit:%ld, lastlog:%ld, lastsnapshot:%ld, standby:%d, replica-num:%d, "
- "lconfig:%ld, changing:%d",
- pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
- pSyncNode->commitIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->pRaftCfg->isStandBy,
- pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing);
+ char logBuf[256 + 256];
+ if (pSyncNode != NULL && pSyncNode->pRaftCfg != NULL && pSyncNode->pRaftStore != NULL) {
+ snprintf(logBuf, sizeof(logBuf),
+ "vgId:%d, sync %s %s, term:%" PRIu64 ", commit:%" PRId64 ", first:%" PRId64 ", last:%" PRId64
+ ", snapshot:%" PRId64
+ ", standby:%d, "
+ "strategy:%d, batch:%d, "
+ "replica-num:%d, "
+ "lconfig:%" PRId64 ", changing:%d, restore:%d, %s",
+ pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
+ pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex,
+ pSyncNode->pRaftCfg->isStandBy, pSyncNode->pRaftCfg->snapshotStrategy, pSyncNode->pRaftCfg->batchSize,
+ pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing,
+ pSyncNode->restoreFinish, printStr);
+ } else {
+ snprintf(logBuf, sizeof(logBuf), "%s", str);
+ }
sDebug("%s", logBuf);
} else {
- int len = 128 + userStrLen;
+ int len = 256 + userStrLen;
char* s = (char*)taosMemoryMalloc(len);
- snprintf(s, len,
- "vgId:%d, sync %s %s, term:%lu, commit:%ld, lastlog:%ld, lastsnapshot:%ld, standby:%d, replica-num:%d, "
- "lconfig:%ld, changing:%d",
- pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
- pSyncNode->commitIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->pRaftCfg->isStandBy,
- pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing);
+ if (pSyncNode != NULL && pSyncNode->pRaftCfg != NULL && pSyncNode->pRaftStore != NULL) {
+ snprintf(s, len,
+ "vgId:%d, sync %s %s, term:%" PRIu64 ", commit:%" PRId64 ", first:%" PRId64 ", last:%" PRId64
+ ", snapshot:%" PRId64
+ ", standby:%d, "
+ "strategy:%d, batch:%d, "
+ "replica-num:%d, "
+ "lconfig:%" PRId64 ", changing:%d, restore:%d, %s",
+ pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
+ pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex,
+ pSyncNode->pRaftCfg->isStandBy, pSyncNode->pRaftCfg->snapshotStrategy, pSyncNode->pRaftCfg->batchSize,
+ pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing,
+ pSyncNode->restoreFinish, printStr);
+ } else {
+ snprintf(s, len, "%s", str);
+ }
sDebug("%s", s);
taosMemoryFree(s);
}
+
+ taosMemoryFree(pCfgStr);
+}
+
+void syncNodeErrorLog(const SSyncNode* pSyncNode, char* str) {
+ int32_t userStrLen = strlen(str);
+
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
+ if (pSyncNode->pFsm != NULL && pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
+ pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
+ }
+
+ SyncIndex logLastIndex = SYNC_INDEX_INVALID;
+ SyncIndex logBeginIndex = SYNC_INDEX_INVALID;
+ if (pSyncNode->pLogStore != NULL) {
+ logLastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore);
+ logBeginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore);
+ }
+
+ char* pCfgStr = syncCfg2SimpleStr(&(pSyncNode->pRaftCfg->cfg));
+ char* printStr = "";
+ if (pCfgStr != NULL) {
+ printStr = pCfgStr;
+ }
+
+ if (userStrLen < 256) {
+ char logBuf[256 + 256];
+ if (pSyncNode != NULL && pSyncNode->pRaftCfg != NULL && pSyncNode->pRaftStore != NULL) {
+ snprintf(logBuf, sizeof(logBuf),
+ "vgId:%d, sync %s %s, term:%" PRIu64 ", commit:%" PRId64 ", first:%" PRId64 ", last:%" PRId64
+ ", snapshot:%" PRId64
+ ", standby:%d, "
+ "replica-num:%d, "
+ "lconfig:%" PRId64 ", changing:%d, restore:%d, %s",
+ pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
+ pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex,
+ pSyncNode->pRaftCfg->isStandBy, pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex,
+ pSyncNode->changing, pSyncNode->restoreFinish, printStr);
+ } else {
+ snprintf(logBuf, sizeof(logBuf), "%s", str);
+ }
+ sError("%s", logBuf);
+
+ } else {
+ int len = 256 + userStrLen;
+ char* s = (char*)taosMemoryMalloc(len);
+ if (pSyncNode != NULL && pSyncNode->pRaftCfg != NULL && pSyncNode->pRaftStore != NULL) {
+ snprintf(s, len,
+ "vgId:%d, sync %s %s, term:%" PRIu64 ", commit:%" PRId64 ", first:%" PRId64 ", last:%" PRId64
+ ", snapshot:%" PRId64
+ ", standby:%d, "
+ "replica-num:%d, "
+ "lconfig:%" PRId64 ", changing:%d, restore:%d, %s",
+ pSyncNode->vgId, syncUtilState2String(pSyncNode->state), str, pSyncNode->pRaftStore->currentTerm,
+ pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex,
+ pSyncNode->pRaftCfg->isStandBy, pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex,
+ pSyncNode->changing, pSyncNode->restoreFinish, printStr);
+ } else {
+ snprintf(s, len, "%s", str);
+ }
+ sError("%s", s);
+ taosMemoryFree(s);
+ }
+
+ taosMemoryFree(pCfgStr);
}
char* syncNode2SimpleStr(const SSyncNode* pSyncNode) {
int len = 256;
char* s = (char*)taosMemoryMalloc(len);
+
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
+ if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
+ pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
+ }
+ SyncIndex logLastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore);
+ SyncIndex logBeginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore);
+
snprintf(s, len,
- "syncNode: vgId:%d, currentTerm:%lu, commitIndex:%ld, state:%d %s, isStandBy:%d, "
- "electTimerLogicClock:%lu, "
- "electTimerLogicClockUser:%lu, "
- "electTimerMS:%d, replicaNum:%d",
- pSyncNode->vgId, pSyncNode->pRaftStore->currentTerm, pSyncNode->commitIndex, pSyncNode->state,
- syncUtilState2String(pSyncNode->state), pSyncNode->pRaftCfg->isStandBy, pSyncNode->electTimerLogicClock,
- pSyncNode->electTimerLogicClockUser, pSyncNode->electTimerMS, pSyncNode->replicaNum);
+ "vgId:%d, sync %s, term:%" PRIu64 ", commit:%" PRId64 ", first:%" PRId64 ", last:%" PRId64
+ ", snapshot:%" PRId64
+ ", standby:%d, "
+ "replica-num:%d, "
+ "lconfig:%" PRId64 ", changing:%d, restore:%d",
+ pSyncNode->vgId, syncUtilState2String(pSyncNode->state), pSyncNode->pRaftStore->currentTerm,
+ pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->pRaftCfg->isStandBy,
+ pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing, pSyncNode->restoreFinish);
+
return s;
}
@@ -1389,6 +1700,17 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde
isAdd = false;
}
+ // log begin config change
+ do {
+ char eventLog[256];
+ char* pOldCfgStr = syncCfg2SimpleStr(&oldConfig);
+ char* pNewCfgStr = syncCfg2SimpleStr(pNewConfig);
+ snprintf(eventLog, sizeof(eventLog), "begin do config change, from %s to %s", pOldCfgStr, pNewCfgStr);
+ syncNodeEventLog(pSyncNode, eventLog);
+ taosMemoryFree(pOldCfgStr);
+ taosMemoryFree(pNewCfgStr);
+ } while (0);
+
if (IamInNew) {
pSyncNode->pRaftCfg->isStandBy = 0; // change isStandBy to normal
}
@@ -1396,7 +1718,7 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde
pSyncNode->pRaftCfg->isStandBy = 1; // set standby
}
- // persist last config index
+ // add last config index
raftCfgAddConfigIndex(pSyncNode->pRaftCfg, lastConfigChangeIndex);
if (IamInNew) {
@@ -1465,7 +1787,7 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde
do {
char eventLog[256];
- snprintf(eventLog, sizeof(eventLog), "snapshot sender reset for %lu, newIndex:%d, %s:%d, %p",
+ snprintf(eventLog, sizeof(eventLog), "snapshot sender reset for: %" PRIu64 ", newIndex:%d, %s:%d, %p",
(pSyncNode->replicasId)[i].addr, i, host, port, oldSenders[j]);
syncNodeEventLog(pSyncNode, eventLog);
} while (0);
@@ -1521,14 +1843,20 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde
char tmpbuf[512];
char* oldStr = syncCfg2SimpleStr(&oldConfig);
char* newStr = syncCfg2SimpleStr(pNewConfig);
- snprintf(tmpbuf, sizeof(tmpbuf), "config change from %d to %d, index:%ld, %s --> %s", oldConfig.replicaNum,
- pNewConfig->replicaNum, lastConfigChangeIndex, oldStr, newStr);
+ snprintf(tmpbuf, sizeof(tmpbuf), "config change from %d to %d, index:%" PRId64 ", %s --> %s",
+ oldConfig.replicaNum, pNewConfig->replicaNum, lastConfigChangeIndex, oldStr, newStr);
taosMemoryFree(oldStr);
taosMemoryFree(newStr);
// change isStandBy to normal (election timeout)
if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) {
syncNodeBecomeLeader(pSyncNode, tmpbuf);
+
+ // Raft 3.6.2 Committing entries from previous terms
+ syncNodeReplicate(pSyncNode);
+ syncNodeAppendNoop(pSyncNode);
+ syncMaybeAdvanceCommitIndex(pSyncNode);
+
} else {
syncNodeBecomeFollower(pSyncNode, tmpbuf);
}
@@ -1539,14 +1867,25 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde
char tmpbuf[512];
char* oldStr = syncCfg2SimpleStr(&oldConfig);
char* newStr = syncCfg2SimpleStr(pNewConfig);
- snprintf(tmpbuf, sizeof(tmpbuf), "do not config change from %d to %d, index:%ld, %s --> %s", oldConfig.replicaNum,
- pNewConfig->replicaNum, lastConfigChangeIndex, oldStr, newStr);
+ snprintf(tmpbuf, sizeof(tmpbuf), "do not config change from %d to %d, index:%" PRId64 ", %s --> %s",
+ oldConfig.replicaNum, pNewConfig->replicaNum, lastConfigChangeIndex, oldStr, newStr);
taosMemoryFree(oldStr);
taosMemoryFree(newStr);
syncNodeEventLog(pSyncNode, tmpbuf);
}
_END:
+
+ // log end config change
+ do {
+ char eventLog[256];
+ char* pOldCfgStr = syncCfg2SimpleStr(&oldConfig);
+ char* pNewCfgStr = syncCfg2SimpleStr(pNewConfig);
+ snprintf(eventLog, sizeof(eventLog), "end do config change, from %s to %s", pOldCfgStr, pNewCfgStr);
+ syncNodeEventLog(pSyncNode, eventLog);
+ taosMemoryFree(pOldCfgStr);
+ taosMemoryFree(pNewCfgStr);
+ } while (0);
return;
}
@@ -1566,7 +1905,7 @@ void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term) {
if (term > pSyncNode->pRaftStore->currentTerm) {
raftStoreSetTerm(pSyncNode->pRaftStore, term);
char tmpBuf[64];
- snprintf(tmpBuf, sizeof(tmpBuf), "update term to %lu", term);
+ snprintf(tmpBuf, sizeof(tmpBuf), "update term to %" PRIu64, term);
syncNodeBecomeFollower(pSyncNode, tmpBuf);
raftStoreClearVote(pSyncNode->pRaftStore);
}
@@ -1663,16 +2002,9 @@ void syncNodeBecomeLeader(SSyncNode* pSyncNode, const char* debugStr) {
// stop elect timer
syncNodeStopElectTimer(pSyncNode);
- // start replicate right now!
- syncNodeReplicate(pSyncNode);
-
// start heartbeat timer
syncNodeStartHeartbeatTimer(pSyncNode);
- // append noop
- syncNodeAppendNoop(pSyncNode);
- syncMaybeAdvanceCommitIndex(pSyncNode); // maybe only one replica
-
// trace log
do {
int32_t debugStrLen = strlen(debugStr);
@@ -1690,34 +2022,34 @@ void syncNodeBecomeLeader(SSyncNode* pSyncNode, const char* debugStr) {
}
void syncNodeCandidate2Leader(SSyncNode* pSyncNode) {
- assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
- assert(voteGrantedMajority(pSyncNode->pVotesGranted));
+ ASSERT(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
+ ASSERT(voteGrantedMajority(pSyncNode->pVotesGranted));
syncNodeBecomeLeader(pSyncNode, "candidate to leader");
syncNodeLog2("==state change syncNodeCandidate2Leader==", pSyncNode);
// Raft 3.6.2 Committing entries from previous terms
-
- // do not use this
- // syncNodeEqNoop(pSyncNode);
+ syncNodeReplicate(pSyncNode);
+ syncNodeAppendNoop(pSyncNode);
+ syncMaybeAdvanceCommitIndex(pSyncNode);
}
void syncNodeFollower2Candidate(SSyncNode* pSyncNode) {
- assert(pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER);
+ ASSERT(pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER);
pSyncNode->state = TAOS_SYNC_STATE_CANDIDATE;
syncNodeLog2("==state change syncNodeFollower2Candidate==", pSyncNode);
}
void syncNodeLeader2Follower(SSyncNode* pSyncNode) {
- assert(pSyncNode->state == TAOS_SYNC_STATE_LEADER);
+ ASSERT(pSyncNode->state == TAOS_SYNC_STATE_LEADER);
syncNodeBecomeFollower(pSyncNode, "leader to follower");
syncNodeLog2("==state change syncNodeLeader2Follower==", pSyncNode);
}
void syncNodeCandidate2Follower(SSyncNode* pSyncNode) {
- assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
+ ASSERT(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE);
syncNodeBecomeFollower(pSyncNode, "candidate to follower");
syncNodeLog2("==state change syncNodeCandidate2Follower==", pSyncNode);
@@ -1728,8 +2060,8 @@ void syncNodeCandidate2Follower(SSyncNode* pSyncNode) {
// just called by syncNodeVoteForSelf
// need assert
void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) {
- assert(term == pSyncNode->pRaftStore->currentTerm);
- assert(!raftStoreHasVoted(pSyncNode->pRaftStore));
+ ASSERT(term == pSyncNode->pRaftStore->currentTerm);
+ ASSERT(!raftStoreHasVoted(pSyncNode->pRaftStore));
raftStoreVote(pSyncNode->pRaftStore, pRaftId);
}
@@ -1750,9 +2082,11 @@ void syncNodeVoteForSelf(SSyncNode* pSyncNode) {
}
// snapshot --------------
+
+// return if has a snapshot
bool syncNodeHasSnapshot(SSyncNode* pSyncNode) {
bool ret = false;
- SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0, .lastConfigIndex = -1};
if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
if (snapshot.lastApplyIndex >= SYNC_INDEX_BEGIN) {
@@ -1762,19 +2096,10 @@ bool syncNodeHasSnapshot(SSyncNode* pSyncNode) {
return ret;
}
-bool syncNodeIsIndexInSnapshot(SSyncNode* pSyncNode, SyncIndex index) {
- ASSERT(syncNodeHasSnapshot(pSyncNode));
- ASSERT(pSyncNode->pFsm->FpGetSnapshotInfo != NULL);
- ASSERT(index >= SYNC_INDEX_BEGIN);
-
- SSnapshot snapshot;
- pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
- bool b = (index <= snapshot.lastApplyIndex);
- return b;
-}
-
+// return max(logLastIndex, snapshotLastIndex)
+// if no snapshot and log, return -1
SyncIndex syncNodeGetLastIndex(SSyncNode* pSyncNode) {
- SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0, .lastConfigIndex = -1};
if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
}
@@ -1784,11 +2109,13 @@ SyncIndex syncNodeGetLastIndex(SSyncNode* pSyncNode) {
return lastIndex;
}
+// return the last term of snapshot and log
+// if error, return SYNC_TERM_INVALID (by syncLogLastTerm)
SyncTerm syncNodeGetLastTerm(SSyncNode* pSyncNode) {
SyncTerm lastTerm = 0;
if (syncNodeHasSnapshot(pSyncNode)) {
// has snapshot
- SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0, .lastConfigIndex = -1};
if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
}
@@ -1815,78 +2142,62 @@ int32_t syncNodeGetLastIndexTerm(SSyncNode* pSyncNode, SyncIndex* pLastIndex, Sy
return 0;
}
+// return append-entries first try index
SyncIndex syncNodeSyncStartIndex(SSyncNode* pSyncNode) {
SyncIndex syncStartIndex = syncNodeGetLastIndex(pSyncNode) + 1;
return syncStartIndex;
}
+// if index > 0, return index - 1
+// else, return -1
SyncIndex syncNodeGetPreIndex(SSyncNode* pSyncNode, SyncIndex index) {
- ASSERT(index >= SYNC_INDEX_BEGIN);
- SyncIndex syncStartIndex = syncNodeSyncStartIndex(pSyncNode);
- ASSERT(index <= syncStartIndex);
-
SyncIndex preIndex = index - 1;
+ if (preIndex < SYNC_INDEX_INVALID) {
+ preIndex = SYNC_INDEX_INVALID;
+ }
+
return preIndex;
}
+// if index < 0, return SYNC_TERM_INVALID
+// if index == 0, return 0
+// if index > 0, return preTerm
+// if error, return SYNC_TERM_INVALID
SyncTerm syncNodeGetPreTerm(SSyncNode* pSyncNode, SyncIndex index) {
- ASSERT(index >= SYNC_INDEX_BEGIN);
- SyncIndex syncStartIndex = syncNodeSyncStartIndex(pSyncNode);
- ASSERT(index <= syncStartIndex);
+ if (index < SYNC_INDEX_BEGIN) {
+ return SYNC_TERM_INVALID;
+ }
if (index == SYNC_INDEX_BEGIN) {
return 0;
}
- SyncTerm preTerm = 0;
- if (syncNodeHasSnapshot(pSyncNode)) {
- // has snapshot
- SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0};
- if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
- pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
- }
-
- if (index > snapshot.lastApplyIndex + 1) {
- // should be log preTerm
- SSyncRaftEntry* pPreEntry = NULL;
- int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, index - 1, &pPreEntry);
- ASSERT(code == 0);
- ASSERT(pPreEntry != NULL);
-
- preTerm = pPreEntry->term;
- taosMemoryFree(pPreEntry);
-
- } else if (index == snapshot.lastApplyIndex + 1) {
- preTerm = snapshot.lastApplyTerm;
-
- } else {
- // maybe snapshot change
- sError("sync get pre term, bad scene. index:%ld", index);
- logStoreLog2("sync get pre term, bad scene", pSyncNode->pLogStore);
-
- SSyncRaftEntry* pPreEntry = NULL;
- int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, index - 1, &pPreEntry);
- ASSERT(code == 0);
- ASSERT(pPreEntry != NULL);
-
- preTerm = pPreEntry->term;
- taosMemoryFree(pPreEntry);
- }
-
- } else {
- // no snapshot
- ASSERT(index > SYNC_INDEX_BEGIN);
-
- SSyncRaftEntry* pPreEntry = NULL;
- int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, index - 1, &pPreEntry);
- ASSERT(code == 0);
+ SyncTerm preTerm = 0;
+ SyncIndex preIndex = index - 1;
+ SSyncRaftEntry* pPreEntry = NULL;
+ int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, preIndex, &pPreEntry);
+ if (code == 0) {
ASSERT(pPreEntry != NULL);
-
preTerm = pPreEntry->term;
taosMemoryFree(pPreEntry);
+ return preTerm;
+ } else {
+ SSnapshot snapshot = {.data = NULL, .lastApplyIndex = -1, .lastApplyTerm = 0, .lastConfigIndex = -1};
+ if (pSyncNode->pFsm->FpGetSnapshotInfo != NULL) {
+ pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
+ if (snapshot.lastApplyIndex == preIndex) {
+ return snapshot.lastApplyTerm;
+ }
+ }
}
- return preTerm;
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "sync node get pre term error, index:%" PRId64, index);
+ syncNodeErrorLog(pSyncNode, logBuf);
+ } while (0);
+
+ return SYNC_TERM_INVALID;
}
// get pre index and term of "index"
@@ -1899,32 +2210,38 @@ int32_t syncNodeGetPreIndexTerm(SSyncNode* pSyncNode, SyncIndex index, SyncIndex
// for debug --------------
void syncNodePrint(SSyncNode* pObj) {
char* serialized = syncNode2Str(pObj);
- printf("syncNodePrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncNodePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncNodePrint2(char* s, SSyncNode* pObj) {
char* serialized = syncNode2Str(pObj);
- printf("syncNodePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncNodePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncNodeLog(SSyncNode* pObj) {
char* serialized = syncNode2Str(pObj);
- sTraceLong("syncNodeLog | len:%lu | %s", strlen(serialized), serialized);
+ sTraceLong("syncNodeLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncNodeLog2(char* s, SSyncNode* pObj) {
if (gRaftDetailLog) {
char* serialized = syncNode2Str(pObj);
- sTraceLong("syncNodeLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTraceLong("syncNodeLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
+void syncNodeLog3(char* s, SSyncNode* pObj) {
+ char* serialized = syncNode2Str(pObj);
+ sTraceLong("syncNodeLog3 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
+ taosMemoryFree(serialized);
+}
+
// ------ local funciton ---------
// enqueue message ----
static void syncNodeEqPingTimer(void* param, void* tmrId) {
@@ -1956,7 +2273,7 @@ static void syncNodeEqPingTimer(void* param, void* tmrId) {
}
} else {
- sTrace("==syncNodeEqPingTimer== pingTimerLogicClock:%" PRIu64 ", pingTimerLogicClockUser:%" PRIu64 "",
+ sTrace("==syncNodeEqPingTimer== pingTimerLogicClock:%" PRIu64 ", pingTimerLogicClockUser:%" PRIu64,
pSyncNode->pingTimerLogicClock, pSyncNode->pingTimerLogicClockUser);
}
}
@@ -1991,7 +2308,7 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) {
sError("sync env is stop, syncNodeEqElectTimer");
}
} else {
- sTrace("==syncNodeEqElectTimer== electTimerLogicClock:%" PRIu64 ", electTimerLogicClockUser:%" PRIu64 "",
+ sTrace("==syncNodeEqElectTimer== electTimerLogicClock:%" PRIu64 ", electTimerLogicClockUser:%" PRIu64,
pSyncNode->electTimerLogicClock, pSyncNode->electTimerLogicClockUser);
}
}
@@ -2036,17 +2353,17 @@ static void syncNodeEqHeartbeatTimer(void* param, void* tmrId) {
static int32_t syncNodeEqNoop(SSyncNode* ths) {
int32_t ret = 0;
- assert(ths->state == TAOS_SYNC_STATE_LEADER);
+ ASSERT(ths->state == TAOS_SYNC_STATE_LEADER);
- SyncIndex index = ths->pLogStore->getLastIndex(ths->pLogStore) + 1;
+ SyncIndex index = ths->pLogStore->syncLogWriteIndex(ths->pLogStore);
SyncTerm term = ths->pRaftStore->currentTerm;
SSyncRaftEntry* pEntry = syncEntryBuildNoop(term, index, ths->vgId);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
uint32_t entryLen;
char* serialized = syncEntrySerialize(pEntry, &entryLen);
SyncClientRequest* pSyncMsg = syncClientRequestBuild(entryLen);
- assert(pSyncMsg->dataLen == entryLen);
+ ASSERT(pSyncMsg->dataLen == entryLen);
memcpy(pSyncMsg->data, serialized, entryLen);
SRpcMsg rpcMsg = {0};
@@ -2066,14 +2383,14 @@ static int32_t syncNodeEqNoop(SSyncNode* ths) {
static int32_t syncNodeAppendNoop(SSyncNode* ths) {
int32_t ret = 0;
- SyncIndex index = ths->pLogStore->getLastIndex(ths->pLogStore) + 1;
+ SyncIndex index = ths->pLogStore->syncLogWriteIndex(ths->pLogStore);
SyncTerm term = ths->pRaftStore->currentTerm;
SSyncRaftEntry* pEntry = syncEntryBuildNoop(term, index, ths->vgId);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
if (ths->state == TAOS_SYNC_STATE_LEADER) {
- // ths->pLogStore->appendEntry(ths->pLogStore, pEntry);
- ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry);
+ int32_t code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry);
+ ASSERT(code == 0);
syncNodeReplicate(ths);
}
@@ -2086,8 +2403,9 @@ int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg) {
// log state
char logBuf[1024] = {0};
snprintf(logBuf, sizeof(logBuf),
- "==syncNodeOnPingCb== vgId:%d, state: %d, %s, term:%lu electTimerLogicClock:%lu, "
- "electTimerLogicClockUser:%lu, electTimerMS:%d",
+ "==syncNodeOnPingCb== vgId:%d, state: %d, %s, term:%" PRIu64 " electTimerLogicClock:%" PRIu64
+ ", "
+ "electTimerLogicClockUser:%" PRIu64 ", electTimerMS:%d",
ths->vgId, ths->state, syncUtilState2String(ths->state), ths->pRaftStore->currentTerm,
ths->electTimerLogicClock, ths->electTimerLogicClockUser, ths->electTimerMS);
@@ -2125,28 +2443,35 @@ int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg) {
// /\ UNCHANGED <>
//
-int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg) {
+int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg, SyncIndex* pRetIndex) {
int32_t ret = 0;
+ int32_t code = 0;
syncClientRequestLog2("==syncNodeOnClientRequestCb==", pMsg);
SyncIndex index = ths->pLogStore->syncLogWriteIndex(ths->pLogStore);
SyncTerm term = ths->pRaftStore->currentTerm;
SSyncRaftEntry* pEntry = syncEntryBuild2((SyncClientRequest*)pMsg, term, index);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
if (ths->state == TAOS_SYNC_STATE_LEADER) {
- // ths->pLogStore->appendEntry(ths->pLogStore, pEntry);
- ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry);
+ // append entry
+ code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry);
+ if (code != 0) {
+ // del resp mgr, call FpCommitCb
+ ASSERT(0);
+ return -1;
+ }
- // start replicate right now!
- syncNodeReplicate(ths);
+ // if mulit replica, start replicate right now
+ if (ths->replicaNum > 1) {
+ syncNodeReplicate(ths);
+ }
// pre commit
SRpcMsg rpcMsg;
syncEntry2OriginalRpc(pEntry, &rpcMsg);
if (ths->pFsm != NULL) {
- // if (ths->pFsm->FpPreCommitCb != NULL && pEntry->originalRpcType != TDMT_SYNC_NOOP) {
if (ths->pFsm->FpPreCommitCb != NULL && syncUtilUserPreCommit(pEntry->originalRpcType)) {
SFsmCbMeta cbMeta = {0};
cbMeta.index = pEntry->index;
@@ -2160,8 +2485,10 @@ int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg) {
}
rpcFreeCont(rpcMsg.pCont);
- // only myself, maybe commit
- syncMaybeAdvanceCommitIndex(ths);
+ // if only myself, maybe commit right now
+ if (ths->replicaNum == 1) {
+ syncMaybeAdvanceCommitIndex(ths);
+ }
} else {
// pre commit
@@ -2169,7 +2496,6 @@ int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg) {
syncEntry2OriginalRpc(pEntry, &rpcMsg);
if (ths->pFsm != NULL) {
- // if (ths->pFsm->FpPreCommitCb != NULL && pEntry->originalRpcType != TDMT_SYNC_NOOP) {
if (ths->pFsm->FpPreCommitCb != NULL && syncUtilUserPreCommit(pEntry->originalRpcType)) {
SFsmCbMeta cbMeta = {0};
cbMeta.index = pEntry->index;
@@ -2184,10 +2510,73 @@ int32_t syncNodeOnClientRequestCb(SSyncNode* ths, SyncClientRequest* pMsg) {
rpcFreeCont(rpcMsg.pCont);
}
+ if (pRetIndex != NULL) {
+ if (ret == 0 && pEntry != NULL) {
+ *pRetIndex = pEntry->index;
+ } else {
+ *pRetIndex = SYNC_INDEX_INVALID;
+ }
+ }
+
syncEntryDestory(pEntry);
return ret;
}
+int32_t syncNodeOnClientRequestBatchCb(SSyncNode* ths, SyncClientRequestBatch* pMsg) {
+ int32_t code = 0;
+
+ if (ths->state != TAOS_SYNC_STATE_LEADER) {
+ // call FpCommitCb, delete resp mgr
+ return -1;
+ }
+
+ SyncIndex index = ths->pLogStore->syncLogWriteIndex(ths->pLogStore);
+ SyncTerm term = ths->pRaftStore->currentTerm;
+
+ int32_t raftMetaArrayLen = sizeof(SRaftMeta) * pMsg->dataCount;
+ int32_t rpcArrayLen = sizeof(SRpcMsg) * pMsg->dataCount;
+ SRaftMeta* raftMetaArr = (SRaftMeta*)(pMsg->data);
+ SRpcMsg* msgArr = (SRpcMsg*)((char*)(pMsg->data) + raftMetaArrayLen);
+ for (int32_t i = 0; i < pMsg->dataCount; ++i) {
+ SSyncRaftEntry* pEntry = syncEntryBuild(msgArr[i].contLen);
+ ASSERT(pEntry != NULL);
+
+ pEntry->originalRpcType = msgArr[i].msgType;
+ pEntry->seqNum = raftMetaArr[i].seqNum;
+ pEntry->isWeak = raftMetaArr[i].isWeak;
+ pEntry->term = term;
+ pEntry->index = index;
+ memcpy(pEntry->data, msgArr[i].pCont, msgArr[i].contLen);
+ ASSERT(msgArr[i].contLen == pEntry->dataLen);
+
+ code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry);
+ if (code != 0) {
+ // del resp mgr, call FpCommitCb
+ ASSERT(0);
+ return -1;
+ }
+
+ // update rpc msg conn apply.index
+ msgArr[i].info.conn.applyIndex = pEntry->index;
+ }
+
+ // fsync once
+ SSyncLogStoreData* pData = ths->pLogStore->data;
+ SWal* pWal = pData->pWal;
+ walFsync(pWal, true);
+
+ if (ths->replicaNum > 1) {
+ // if multi replica, start replicate right now
+ syncNodeReplicate(ths);
+
+ } else if (ths->replicaNum == 1) {
+ // one replica
+ syncMaybeAdvanceCommitIndex(ths);
+ }
+
+ return 0;
+}
+
static void syncFreeNode(void* param) {
SSyncNode* pNode = param;
// inner object already free
@@ -2212,7 +2601,7 @@ const char* syncStr(ESyncState state) {
static int32_t syncDoLeaderTransfer(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyncRaftEntry* pEntry) {
SyncLeaderTransfer* pSyncLeaderTransfer = syncLeaderTransferFromRpcMsg2(pRpcMsg);
- syncNodeEventLog(ths, "begin leader transfer");
+ syncNodeEventLog(ths, "do leader transfer");
bool sameId = syncUtilSameId(&(pSyncLeaderTransfer->newLeaderId), &(ths->myRaftId));
bool sameNodeInfo = strcmp(pSyncLeaderTransfer->newNodeInfo.nodeFqdn, ths->myNodeInfo.nodeFqdn) == 0 &&
@@ -2226,7 +2615,7 @@ static int32_t syncDoLeaderTransfer(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyncRaftE
ASSERT(ret == 0);
char eventLog[256];
- snprintf(eventLog, sizeof(eventLog), "maybe leader transfer to %s:%d %lu",
+ snprintf(eventLog, sizeof(eventLog), "maybe leader transfer to %s:%d %" PRIu64,
pSyncLeaderTransfer->newNodeInfo.nodeFqdn, pSyncLeaderTransfer->newNodeInfo.nodePort,
pSyncLeaderTransfer->newLeaderId.addr);
syncNodeEventLog(ths, eventLog);
@@ -2290,13 +2679,13 @@ static int32_t syncNodeConfigChangeFinish(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyn
ths->pFsm->FpReConfigCb(ths->pFsm, pRpcMsg, cbMeta);
}
- // update changing
+ // clear changing
ths->changing = false;
char tmpbuf[512];
char* oldStr = syncCfg2SimpleStr(&(pFinish->oldCfg));
char* newStr = syncCfg2SimpleStr(&(pFinish->newCfg));
- snprintf(tmpbuf, sizeof(tmpbuf), "config change finish from %d to %d, index:%ld, %s --> %s",
+ snprintf(tmpbuf, sizeof(tmpbuf), "config change finish from %d to %d, index:%" PRId64 ", %s --> %s",
pFinish->oldCfg.replicaNum, pFinish->newCfg.replicaNum, pFinish->newCfgIndex, oldStr, newStr);
taosMemoryFree(oldStr);
taosMemoryFree(newStr);
@@ -2309,6 +2698,9 @@ static int32_t syncNodeConfigChangeFinish(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyn
static int32_t syncNodeConfigChange(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyncRaftEntry* pEntry,
SyncReconfigFinish* pFinish) {
+ // set changing
+ ths->changing = true;
+
// old config
SSyncCfg oldSyncCfg = ths->pRaftCfg->cfg;
@@ -2345,12 +2737,16 @@ static int32_t syncNodeProposeConfigChangeFinish(SSyncNode* ths, SyncReconfigFin
return 0;
}
+bool syncNodeIsOptimizedOneReplica(SSyncNode* ths, SRpcMsg* pMsg) {
+ return (ths->replicaNum == 1 && syncUtilUserCommit(pMsg->msgType) && ths->vgId != 1);
+}
+
int32_t syncNodeCommit(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex, uint64_t flag) {
int32_t code = 0;
ESyncState state = flag;
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "commit by wal from index:%ld to index:%ld", beginIndex, endIndex);
+ snprintf(eventLog, sizeof(eventLog), "commit by wal from index:%" PRId64 " to index:%" PRId64, beginIndex, endIndex);
syncNodeEventLog(ths, eventLog);
// execute fsm
@@ -2366,19 +2762,33 @@ int32_t syncNodeCommit(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex,
syncEntry2OriginalRpc(pEntry, &rpcMsg);
// user commit
- if (ths->pFsm->FpCommitCb != NULL && syncUtilUserCommit(pEntry->originalRpcType)) {
- SFsmCbMeta cbMeta = {0};
- cbMeta.index = pEntry->index;
- cbMeta.lastConfigIndex = syncNodeGetSnapshotConfigIndex(ths, cbMeta.index);
- cbMeta.isWeak = pEntry->isWeak;
- cbMeta.code = 0;
- cbMeta.state = ths->state;
- cbMeta.seqNum = pEntry->seqNum;
- cbMeta.term = pEntry->term;
- cbMeta.currentTerm = ths->pRaftStore->currentTerm;
- cbMeta.flag = flag;
-
- ths->pFsm->FpCommitCb(ths->pFsm, &rpcMsg, cbMeta);
+ if ((ths->pFsm->FpCommitCb != NULL) && syncUtilUserCommit(pEntry->originalRpcType)) {
+ bool internalExecute = true;
+ if ((ths->replicaNum == 1) && ths->restoreFinish && (ths->vgId != 1)) {
+ internalExecute = false;
+ }
+
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "index:%" PRId64 ", internalExecute:%d", i, internalExecute);
+ syncNodeEventLog(ths, logBuf);
+ } while (0);
+
+ // execute fsm in apply thread, or execute outside syncPropose
+ if (internalExecute) {
+ SFsmCbMeta cbMeta = {0};
+ cbMeta.index = pEntry->index;
+ cbMeta.lastConfigIndex = syncNodeGetSnapshotConfigIndex(ths, cbMeta.index);
+ cbMeta.isWeak = pEntry->isWeak;
+ cbMeta.code = 0;
+ cbMeta.state = ths->state;
+ cbMeta.seqNum = pEntry->seqNum;
+ cbMeta.term = pEntry->term;
+ cbMeta.currentTerm = ths->pRaftStore->currentTerm;
+ cbMeta.flag = flag;
+
+ ths->pFsm->FpCommitCb(ths->pFsm, &rpcMsg, cbMeta);
+ }
}
// config change
@@ -2417,7 +2827,7 @@ int32_t syncNodeCommit(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex,
ths->restoreFinish = true;
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "restore finish, index:%ld", pEntry->index);
+ snprintf(eventLog, sizeof(eventLog), "restore finish, index:%" PRId64, pEntry->index);
syncNodeEventLog(ths, eventLog);
}
}
diff --git a/source/libs/sync/src/syncMessage.c b/source/libs/sync/src/syncMessage.c
index 454609009c8ecd3dfee235c5ea87ecd2a49c0fe2..42a3290d5ba2d2b0effb655c4aa66f5539e89b86 100644
--- a/source/libs/sync/src/syncMessage.c
+++ b/source/libs/sync/src/syncMessage.c
@@ -15,6 +15,7 @@
#include "syncMessage.h"
#include "syncRaftCfg.h"
+#include "syncRaftEntry.h"
#include "syncUtil.h"
#include "tcoding.h"
@@ -132,28 +133,28 @@ char* syncRpcMsg2Str(SRpcMsg* pRpcMsg) {
// for debug ----------------------
void syncRpcMsgPrint(SRpcMsg* pMsg) {
char* serialized = syncRpcMsg2Str(pMsg);
- printf("syncRpcMsgPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncRpcMsgPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRpcMsgPrint2(char* s, SRpcMsg* pMsg) {
char* serialized = syncRpcMsg2Str(pMsg);
- printf("syncRpcMsgPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncRpcMsgPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRpcMsgLog(SRpcMsg* pMsg) {
char* serialized = syncRpcMsg2Str(pMsg);
- sTrace("syncRpcMsgLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncRpcMsgLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncRpcMsgLog2(char* s, SRpcMsg* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncRpcMsg2Str(pMsg);
- sTrace("syncRpcMsgLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncRpcMsgLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -186,18 +187,18 @@ void syncTimeoutDestroy(SyncTimeout* pMsg) {
}
void syncTimeoutSerialize(const SyncTimeout* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncTimeoutDeserialize(const char* buf, uint32_t len, SyncTimeout* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncTimeoutSerialize2(const SyncTimeout* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncTimeoutSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -208,9 +209,9 @@ char* syncTimeoutSerialize2(const SyncTimeout* pMsg, uint32_t* len) {
SyncTimeout* syncTimeoutDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncTimeout* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncTimeoutDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -228,7 +229,7 @@ void syncTimeoutFromRpcMsg(const SRpcMsg* pRpcMsg, SyncTimeout* pMsg) {
SyncTimeout* syncTimeoutFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncTimeout* pMsg = syncTimeoutDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -241,7 +242,7 @@ cJSON* syncTimeout2Json(const SyncTimeout* pMsg) {
cJSON_AddNumberToObject(pRoot, "vgId", pMsg->vgId);
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON_AddNumberToObject(pRoot, "timeoutType", pMsg->timeoutType);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->logicClock);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->logicClock);
cJSON_AddStringToObject(pRoot, "logicClock", u64buf);
cJSON_AddNumberToObject(pRoot, "timerMS", pMsg->timerMS);
snprintf(u64buf, sizeof(u64buf), "%p", pMsg->data);
@@ -270,21 +271,21 @@ void syncTimeoutPrint(const SyncTimeout* pMsg) {
void syncTimeoutPrint2(char* s, const SyncTimeout* pMsg) {
char* serialized = syncTimeout2Str(pMsg);
- printf("syncTimeoutPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncTimeoutPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncTimeoutLog(const SyncTimeout* pMsg) {
char* serialized = syncTimeout2Str(pMsg);
- sTrace("syncTimeoutLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncTimeoutLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncTimeoutLog2(char* s, const SyncTimeout* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncTimeout2Str(pMsg);
- sTrace("syncTimeoutLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncTimeoutLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -322,19 +323,19 @@ void syncPingDestroy(SyncPing* pMsg) {
}
void syncPingSerialize(const SyncPing* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncPingDeserialize(const char* buf, uint32_t len, SyncPing* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
- assert(pMsg->bytes == sizeof(SyncPing) + pMsg->dataLen);
+ ASSERT(len == pMsg->bytes);
+ ASSERT(pMsg->bytes == sizeof(SyncPing) + pMsg->dataLen);
}
char* syncPingSerialize2(const SyncPing* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncPingSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -345,9 +346,9 @@ char* syncPingSerialize2(const SyncPing* pMsg, uint32_t* len) {
SyncPing* syncPingDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncPing* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncPingDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -406,7 +407,7 @@ SyncPing* syncPingDeserialize3(void* buf, int32_t bufLen) {
}
pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
pMsg->bytes = bytes;
if (tDecodeI32(&decoder, &pMsg->vgId) < 0) {
@@ -435,7 +436,7 @@ SyncPing* syncPingDeserialize3(void* buf, int32_t bufLen) {
if (tDecodeBinary(&decoder, (uint8_t**)(&data), &len) < 0) {
return NULL;
}
- assert(len = pMsg->dataLen);
+ ASSERT(len = pMsg->dataLen);
memcpy(pMsg->data, data, len);
tEndDecode(&decoder);
@@ -457,7 +458,7 @@ void syncPingFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPing* pMsg) {
SyncPing* syncPingFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncPing* pMsg = syncPingDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -471,7 +472,7 @@ cJSON* syncPing2Json(const SyncPing* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -486,7 +487,7 @@ cJSON* syncPing2Json(const SyncPing* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -525,28 +526,28 @@ char* syncPing2Str(const SyncPing* pMsg) {
// for debug ----------------------
void syncPingPrint(const SyncPing* pMsg) {
char* serialized = syncPing2Str(pMsg);
- printf("syncPingPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncPingPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncPingPrint2(char* s, const SyncPing* pMsg) {
char* serialized = syncPing2Str(pMsg);
- printf("syncPingPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncPingPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncPingLog(const SyncPing* pMsg) {
char* serialized = syncPing2Str(pMsg);
- sTrace("syncPingLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncPingLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncPingLog2(char* s, const SyncPing* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncPing2Str(pMsg);
- sTrace("syncPingLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncPingLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -584,19 +585,19 @@ void syncPingReplyDestroy(SyncPingReply* pMsg) {
}
void syncPingReplySerialize(const SyncPingReply* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncPingReplyDeserialize(const char* buf, uint32_t len, SyncPingReply* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
- assert(pMsg->bytes == sizeof(SyncPing) + pMsg->dataLen);
+ ASSERT(len == pMsg->bytes);
+ ASSERT(pMsg->bytes == sizeof(SyncPingReply) + pMsg->dataLen);
}
char* syncPingReplySerialize2(const SyncPingReply* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncPingReplySerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -607,9 +608,9 @@ char* syncPingReplySerialize2(const SyncPingReply* pMsg, uint32_t* len) {
SyncPingReply* syncPingReplyDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncPingReply* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncPingReplyDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -668,7 +669,7 @@ SyncPingReply* syncPingReplyDeserialize3(void* buf, int32_t bufLen) {
}
pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
pMsg->bytes = bytes;
if (tDecodeI32(&decoder, &pMsg->vgId) < 0) {
@@ -697,7 +698,7 @@ SyncPingReply* syncPingReplyDeserialize3(void* buf, int32_t bufLen) {
if (tDecodeBinary(&decoder, (uint8_t**)(&data), &len) < 0) {
return NULL;
}
- assert(len = pMsg->dataLen);
+ ASSERT(len = pMsg->dataLen);
memcpy(pMsg->data, data, len);
tEndDecode(&decoder);
@@ -719,7 +720,7 @@ void syncPingReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPingReply* pMsg) {
SyncPingReply* syncPingReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncPingReply* pMsg = syncPingReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -733,7 +734,7 @@ cJSON* syncPingReply2Json(const SyncPingReply* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -748,7 +749,7 @@ cJSON* syncPingReply2Json(const SyncPingReply* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -844,18 +845,18 @@ void syncClientRequestDestroy(SyncClientRequest* pMsg) {
}
void syncClientRequestSerialize(const SyncClientRequest* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncClientRequestDeserialize(const char* buf, uint32_t len, SyncClientRequest* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncClientRequestSerialize2(const SyncClientRequest* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncClientRequestSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -866,9 +867,9 @@ char* syncClientRequestSerialize2(const SyncClientRequest* pMsg, uint32_t* len)
SyncClientRequest* syncClientRequestDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncClientRequest* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncClientRequestDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -888,7 +889,7 @@ void syncClientRequestFromRpcMsg(const SRpcMsg* pRpcMsg, SyncClientRequest* pMsg
// step 3. RpcMsg => SyncClientRequest, from queue
SyncClientRequest* syncClientRequestFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncClientRequest* pMsg = syncClientRequestDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -901,7 +902,7 @@ cJSON* syncClientRequest2Json(const SyncClientRequest* pMsg) {
cJSON_AddNumberToObject(pRoot, "vgId", pMsg->vgId);
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON_AddNumberToObject(pRoot, "originalRpcType", pMsg->originalRpcType);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->seqNum);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->seqNum);
cJSON_AddStringToObject(pRoot, "seqNum", u64buf);
cJSON_AddNumberToObject(pRoot, "isWeak", pMsg->isWeak);
cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen);
@@ -930,28 +931,198 @@ char* syncClientRequest2Str(const SyncClientRequest* pMsg) {
// for debug ----------------------
void syncClientRequestPrint(const SyncClientRequest* pMsg) {
char* serialized = syncClientRequest2Str(pMsg);
- printf("syncClientRequestPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncClientRequestPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncClientRequestPrint2(char* s, const SyncClientRequest* pMsg) {
char* serialized = syncClientRequest2Str(pMsg);
- printf("syncClientRequestPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncClientRequestPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncClientRequestLog(const SyncClientRequest* pMsg) {
char* serialized = syncClientRequest2Str(pMsg);
- sTrace("syncClientRequestLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncClientRequestLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncClientRequestLog2(char* s, const SyncClientRequest* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncClientRequest2Str(pMsg);
- sTrace("syncClientRequestLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncClientRequestLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
+ taosMemoryFree(serialized);
+ }
+}
+
+// ---- message process SyncClientRequestBatch----
+
+// block1:
+// block2: SRaftMeta array
+// block3: rpc msg array (with pCont)
+
+SyncClientRequestBatch* syncClientRequestBatchBuild(SRpcMsg* rpcMsgArr, SRaftMeta* raftArr, int32_t arrSize,
+ int32_t vgId) {
+ ASSERT(rpcMsgArr != NULL);
+ ASSERT(arrSize > 0);
+
+ int32_t dataLen = 0;
+ int32_t raftMetaArrayLen = sizeof(SRaftMeta) * arrSize;
+ int32_t rpcArrayLen = sizeof(SRpcMsg) * arrSize;
+ dataLen += (raftMetaArrayLen + rpcArrayLen);
+
+ uint32_t bytes = sizeof(SyncClientRequestBatch) + dataLen;
+ SyncClientRequestBatch* pMsg = taosMemoryMalloc(bytes);
+ memset(pMsg, 0, bytes);
+ pMsg->bytes = bytes;
+ pMsg->vgId = vgId;
+ pMsg->msgType = TDMT_SYNC_CLIENT_REQUEST_BATCH;
+ pMsg->dataCount = arrSize;
+ pMsg->dataLen = dataLen;
+
+ SRaftMeta* raftMetaArr = (SRaftMeta*)(pMsg->data);
+ SRpcMsg* msgArr = (SRpcMsg*)((char*)(pMsg->data) + raftMetaArrayLen);
+
+ for (int i = 0; i < arrSize; ++i) {
+ // init raftMetaArr
+ raftMetaArr[i].isWeak = raftArr[i].isWeak;
+ raftMetaArr[i].seqNum = raftArr[i].seqNum;
+
+ // init msgArr
+ msgArr[i] = rpcMsgArr[i];
+ }
+
+ return pMsg;
+}
+
+void syncClientRequestBatch2RpcMsg(const SyncClientRequestBatch* pSyncMsg, SRpcMsg* pRpcMsg) {
+ memset(pRpcMsg, 0, sizeof(*pRpcMsg));
+ pRpcMsg->msgType = pSyncMsg->msgType;
+ pRpcMsg->contLen = pSyncMsg->bytes;
+ pRpcMsg->pCont = rpcMallocCont(pRpcMsg->contLen);
+ memcpy(pRpcMsg->pCont, pSyncMsg, pRpcMsg->contLen);
+}
+
+void syncClientRequestBatchDestroy(SyncClientRequestBatch* pMsg) {
+ if (pMsg != NULL) {
+ taosMemoryFree(pMsg);
+ }
+}
+
+void syncClientRequestBatchDestroyDeep(SyncClientRequestBatch* pMsg) {
+ if (pMsg != NULL) {
+ int32_t arrSize = pMsg->dataCount;
+ int32_t raftMetaArrayLen = sizeof(SRaftMeta) * arrSize;
+ SRpcMsg* msgArr = (SRpcMsg*)((char*)(pMsg->data) + raftMetaArrayLen);
+ for (int i = 0; i < arrSize; ++i) {
+ if (msgArr[i].pCont != NULL) {
+ rpcFreeCont(msgArr[i].pCont);
+ }
+ }
+
+ taosMemoryFree(pMsg);
+ }
+}
+
+SRaftMeta* syncClientRequestBatchMetaArr(const SyncClientRequestBatch* pSyncMsg) {
+ SRaftMeta* raftMetaArr = (SRaftMeta*)(pSyncMsg->data);
+ return raftMetaArr;
+}
+
+SRpcMsg* syncClientRequestBatchRpcMsgArr(const SyncClientRequestBatch* pSyncMsg) {
+ int32_t arrSize = pSyncMsg->dataCount;
+ int32_t raftMetaArrayLen = sizeof(SRaftMeta) * arrSize;
+ SRpcMsg* msgArr = (SRpcMsg*)((char*)(pSyncMsg->data) + raftMetaArrayLen);
+ return msgArr;
+}
+
+SyncClientRequestBatch* syncClientRequestBatchFromRpcMsg(const SRpcMsg* pRpcMsg) {
+ SyncClientRequestBatch* pSyncMsg = taosMemoryMalloc(pRpcMsg->contLen);
+ ASSERT(pSyncMsg != NULL);
+ memcpy(pSyncMsg, pRpcMsg->pCont, pRpcMsg->contLen);
+ ASSERT(pRpcMsg->contLen == pSyncMsg->bytes);
+
+ return pSyncMsg;
+}
+
+cJSON* syncClientRequestBatch2Json(const SyncClientRequestBatch* pMsg) {
+ char u64buf[128] = {0};
+ cJSON* pRoot = cJSON_CreateObject();
+
+ if (pMsg != NULL) {
+ cJSON_AddNumberToObject(pRoot, "bytes", pMsg->bytes);
+ cJSON_AddNumberToObject(pRoot, "vgId", pMsg->vgId);
+ cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
+ cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen);
+ cJSON_AddNumberToObject(pRoot, "dataCount", pMsg->dataCount);
+
+ SRaftMeta* metaArr = syncClientRequestBatchMetaArr(pMsg);
+ SRpcMsg* msgArr = syncClientRequestBatchRpcMsgArr(pMsg);
+
+ cJSON* pMetaArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "metaArr", pMetaArr);
+ for (int i = 0; i < pMsg->dataCount; ++i) {
+ cJSON* pMeta = cJSON_CreateObject();
+ cJSON_AddNumberToObject(pMeta, "seqNum", metaArr[i].seqNum);
+ cJSON_AddNumberToObject(pMeta, "isWeak", metaArr[i].isWeak);
+ cJSON_AddItemToArray(pMetaArr, pMeta);
+ }
+
+ cJSON* pMsgArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "msgArr", pMsgArr);
+ for (int i = 0; i < pMsg->dataCount; ++i) {
+ cJSON* pRpcMsgJson = syncRpcMsg2Json(&msgArr[i]);
+ cJSON_AddItemToArray(pMsgArr, pRpcMsgJson);
+ }
+
+ char* s;
+ s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen);
+ cJSON_AddStringToObject(pRoot, "data", s);
+ taosMemoryFree(s);
+ s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen);
+ cJSON_AddStringToObject(pRoot, "data2", s);
+ taosMemoryFree(s);
+ }
+
+ cJSON* pJson = cJSON_CreateObject();
+ cJSON_AddItemToObject(pJson, "SyncClientRequestBatch", pRoot);
+ return pJson;
+}
+
+char* syncClientRequestBatch2Str(const SyncClientRequestBatch* pMsg) {
+ cJSON* pJson = syncClientRequestBatch2Json(pMsg);
+ char* serialized = cJSON_Print(pJson);
+ cJSON_Delete(pJson);
+ return serialized;
+}
+
+// for debug ----------------------
+void syncClientRequestBatchPrint(const SyncClientRequestBatch* pMsg) {
+ char* serialized = syncClientRequestBatch2Str(pMsg);
+ printf("syncClientRequestBatchPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void syncClientRequestBatchPrint2(char* s, const SyncClientRequestBatch* pMsg) {
+ char* serialized = syncClientRequestBatch2Str(pMsg);
+ printf("syncClientRequestBatchPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void syncClientRequestBatchLog(const SyncClientRequestBatch* pMsg) {
+ char* serialized = syncClientRequestBatch2Str(pMsg);
+ sTrace("syncClientRequestBatchLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
+ taosMemoryFree(serialized);
+}
+
+void syncClientRequestBatchLog2(char* s, const SyncClientRequestBatch* pMsg) {
+ if (gRaftDetailLog) {
+ char* serialized = syncClientRequestBatch2Str(pMsg);
+ sTraceLong("syncClientRequestBatchLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -974,18 +1145,18 @@ void syncRequestVoteDestroy(SyncRequestVote* pMsg) {
}
void syncRequestVoteSerialize(const SyncRequestVote* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncRequestVoteDeserialize(const char* buf, uint32_t len, SyncRequestVote* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncRequestVoteSerialize2(const SyncRequestVote* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncRequestVoteSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -996,9 +1167,9 @@ char* syncRequestVoteSerialize2(const SyncRequestVote* pMsg, uint32_t* len) {
SyncRequestVote* syncRequestVoteDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncRequestVote* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncRequestVoteDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1016,7 +1187,7 @@ void syncRequestVoteFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVote* pMsg) {
SyncRequestVote* syncRequestVoteFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncRequestVote* pMsg = syncRequestVoteDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1030,7 +1201,7 @@ cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1058,11 +1229,11 @@ cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->lastLogIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->lastLogIndex);
cJSON_AddStringToObject(pRoot, "lastLogIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->lastLogTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->lastLogTerm);
cJSON_AddStringToObject(pRoot, "lastLogTerm", u64buf);
}
@@ -1081,28 +1252,28 @@ char* syncRequestVote2Str(const SyncRequestVote* pMsg) {
// for debug ----------------------
void syncRequestVotePrint(const SyncRequestVote* pMsg) {
char* serialized = syncRequestVote2Str(pMsg);
- printf("syncRequestVotePrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncRequestVotePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRequestVotePrint2(char* s, const SyncRequestVote* pMsg) {
char* serialized = syncRequestVote2Str(pMsg);
- printf("syncRequestVotePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncRequestVotePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRequestVoteLog(const SyncRequestVote* pMsg) {
char* serialized = syncRequestVote2Str(pMsg);
- sTrace("syncRequestVoteLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncRequestVoteLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncRequestVoteLog2(char* s, const SyncRequestVote* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncRequestVote2Str(pMsg);
- sTrace("syncRequestVoteLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncRequestVoteLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1125,18 +1296,18 @@ void syncRequestVoteReplyDestroy(SyncRequestVoteReply* pMsg) {
}
void syncRequestVoteReplySerialize(const SyncRequestVoteReply* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncRequestVoteReplyDeserialize(const char* buf, uint32_t len, SyncRequestVoteReply* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncRequestVoteReplySerialize2(const SyncRequestVoteReply* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncRequestVoteReplySerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1147,9 +1318,9 @@ char* syncRequestVoteReplySerialize2(const SyncRequestVoteReply* pMsg, uint32_t*
SyncRequestVoteReply* syncRequestVoteReplyDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncRequestVoteReply* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncRequestVoteReplyDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1167,7 +1338,7 @@ void syncRequestVoteReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVoteReply
SyncRequestVoteReply* syncRequestVoteReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncRequestVoteReply* pMsg = syncRequestVoteReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1181,7 +1352,7 @@ cJSON* syncRequestVoteReply2Json(const SyncRequestVoteReply* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1209,7 +1380,7 @@ cJSON* syncRequestVoteReply2Json(const SyncRequestVoteReply* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
cJSON_AddNumberToObject(pRoot, "vote_granted", pMsg->voteGranted);
}
@@ -1229,28 +1400,28 @@ char* syncRequestVoteReply2Str(const SyncRequestVoteReply* pMsg) {
// for debug ----------------------
void syncRequestVoteReplyPrint(const SyncRequestVoteReply* pMsg) {
char* serialized = syncRequestVoteReply2Str(pMsg);
- printf("syncRequestVoteReplyPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncRequestVoteReplyPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRequestVoteReplyPrint2(char* s, const SyncRequestVoteReply* pMsg) {
char* serialized = syncRequestVoteReply2Str(pMsg);
- printf("syncRequestVoteReplyPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncRequestVoteReplyPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncRequestVoteReplyLog(const SyncRequestVoteReply* pMsg) {
char* serialized = syncRequestVoteReply2Str(pMsg);
- sTrace("syncRequestVoteReplyLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncRequestVoteReplyLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncRequestVoteReplyLog2(char* s, const SyncRequestVoteReply* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncRequestVoteReply2Str(pMsg);
- sTrace("syncRequestVoteReplyLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncRequestVoteReplyLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1274,19 +1445,19 @@ void syncAppendEntriesDestroy(SyncAppendEntries* pMsg) {
}
void syncAppendEntriesSerialize(const SyncAppendEntries* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncAppendEntriesDeserialize(const char* buf, uint32_t len, SyncAppendEntries* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
- assert(pMsg->bytes == sizeof(SyncAppendEntries) + pMsg->dataLen);
+ ASSERT(len == pMsg->bytes);
+ ASSERT(pMsg->bytes == sizeof(SyncAppendEntries) + pMsg->dataLen);
}
char* syncAppendEntriesSerialize2(const SyncAppendEntries* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncAppendEntriesSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1297,9 +1468,9 @@ char* syncAppendEntriesSerialize2(const SyncAppendEntries* pMsg, uint32_t* len)
SyncAppendEntries* syncAppendEntriesDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncAppendEntries* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncAppendEntriesDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1317,7 +1488,7 @@ void syncAppendEntriesFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntries* pMsg
SyncAppendEntries* syncAppendEntriesFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncAppendEntries* pMsg = syncAppendEntriesDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1331,7 +1502,7 @@ cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1346,7 +1517,7 @@ cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -1360,19 +1531,19 @@ cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->privateTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->privateTerm);
cJSON_AddStringToObject(pRoot, "privateTerm", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->prevLogIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->prevLogIndex);
cJSON_AddStringToObject(pRoot, "prevLogIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->prevLogTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->prevLogTerm);
cJSON_AddStringToObject(pRoot, "pre_log_term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->commitIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->commitIndex);
cJSON_AddStringToObject(pRoot, "commitIndex", u64buf);
cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen);
@@ -1400,28 +1571,267 @@ char* syncAppendEntries2Str(const SyncAppendEntries* pMsg) {
// for debug ----------------------
void syncAppendEntriesPrint(const SyncAppendEntries* pMsg) {
char* serialized = syncAppendEntries2Str(pMsg);
- printf("syncAppendEntriesPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncAppendEntriesPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncAppendEntriesPrint2(char* s, const SyncAppendEntries* pMsg) {
char* serialized = syncAppendEntries2Str(pMsg);
- printf("syncAppendEntriesPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncAppendEntriesPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncAppendEntriesLog(const SyncAppendEntries* pMsg) {
char* serialized = syncAppendEntries2Str(pMsg);
- sTrace("syncAppendEntriesLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncAppendEntriesLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncAppendEntriesLog2(char* s, const SyncAppendEntries* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncAppendEntries2Str(pMsg);
- sTrace("syncAppendEntriesLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncAppendEntriesLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
+ taosMemoryFree(serialized);
+ }
+}
+
+// ---- message process SyncAppendEntriesBatch----
+
+// block1: SOffsetAndContLen
+// block2: SOffsetAndContLen Array
+// block3: entry Array
+
+SyncAppendEntriesBatch* syncAppendEntriesBatchBuild(SSyncRaftEntry** entryPArr, int32_t arrSize, int32_t vgId) {
+ ASSERT(entryPArr != NULL);
+ ASSERT(arrSize >= 0);
+
+ int32_t dataLen = 0;
+ int32_t metaArrayLen = sizeof(SOffsetAndContLen) * arrSize; //
+ int32_t entryArrayLen = 0;
+ for (int i = 0; i < arrSize; ++i) { // SRpcMsg pCont
+ SSyncRaftEntry* pEntry = entryPArr[i];
+ entryArrayLen += pEntry->bytes;
+ }
+ dataLen += (metaArrayLen + entryArrayLen);
+
+ uint32_t bytes = sizeof(SyncAppendEntriesBatch) + dataLen;
+ SyncAppendEntriesBatch* pMsg = taosMemoryMalloc(bytes);
+ memset(pMsg, 0, bytes);
+ pMsg->bytes = bytes;
+ pMsg->vgId = vgId;
+ pMsg->msgType = TDMT_SYNC_APPEND_ENTRIES_BATCH;
+ pMsg->dataCount = arrSize;
+ pMsg->dataLen = dataLen;
+
+ SOffsetAndContLen* metaArr = (SOffsetAndContLen*)(pMsg->data);
+ char* pData = pMsg->data;
+
+ for (int i = 0; i < arrSize; ++i) {
+ // init meta
+ if (i == 0) {
+ metaArr[i].offset = metaArrayLen;
+ metaArr[i].contLen = entryPArr[i]->bytes;
+ } else {
+ metaArr[i].offset = metaArr[i - 1].offset + metaArr[i - 1].contLen;
+ metaArr[i].contLen = entryPArr[i]->bytes;
+ }
+
+ // init entry array
+ ASSERT(metaArr[i].contLen == entryPArr[i]->bytes);
+ memcpy(pData + metaArr[i].offset, entryPArr[i], metaArr[i].contLen);
+ }
+
+ return pMsg;
+}
+
+SOffsetAndContLen* syncAppendEntriesBatchMetaTableArray(SyncAppendEntriesBatch* pMsg) {
+ return (SOffsetAndContLen*)(pMsg->data);
+}
+
+void syncAppendEntriesBatchDestroy(SyncAppendEntriesBatch* pMsg) {
+ if (pMsg != NULL) {
+ taosMemoryFree(pMsg);
+ }
+}
+
+void syncAppendEntriesBatchSerialize(const SyncAppendEntriesBatch* pMsg, char* buf, uint32_t bufLen) {
+ ASSERT(pMsg->bytes <= bufLen);
+ memcpy(buf, pMsg, pMsg->bytes);
+}
+
+void syncAppendEntriesBatchDeserialize(const char* buf, uint32_t len, SyncAppendEntriesBatch* pMsg) {
+ memcpy(pMsg, buf, len);
+ ASSERT(len == pMsg->bytes);
+ ASSERT(pMsg->bytes == sizeof(SyncAppendEntriesBatch) + pMsg->dataLen);
+}
+
+char* syncAppendEntriesBatchSerialize2(const SyncAppendEntriesBatch* pMsg, uint32_t* len) {
+ char* buf = taosMemoryMalloc(pMsg->bytes);
+ ASSERT(buf != NULL);
+ syncAppendEntriesBatchSerialize(pMsg, buf, pMsg->bytes);
+ if (len != NULL) {
+ *len = pMsg->bytes;
+ }
+ return buf;
+}
+
+SyncAppendEntriesBatch* syncAppendEntriesBatchDeserialize2(const char* buf, uint32_t len) {
+ uint32_t bytes = *((uint32_t*)buf);
+ SyncAppendEntriesBatch* pMsg = taosMemoryMalloc(bytes);
+ ASSERT(pMsg != NULL);
+ syncAppendEntriesBatchDeserialize(buf, len, pMsg);
+ ASSERT(len == pMsg->bytes);
+ return pMsg;
+}
+
+void syncAppendEntriesBatch2RpcMsg(const SyncAppendEntriesBatch* pMsg, SRpcMsg* pRpcMsg) {
+ memset(pRpcMsg, 0, sizeof(*pRpcMsg));
+ pRpcMsg->msgType = pMsg->msgType;
+ pRpcMsg->contLen = pMsg->bytes;
+ pRpcMsg->pCont = rpcMallocCont(pRpcMsg->contLen);
+ syncAppendEntriesBatchSerialize(pMsg, pRpcMsg->pCont, pRpcMsg->contLen);
+}
+
+void syncAppendEntriesBatchFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntriesBatch* pMsg) {
+ syncAppendEntriesBatchDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg);
+}
+
+SyncAppendEntriesBatch* syncAppendEntriesBatchFromRpcMsg2(const SRpcMsg* pRpcMsg) {
+ SyncAppendEntriesBatch* pMsg = syncAppendEntriesBatchDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
+ ASSERT(pMsg != NULL);
+ return pMsg;
+}
+
+cJSON* syncAppendEntriesBatch2Json(const SyncAppendEntriesBatch* pMsg) {
+ char u64buf[128] = {0};
+ cJSON* pRoot = cJSON_CreateObject();
+
+ if (pMsg != NULL) {
+ cJSON_AddNumberToObject(pRoot, "bytes", pMsg->bytes);
+ cJSON_AddNumberToObject(pRoot, "vgId", pMsg->vgId);
+ cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
+
+ cJSON* pSrcId = cJSON_CreateObject();
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
+ cJSON_AddStringToObject(pSrcId, "addr", u64buf);
+ {
+ uint64_t u64 = pMsg->srcId.addr;
+ cJSON* pTmp = pSrcId;
+ char host[128] = {0};
+ uint16_t port;
+ syncUtilU642Addr(u64, host, sizeof(host), &port);
+ cJSON_AddStringToObject(pTmp, "addr_host", host);
+ cJSON_AddNumberToObject(pTmp, "addr_port", port);
+ }
+ cJSON_AddNumberToObject(pSrcId, "vgId", pMsg->srcId.vgId);
+ cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
+
+ cJSON* pDestId = cJSON_CreateObject();
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
+ cJSON_AddStringToObject(pDestId, "addr", u64buf);
+ {
+ uint64_t u64 = pMsg->destId.addr;
+ cJSON* pTmp = pDestId;
+ char host[128] = {0};
+ uint16_t port;
+ syncUtilU642Addr(u64, host, sizeof(host), &port);
+ cJSON_AddStringToObject(pTmp, "addr_host", host);
+ cJSON_AddNumberToObject(pTmp, "addr_port", port);
+ }
+ cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
+ cJSON_AddItemToObject(pRoot, "destId", pDestId);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
+ cJSON_AddStringToObject(pRoot, "term", u64buf);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->prevLogIndex);
+ cJSON_AddStringToObject(pRoot, "prevLogIndex", u64buf);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->prevLogTerm);
+ cJSON_AddStringToObject(pRoot, "prevLogTerm", u64buf);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->commitIndex);
+ cJSON_AddStringToObject(pRoot, "commitIndex", u64buf);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->privateTerm);
+ cJSON_AddStringToObject(pRoot, "privateTerm", u64buf);
+
+ cJSON_AddNumberToObject(pRoot, "dataCount", pMsg->dataCount);
+ cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen);
+
+ int32_t metaArrayLen = sizeof(SOffsetAndContLen) * pMsg->dataCount; //
+ int32_t entryArrayLen = pMsg->dataLen - metaArrayLen;
+
+ cJSON_AddNumberToObject(pRoot, "metaArrayLen", metaArrayLen);
+ cJSON_AddNumberToObject(pRoot, "entryArrayLen", entryArrayLen);
+
+ SOffsetAndContLen* metaArr = (SOffsetAndContLen*)(pMsg->data);
+
+ cJSON* pMetaArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "metaArr", pMetaArr);
+ for (int i = 0; i < pMsg->dataCount; ++i) {
+ cJSON* pMeta = cJSON_CreateObject();
+ cJSON_AddNumberToObject(pMeta, "offset", metaArr[i].offset);
+ cJSON_AddNumberToObject(pMeta, "contLen", metaArr[i].contLen);
+ cJSON_AddItemToArray(pMetaArr, pMeta);
+ }
+
+ cJSON* pEntryArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "entryArr", pEntryArr);
+ for (int i = 0; i < pMsg->dataCount; ++i) {
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)(pMsg->data + metaArr[i].offset);
+ cJSON* pEntryJson = syncEntry2Json(pEntry);
+ cJSON_AddItemToArray(pEntryArr, pEntryJson);
+ }
+
+ char* s;
+ s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen);
+ cJSON_AddStringToObject(pRoot, "data", s);
+ taosMemoryFree(s);
+ s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen);
+ cJSON_AddStringToObject(pRoot, "data2", s);
+ taosMemoryFree(s);
+ }
+
+ cJSON* pJson = cJSON_CreateObject();
+ cJSON_AddItemToObject(pJson, "SyncAppendEntriesBatch", pRoot);
+ return pJson;
+}
+
+char* syncAppendEntriesBatch2Str(const SyncAppendEntriesBatch* pMsg) {
+ cJSON* pJson = syncAppendEntriesBatch2Json(pMsg);
+ char* serialized = cJSON_Print(pJson);
+ cJSON_Delete(pJson);
+ return serialized;
+}
+
+// for debug ----------------------
+void syncAppendEntriesBatchPrint(const SyncAppendEntriesBatch* pMsg) {
+ char* serialized = syncAppendEntriesBatch2Str(pMsg);
+ printf("syncAppendEntriesBatchPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void syncAppendEntriesBatchPrint2(char* s, const SyncAppendEntriesBatch* pMsg) {
+ char* serialized = syncAppendEntriesBatch2Str(pMsg);
+ printf("syncAppendEntriesBatchPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void syncAppendEntriesBatchLog(const SyncAppendEntriesBatch* pMsg) {
+ char* serialized = syncAppendEntriesBatch2Str(pMsg);
+ sTrace("syncAppendEntriesBatchLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
+ taosMemoryFree(serialized);
+}
+
+void syncAppendEntriesBatchLog2(char* s, const SyncAppendEntriesBatch* pMsg) {
+ if (gRaftDetailLog) {
+ char* serialized = syncAppendEntriesBatch2Str(pMsg);
+ sTraceLong("syncAppendEntriesBatchLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1444,18 +1854,18 @@ void syncAppendEntriesReplyDestroy(SyncAppendEntriesReply* pMsg) {
}
void syncAppendEntriesReplySerialize(const SyncAppendEntriesReply* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncAppendEntriesReplyDeserialize(const char* buf, uint32_t len, SyncAppendEntriesReply* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncAppendEntriesReplySerialize2(const SyncAppendEntriesReply* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncAppendEntriesReplySerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1466,9 +1876,9 @@ char* syncAppendEntriesReplySerialize2(const SyncAppendEntriesReply* pMsg, uint3
SyncAppendEntriesReply* syncAppendEntriesReplyDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncAppendEntriesReply* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncAppendEntriesReplyDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1486,7 +1896,7 @@ void syncAppendEntriesReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntriesR
SyncAppendEntriesReply* syncAppendEntriesReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncAppendEntriesReply* pMsg = syncAppendEntriesReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1500,7 +1910,7 @@ cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1515,7 +1925,7 @@ cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -1529,13 +1939,13 @@ cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->privateTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->privateTerm);
cJSON_AddStringToObject(pRoot, "privateTerm", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
cJSON_AddNumberToObject(pRoot, "success", pMsg->success);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->matchIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->matchIndex);
cJSON_AddStringToObject(pRoot, "matchIndex", u64buf);
}
@@ -1554,28 +1964,28 @@ char* syncAppendEntriesReply2Str(const SyncAppendEntriesReply* pMsg) {
// for debug ----------------------
void syncAppendEntriesReplyPrint(const SyncAppendEntriesReply* pMsg) {
char* serialized = syncAppendEntriesReply2Str(pMsg);
- printf("syncAppendEntriesReplyPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncAppendEntriesReplyPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncAppendEntriesReplyPrint2(char* s, const SyncAppendEntriesReply* pMsg) {
char* serialized = syncAppendEntriesReply2Str(pMsg);
- printf("syncAppendEntriesReplyPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncAppendEntriesReplyPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncAppendEntriesReplyLog(const SyncAppendEntriesReply* pMsg) {
char* serialized = syncAppendEntriesReply2Str(pMsg);
- sTrace("syncAppendEntriesReplyLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncAppendEntriesReplyLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncAppendEntriesReplyLog2(char* s, const SyncAppendEntriesReply* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncAppendEntriesReply2Str(pMsg);
- sTrace("syncAppendEntriesReplyLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncAppendEntriesReplyLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1607,18 +2017,18 @@ void syncApplyMsgDestroy(SyncApplyMsg* pMsg) {
}
void syncApplyMsgSerialize(const SyncApplyMsg* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncApplyMsgDeserialize(const char* buf, uint32_t len, SyncApplyMsg* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncApplyMsgSerialize2(const SyncApplyMsg* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncApplyMsgSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1629,9 +2039,9 @@ char* syncApplyMsgSerialize2(const SyncApplyMsg* pMsg, uint32_t* len) {
SyncApplyMsg* syncApplyMsgDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncApplyMsg* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncApplyMsgDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1673,13 +2083,13 @@ cJSON* syncApplyMsg2Json(const SyncApplyMsg* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON_AddNumberToObject(pRoot, "originalRpcType", pMsg->originalRpcType);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->fsmMeta.index);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->fsmMeta.index);
cJSON_AddStringToObject(pRoot, "fsmMeta.index", u64buf);
cJSON_AddNumberToObject(pRoot, "fsmMeta.isWeak", pMsg->fsmMeta.isWeak);
cJSON_AddNumberToObject(pRoot, "fsmMeta.code", pMsg->fsmMeta.code);
cJSON_AddNumberToObject(pRoot, "fsmMeta.state", pMsg->fsmMeta.state);
cJSON_AddStringToObject(pRoot, "fsmMeta.state.str", syncUtilState2String(pMsg->fsmMeta.state));
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->fsmMeta.seqNum);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->fsmMeta.seqNum);
cJSON_AddStringToObject(pRoot, "fsmMeta.seqNum", u64buf);
cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen);
@@ -1707,28 +2117,28 @@ char* syncApplyMsg2Str(const SyncApplyMsg* pMsg) {
// for debug ----------------------
void syncApplyMsgPrint(const SyncApplyMsg* pMsg) {
char* serialized = syncApplyMsg2Str(pMsg);
- printf("syncApplyMsgPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncApplyMsgPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncApplyMsgPrint2(char* s, const SyncApplyMsg* pMsg) {
char* serialized = syncApplyMsg2Str(pMsg);
- printf("syncApplyMsgPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncApplyMsgPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncApplyMsgLog(const SyncApplyMsg* pMsg) {
char* serialized = syncApplyMsg2Str(pMsg);
- sTrace("ssyncApplyMsgLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("ssyncApplyMsgLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncApplyMsgLog2(char* s, const SyncApplyMsg* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncApplyMsg2Str(pMsg);
- sTrace("syncApplyMsgLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncApplyMsgLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1752,19 +2162,19 @@ void syncSnapshotSendDestroy(SyncSnapshotSend* pMsg) {
}
void syncSnapshotSendSerialize(const SyncSnapshotSend* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncSnapshotSendDeserialize(const char* buf, uint32_t len, SyncSnapshotSend* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
- assert(pMsg->bytes == sizeof(SyncSnapshotSend) + pMsg->dataLen);
+ ASSERT(len == pMsg->bytes);
+ ASSERT(pMsg->bytes == sizeof(SyncSnapshotSend) + pMsg->dataLen);
}
char* syncSnapshotSendSerialize2(const SyncSnapshotSend* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncSnapshotSendSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1775,9 +2185,9 @@ char* syncSnapshotSendSerialize2(const SyncSnapshotSend* pMsg, uint32_t* len) {
SyncSnapshotSend* syncSnapshotSendDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncSnapshotSend* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncSnapshotSendDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1795,7 +2205,7 @@ void syncSnapshotSendFromRpcMsg(const SRpcMsg* pRpcMsg, SyncSnapshotSend* pMsg)
SyncSnapshotSend* syncSnapshotSendFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncSnapshotSend* pMsg = syncSnapshotSendDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1809,7 +2219,7 @@ cJSON* syncSnapshotSend2Json(const SyncSnapshotSend* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1824,7 +2234,7 @@ cJSON* syncSnapshotSend2Json(const SyncSnapshotSend* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -1838,20 +2248,23 @@ cJSON* syncSnapshotSend2Json(const SyncSnapshotSend* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->privateTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->privateTerm);
cJSON_AddStringToObject(pRoot, "privateTerm", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->lastIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->beginIndex);
+ cJSON_AddStringToObject(pRoot, "beginIndex", u64buf);
+
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->lastIndex);
cJSON_AddStringToObject(pRoot, "lastIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->lastConfigIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->lastConfigIndex);
cJSON_AddStringToObject(pRoot, "lastConfigIndex", u64buf);
cJSON_AddItemToObject(pRoot, "lastConfig", syncCfg2Json((SSyncCfg*)&(pMsg->lastConfig)));
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->lastTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->lastTerm);
cJSON_AddStringToObject(pRoot, "lastTerm", u64buf);
cJSON_AddNumberToObject(pRoot, "seq", pMsg->seq);
@@ -1881,28 +2294,28 @@ char* syncSnapshotSend2Str(const SyncSnapshotSend* pMsg) {
// for debug ----------------------
void syncSnapshotSendPrint(const SyncSnapshotSend* pMsg) {
char* serialized = syncSnapshotSend2Str(pMsg);
- printf("syncSnapshotSendPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncSnapshotSendPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncSnapshotSendPrint2(char* s, const SyncSnapshotSend* pMsg) {
char* serialized = syncSnapshotSend2Str(pMsg);
- printf("syncSnapshotSendPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncSnapshotSendPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncSnapshotSendLog(const SyncSnapshotSend* pMsg) {
char* serialized = syncSnapshotSend2Str(pMsg);
- sTrace("syncSnapshotSendLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncSnapshotSendLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncSnapshotSendLog2(char* s, const SyncSnapshotSend* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncSnapshotSend2Str(pMsg);
- sTrace("syncSnapshotSendLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncSnapshotSendLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -1925,18 +2338,18 @@ void syncSnapshotRspDestroy(SyncSnapshotRsp* pMsg) {
}
void syncSnapshotRspSerialize(const SyncSnapshotRsp* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncSnapshotRspDeserialize(const char* buf, uint32_t len, SyncSnapshotRsp* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncSnapshotRspSerialize2(const SyncSnapshotRsp* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncSnapshotRspSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -1947,9 +2360,9 @@ char* syncSnapshotRspSerialize2(const SyncSnapshotRsp* pMsg, uint32_t* len) {
SyncSnapshotRsp* syncSnapshotRspDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncSnapshotRsp* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncSnapshotRspDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -1967,7 +2380,7 @@ void syncSnapshotRspFromRpcMsg(const SRpcMsg* pRpcMsg, SyncSnapshotRsp* pMsg) {
SyncSnapshotRsp* syncSnapshotRspFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncSnapshotRsp* pMsg = syncSnapshotRspDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -1981,7 +2394,7 @@ cJSON* syncSnapshotRsp2Json(const SyncSnapshotRsp* pMsg) {
cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType);
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -1996,7 +2409,7 @@ cJSON* syncSnapshotRsp2Json(const SyncSnapshotRsp* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -2010,16 +2423,16 @@ cJSON* syncSnapshotRsp2Json(const SyncSnapshotRsp* pMsg) {
cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId);
cJSON_AddItemToObject(pRoot, "destId", pDestId);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->privateTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->privateTerm);
cJSON_AddStringToObject(pRoot, "privateTerm", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->lastIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->lastIndex);
cJSON_AddStringToObject(pRoot, "lastIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->lastTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->lastTerm);
cJSON_AddStringToObject(pRoot, "lastTerm", u64buf);
cJSON_AddNumberToObject(pRoot, "ack", pMsg->ack);
@@ -2041,28 +2454,28 @@ char* syncSnapshotRsp2Str(const SyncSnapshotRsp* pMsg) {
// for debug ----------------------
void syncSnapshotRspPrint(const SyncSnapshotRsp* pMsg) {
char* serialized = syncSnapshotRsp2Str(pMsg);
- printf("syncSnapshotRspPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncSnapshotRspPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncSnapshotRspPrint2(char* s, const SyncSnapshotRsp* pMsg) {
char* serialized = syncSnapshotRsp2Str(pMsg);
- printf("syncSnapshotRspPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncSnapshotRspPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncSnapshotRspLog(const SyncSnapshotRsp* pMsg) {
char* serialized = syncSnapshotRsp2Str(pMsg);
- sTrace("syncSnapshotRspLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncSnapshotRspLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncSnapshotRspLog2(char* s, const SyncSnapshotRsp* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncSnapshotRsp2Str(pMsg);
- sTrace("syncSnapshotRspLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncSnapshotRspLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -2085,18 +2498,18 @@ void syncLeaderTransferDestroy(SyncLeaderTransfer* pMsg) {
}
void syncLeaderTransferSerialize(const SyncLeaderTransfer* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncLeaderTransferDeserialize(const char* buf, uint32_t len, SyncLeaderTransfer* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncLeaderTransferSerialize2(const SyncLeaderTransfer* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncLeaderTransferSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -2107,9 +2520,9 @@ char* syncLeaderTransferSerialize2(const SyncLeaderTransfer* pMsg, uint32_t* len
SyncLeaderTransfer* syncLeaderTransferDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncLeaderTransfer* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncLeaderTransferDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -2127,7 +2540,7 @@ void syncLeaderTransferFromRpcMsg(const SRpcMsg* pRpcMsg, SyncLeaderTransfer* pM
SyncLeaderTransfer* syncLeaderTransferFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncLeaderTransfer* pMsg = syncLeaderTransferDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -2142,7 +2555,7 @@ cJSON* syncLeaderTransfer2Json(const SyncLeaderTransfer* pMsg) {
/*
cJSON* pSrcId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->srcId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->srcId.addr);
cJSON_AddStringToObject(pSrcId, "addr", u64buf);
{
uint64_t u64 = pMsg->srcId.addr;
@@ -2157,7 +2570,7 @@ cJSON* syncLeaderTransfer2Json(const SyncLeaderTransfer* pMsg) {
cJSON_AddItemToObject(pRoot, "srcId", pSrcId);
cJSON* pDestId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->destId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->destId.addr);
cJSON_AddStringToObject(pDestId, "addr", u64buf);
{
uint64_t u64 = pMsg->destId.addr;
@@ -2173,7 +2586,7 @@ cJSON* syncLeaderTransfer2Json(const SyncLeaderTransfer* pMsg) {
*/
cJSON* pNewerId = cJSON_CreateObject();
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->newLeaderId.addr);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->newLeaderId.addr);
cJSON_AddStringToObject(pNewerId, "addr", u64buf);
{
uint64_t u64 = pMsg->newLeaderId.addr;
@@ -2203,28 +2616,28 @@ char* syncLeaderTransfer2Str(const SyncLeaderTransfer* pMsg) {
// for debug ----------------------
void syncLeaderTransferPrint(const SyncLeaderTransfer* pMsg) {
char* serialized = syncLeaderTransfer2Str(pMsg);
- printf("syncLeaderTransferPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncLeaderTransferPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncLeaderTransferPrint2(char* s, const SyncLeaderTransfer* pMsg) {
char* serialized = syncLeaderTransfer2Str(pMsg);
- printf("syncLeaderTransferPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncLeaderTransferPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncLeaderTransferLog(const SyncLeaderTransfer* pMsg) {
char* serialized = syncLeaderTransfer2Str(pMsg);
- sTrace("syncLeaderTransferLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncLeaderTransferLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncLeaderTransferLog2(char* s, const SyncLeaderTransfer* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncLeaderTransfer2Str(pMsg);
- sTrace("syncLeaderTransferLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncLeaderTransferLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -2247,18 +2660,18 @@ void syncReconfigFinishDestroy(SyncReconfigFinish* pMsg) {
}
void syncReconfigFinishSerialize(const SyncReconfigFinish* pMsg, char* buf, uint32_t bufLen) {
- assert(pMsg->bytes <= bufLen);
+ ASSERT(pMsg->bytes <= bufLen);
memcpy(buf, pMsg, pMsg->bytes);
}
void syncReconfigFinishDeserialize(const char* buf, uint32_t len, SyncReconfigFinish* pMsg) {
memcpy(pMsg, buf, len);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
}
char* syncReconfigFinishSerialize2(const SyncReconfigFinish* pMsg, uint32_t* len) {
char* buf = taosMemoryMalloc(pMsg->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
syncReconfigFinishSerialize(pMsg, buf, pMsg->bytes);
if (len != NULL) {
*len = pMsg->bytes;
@@ -2269,9 +2682,9 @@ char* syncReconfigFinishSerialize2(const SyncReconfigFinish* pMsg, uint32_t* len
SyncReconfigFinish* syncReconfigFinishDeserialize2(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SyncReconfigFinish* pMsg = taosMemoryMalloc(bytes);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
syncReconfigFinishDeserialize(buf, len, pMsg);
- assert(len == pMsg->bytes);
+ ASSERT(len == pMsg->bytes);
return pMsg;
}
@@ -2289,7 +2702,7 @@ void syncReconfigFinishFromRpcMsg(const SRpcMsg* pRpcMsg, SyncReconfigFinish* pM
SyncReconfigFinish* syncReconfigFinishFromRpcMsg2(const SRpcMsg* pRpcMsg) {
SyncReconfigFinish* pMsg = syncReconfigFinishDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen);
- assert(pMsg != NULL);
+ ASSERT(pMsg != NULL);
return pMsg;
}
@@ -2307,13 +2720,13 @@ cJSON* syncReconfigFinish2Json(const SyncReconfigFinish* pMsg) {
cJSON_AddItemToObject(pRoot, "oldCfg", pOldCfg);
cJSON_AddItemToObject(pRoot, "newCfg", pNewCfg);
- snprintf(u64buf, sizeof(u64buf), "%ld", pMsg->newCfgIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, pMsg->newCfgIndex);
cJSON_AddStringToObject(pRoot, "newCfgIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->newCfgTerm);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->newCfgTerm);
cJSON_AddStringToObject(pRoot, "newCfgTerm", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->newCfgSeqNum);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pMsg->newCfgSeqNum);
cJSON_AddStringToObject(pRoot, "newCfgSeqNum", u64buf);
}
@@ -2332,28 +2745,28 @@ char* syncReconfigFinish2Str(const SyncReconfigFinish* pMsg) {
// for debug ----------------------
void syncReconfigFinishPrint(const SyncReconfigFinish* pMsg) {
char* serialized = syncReconfigFinish2Str(pMsg);
- printf("syncReconfigFinishPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncReconfigFinishPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncReconfigFinishPrint2(char* s, const SyncReconfigFinish* pMsg) {
char* serialized = syncReconfigFinish2Str(pMsg);
- printf("syncReconfigFinishPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncReconfigFinishPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncReconfigFinishLog(const SyncReconfigFinish* pMsg) {
char* serialized = syncReconfigFinish2Str(pMsg);
- sTrace("syncReconfigFinishLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncReconfigFinishLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncReconfigFinishLog2(char* s, const SyncReconfigFinish* pMsg) {
if (gRaftDetailLog) {
char* serialized = syncReconfigFinish2Str(pMsg);
- sTrace("syncReconfigFinishLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncReconfigFinishLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncOnMessage.c b/source/libs/sync/src/syncOnMessage.c
deleted file mode 100644
index ce8bed9cd39c44df9b090ae931cba063d1dda53c..0000000000000000000000000000000000000000
--- a/source/libs/sync/src/syncOnMessage.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#include "syncOnMessage.h"
-
-// TLA+ Spec
-// Receive(m) ==
-// LET i == m.mdest
-// j == m.msource
-// IN \* Any RPC with a newer term causes the recipient to advance
-// \* its term first. Responses with stale terms are ignored.
-// \/ UpdateTerm(i, j, m)
-// \/ /\ m.mtype = RequestVoteRequest
-// /\ HandleRequestVoteRequest(i, j, m)
-// \/ /\ m.mtype = RequestVoteResponse
-// /\ \/ DropStaleResponse(i, j, m)
-// \/ HandleRequestVoteResponse(i, j, m)
-// \/ /\ m.mtype = AppendEntriesRequest
-// /\ HandleAppendEntriesRequest(i, j, m)
-// \/ /\ m.mtype = AppendEntriesResponse
-// /\ \/ DropStaleResponse(i, j, m)
-// \/ HandleAppendEntriesResponse(i, j, m)
-
-// DuplicateMessage(m) ==
-// /\ Send(m)
-// /\ UNCHANGED <>
-
-// DropMessage(m) ==
-// /\ Discard(m)
-// /\ UNCHANGED <>
-
-// Next == /\ \/ \E i \in Server : Restart(i)
-// \/ \E i \in Server : Timeout(i)
-// \/ \E i,j \in Server : RequestVote(i, j)
-// \/ \E i \in Server : BecomeLeader(i)
-// \/ \E i \in Server, v \in Value : ClientRequest(i, v)
-// \/ \E i \in Server : AdvanceCommitIndex(i)
-// \/ \E i,j \in Server : AppendEntries(i, j)
-// \/ \E m \in DOMAIN messages : Receive(m)
-// \/ \E m \in DOMAIN messages : DuplicateMessage(m)
-// \/ \E m \in DOMAIN messages : DropMessage(m)
-// \* History variable that tracks every log ever:
-// /\ allLogs' = allLogs \cup {log[i] : i \in Server}
-//
\ No newline at end of file
diff --git a/source/libs/sync/src/syncRaftCfg.c b/source/libs/sync/src/syncRaftCfg.c
index 08c3e0126c143acb4196d9196ed8ee09f6678f43..0bbeaaf5b0c78003e8fdcf617845a45546873d9e 100644
--- a/source/libs/sync/src/syncRaftCfg.c
+++ b/source/libs/sync/src/syncRaftCfg.c
@@ -24,42 +24,47 @@ SRaftCfg *raftCfgOpen(const char *path) {
snprintf(pCfg->path, sizeof(pCfg->path), "%s", path);
pCfg->pFile = taosOpenFile(pCfg->path, TD_FILE_READ | TD_FILE_WRITE);
- assert(pCfg->pFile != NULL);
+ ASSERT(pCfg->pFile != NULL);
taosLSeekFile(pCfg->pFile, 0, SEEK_SET);
char buf[1024] = {0};
int len = taosReadFile(pCfg->pFile, buf, sizeof(buf));
- assert(len > 0);
+ ASSERT(len > 0);
int32_t ret = raftCfgFromStr(buf, pCfg);
- assert(ret == 0);
+ ASSERT(ret == 0);
return pCfg;
}
int32_t raftCfgClose(SRaftCfg *pRaftCfg) {
int64_t ret = taosCloseFile(&(pRaftCfg->pFile));
- assert(ret == 0);
+ ASSERT(ret == 0);
taosMemoryFree(pRaftCfg);
return 0;
}
int32_t raftCfgPersist(SRaftCfg *pRaftCfg) {
- assert(pRaftCfg != NULL);
+ ASSERT(pRaftCfg != NULL);
char *s = raftCfg2Str(pRaftCfg);
taosLSeekFile(pRaftCfg->pFile, 0, SEEK_SET);
char buf[CONFIG_FILE_LEN] = {0};
memset(buf, 0, sizeof(buf));
- ASSERT(strlen(s) + 1 <= CONFIG_FILE_LEN);
+
+ if (strlen(s) + 1 > CONFIG_FILE_LEN) {
+ sError("too long config str:%s", s);
+ ASSERT(0);
+ }
+
snprintf(buf, sizeof(buf), "%s", s);
int64_t ret = taosWriteFile(pRaftCfg->pFile, buf, sizeof(buf));
- assert(ret == sizeof(buf));
+ ASSERT(ret == sizeof(buf));
// int64_t ret = taosWriteFile(pRaftCfg->pFile, s, strlen(s) + 1);
- // assert(ret == strlen(s) + 1);
+ // ASSERT(ret == strlen(s) + 1);
taosMemoryFree(s);
taosFsyncFile(pRaftCfg->pFile);
@@ -102,26 +107,30 @@ char *syncCfg2Str(SSyncCfg *pSyncCfg) {
}
char *syncCfg2SimpleStr(SSyncCfg *pSyncCfg) {
- int32_t len = 512;
- char * s = taosMemoryMalloc(len);
- memset(s, 0, len);
-
- snprintf(s, len, "{replica-num:%d, my-index:%d, ", pSyncCfg->replicaNum, pSyncCfg->myIndex);
- char *p = s + strlen(s);
- for (int i = 0; i < pSyncCfg->replicaNum; ++i) {
- /*
- if (p + 128 + 32 > s + len) {
- break;
+ if (pSyncCfg != NULL) {
+ int32_t len = 512;
+ char * s = taosMemoryMalloc(len);
+ memset(s, 0, len);
+
+ snprintf(s, len, "{replica-num:%d, my-index:%d, ", pSyncCfg->replicaNum, pSyncCfg->myIndex);
+ char *p = s + strlen(s);
+ for (int i = 0; i < pSyncCfg->replicaNum; ++i) {
+ /*
+ if (p + 128 + 32 > s + len) {
+ break;
+ }
+ */
+ char buf[128 + 32];
+ snprintf(buf, sizeof(buf), "%s:%d, ", pSyncCfg->nodeInfo[i].nodeFqdn, pSyncCfg->nodeInfo[i].nodePort);
+ strncpy(p, buf, sizeof(buf));
+ p = s + strlen(s);
}
- */
- char buf[128 + 32];
- snprintf(buf, sizeof(buf), "%s:%d, ", pSyncCfg->nodeInfo[i].nodeFqdn, pSyncCfg->nodeInfo[i].nodePort);
- strncpy(p, buf, sizeof(buf));
- p = s + strlen(s);
+ strcpy(p - 2, "}");
+
+ return s;
}
- strcpy(p - 2, "}");
- return s;
+ return NULL;
}
int32_t syncCfgFromJson(const cJSON *pRoot, SSyncCfg *pSyncCfg) {
@@ -130,27 +139,27 @@ int32_t syncCfgFromJson(const cJSON *pRoot, SSyncCfg *pSyncCfg) {
const cJSON *pJson = pRoot;
cJSON *pReplicaNum = cJSON_GetObjectItem(pJson, "replicaNum");
- assert(cJSON_IsNumber(pReplicaNum));
+ ASSERT(cJSON_IsNumber(pReplicaNum));
pSyncCfg->replicaNum = cJSON_GetNumberValue(pReplicaNum);
cJSON *pMyIndex = cJSON_GetObjectItem(pJson, "myIndex");
- assert(cJSON_IsNumber(pMyIndex));
+ ASSERT(cJSON_IsNumber(pMyIndex));
pSyncCfg->myIndex = cJSON_GetNumberValue(pMyIndex);
cJSON *pNodeInfoArr = cJSON_GetObjectItem(pJson, "nodeInfo");
int arraySize = cJSON_GetArraySize(pNodeInfoArr);
- assert(arraySize == pSyncCfg->replicaNum);
+ ASSERT(arraySize == pSyncCfg->replicaNum);
for (int i = 0; i < arraySize; ++i) {
cJSON *pNodeInfo = cJSON_GetArrayItem(pNodeInfoArr, i);
- assert(pNodeInfo != NULL);
+ ASSERT(pNodeInfo != NULL);
cJSON *pNodePort = cJSON_GetObjectItem(pNodeInfo, "nodePort");
- assert(cJSON_IsNumber(pNodePort));
+ ASSERT(cJSON_IsNumber(pNodePort));
((pSyncCfg->nodeInfo)[i]).nodePort = cJSON_GetNumberValue(pNodePort);
cJSON *pNodeFqdn = cJSON_GetObjectItem(pNodeInfo, "nodeFqdn");
- assert(cJSON_IsString(pNodeFqdn));
+ ASSERT(cJSON_IsString(pNodeFqdn));
snprintf(((pSyncCfg->nodeInfo)[i]).nodeFqdn, sizeof(((pSyncCfg->nodeInfo)[i]).nodeFqdn), "%s",
pNodeFqdn->valuestring);
}
@@ -160,10 +169,10 @@ int32_t syncCfgFromJson(const cJSON *pRoot, SSyncCfg *pSyncCfg) {
int32_t syncCfgFromStr(const char *s, SSyncCfg *pSyncCfg) {
cJSON *pRoot = cJSON_Parse(s);
- assert(pRoot != NULL);
+ ASSERT(pRoot != NULL);
int32_t ret = syncCfgFromJson(pRoot, pSyncCfg);
- assert(ret == 0);
+ ASSERT(ret == 0);
cJSON_Delete(pRoot);
return 0;
@@ -173,17 +182,18 @@ cJSON *raftCfg2Json(SRaftCfg *pRaftCfg) {
cJSON *pRoot = cJSON_CreateObject();
cJSON_AddItemToObject(pRoot, "SSyncCfg", syncCfg2Json(&(pRaftCfg->cfg)));
cJSON_AddNumberToObject(pRoot, "isStandBy", pRaftCfg->isStandBy);
- cJSON_AddNumberToObject(pRoot, "snapshotEnable", pRaftCfg->snapshotEnable);
+ cJSON_AddNumberToObject(pRoot, "snapshotStrategy", pRaftCfg->snapshotStrategy);
+ cJSON_AddNumberToObject(pRoot, "batchSize", pRaftCfg->batchSize);
char buf64[128];
- snprintf(buf64, sizeof(buf64), "%ld", pRaftCfg->lastConfigIndex);
+ snprintf(buf64, sizeof(buf64), "%" PRId64, pRaftCfg->lastConfigIndex);
cJSON_AddStringToObject(pRoot, "lastConfigIndex", buf64);
cJSON_AddNumberToObject(pRoot, "configIndexCount", pRaftCfg->configIndexCount);
cJSON *pIndexArr = cJSON_CreateArray();
cJSON_AddItemToObject(pRoot, "configIndexArr", pIndexArr);
for (int i = 0; i < pRaftCfg->configIndexCount; ++i) {
- snprintf(buf64, sizeof(buf64), "%ld", (pRaftCfg->configIndexArr)[i]);
+ snprintf(buf64, sizeof(buf64), "%" PRId64, (pRaftCfg->configIndexArr)[i]);
cJSON *pIndexObj = cJSON_CreateObject();
cJSON_AddStringToObject(pIndexObj, "index", buf64);
cJSON_AddItemToArray(pIndexArr, pIndexObj);
@@ -202,15 +212,25 @@ char *raftCfg2Str(SRaftCfg *pRaftCfg) {
}
int32_t raftCfgCreateFile(SSyncCfg *pCfg, SRaftCfgMeta meta, const char *path) {
- assert(pCfg != NULL);
+ ASSERT(pCfg != NULL);
TdFilePtr pFile = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE);
- assert(pFile != NULL);
+ if (pFile == NULL) {
+ int32_t err = terrno;
+ const char *errStr = tstrerror(err);
+ int32_t sysErr = errno;
+ const char *sysErrStr = strerror(errno);
+ sError("create raft cfg file error, err:%d %X, msg:%s, syserr:%d, sysmsg:%s", err, err, errStr, sysErr, sysErrStr);
+ ASSERT(0);
+
+ return -1;
+ }
SRaftCfg raftCfg;
raftCfg.cfg = *pCfg;
raftCfg.isStandBy = meta.isStandBy;
- raftCfg.snapshotEnable = meta.snapshotEnable;
+ raftCfg.batchSize = meta.batchSize;
+ raftCfg.snapshotStrategy = meta.snapshotStrategy;
raftCfg.lastConfigIndex = meta.lastConfigIndex;
raftCfg.configIndexCount = 1;
memset(raftCfg.configIndexArr, 0, sizeof(raftCfg.configIndexArr));
@@ -222,10 +242,10 @@ int32_t raftCfgCreateFile(SSyncCfg *pCfg, SRaftCfgMeta meta, const char *path) {
ASSERT(strlen(s) + 1 <= CONFIG_FILE_LEN);
snprintf(buf, sizeof(buf), "%s", s);
int64_t ret = taosWriteFile(pFile, buf, sizeof(buf));
- assert(ret == sizeof(buf));
+ ASSERT(ret == sizeof(buf));
// int64_t ret = taosWriteFile(pFile, s, strlen(s) + 1);
- // assert(ret == strlen(s) + 1);
+ // ASSERT(ret == strlen(s) + 1);
taosMemoryFree(s);
taosCloseFile(&pFile);
@@ -239,8 +259,11 @@ int32_t raftCfgFromJson(const cJSON *pRoot, SRaftCfg *pRaftCfg) {
cJSON *pJsonIsStandBy = cJSON_GetObjectItem(pJson, "isStandBy");
pRaftCfg->isStandBy = cJSON_GetNumberValue(pJsonIsStandBy);
- cJSON *pJsonSnapshotEnable = cJSON_GetObjectItem(pJson, "snapshotEnable");
- pRaftCfg->snapshotEnable = cJSON_GetNumberValue(pJsonSnapshotEnable);
+ cJSON *pJsonBatchSize = cJSON_GetObjectItem(pJson, "batchSize");
+ pRaftCfg->batchSize = cJSON_GetNumberValue(pJsonBatchSize);
+
+ cJSON *pJsonSnapshotStrategy = cJSON_GetObjectItem(pJson, "snapshotStrategy");
+ pRaftCfg->snapshotStrategy = cJSON_GetNumberValue(pJsonSnapshotStrategy);
cJSON *pJsonLastConfigIndex = cJSON_GetObjectItem(pJson, "lastConfigIndex");
pRaftCfg->lastConfigIndex = atoll(cJSON_GetStringValue(pJsonLastConfigIndex));
@@ -250,15 +273,15 @@ int32_t raftCfgFromJson(const cJSON *pRoot, SRaftCfg *pRaftCfg) {
cJSON *pIndexArr = cJSON_GetObjectItem(pJson, "configIndexArr");
int arraySize = cJSON_GetArraySize(pIndexArr);
- assert(arraySize == pRaftCfg->configIndexCount);
+ ASSERT(arraySize == pRaftCfg->configIndexCount);
memset(pRaftCfg->configIndexArr, 0, sizeof(pRaftCfg->configIndexArr));
for (int i = 0; i < arraySize; ++i) {
cJSON *pIndexObj = cJSON_GetArrayItem(pIndexArr, i);
- assert(pIndexObj != NULL);
+ ASSERT(pIndexObj != NULL);
cJSON *pIndex = cJSON_GetObjectItem(pIndexObj, "index");
- assert(cJSON_IsString(pIndex));
+ ASSERT(cJSON_IsString(pIndex));
(pRaftCfg->configIndexArr)[i] = atoll(pIndex->valuestring);
}
@@ -271,10 +294,10 @@ int32_t raftCfgFromJson(const cJSON *pRoot, SRaftCfg *pRaftCfg) {
int32_t raftCfgFromStr(const char *s, SRaftCfg *pRaftCfg) {
cJSON *pRoot = cJSON_Parse(s);
- assert(pRoot != NULL);
+ ASSERT(pRoot != NULL);
int32_t ret = raftCfgFromJson(pRoot, pRaftCfg);
- assert(ret == 0);
+ ASSERT(ret == 0);
cJSON_Delete(pRoot);
return 0;
@@ -283,58 +306,58 @@ int32_t raftCfgFromStr(const char *s, SRaftCfg *pRaftCfg) {
// for debug ----------------------
void syncCfgPrint(SSyncCfg *pCfg) {
char *serialized = syncCfg2Str(pCfg);
- printf("syncCfgPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("syncCfgPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncCfgPrint2(char *s, SSyncCfg *pCfg) {
char *serialized = syncCfg2Str(pCfg);
- printf("syncCfgPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("syncCfgPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void syncCfgLog(SSyncCfg *pCfg) {
char *serialized = syncCfg2Str(pCfg);
- sTrace("syncCfgLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("syncCfgLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void syncCfgLog2(char *s, SSyncCfg *pCfg) {
char *serialized = syncCfg2Str(pCfg);
- sTrace("syncCfgLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncCfgLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
void syncCfgLog3(char *s, SSyncCfg *pCfg) {
char *serialized = syncCfg2SimpleStr(pCfg);
- sTrace("syncCfgLog3 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("syncCfgLog3 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
void raftCfgPrint(SRaftCfg *pCfg) {
char *serialized = raftCfg2Str(pCfg);
- printf("raftCfgPrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("raftCfgPrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void raftCfgPrint2(char *s, SRaftCfg *pCfg) {
char *serialized = raftCfg2Str(pCfg);
- printf("raftCfgPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("raftCfgPrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void raftCfgLog(SRaftCfg *pCfg) {
char *serialized = raftCfg2Str(pCfg);
- sTrace("raftCfgLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("raftCfgLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void raftCfgLog2(char *s, SRaftCfg *pCfg) {
char *serialized = raftCfg2Str(pCfg);
- sTrace("raftCfgLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("raftCfgLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
diff --git a/source/libs/sync/src/syncRaftEntry.c b/source/libs/sync/src/syncRaftEntry.c
index 05a2dbaa3f36b00cd9202844d65f97f022ba22ae..89e67fab288b5a2a0594829b6a39b27bdf698c44 100644
--- a/source/libs/sync/src/syncRaftEntry.c
+++ b/source/libs/sync/src/syncRaftEntry.c
@@ -19,7 +19,7 @@
SSyncRaftEntry* syncEntryBuild(uint32_t dataLen) {
uint32_t bytes = sizeof(SSyncRaftEntry) + dataLen;
SSyncRaftEntry* pEntry = taosMemoryMalloc(bytes);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
memset(pEntry, 0, bytes);
pEntry->bytes = bytes;
pEntry->dataLen = dataLen;
@@ -29,14 +29,14 @@ SSyncRaftEntry* syncEntryBuild(uint32_t dataLen) {
// step 4. SyncClientRequest => SSyncRaftEntry, add term, index
SSyncRaftEntry* syncEntryBuild2(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index) {
SSyncRaftEntry* pEntry = syncEntryBuild3(pMsg, term, index);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
return pEntry;
}
SSyncRaftEntry* syncEntryBuild3(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index) {
SSyncRaftEntry* pEntry = syncEntryBuild(pMsg->dataLen);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
pEntry->msgType = pMsg->msgType;
pEntry->originalRpcType = pMsg->originalRpcType;
@@ -50,6 +50,22 @@ SSyncRaftEntry* syncEntryBuild3(SyncClientRequest* pMsg, SyncTerm term, SyncInde
return pEntry;
}
+SSyncRaftEntry* syncEntryBuild4(SRpcMsg* pOriginalMsg, SyncTerm term, SyncIndex index) {
+ SSyncRaftEntry* pEntry = syncEntryBuild(pOriginalMsg->contLen);
+ ASSERT(pEntry != NULL);
+
+ pEntry->msgType = TDMT_SYNC_CLIENT_REQUEST;
+ pEntry->originalRpcType = pOriginalMsg->msgType;
+ pEntry->seqNum = 0;
+ pEntry->isWeak = 0;
+ pEntry->term = term;
+ pEntry->index = index;
+ pEntry->dataLen = pOriginalMsg->contLen;
+ memcpy(pEntry->data, pOriginalMsg->pCont, pOriginalMsg->contLen);
+
+ return pEntry;
+}
+
SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId) {
// init rpcMsg
SMsgHead head;
@@ -63,7 +79,7 @@ SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId)
memcpy(rpcMsg.pCont, &head, sizeof(head));
SSyncRaftEntry* pEntry = syncEntryBuild(rpcMsg.contLen);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
pEntry->msgType = TDMT_SYNC_CLIENT_REQUEST;
pEntry->originalRpcType = TDMT_SYNC_NOOP;
@@ -72,7 +88,7 @@ SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId)
pEntry->term = term;
pEntry->index = index;
- assert(pEntry->dataLen == rpcMsg.contLen);
+ ASSERT(pEntry->dataLen == rpcMsg.contLen);
memcpy(pEntry->data, rpcMsg.pCont, rpcMsg.contLen);
rpcFreeCont(rpcMsg.pCont);
@@ -88,7 +104,7 @@ void syncEntryDestory(SSyncRaftEntry* pEntry) {
// step 5. SSyncRaftEntry => bin, to raft log
char* syncEntrySerialize(const SSyncRaftEntry* pEntry, uint32_t* len) {
char* buf = taosMemoryMalloc(pEntry->bytes);
- assert(buf != NULL);
+ ASSERT(buf != NULL);
memcpy(buf, pEntry, pEntry->bytes);
if (len != NULL) {
*len = pEntry->bytes;
@@ -100,9 +116,9 @@ char* syncEntrySerialize(const SSyncRaftEntry* pEntry, uint32_t* len) {
SSyncRaftEntry* syncEntryDeserialize(const char* buf, uint32_t len) {
uint32_t bytes = *((uint32_t*)buf);
SSyncRaftEntry* pEntry = taosMemoryMalloc(bytes);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
memcpy(pEntry, buf, len);
- assert(len == pEntry->bytes);
+ ASSERT(len == pEntry->bytes);
return pEntry;
}
@@ -114,12 +130,12 @@ cJSON* syncEntry2Json(const SSyncRaftEntry* pEntry) {
cJSON_AddNumberToObject(pRoot, "bytes", pEntry->bytes);
cJSON_AddNumberToObject(pRoot, "msgType", pEntry->msgType);
cJSON_AddNumberToObject(pRoot, "originalRpcType", pEntry->originalRpcType);
- snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->seqNum);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pEntry->seqNum);
cJSON_AddStringToObject(pRoot, "seqNum", u64buf);
cJSON_AddNumberToObject(pRoot, "isWeak", pEntry->isWeak);
- snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->term);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pEntry->term);
cJSON_AddStringToObject(pRoot, "term", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->index);
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, pEntry->index);
cJSON_AddStringToObject(pRoot, "index", u64buf);
cJSON_AddNumberToObject(pRoot, "dataLen", pEntry->dataLen);
@@ -180,3 +196,489 @@ void syncEntryLog2(char* s, const SSyncRaftEntry* pObj) {
sTrace("syncEntryLog2 | len:%zu | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
+
+//-----------------------------------
+SRaftEntryHashCache* raftCacheCreate(SSyncNode* pSyncNode, int32_t maxCount) {
+ SRaftEntryHashCache* pCache = taosMemoryMalloc(sizeof(SRaftEntryHashCache));
+ if (pCache == NULL) {
+ sError("vgId:%d raft cache create error", pSyncNode->vgId);
+ return NULL;
+ }
+
+ pCache->pEntryHash =
+ taosHashInit(sizeof(SyncIndex), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
+ if (pCache->pEntryHash == NULL) {
+ sError("vgId:%d raft cache create hash error", pSyncNode->vgId);
+ return NULL;
+ }
+
+ taosThreadMutexInit(&(pCache->mutex), NULL);
+ pCache->maxCount = maxCount;
+ pCache->currentCount = 0;
+ pCache->pSyncNode = pSyncNode;
+
+ return pCache;
+}
+
+void raftCacheDestroy(SRaftEntryHashCache* pCache) {
+ if (pCache != NULL) {
+ taosThreadMutexLock(&(pCache->mutex));
+ taosHashCleanup(pCache->pEntryHash);
+ taosThreadMutexUnlock(&(pCache->mutex));
+ taosThreadMutexDestroy(&(pCache->mutex));
+ taosMemoryFree(pCache);
+ }
+}
+
+// success, return 1
+// max count, return 0
+// error, return -1
+int32_t raftCachePutEntry(struct SRaftEntryHashCache* pCache, SSyncRaftEntry* pEntry) {
+ taosThreadMutexLock(&(pCache->mutex));
+
+ if (pCache->currentCount >= pCache->maxCount) {
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+ }
+
+ taosHashPut(pCache->pEntryHash, &(pEntry->index), sizeof(pEntry->index), pEntry, pEntry->bytes);
+ ++(pCache->currentCount);
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "raft cache add, type:%s,%d, type2:%s,%d, index:%" PRId64 ", bytes:%d",
+ TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType,
+ pEntry->index, pEntry->bytes);
+ syncNodeEventLog(pCache->pSyncNode, eventLog);
+ } while (0);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 1;
+}
+
+// success, return 0
+// error, return -1
+// not exist, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST
+int32_t raftCacheGetEntry(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) {
+ if (ppEntry == NULL) {
+ return -1;
+ }
+ *ppEntry = NULL;
+
+ taosThreadMutexLock(&(pCache->mutex));
+ void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index));
+ if (pTmp != NULL) {
+ SSyncRaftEntry* pEntry = pTmp;
+ *ppEntry = taosMemoryMalloc(pEntry->bytes);
+ memcpy(*ppEntry, pTmp, pEntry->bytes);
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "raft cache get, type:%s,%d, type2:%s,%d, index:%" PRId64,
+ TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType),
+ (*ppEntry)->originalRpcType, (*ppEntry)->index);
+ syncNodeEventLog(pCache->pSyncNode, eventLog);
+ } while (0);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+ }
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ terrno = TSDB_CODE_WAL_LOG_NOT_EXIST;
+ return -1;
+}
+
+// success, return 0
+// error, return -1
+// not exist, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST
+int32_t raftCacheGetEntryP(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) {
+ if (ppEntry == NULL) {
+ return -1;
+ }
+ *ppEntry = NULL;
+
+ taosThreadMutexLock(&(pCache->mutex));
+ void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index));
+ if (pTmp != NULL) {
+ SSyncRaftEntry* pEntry = pTmp;
+ *ppEntry = pEntry;
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "raft cache get, type:%s,%d, type2:%s,%d, index:%" PRId64,
+ TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType),
+ (*ppEntry)->originalRpcType, (*ppEntry)->index);
+ syncNodeEventLog(pCache->pSyncNode, eventLog);
+ } while (0);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+ }
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ terrno = TSDB_CODE_WAL_LOG_NOT_EXIST;
+ return -1;
+}
+
+int32_t raftCacheDelEntry(struct SRaftEntryHashCache* pCache, SyncIndex index) {
+ taosThreadMutexLock(&(pCache->mutex));
+ taosHashRemove(pCache->pEntryHash, &index, sizeof(index));
+ --(pCache->currentCount);
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+}
+
+int32_t raftCacheGetAndDel(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) {
+ if (ppEntry == NULL) {
+ return -1;
+ }
+ *ppEntry = NULL;
+
+ taosThreadMutexLock(&(pCache->mutex));
+ void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index));
+ if (pTmp != NULL) {
+ SSyncRaftEntry* pEntry = pTmp;
+ *ppEntry = taosMemoryMalloc(pEntry->bytes);
+ memcpy(*ppEntry, pTmp, pEntry->bytes);
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "raft cache get-and-del, type:%s,%d, type2:%s,%d, index:%" PRId64,
+ TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType),
+ (*ppEntry)->originalRpcType, (*ppEntry)->index);
+ syncNodeEventLog(pCache->pSyncNode, eventLog);
+ } while (0);
+
+ taosHashRemove(pCache->pEntryHash, &index, sizeof(index));
+ --(pCache->currentCount);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+ }
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ terrno = TSDB_CODE_WAL_LOG_NOT_EXIST;
+ return -1;
+}
+
+int32_t raftCacheClear(struct SRaftEntryHashCache* pCache) {
+ taosThreadMutexLock(&(pCache->mutex));
+ taosHashClear(pCache->pEntryHash);
+ pCache->currentCount = 0;
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+}
+
+//-----------------------------------
+cJSON* raftCache2Json(SRaftEntryHashCache* pCache) {
+ char u64buf[128] = {0};
+ cJSON* pRoot = cJSON_CreateObject();
+
+ if (pCache != NULL) {
+ taosThreadMutexLock(&(pCache->mutex));
+
+ snprintf(u64buf, sizeof(u64buf), "%p", pCache->pSyncNode);
+ cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf);
+ cJSON_AddNumberToObject(pRoot, "currentCount", pCache->currentCount);
+ cJSON_AddNumberToObject(pRoot, "maxCount", pCache->maxCount);
+ cJSON* pEntries = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "entries", pEntries);
+
+ SSyncRaftEntry* pIter = (SSyncRaftEntry*)taosHashIterate(pCache->pEntryHash, NULL);
+ if (pIter != NULL) {
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)pIter;
+ cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry));
+ }
+ while (pIter) {
+ pIter = taosHashIterate(pCache->pEntryHash, pIter);
+ if (pIter != NULL) {
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)pIter;
+ cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry));
+ }
+ }
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ }
+
+ cJSON* pJson = cJSON_CreateObject();
+ cJSON_AddItemToObject(pJson, "SRaftEntryHashCache", pRoot);
+ return pJson;
+}
+
+char* raftCache2Str(SRaftEntryHashCache* pCache) {
+ cJSON* pJson = raftCache2Json(pCache);
+ char* serialized = cJSON_Print(pJson);
+ cJSON_Delete(pJson);
+ return serialized;
+}
+
+void raftCachePrint(SRaftEntryHashCache* pCache) {
+ char* serialized = raftCache2Str(pCache);
+ printf("raftCachePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void raftCachePrint2(char* s, SRaftEntryHashCache* pCache) {
+ char* serialized = raftCache2Str(pCache);
+ printf("raftCachePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void raftCacheLog(SRaftEntryHashCache* pCache) {
+ char* serialized = raftCache2Str(pCache);
+ sTrace("raftCacheLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
+ taosMemoryFree(serialized);
+}
+
+void raftCacheLog2(char* s, SRaftEntryHashCache* pCache) {
+ if (gRaftDetailLog) {
+ char* serialized = raftCache2Str(pCache);
+ sTraceLong("raftCacheLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
+ taosMemoryFree(serialized);
+ }
+}
+
+//-----------------------------------
+static char* keyFn(const void* pData) {
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)pData;
+ return (char*)(&(pEntry->index));
+}
+
+static int cmpFn(const void* p1, const void* p2) { return memcmp(p1, p2, sizeof(SyncIndex)); }
+
+SRaftEntryCache* raftEntryCacheCreate(SSyncNode* pSyncNode, int32_t maxCount) {
+ SRaftEntryCache* pCache = taosMemoryMalloc(sizeof(SRaftEntryCache));
+ if (pCache == NULL) {
+ sError("vgId:%d raft cache create error", pSyncNode->vgId);
+ return NULL;
+ }
+
+ pCache->pSkipList =
+ tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_BINARY, sizeof(SyncIndex), cmpFn, SL_ALLOW_DUP_KEY, keyFn);
+ if (pCache->pSkipList == NULL) {
+ sError("vgId:%d raft cache create hash error", pSyncNode->vgId);
+ return NULL;
+ }
+
+ taosThreadMutexInit(&(pCache->mutex), NULL);
+ pCache->maxCount = maxCount;
+ pCache->currentCount = 0;
+ pCache->pSyncNode = pSyncNode;
+
+ return pCache;
+}
+
+void raftEntryCacheDestroy(SRaftEntryCache* pCache) {
+ if (pCache != NULL) {
+ taosThreadMutexLock(&(pCache->mutex));
+ tSkipListDestroy(pCache->pSkipList);
+ taosThreadMutexUnlock(&(pCache->mutex));
+ taosThreadMutexDestroy(&(pCache->mutex));
+ taosMemoryFree(pCache);
+ }
+}
+
+// success, return 1
+// max count, return 0
+// error, return -1
+int32_t raftEntryCachePutEntry(struct SRaftEntryCache* pCache, SSyncRaftEntry* pEntry) {
+ taosThreadMutexLock(&(pCache->mutex));
+
+ if (pCache->currentCount >= pCache->maxCount) {
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 0;
+ }
+
+ SSkipListNode* pSkipListNode = tSkipListPut(pCache->pSkipList, pEntry);
+ ASSERT(pSkipListNode != NULL);
+ ++(pCache->currentCount);
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "raft cache add, type:%s,%d, type2:%s,%d, index:%" PRId64 ", bytes:%d",
+ TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType,
+ pEntry->index, pEntry->bytes);
+ syncNodeEventLog(pCache->pSyncNode, eventLog);
+ } while (0);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return 1;
+}
+
+// find one, return 1
+// not found, return 0
+// error, return -1
+int32_t raftEntryCacheGetEntry(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) {
+ ASSERT(ppEntry != NULL);
+ SSyncRaftEntry* pEntry = NULL;
+ int32_t code = raftEntryCacheGetEntryP(pCache, index, &pEntry);
+ if (code == 1) {
+ *ppEntry = taosMemoryMalloc(pEntry->bytes);
+ memcpy(*ppEntry, pEntry, pEntry->bytes);
+ } else {
+ *ppEntry = NULL;
+ }
+ return code;
+}
+
+// find one, return 1
+// not found, return 0
+// error, return -1
+int32_t raftEntryCacheGetEntryP(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) {
+ taosThreadMutexLock(&(pCache->mutex));
+
+ SyncIndex index2 = index;
+ int32_t code = 0;
+
+ SArray* entryPArray = tSkipListGet(pCache->pSkipList, (char*)(&index2));
+ int32_t arraySize = taosArrayGetSize(entryPArray);
+ if (arraySize == 1) {
+ SSkipListNode** ppNode = (SSkipListNode**)taosArrayGet(entryPArray, 0);
+ ASSERT(*ppNode != NULL);
+ *ppEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(*ppNode);
+ code = 1;
+
+ } else if (arraySize == 0) {
+ code = 0;
+
+ } else {
+ ASSERT(0);
+
+ code = -1;
+ }
+ taosArrayDestroy(entryPArray);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return code;
+}
+
+// count = -1, clear all
+// count >= 0, clear count
+// return -1, error
+// return delete count
+int32_t raftEntryCacheClear(struct SRaftEntryCache* pCache, int32_t count) {
+ taosThreadMutexLock(&(pCache->mutex));
+ int32_t returnCnt = 0;
+
+ if (count == -1) {
+ // clear all
+ SSkipListIterator* pIter = tSkipListCreateIter(pCache->pSkipList);
+ while (tSkipListIterNext(pIter)) {
+ SSkipListNode* pNode = tSkipListIterGet(pIter);
+ ASSERT(pNode != NULL);
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(pNode);
+ syncEntryDestory(pEntry);
+ ++returnCnt;
+ }
+ tSkipListDestroyIter(pIter);
+
+ tSkipListDestroy(pCache->pSkipList);
+ pCache->pSkipList =
+ tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_BINARY, sizeof(SyncIndex), cmpFn, SL_ALLOW_DUP_KEY, keyFn);
+ ASSERT(pCache->pSkipList != NULL);
+
+ } else {
+ // clear count
+ int i = 0;
+ SSkipListIterator* pIter = tSkipListCreateIter(pCache->pSkipList);
+ SArray* delNodeArray = taosArrayInit(0, sizeof(SSkipListNode*));
+
+ // free entry
+ while (tSkipListIterNext(pIter)) {
+ SSkipListNode* pNode = tSkipListIterGet(pIter);
+ ASSERT(pNode != NULL);
+ if (i++ >= count) {
+ break;
+ }
+
+ // sDebug("push pNode:%p", pNode);
+ taosArrayPush(delNodeArray, &pNode);
+ ++returnCnt;
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(pNode);
+ syncEntryDestory(pEntry);
+ }
+ tSkipListDestroyIter(pIter);
+
+ // delete skiplist node
+ int32_t arraySize = taosArrayGetSize(delNodeArray);
+ for (int32_t i = 0; i < arraySize; ++i) {
+ SSkipListNode** ppNode = taosArrayGet(delNodeArray, i);
+ // sDebug("get pNode:%p", *ppNode);
+ tSkipListRemoveNode(pCache->pSkipList, *ppNode);
+ }
+ taosArrayDestroy(delNodeArray);
+ }
+
+ pCache->currentCount -= returnCnt;
+ taosThreadMutexUnlock(&(pCache->mutex));
+ return returnCnt;
+}
+
+cJSON* raftEntryCache2Json(SRaftEntryCache* pCache) {
+ char u64buf[128] = {0};
+ cJSON* pRoot = cJSON_CreateObject();
+
+ if (pCache != NULL) {
+ taosThreadMutexLock(&(pCache->mutex));
+
+ snprintf(u64buf, sizeof(u64buf), "%p", pCache->pSyncNode);
+ cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf);
+ cJSON_AddNumberToObject(pRoot, "currentCount", pCache->currentCount);
+ cJSON_AddNumberToObject(pRoot, "maxCount", pCache->maxCount);
+ cJSON* pEntries = cJSON_CreateArray();
+ cJSON_AddItemToObject(pRoot, "entries", pEntries);
+
+ SSkipListIterator* pIter = tSkipListCreateIter(pCache->pSkipList);
+ while (tSkipListIterNext(pIter)) {
+ SSkipListNode* pNode = tSkipListIterGet(pIter);
+ ASSERT(pNode != NULL);
+ SSyncRaftEntry* pEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(pNode);
+ cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry));
+ }
+ tSkipListDestroyIter(pIter);
+
+ taosThreadMutexUnlock(&(pCache->mutex));
+ }
+
+ cJSON* pJson = cJSON_CreateObject();
+ cJSON_AddItemToObject(pJson, "SRaftEntryCache", pRoot);
+ return pJson;
+}
+
+char* raftEntryCache2Str(SRaftEntryCache* pObj) {
+ cJSON* pJson = raftEntryCache2Json(pObj);
+ char* serialized = cJSON_Print(pJson);
+ cJSON_Delete(pJson);
+ return serialized;
+}
+
+void raftEntryCachePrint(SRaftEntryCache* pObj) {
+ char* serialized = raftEntryCache2Str(pObj);
+ printf("raftEntryCachePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void raftEntryCachePrint2(char* s, SRaftEntryCache* pObj) {
+ char* serialized = raftEntryCache2Str(pObj);
+ printf("raftEntryCachePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
+ fflush(NULL);
+ taosMemoryFree(serialized);
+}
+
+void raftEntryCacheLog(SRaftEntryCache* pObj) {
+ char* serialized = raftEntryCache2Str(pObj);
+ sTrace("raftEntryCacheLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
+ taosMemoryFree(serialized);
+}
+
+void raftEntryCacheLog2(char* s, SRaftEntryCache* pObj) {
+ if (gRaftDetailLog) {
+ char* serialized = raftEntryCache2Str(pObj);
+ sTraceLong("raftEntryCacheLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
+ taosMemoryFree(serialized);
+ }
+}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c
index 79d9b329c10bf8e2fc6db6ee7865bd31fbc764ae..edc01c9a05711648b819880a3936e3666fe07bc8 100644
--- a/source/libs/sync/src/syncRaftLog.c
+++ b/source/libs/sync/src/syncRaftLog.c
@@ -16,25 +16,29 @@
#include "syncRaftLog.h"
#include "syncRaftCfg.h"
#include "syncRaftStore.h"
-#include "wal.h"
-// refactor, log[0 .. n] ==> log[m .. n]
-static int32_t raftLogSetBeginIndex(struct SSyncLogStore* pLogStore, SyncIndex beginIndex);
+//-------------------------------
+// log[m .. n]
+
+// public function
+static int32_t raftLogRestoreFromSnapshot(struct SSyncLogStore* pLogStore, SyncIndex snapshotIndex);
static SyncIndex raftLogBeginIndex(struct SSyncLogStore* pLogStore);
static SyncIndex raftLogEndIndex(struct SSyncLogStore* pLogStore);
static SyncIndex raftLogWriteIndex(struct SSyncLogStore* pLogStore);
static bool raftLogIsEmpty(struct SSyncLogStore* pLogStore);
static int32_t raftLogEntryCount(struct SSyncLogStore* pLogStore);
-static bool raftLogInRange(struct SSyncLogStore* pLogStore, SyncIndex index);
static SyncIndex raftLogLastIndex(struct SSyncLogStore* pLogStore);
static SyncTerm raftLogLastTerm(struct SSyncLogStore* pLogStore);
static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry);
static int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncRaftEntry** ppEntry);
static int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex fromIndex);
+static bool raftLogExist(struct SSyncLogStore* pLogStore, SyncIndex index);
+// private function
static int32_t raftLogGetLastEntry(SSyncLogStore* pLogStore, SSyncRaftEntry** ppLastEntry);
//-------------------------------
+// log[0 .. n]
static SSyncRaftEntry* logStoreGetLastEntry(SSyncLogStore* pLogStore);
static SyncIndex logStoreLastIndex(SSyncLogStore* pLogStore);
static SyncTerm logStoreLastTerm(SSyncLogStore* pLogStore);
@@ -44,34 +48,103 @@ static int32_t logStoreTruncate(SSyncLogStore* pLogStore, SyncIndex from
static int32_t logStoreUpdateCommitIndex(SSyncLogStore* pLogStore, SyncIndex index);
static SyncIndex logStoreGetCommitIndex(SSyncLogStore* pLogStore);
-// refactor, log[0 .. n] ==> log[m .. n]
-static int32_t raftLogSetBeginIndex(struct SSyncLogStore* pLogStore, SyncIndex beginIndex) {
- sTrace("raftLogSetBeginIndex beginIndex:%ld", beginIndex);
+//-------------------------------
+SSyncLogStore* logStoreCreate(SSyncNode* pSyncNode) {
+ SSyncLogStore* pLogStore = taosMemoryMalloc(sizeof(SSyncLogStore));
+ ASSERT(pLogStore != NULL);
+
+ pLogStore->data = taosMemoryMalloc(sizeof(SSyncLogStoreData));
+ ASSERT(pLogStore->data != NULL);
+
+ SSyncLogStoreData* pData = pLogStore->data;
+ pData->pSyncNode = pSyncNode;
+ pData->pWal = pSyncNode->pWal;
+ ASSERT(pData->pWal != NULL);
+
+ taosThreadMutexInit(&(pData->mutex), NULL);
+ pData->pWalHandle = walOpenReader(pData->pWal, NULL);
+ ASSERT(pData->pWalHandle != NULL);
+
+ pLogStore->appendEntry = logStoreAppendEntry;
+ pLogStore->getEntry = logStoreGetEntry;
+ pLogStore->truncate = logStoreTruncate;
+ pLogStore->getLastIndex = logStoreLastIndex;
+ pLogStore->getLastTerm = logStoreLastTerm;
+ pLogStore->updateCommitIndex = logStoreUpdateCommitIndex;
+ pLogStore->getCommitIndex = logStoreGetCommitIndex;
+
+ pLogStore->syncLogRestoreFromSnapshot = raftLogRestoreFromSnapshot;
+ pLogStore->syncLogBeginIndex = raftLogBeginIndex;
+ pLogStore->syncLogEndIndex = raftLogEndIndex;
+ pLogStore->syncLogIsEmpty = raftLogIsEmpty;
+ pLogStore->syncLogEntryCount = raftLogEntryCount;
+ pLogStore->syncLogLastIndex = raftLogLastIndex;
+ pLogStore->syncLogLastTerm = raftLogLastTerm;
+ pLogStore->syncLogAppendEntry = raftLogAppendEntry;
+ pLogStore->syncLogGetEntry = raftLogGetEntry;
+ pLogStore->syncLogTruncate = raftLogTruncate;
+ pLogStore->syncLogWriteIndex = raftLogWriteIndex;
+ pLogStore->syncLogExist = raftLogExist;
+
+ return pLogStore;
+}
+
+void logStoreDestory(SSyncLogStore* pLogStore) {
+ if (pLogStore != NULL) {
+ SSyncLogStoreData* pData = pLogStore->data;
- // if beginIndex == 0, donot need call this funciton
- ASSERT(beginIndex > 0);
+ taosThreadMutexLock(&(pData->mutex));
+ if (pData->pWalHandle != NULL) {
+ walCloseReader(pData->pWalHandle);
+ pData->pWalHandle = NULL;
+ }
+ taosThreadMutexUnlock(&(pData->mutex));
+ taosThreadMutexDestroy(&(pData->mutex));
+
+ taosMemoryFree(pLogStore->data);
+ taosMemoryFree(pLogStore);
+ }
+}
+
+//-------------------------------
+// log[m .. n]
+static int32_t raftLogRestoreFromSnapshot(struct SSyncLogStore* pLogStore, SyncIndex snapshotIndex) {
+ ASSERT(snapshotIndex >= 0);
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
- pData->beginIndex = beginIndex;
- walRestoreFromSnapshot(pWal, beginIndex - 1);
+ int32_t code = walRestoreFromSnapshot(pWal, snapshotIndex);
+ if (code != 0) {
+ int32_t err = terrno;
+ const char* errStr = tstrerror(err);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf),
+ "wal restore from snapshot error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ snapshotIndex, err, err, errStr, sysErr, sysErrStr);
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+
+ return -1;
+ }
+
return 0;
}
-int32_t raftLogResetBeginIndex(struct SSyncLogStore* pLogStore) { return 0; }
-
static SyncIndex raftLogBeginIndex(struct SSyncLogStore* pLogStore) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
- return pData->beginIndex;
+ SyncIndex firstVer = walGetFirstVer(pWal);
+ return firstVer;
}
static SyncIndex raftLogEndIndex(struct SSyncLogStore* pLogStore) { return raftLogLastIndex(pLogStore); }
static bool raftLogIsEmpty(struct SSyncLogStore* pLogStore) {
- SyncIndex beginIndex = raftLogBeginIndex(pLogStore);
- SyncIndex endIndex = raftLogEndIndex(pLogStore);
- return (endIndex < beginIndex);
+ SSyncLogStoreData* pData = pLogStore->data;
+ SWal* pWal = pData->pWal;
+ return walIsEmpty(pWal);
}
static int32_t raftLogEntryCount(struct SSyncLogStore* pLogStore) {
@@ -81,38 +154,13 @@ static int32_t raftLogEntryCount(struct SSyncLogStore* pLogStore) {
return count > 0 ? count : 0;
}
-static bool raftLogInRange(struct SSyncLogStore* pLogStore, SyncIndex index) {
- SyncIndex beginIndex = raftLogBeginIndex(pLogStore);
- SyncIndex endIndex = raftLogEndIndex(pLogStore);
- if (index >= beginIndex && index <= endIndex) {
- return true;
- } else {
- return false;
- }
-}
-
static SyncIndex raftLogLastIndex(struct SSyncLogStore* pLogStore) {
SyncIndex lastIndex;
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
SyncIndex lastVer = walGetLastVer(pWal);
- SyncIndex firstVer = walGetFirstVer(pWal);
-
- if (lastVer < firstVer) {
- // no record
- lastIndex = -1;
-
- } else {
- if (firstVer >= 0) {
- lastIndex = lastVer;
- } else if (firstVer == -1) {
- lastIndex = -1;
- } else {
- ASSERT(0);
- }
- }
- return lastIndex;
+ return lastVer;
}
static SyncIndex raftLogWriteIndex(struct SSyncLogStore* pLogStore) {
@@ -122,31 +170,87 @@ static SyncIndex raftLogWriteIndex(struct SSyncLogStore* pLogStore) {
return lastVer + 1;
}
+static bool raftLogExist(struct SSyncLogStore* pLogStore, SyncIndex index) {
+ SSyncLogStoreData* pData = pLogStore->data;
+ SWal* pWal = pData->pWal;
+ bool b = walLogExist(pWal, index);
+ return b;
+}
+
+// if success, return last term
+// if not log, return 0
+// if error, return SYNC_TERM_INVALID
static SyncTerm raftLogLastTerm(struct SSyncLogStore* pLogStore) {
- SyncTerm lastTerm = 0;
- if (raftLogEntryCount(pLogStore) == 0) {
- lastTerm = 0;
+ SSyncLogStoreData* pData = pLogStore->data;
+ SWal* pWal = pData->pWal;
+ if (walIsEmpty(pWal)) {
+ return 0;
} else {
SSyncRaftEntry* pLastEntry;
int32_t code = raftLogGetLastEntry(pLogStore, &pLastEntry);
- ASSERT(code == 0);
- if (pLastEntry != NULL) {
- lastTerm = pLastEntry->term;
+ if (code == 0 && pLastEntry != NULL) {
+ SyncTerm lastTerm = pLastEntry->term;
taosMemoryFree(pLastEntry);
+ return lastTerm;
+ } else {
+ return SYNC_TERM_INVALID;
}
}
- return lastTerm;
+
+ // can not be here!
+ return SYNC_TERM_INVALID;
+}
+
+static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) {
+ SSyncLogStoreData* pData = pLogStore->data;
+ SWal* pWal = pData->pWal;
+
+ SyncIndex index = 0;
+ SWalSyncInfo syncMeta;
+ syncMeta.isWeek = pEntry->isWeak;
+ syncMeta.seqNum = pEntry->seqNum;
+ syncMeta.term = pEntry->term;
+ index = walAppendLog(pWal, pEntry->originalRpcType, syncMeta, pEntry->data, pEntry->dataLen);
+ if (index < 0) {
+ int32_t err = terrno;
+ const char* errStr = tstrerror(err);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal write error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pEntry->index, err, err, errStr, sysErr, sysErrStr);
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+
+ ASSERT(0);
+ return -1;
+ }
+ pEntry->index = index;
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "write index:%" PRId64 ", type:%s,%d, type2:%s,%d", pEntry->index,
+ TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType);
+ syncNodeEventLog(pData->pSyncNode, eventLog);
+ } while (0);
+
+ return 0;
}
+#if 0
static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
SyncIndex writeIndex = raftLogWriteIndex(pLogStore);
- ASSERT(pEntry->index == writeIndex);
+ if (pEntry->index != writeIndex) {
+ sError("vgId:%d wal write index error, entry-index:%" PRId64 " update to %" PRId64, pData->pSyncNode->vgId,
+ pEntry->index, writeIndex);
+ pEntry->index = writeIndex;
+ }
int code = 0;
- SSyncLogMeta syncMeta;
+ SWalSyncInfo syncMeta;
syncMeta.isWeek = pEntry->isWeak;
syncMeta.seqNum = pEntry->seqNum;
syncMeta.term = pEntry->term;
@@ -154,65 +258,95 @@ static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntr
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("raftLogAppendEntry error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal write error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pEntry->index, err, err, errStr, sysErr, sysErrStr);
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+
ASSERT(0);
}
- walFsync(pWal, true);
+ // walFsync(pWal, true);
- char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "write index:%ld, type:%s,%d, type2:%s,%d", pEntry->index,
- TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType);
- syncNodeEventLog(pData->pSyncNode, eventLog);
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "write index:%" PRId64 ", type:%s,%d, type2:%s,%d", pEntry->index,
+ TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType);
+ syncNodeEventLog(pData->pSyncNode, eventLog);
+ } while (0);
return code;
}
+#endif
+// entry found, return 0
+// entry not found, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST
+// other error, return -1
static int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncRaftEntry** ppEntry) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
int32_t code;
*ppEntry = NULL;
- if (raftLogInRange(pLogStore, index)) {
- SWalReadHandle* pWalHandle = walOpenReadHandle(pWal);
- ASSERT(pWalHandle != NULL);
- code = walReadWithHandle(pWalHandle, index);
- if (code != 0) {
- int32_t err = terrno;
- const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("raftLogGetEntry error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
- ASSERT(0);
- walCloseReadHandle(pWalHandle);
- return code;
- }
+ // SWalReadHandle* pWalHandle = walOpenReadHandle(pWal);
+ SWalReader* pWalHandle = pData->pWalHandle;
+ if (pWalHandle == NULL) {
+ terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
+ return -1;
+ }
- *ppEntry = syncEntryBuild(pWalHandle->pHead->head.bodyLen);
- ASSERT(*ppEntry != NULL);
- (*ppEntry)->msgType = TDMT_SYNC_CLIENT_REQUEST;
- (*ppEntry)->originalRpcType = pWalHandle->pHead->head.msgType;
- (*ppEntry)->seqNum = pWalHandle->pHead->head.syncMeta.seqNum;
- (*ppEntry)->isWeak = pWalHandle->pHead->head.syncMeta.isWeek;
- (*ppEntry)->term = pWalHandle->pHead->head.syncMeta.term;
- (*ppEntry)->index = index;
- ASSERT((*ppEntry)->dataLen == pWalHandle->pHead->head.bodyLen);
- memcpy((*ppEntry)->data, pWalHandle->pHead->head.body, pWalHandle->pHead->head.bodyLen);
-
- // need to hold, do not new every time!!
- walCloseReadHandle(pWalHandle);
+ taosThreadMutexLock(&(pData->mutex));
- } else {
- // index not in range
- code = 0;
+ code = walReadVer(pWalHandle, index);
+ if (code != 0) {
+ int32_t err = terrno;
+ const char* errStr = tstrerror(err);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal read error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ index, err, err, errStr, sysErr, sysErrStr);
+ if (terrno == TSDB_CODE_WAL_LOG_NOT_EXIST) {
+ syncNodeEventLog(pData->pSyncNode, logBuf);
+ } else {
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+ }
+ } while (0);
+
+ /*
+ int32_t saveErr = terrno;
+ walCloseReadHandle(pWalHandle);
+ terrno = saveErr;
+ */
+
+ taosThreadMutexUnlock(&(pData->mutex));
+ return code;
}
+ *ppEntry = syncEntryBuild(pWalHandle->pHead->head.bodyLen);
+ ASSERT(*ppEntry != NULL);
+ (*ppEntry)->msgType = TDMT_SYNC_CLIENT_REQUEST;
+ (*ppEntry)->originalRpcType = pWalHandle->pHead->head.msgType;
+ (*ppEntry)->seqNum = pWalHandle->pHead->head.syncMeta.seqNum;
+ (*ppEntry)->isWeak = pWalHandle->pHead->head.syncMeta.isWeek;
+ (*ppEntry)->term = pWalHandle->pHead->head.syncMeta.term;
+ (*ppEntry)->index = index;
+ ASSERT((*ppEntry)->dataLen == pWalHandle->pHead->head.bodyLen);
+ memcpy((*ppEntry)->data, pWalHandle->pHead->head.body, pWalHandle->pHead->head.bodyLen);
+
+ /*
+ int32_t saveErr = terrno;
+ walCloseReadHandle(pWalHandle);
+ terrno = saveErr;
+ */
+
+ taosThreadMutexUnlock(&(pData->mutex));
return code;
}
@@ -223,88 +357,59 @@ static int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex fromIn
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("raftLogTruncate error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+ sError("vgId:%d wal truncate error, from-index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pData->pSyncNode->vgId, fromIndex, err, err, errStr, sysErr, sysErrStr);
+
ASSERT(0);
}
- return code;
-}
-static int32_t raftLogGetLastEntry(SSyncLogStore* pLogStore, SSyncRaftEntry** ppLastEntry) {
- *ppLastEntry = NULL;
- if (raftLogEntryCount(pLogStore) == 0) {
- return 0;
- }
- SyncIndex lastIndex = raftLogLastIndex(pLogStore);
- int32_t code = raftLogGetEntry(pLogStore, lastIndex, ppLastEntry);
+ // event log
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal truncate, from-index:%" PRId64, fromIndex);
+ syncNodeEventLog(pData->pSyncNode, logBuf);
+ } while (0);
+
return code;
}
-//-------------------------------
-SSyncLogStore* logStoreCreate(SSyncNode* pSyncNode) {
- SSyncLogStore* pLogStore = taosMemoryMalloc(sizeof(SSyncLogStore));
- assert(pLogStore != NULL);
-
- pLogStore->data = taosMemoryMalloc(sizeof(SSyncLogStoreData));
- assert(pLogStore->data != NULL);
-
+// entry found, return 0
+// entry not found, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST
+// other error, return -1
+static int32_t raftLogGetLastEntry(SSyncLogStore* pLogStore, SSyncRaftEntry** ppLastEntry) {
SSyncLogStoreData* pData = pLogStore->data;
- pData->pSyncNode = pSyncNode;
- pData->pWal = pSyncNode->pWal;
+ SWal* pWal = pData->pWal;
+ ASSERT(ppLastEntry != NULL);
- SyncIndex firstVer = walGetFirstVer(pData->pWal);
- SyncIndex lastVer = walGetLastVer(pData->pWal);
- if (firstVer >= 0) {
- pData->beginIndex = firstVer;
- } else if (firstVer == -1) {
- pData->beginIndex = lastVer + 1;
+ *ppLastEntry = NULL;
+ if (walIsEmpty(pWal)) {
+ terrno = TSDB_CODE_WAL_LOG_NOT_EXIST;
+ return -1;
} else {
- ASSERT(0);
+ SyncIndex lastIndex = raftLogLastIndex(pLogStore);
+ ASSERT(lastIndex >= SYNC_INDEX_BEGIN);
+ int32_t code = raftLogGetEntry(pLogStore, lastIndex, ppLastEntry);
+ return code;
}
- pLogStore->appendEntry = logStoreAppendEntry;
- pLogStore->getEntry = logStoreGetEntry;
- pLogStore->truncate = logStoreTruncate;
- pLogStore->getLastIndex = logStoreLastIndex;
- pLogStore->getLastTerm = logStoreLastTerm;
- pLogStore->updateCommitIndex = logStoreUpdateCommitIndex;
- pLogStore->getCommitIndex = logStoreGetCommitIndex;
-
- pLogStore->syncLogSetBeginIndex = raftLogSetBeginIndex;
- pLogStore->syncLogBeginIndex = raftLogBeginIndex;
- pLogStore->syncLogEndIndex = raftLogEndIndex;
- pLogStore->syncLogIsEmpty = raftLogIsEmpty;
- pLogStore->syncLogEntryCount = raftLogEntryCount;
- pLogStore->syncLogInRange = raftLogInRange;
- pLogStore->syncLogLastIndex = raftLogLastIndex;
- pLogStore->syncLogLastTerm = raftLogLastTerm;
- pLogStore->syncLogAppendEntry = raftLogAppendEntry;
- pLogStore->syncLogGetEntry = raftLogGetEntry;
- pLogStore->syncLogTruncate = raftLogTruncate;
- pLogStore->syncLogWriteIndex = raftLogWriteIndex;
-
- return pLogStore;
-}
-
-void logStoreDestory(SSyncLogStore* pLogStore) {
- if (pLogStore != NULL) {
- taosMemoryFree(pLogStore->data);
- taosMemoryFree(pLogStore);
- }
+ return -1;
}
//-------------------------------
+// log[0 .. n]
+
+#if 0
int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
SyncIndex lastIndex = logStoreLastIndex(pLogStore);
- assert(pEntry->index == lastIndex + 1);
+ ASSERT(pEntry->index == lastIndex + 1);
int code = 0;
- SSyncLogMeta syncMeta;
+ SWalSyncInfo syncMeta;
syncMeta.isWeek = pEntry->isWeak;
syncMeta.seqNum = pEntry->seqNum;
syncMeta.term = pEntry->term;
@@ -312,45 +417,99 @@ int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) {
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("walWriteWithSyncInfo error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal write error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pEntry->index, err, err, errStr, sysErr, sysErrStr);
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+
ASSERT(0);
}
- walFsync(pWal, true);
+ // walFsync(pWal, true);
char eventLog[128];
- snprintf(eventLog, sizeof(eventLog), "old write index:%ld, type:%s,%d, type2:%s,%d", pEntry->index,
+ snprintf(eventLog, sizeof(eventLog), "old write index:%" PRId64 ", type:%s,%d, type2:%s,%d", pEntry->index,
TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType);
syncNodeEventLog(pData->pSyncNode, eventLog);
return code;
}
+#endif
+
+int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) {
+ SSyncLogStoreData* pData = pLogStore->data;
+ SWal* pWal = pData->pWal;
+
+ SyncIndex index = 0;
+ SWalSyncInfo syncMeta;
+ syncMeta.isWeek = pEntry->isWeak;
+ syncMeta.seqNum = pEntry->seqNum;
+ syncMeta.term = pEntry->term;
+
+ index = walAppendLog(pWal, pEntry->originalRpcType, syncMeta, pEntry->data, pEntry->dataLen);
+ if (index < 0) {
+ int32_t err = terrno;
+ const char* errStr = tstrerror(err);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal write error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pEntry->index, err, err, errStr, sysErr, sysErrStr);
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+
+ ASSERT(0);
+ return -1;
+ }
+ pEntry->index = index;
+
+ do {
+ char eventLog[128];
+ snprintf(eventLog, sizeof(eventLog), "write2 index:%" PRId64 ", type:%s,%d, type2:%s,%d", pEntry->index,
+ TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType);
+ syncNodeEventLog(pData->pSyncNode, eventLog);
+ } while (0);
+
+ return 0;
+}
SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
if (index >= SYNC_INDEX_BEGIN && index <= logStoreLastIndex(pLogStore)) {
- SWalReadHandle* pWalHandle = walOpenReadHandle(pWal);
+ taosThreadMutexLock(&(pData->mutex));
+
+ // SWalReadHandle* pWalHandle = walOpenReadHandle(pWal);
+ SWalReader* pWalHandle = pData->pWalHandle;
ASSERT(pWalHandle != NULL);
- int32_t code = walReadWithHandle(pWalHandle, index);
+ int32_t code = walReadVer(pWalHandle, index);
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("walReadWithHandle error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal read error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ index, err, err, errStr, sysErr, sysErrStr);
+ if (terrno == TSDB_CODE_WAL_LOG_NOT_EXIST) {
+ syncNodeEventLog(pData->pSyncNode, logBuf);
+ } else {
+ syncNodeErrorLog(pData->pSyncNode, logBuf);
+ }
+ } while (0);
+
ASSERT(0);
}
- // assert(walReadWithHandle(pWalHandle, index) == 0);
SSyncRaftEntry* pEntry = syncEntryBuild(pWalHandle->pHead->head.bodyLen);
- assert(pEntry != NULL);
+ ASSERT(pEntry != NULL);
pEntry->msgType = TDMT_SYNC_CLIENT_REQUEST;
pEntry->originalRpcType = pWalHandle->pHead->head.msgType;
@@ -358,11 +517,16 @@ SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index) {
pEntry->isWeak = pWalHandle->pHead->head.syncMeta.isWeek;
pEntry->term = pWalHandle->pHead->head.syncMeta.term;
pEntry->index = index;
- assert(pEntry->dataLen == pWalHandle->pHead->head.bodyLen);
+ ASSERT(pEntry->dataLen == pWalHandle->pHead->head.bodyLen);
memcpy(pEntry->data, pWalHandle->pHead->head.body, pWalHandle->pHead->head.bodyLen);
- // need to hold, do not new every time!!
- walCloseReadHandle(pWalHandle);
+ /*
+ int32_t saveErr = terrno;
+ walCloseReadHandle(pWalHandle);
+ terrno = saveErr;
+ */
+
+ taosThreadMutexUnlock(&(pData->mutex));
return pEntry;
} else {
@@ -373,17 +537,26 @@ SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index) {
int32_t logStoreTruncate(SSyncLogStore* pLogStore, SyncIndex fromIndex) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
- // assert(walRollback(pWal, fromIndex) == 0);
+ // ASSERT(walRollback(pWal, fromIndex) == 0);
int32_t code = walRollback(pWal, fromIndex);
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("walRollback error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr,
- linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+ sError("vgId:%d wal truncate error, from-index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pData->pSyncNode->vgId, fromIndex, err, err, errStr, sysErr, sysErrStr);
+
ASSERT(0);
}
+
+ // event log
+ do {
+ char logBuf[128];
+ snprintf(logBuf, sizeof(logBuf), "wal truncate, from-index:%" PRId64, fromIndex);
+ syncNodeEventLog(pData->pSyncNode, logBuf);
+ } while (0);
+
return 0;
}
@@ -407,14 +580,16 @@ SyncTerm logStoreLastTerm(SSyncLogStore* pLogStore) {
int32_t logStoreUpdateCommitIndex(SSyncLogStore* pLogStore, SyncIndex index) {
SSyncLogStoreData* pData = pLogStore->data;
SWal* pWal = pData->pWal;
- // assert(walCommit(pWal, index) == 0);
+ // ASSERT(walCommit(pWal, index) == 0);
int32_t code = walCommit(pWal, index);
if (code != 0) {
int32_t err = terrno;
const char* errStr = tstrerror(err);
- int32_t linuxErr = errno;
- const char* linuxErrMsg = strerror(errno);
- sError("walCommit error, err:%d %X, msg:%s, linuxErr:%d, linuxErrMsg:%s", err, err, errStr, linuxErr, linuxErrMsg);
+ int32_t sysErr = errno;
+ const char* sysErrStr = strerror(errno);
+ sError("vgId:%d wal update commit index error, index:%" PRId64 ", err:%d %X, msg:%s, syserr:%d, sysmsg:%s",
+ pData->pSyncNode->vgId, index, err, err, errStr, sysErr, sysErrStr);
+
ASSERT(0);
}
return 0;
@@ -448,34 +623,37 @@ cJSON* logStore2Json(SSyncLogStore* pLogStore) {
snprintf(u64buf, sizeof(u64buf), "%p", pData->pWal);
cJSON_AddStringToObject(pRoot, "pWal", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pData->beginIndex);
+ SyncIndex beginIndex = raftLogBeginIndex(pLogStore);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, beginIndex);
cJSON_AddStringToObject(pRoot, "beginIndex", u64buf);
SyncIndex endIndex = raftLogEndIndex(pLogStore);
- snprintf(u64buf, sizeof(u64buf), "%ld", endIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, endIndex);
cJSON_AddStringToObject(pRoot, "endIndex", u64buf);
int32_t count = raftLogEntryCount(pLogStore);
cJSON_AddNumberToObject(pRoot, "entryCount", count);
- snprintf(u64buf, sizeof(u64buf), "%ld", raftLogWriteIndex(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, raftLogWriteIndex(pLogStore));
cJSON_AddStringToObject(pRoot, "WriteIndex", u64buf);
snprintf(u64buf, sizeof(u64buf), "%d", raftLogIsEmpty(pLogStore));
cJSON_AddStringToObject(pRoot, "IsEmpty", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", raftLogLastIndex(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, raftLogLastIndex(pLogStore));
cJSON_AddStringToObject(pRoot, "LastIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", raftLogLastTerm(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, raftLogLastTerm(pLogStore));
cJSON_AddStringToObject(pRoot, "LastTerm", u64buf);
cJSON* pEntries = cJSON_CreateArray();
cJSON_AddItemToObject(pRoot, "pEntries", pEntries);
- for (SyncIndex i = pData->beginIndex; i <= endIndex; ++i) {
- SSyncRaftEntry* pEntry = logStoreGetEntry(pLogStore, i);
- cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry));
- syncEntryDestory(pEntry);
+ if (!raftLogIsEmpty(pLogStore)) {
+ for (SyncIndex i = beginIndex; i <= endIndex; ++i) {
+ SSyncRaftEntry* pEntry = logStoreGetEntry(pLogStore, i);
+ cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry));
+ syncEntryDestory(pEntry);
+ }
}
}
@@ -502,25 +680,26 @@ cJSON* logStoreSimple2Json(SSyncLogStore* pLogStore) {
snprintf(u64buf, sizeof(u64buf), "%p", pData->pWal);
cJSON_AddStringToObject(pRoot, "pWal", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", pData->beginIndex);
+ SyncIndex beginIndex = raftLogBeginIndex(pLogStore);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, beginIndex);
cJSON_AddStringToObject(pRoot, "beginIndex", u64buf);
SyncIndex endIndex = raftLogEndIndex(pLogStore);
- snprintf(u64buf, sizeof(u64buf), "%ld", endIndex);
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, endIndex);
cJSON_AddStringToObject(pRoot, "endIndex", u64buf);
int32_t count = raftLogEntryCount(pLogStore);
cJSON_AddNumberToObject(pRoot, "entryCount", count);
- snprintf(u64buf, sizeof(u64buf), "%ld", raftLogWriteIndex(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, raftLogWriteIndex(pLogStore));
cJSON_AddStringToObject(pRoot, "WriteIndex", u64buf);
snprintf(u64buf, sizeof(u64buf), "%d", raftLogIsEmpty(pLogStore));
cJSON_AddStringToObject(pRoot, "IsEmpty", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%ld", raftLogLastIndex(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRId64, raftLogLastIndex(pLogStore));
cJSON_AddStringToObject(pRoot, "LastIndex", u64buf);
- snprintf(u64buf, sizeof(u64buf), "%lu", raftLogLastTerm(pLogStore));
+ snprintf(u64buf, sizeof(u64buf), "%" PRIu64, raftLogLastTerm(pLogStore));
cJSON_AddStringToObject(pRoot, "LastTerm", u64buf);
}
@@ -545,14 +724,14 @@ SyncIndex logStoreFirstIndex(SSyncLogStore* pLogStore) {
// for debug -----------------
void logStorePrint(SSyncLogStore* pLogStore) {
char* serialized = logStore2Str(pLogStore);
- printf("logStorePrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("logStorePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void logStorePrint2(char* s, SSyncLogStore* pLogStore) {
char* serialized = logStore2Str(pLogStore);
- printf("logStorePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("logStorePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
@@ -560,7 +739,7 @@ void logStorePrint2(char* s, SSyncLogStore* pLogStore) {
void logStoreLog(SSyncLogStore* pLogStore) {
if (gRaftDetailLog) {
char* serialized = logStore2Str(pLogStore);
- sTraceLong("logStoreLog | len:%lu | %s", strlen(serialized), serialized);
+ sTraceLong("logStoreLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
}
@@ -568,7 +747,7 @@ void logStoreLog(SSyncLogStore* pLogStore) {
void logStoreLog2(char* s, SSyncLogStore* pLogStore) {
if (gRaftDetailLog) {
char* serialized = logStore2Str(pLogStore);
- sTraceLong("logStoreLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTraceLong("logStoreLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
@@ -576,28 +755,28 @@ void logStoreLog2(char* s, SSyncLogStore* pLogStore) {
// for debug -----------------
void logStoreSimplePrint(SSyncLogStore* pLogStore) {
char* serialized = logStoreSimple2Str(pLogStore);
- printf("logStoreSimplePrint | len:%lu | %s \n", strlen(serialized), serialized);
+ printf("logStoreSimplePrint | len:%" PRIu64 " | %s \n", strlen(serialized), serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void logStoreSimplePrint2(char* s, SSyncLogStore* pLogStore) {
char* serialized = logStoreSimple2Str(pLogStore);
- printf("logStoreSimplePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized);
+ printf("logStoreSimplePrint2 | len:%" PRIu64 " | %s | %s \n", strlen(serialized), s, serialized);
fflush(NULL);
taosMemoryFree(serialized);
}
void logStoreSimpleLog(SSyncLogStore* pLogStore) {
char* serialized = logStoreSimple2Str(pLogStore);
- sTrace("logStoreSimpleLog | len:%lu | %s", strlen(serialized), serialized);
+ sTrace("logStoreSimpleLog | len:%" PRIu64 " | %s", strlen(serialized), serialized);
taosMemoryFree(serialized);
}
void logStoreSimpleLog2(char* s, SSyncLogStore* pLogStore) {
if (gRaftDetailLog) {
char* serialized = logStoreSimple2Str(pLogStore);
- sTrace("logStoreSimpleLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized);
+ sTrace("logStoreSimpleLog2 | len:%" PRIu64 " | %s | %s", strlen(serialized), s, serialized);
taosMemoryFree(serialized);
}
}
diff --git a/source/libs/sync/src/syncRaftStore.c b/source/libs/sync/src/syncRaftStore.c
index 52e815292607d69e7d364f6a11c31c184f07914a..9f5cba6c6607d3a3146fa0c1c55870d9713e110d 100644
--- a/source/libs/sync/src/syncRaftStore.c
+++ b/source/libs/sync/src/syncRaftStore.c
@@ -39,40 +39,40 @@ SRaftStore *raftStoreOpen(const char *path) {
if (!raftStoreFileExist(pRaftStore->path)) {
ret = raftStoreInit(pRaftStore);
- assert(ret == 0);
+ ASSERT(ret == 0);
}
pRaftStore->pFile = taosOpenFile(path, TD_FILE_READ | TD_FILE_WRITE);
- assert(pRaftStore->pFile != NULL);
+ ASSERT(pRaftStore->pFile != NULL);
int len = taosReadFile(pRaftStore->pFile, storeBuf, RAFT_STORE_BLOCK_SIZE);
- assert(len == RAFT_STORE_BLOCK_SIZE);
+ ASSERT(len == RAFT_STORE_BLOCK_SIZE);
ret = raftStoreDeserialize(pRaftStore, storeBuf, len);
- assert(ret == 0);
+ ASSERT(ret == 0);
return pRaftStore;
}
static int32_t raftStoreInit(SRaftStore *pRaftStore) {
- assert(pRaftStore != NULL);
+ ASSERT(pRaftStore != NULL);
pRaftStore->pFile = taosOpenFile(pRaftStore->path, TD_FILE_CREATE | TD_FILE_WRITE);
- assert(pRaftStore->pFile != NULL);
+ ASSERT(pRaftStore->pFile != NULL);
pRaftStore->currentTerm = 0;
pRaftStore->voteFor.addr = 0;
pRaftStore->voteFor.vgId = 0;
int32_t ret = raftStorePersist(pRaftStore);
- assert(ret == 0);
+ ASSERT(ret == 0);
taosCloseFile(&pRaftStore->pFile);
return 0;
}
int32_t raftStoreClose(SRaftStore *pRaftStore) {
- assert(pRaftStore != NULL);
+ ASSERT(pRaftStore != NULL);
taosCloseFile(&pRaftStore->pFile);
taosMemoryFree(pRaftStore);
@@ -81,17 +81,17 @@ int32_t raftStoreClose(SRaftStore *pRaftStore) {
}
int32_t raftStorePersist(SRaftStore *pRaftStore) {
- assert(pRaftStore != NULL);
+ ASSERT(pRaftStore != NULL);
int32_t ret;
char storeBuf[RAFT_STORE_BLOCK_SIZE] = {0};
ret = raftStoreSerialize(pRaftStore, storeBuf, sizeof(storeBuf));
- assert(ret == 0);
+ ASSERT(ret == 0);
taosLSeekFile(pRaftStore->pFile, 0, SEEK_SET);
ret = taosWriteFile(pRaftStore->pFile, storeBuf, sizeof(storeBuf));
- assert(ret == RAFT_STORE_BLOCK_SIZE);
+ ASSERT(ret == RAFT_STORE_BLOCK_SIZE);
taosFsyncFile(pRaftStore->pFile);
return 0;
@@ -103,7 +103,7 @@ static bool raftStoreFileExist(char *path) {
}
int32_t raftStoreSerialize(SRaftStore *pRaftStore, char *buf, size_t len) {
- assert(pRaftStore != NULL);
+ ASSERT(pRaftStore != NULL);
cJSON *pRoot = cJSON_CreateObject();
@@ -125,7 +125,7 @@ int32_t raftStoreSerialize(SRaftStore *pRaftStore, char *buf, size_t len) {
char *serialized = cJSON_Print(pRoot);
int len2 = strlen(serialized);
- assert(len2 < len);
+ ASSERT(len2 < len);
memset(buf, 0, len);
snprintf(buf, len, "%s", serialized);
taosMemoryFree(serialized);
@@ -135,17 +135,17 @@ int32_t raftStoreSerialize(SRaftStore *pRaftStore, char *buf, size_t len) {
}
int32_t raftStoreDeserialize(SRaftStore *pRaftStore, char *buf, size_t len) {
- assert(pRaftStore != NULL);
+ ASSERT(pRaftStore != NULL);
- assert(len > 0 && len <= RAFT_STORE_BLOCK_SIZE);
+ ASSERT(len > 0 && len <= RAFT_STORE_BLOCK_SIZE);
cJSON *pRoot = cJSON_Parse(buf);
cJSON *pCurrentTerm = cJSON_GetObjectItem(pRoot, "current_term");
- assert(cJSON_IsString(pCurrentTerm));
+ ASSERT(cJSON_IsString(pCurrentTerm));
sscanf(pCurrentTerm->valuestring, "%lu", &(pRaftStore->currentTerm));
cJSON *pVoteForAddr = cJSON_GetObjectItem(pRoot, "vote_for_addr");
- assert(cJSON_IsString(pVoteForAddr));
+ ASSERT(cJSON_IsString(pVoteForAddr));
sscanf(pVoteForAddr->valuestring, "%lu", &(pRaftStore->voteFor.addr));
cJSON *pVoteForVgid = cJSON_GetObjectItem(pRoot, "vote_for_vgid");
@@ -161,7 +161,7 @@ bool raftStoreHasVoted(SRaftStore *pRaftStore) {
}
void raftStoreVote(SRaftStore *pRaftStore, SRaftId *pRaftId) {
- assert(!syncUtilEmptyId(pRaftId));
+ ASSERT(!syncUtilEmptyId(pRaftId));
pRaftStore->voteFor = *pRaftId;
raftStorePersist(pRaftStore);
}
diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c
index f044ae5733aa7714af208fe9c4208859206ac35e..b6bc4bc8163120f523ede1a8ad5280f9d72cf8b1 100644
--- a/source/libs/sync/src/syncReplication.c
+++ b/source/libs/sync/src/syncReplication.c
@@ -49,7 +49,7 @@
// /\ UNCHANGED <