other: merge 3.0
This commit is contained in:
commit
f4a3567935
|
@ -0,0 +1,28 @@
|
|||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: check-json
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: stable
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pocc/pre-commit-hooks
|
||||
rev: master
|
||||
hooks:
|
||||
- id: cppcheck
|
||||
args: ["--error-exitcode=0"]
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.15.7
|
||||
hooks:
|
||||
- id: typos
|
||||
|
|
@ -314,7 +314,7 @@ def pre_test_build_win() {
|
|||
cd %WIN_CONNECTOR_ROOT%
|
||||
python.exe -m pip install --upgrade pip
|
||||
python -m pip uninstall taospy -y
|
||||
python -m pip install taospy==2.7.6
|
||||
python -m pip install taospy==2.7.10
|
||||
xcopy /e/y/i/f %WIN_INTERNAL_ROOT%\\debug\\build\\lib\\taos.dll C:\\Windows\\System32
|
||||
'''
|
||||
return 1
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "3.0.6.0.alpha")
|
||||
SET(TD_VER_NUMBER "3.1.0.0.alpha")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# geos
|
||||
ExternalProject_Add(geos
|
||||
GIT_REPOSITORY https://github.com/libgeos/geos.git
|
||||
GIT_TAG 3.11.2
|
||||
GIT_TAG 3.12.0
|
||||
SOURCE_DIR "${TD_CONTRIB_DIR}/geos"
|
||||
BINARY_DIR ""
|
||||
CONFIGURE_COMMAND ""
|
||||
|
|
|
@ -33,7 +33,7 @@ The below SQL statement is used to insert one row into table "d1001".
|
|||
INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31);
|
||||
```
|
||||
|
||||
`ts1` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
`ts1` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detail, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
|
||||
### Insert Multiple Rows
|
||||
|
||||
|
@ -43,7 +43,7 @@ Multiple rows can be inserted in a single SQL statement. The example below inser
|
|||
INSERT INTO d1001 VALUES (ts2, 10.2, 220, 0.23) (ts2, 10.3, 218, 0.25);
|
||||
```
|
||||
|
||||
`ts1` and `ts2` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
`ts1` and `ts2` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detail, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
|
||||
### Insert into Multiple Tables
|
||||
|
||||
|
@ -53,7 +53,7 @@ Data can be inserted into multiple tables in the same SQL statement. The example
|
|||
INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31) (ts2, 12.6, 218, 0.33) d1002 VALUES (ts3, 12.3, 221, 0.31);
|
||||
```
|
||||
|
||||
`ts1`, `ts2` and `ts3` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
`ts1`, `ts2` and `ts3` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detail, refer to [TDengine SQL insert timestamp section](/taos-sql/insert).
|
||||
|
||||
For more details about `INSERT` please refer to [INSERT](/taos-sql/insert).
|
||||
|
||||
|
|
|
@ -244,6 +244,8 @@ The following SQL statement creates a topic in TDengine:
|
|||
CREATE TOPIC topic_name AS SELECT ts, c1, c2, c3 FROM tmqdb.stb WHERE c1 > 1;
|
||||
```
|
||||
|
||||
- There is an upper limit to the number of topics created, controlled by the parameter tmqMaxTopicNum, with a default of 20
|
||||
|
||||
Multiple subscription types are supported.
|
||||
|
||||
#### Subscribe to a Column
|
||||
|
@ -265,14 +267,15 @@ You can subscribe to a topic through a SELECT statement. Statements that specify
|
|||
Syntax:
|
||||
|
||||
```sql
|
||||
CREATE TOPIC topic_name AS STABLE stb_name
|
||||
CREATE TOPIC topic_name [with meta] AS STABLE stb_name [where_condition]
|
||||
```
|
||||
|
||||
Creating a topic in this manner differs from a `SELECT * from stbName` statement as follows:
|
||||
|
||||
- The table schema can be modified.
|
||||
- Unstructured data is returned. The format of the data returned changes based on the supertable schema.
|
||||
- A different table schema may exist for every data block to be processed.
|
||||
- The 'with meta' parameter is optional. When selected, statements such as creating super tables and sub tables will be returned, mainly used for Taosx to perform super table migration
|
||||
- The 'where_condition' parameter is optional and will be used to filter and subscribe to sub tables that meet the criteria. Where conditions cannot have ordinary columns, only tags or tbnames. Functions can be used in where conditions to filter tags, but cannot be aggregate functions because sub table tag values cannot be aggregated. It can also be a constant expression, such as 2>1 (subscribing to all child tables), Or false (subscribe to 0 sub tables)
|
||||
- The data returned does not include tags.
|
||||
|
||||
### Subscribe to a Database
|
||||
|
@ -280,10 +283,12 @@ Creating a topic in this manner differs from a `SELECT * from stbName` statement
|
|||
Syntax:
|
||||
|
||||
```sql
|
||||
CREATE TOPIC topic_name [WITH META] AS DATABASE db_name;
|
||||
CREATE TOPIC topic_name [with meta] AS DATABASE db_name;
|
||||
```
|
||||
|
||||
This SQL statement creates a subscription to all tables in the database. You can add the `WITH META` parameter to include schema changes in the subscription, including creating and deleting supertables; adding, deleting, and modifying columns; and creating, deleting, and modifying the tags of subtables. Consumers can determine the message type from the API. Note that this differs from Kafka.
|
||||
This SQL statement creates a subscription to all tables in the database.
|
||||
|
||||
- The 'with meta' parameter is optional. When selected, it will return statements for creating all super tables and sub tables in the database, mainly used for Taosx database migration
|
||||
|
||||
## Create a Consumer
|
||||
|
||||
|
@ -295,7 +300,7 @@ You configure the following parameters when creating a consumer:
|
|||
| `td.connect.user` | string | User Name | |
|
||||
| `td.connect.pass` | string | Password | |
|
||||
| `td.connect.port` | string | Port of the server side | |
|
||||
| `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192. |
|
||||
| `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192. Each topic can create up to 100 consumer groups. |
|
||||
| `client.id` | string | Client ID | Maximum length: 192. |
|
||||
| `auto.offset.reset` | enum | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) |
|
||||
| `enable.auto.commit` | boolean | Commit automatically; true: user application doesn't need to explicitly commit; false: user application need to handle commit by itself | Default value is true |
|
||||
|
|
|
@ -17,7 +17,7 @@ When you create a user-defined function, you must implement standard interface f
|
|||
- For aggregate functions, implement the `aggfn_start`, `aggfn`, and `aggfn_finish` interface functions.
|
||||
- To initialize your function, implement the `udf_init` function. To terminate your function, implement the `udf_destroy` function.
|
||||
|
||||
There are strict naming conventions for these interface functions. The names of the start, finish, init, and destroy interfaces must be <udf-name\>_start, <udf-name\>_finish, <udf-name\>_init, and <udf-name\>_destroy, respectively. Replace `scalarfn`, `aggfn`, and `udf` with the name of your user-defined function.
|
||||
There are strict naming conventions for these interface functions. The names of the start, finish, init, and destroy interfaces must be `_start`, `_finish`, `_init`, and `_destroy`, respectively. Replace `scalarfn`, `aggfn`, and `udf` with the name of your user-defined function.
|
||||
|
||||
### Implementing a Scalar Function in C
|
||||
The implementation of a scalar function is described as follows:
|
||||
|
@ -318,7 +318,7 @@ The implementation of a scalar UDF is described as follows:
|
|||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
|
||||
Description: this function prcesses datablock, which is the input; you can use datablock.data(row, col) to access the python object at location(row,col); the output is a tuple object consisted of objects of type outputtype
|
||||
Description: this function processes datablock, which is the input; you can use datablock.data(row, col) to access the python object at location(row,col); the output is a tuple object consisted of objects of type outputtype
|
||||
|
||||
#### Aggregate UDF Interface
|
||||
|
||||
|
@ -356,7 +356,7 @@ def process(input: datablock) -> tuple[output_type]:
|
|||
# return tuple object consisted of object of type outputtype
|
||||
```
|
||||
|
||||
Note:process() must be implemeted, init() and destroy() must be defined too but they can do nothing.
|
||||
Note:process() must be implemented, init() and destroy() must be defined too but they can do nothing.
|
||||
|
||||
#### Aggregate Template
|
||||
|
||||
|
@ -377,7 +377,7 @@ def finish(buf: bytes) -> output_type:
|
|||
#return obj of type outputtype
|
||||
```
|
||||
|
||||
Note: aggregate UDF requires init(), destroy(), start(), reduce() and finish() to be impemented. start() generates the initial result in buffer, then the input data is divided into multiple row data blocks, reduce() is invoked for each data block `inputs` and intermediate `buf`, finally finish() is invoked to generate final result from the intermediate result `buf`.
|
||||
Note: aggregate UDF requires init(), destroy(), start(), reduce() and finish() to be implemented. start() generates the initial result in buffer, then the input data is divided into multiple row data blocks, reduce() is invoked for each data block `inputs` and intermediate `buf`, finally finish() is invoked to generate final result from the intermediate result `buf`.
|
||||
|
||||
### Data Mapping between TDengine SQL and Python UDF
|
||||
|
||||
|
@ -559,7 +559,7 @@ Note: Prior to TDengine 3.0.5.0 (excluding), updating a UDF requires to restart
|
|||
|
||||
#### Sample 3: UDF with n arguments
|
||||
|
||||
A UDF which accepts n intergers, likee (x1, x2, ..., xn) and output the sum of the product of each value and its sequence number: 1 * x1 + 2 * x2 + ... + n * xn. If there is `null` in the input, then the result is `null`. The difference from sample 1 is that it can accept any number of columns as input and process each column. Assume the program is written in /root/udf/nsum.py:
|
||||
A UDF which accepts n integers, likee (x1, x2, ..., xn) and output the sum of the product of each value and its sequence number: 1 * x1 + 2 * x2 + ... + n * xn. If there is `null` in the input, then the result is `null`. The difference from sample 1 is that it can accept any number of columns as input and process each column. Assume the program is written in /root/udf/nsum.py:
|
||||
|
||||
```python
|
||||
def init():
|
||||
|
@ -607,7 +607,7 @@ Query OK, 4 row(s) in set (0.010653s)
|
|||
|
||||
#### Sample 4: Utilize 3rd party package
|
||||
|
||||
A UDF which accepts a timestamp and output the next closed Sunday. This sample requires to use third party package `moment`, you need to install it firslty.
|
||||
A UDF which accepts a timestamp and output the next closed Sunday. This sample requires to use third party package `moment`, you need to install it firstly.
|
||||
|
||||
```shell
|
||||
pip3 install moment
|
||||
|
@ -701,7 +701,7 @@ Query OK, 4 row(s) in set (1.011474s)
|
|||
|
||||
#### Sample 5: Aggregate Function
|
||||
|
||||
An aggregate function which calculates the difference of the maximum and the minimum in a column. An aggregate funnction takes multiple rows as input and output only one data. The execution process of an aggregate UDF is like map-reduce, the framework divides the input into multiple parts, each mapper processes one block and the reducer aggregates the result of the mappers. The reduce() of Python UDF has the functionality of both map() and reduce(). The reduce() takes two arguments: the data to be processed; and the result of other tasks executing reduce(). For exmaple, assume the code is in `/root/udf/myspread.py`.
|
||||
An aggregate function which calculates the difference of the maximum and the minimum in a column. An aggregate funnction takes multiple rows as input and output only one data. The execution process of an aggregate UDF is like map-reduce, the framework divides the input into multiple parts, each mapper processes one block and the reducer aggregates the result of the mappers. The reduce() of Python UDF has the functionality of both map() and reduce(). The reduce() takes two arguments: the data to be processed; and the result of other tasks executing reduce(). For example, assume the code is in `/root/udf/myspread.py`.
|
||||
|
||||
```python
|
||||
import io
|
||||
|
@ -755,7 +755,7 @@ In this example, we implemented an aggregate function, and added some logging.
|
|||
2. log() is the function for logging, it converts the input object to string and output with an end of line
|
||||
3. destroy() closes the log file \
|
||||
4. start() returns the initial buffer for storing the intermediate result
|
||||
5. reduce() processes each daa block and aggregates the result
|
||||
5. reduce() processes each data block and aggregates the result
|
||||
6. finish() converts the final buffer() to final result\
|
||||
|
||||
Create the UDF.
|
||||
|
|
|
@ -672,7 +672,7 @@ If you input a specific column, the number of non-null values in the column is r
|
|||
ELAPSED(ts_primary_key [, time_unit])
|
||||
```
|
||||
|
||||
**Description**: `elapsed` function can be used to calculate the continuous time length in which there is valid data. If it's used with `INTERVAL` clause, the returned result is the calculated time length within each time window. If it's used without `INTERVAL` caluse, the returned result is the calculated time length within the specified time range. Please be noted that the return value of `elapsed` is the number of `time_unit` in the calculated time length.
|
||||
**Description**: `elapsed` function can be used to calculate the continuous time length in which there is valid data. If it's used with `INTERVAL` clause, the returned result is the calculated time length within each time window. If it's used without `INTERVAL` clause, the returned result is the calculated time length within the specified time range. Please be noted that the return value of `elapsed` is the number of `time_unit` in the calculated time length.
|
||||
|
||||
**Return value type**: Double if the input value is not NULL;
|
||||
|
||||
|
@ -999,18 +999,14 @@ SAMPLE(expr, k)
|
|||
|
||||
**Description**: _k_ sampling values of a specific column. The applicable range of _k_ is [1,1000].
|
||||
|
||||
**Return value type**: Same as the column being operated plus the associated timestamp
|
||||
**Return value type**: Same as the column being operated
|
||||
|
||||
**Applicable data types**: Any data type except for tags of STable
|
||||
**Applicable data types**: Any data type
|
||||
|
||||
**Applicable nested query**: Inner query and Outer query
|
||||
|
||||
**Applicable table types**: standard tables and supertables
|
||||
|
||||
**More explanations**:
|
||||
|
||||
- This function cannot be used in expression calculation.
|
||||
|
||||
|
||||
### TAIL
|
||||
|
||||
|
@ -1055,11 +1051,11 @@ TOP(expr, k)
|
|||
UNIQUE(expr)
|
||||
```
|
||||
|
||||
**Description**: The values that occur the first time in the specified column. The effect is similar to `distinct` keyword, but it can also be used to match tags or timestamp. The first occurrence of a timestamp or tag is used.
|
||||
**Description**: The values that occur the first time in the specified column. The effect is similar to `distinct` keyword.
|
||||
|
||||
**Return value type**:Same as the data type of the column being operated upon
|
||||
|
||||
**Applicable column types**: Any data types except for timestamp
|
||||
**Applicable column types**: Any data types
|
||||
|
||||
**Applicable table types**: table, STable
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ part_list can be any scalar expression, such as a column, constant, scalar funct
|
|||
A PARTITION BY clause is processed as follows:
|
||||
|
||||
- The PARTITION BY clause must occur after the WHERE clause
|
||||
- The PARTITION BY caluse partitions the data according to the specified dimensions, then perform computation on each partition. The performed computation is determined by the rest of the statement - a window clause, GROUP BY clause, or SELECT clause.
|
||||
- The PARTITION BY clause partitions the data according to the specified dimensions, then perform computation on each partition. The performed computation is determined by the rest of the statement - a window clause, GROUP BY clause, or SELECT clause.
|
||||
- The PARTITION BY clause can be used together with a window clause or GROUP BY clause. In this case, the window or GROUP BY clause takes effect on every partition. For example, the following statement partitions the table by the location tag, performs downsampling over a 10 minute window, and returns the maximum value:
|
||||
|
||||
```sql
|
||||
|
|
|
@ -36,7 +36,7 @@ Shows information about connections to the system.
|
|||
SHOW CONSUMERS;
|
||||
```
|
||||
|
||||
Shows information about all active consumers in the system.
|
||||
Shows information about all consumers in the system.
|
||||
|
||||
## SHOW CREATE DATABASE
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ REST connection supports all platforms that can run Java.
|
|||
|
||||
| taos-jdbcdriver version | major changes | TDengine version |
|
||||
| :---------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------: |
|
||||
| 3.2.1 | subscription add seek function | 3.0.5.0 or later |
|
||||
| 3.2.3 | Fixed resultSet data parsing failure in some cases | 3.0.5.0 or later |
|
||||
| 3.2.2 | subscription add seek function | 3.0.5.0 or later |
|
||||
| 3.2.1 | JDBC REST connection supports schemaless/prepareStatement over WebSocket | 3.0.3.0 or later |
|
||||
| 3.2.0 | This version has been deprecated | - |
|
||||
| 3.1.0 | JDBC REST connection supports subscription over WebSocket | - |
|
||||
|
@ -284,9 +285,9 @@ The configuration parameters in the URL are as follows:
|
|||
- batchfetch: true: pulls result sets in batches when executing queries; false: pulls result sets row by row. The default value is: false. batchfetch uses HTTP for data transfer. JDBC REST supports batch pulls. taos-jdbcdriver and TDengine transfer data via WebSocket connection. Compared with HTTP, WebSocket enables JDBC REST connection to support large data volume querying and improve query performance.
|
||||
- charset: specify the charset to parse the string, this parameter is valid only when set batchfetch to true.
|
||||
- batchErrorIgnore: true: when executing executeBatch of Statement, if one SQL execution fails in the middle, continue to execute the following SQL. false: no longer execute any statement after the failed SQL. The default value is: false.
|
||||
- httpConnectTimeout: REST connection timeout in milliseconds, the default value is 5000 ms.
|
||||
- httpSocketTimeout: socket timeout in milliseconds, the default value is 5000 ms. It only takes effect when batchfetch is false.
|
||||
- messageWaitTimeout: message transmission timeout in milliseconds, the default value is 3000 ms. It only takes effect when batchfetch is true.
|
||||
- httpConnectTimeout: REST connection timeout in milliseconds, the default value is 60000 ms.
|
||||
- httpSocketTimeout: socket timeout in milliseconds, the default value is 60000 ms. It only takes effect when batchfetch is false.
|
||||
- messageWaitTimeout: message transmission timeout in milliseconds, the default value is 60000 ms. It only takes effect when batchfetch is true.
|
||||
- useSSL: connecting Securely Using SSL. true: using SSL connection, false: not using SSL connection.
|
||||
- httpPoolSize: size of REST concurrent requests. The default value is 20.
|
||||
|
||||
|
@ -352,9 +353,9 @@ The configuration parameters in properties are as follows.
|
|||
- TSDBDriver.PROPERTY_KEY_CHARSET: In the character set used by the client, the default value is the system character set.
|
||||
- TSDBDriver.PROPERTY_KEY_LOCALE: this only takes effect when using JDBC native connection. Client language environment, the default value is system current locale.
|
||||
- TSDBDriver.PROPERTY_KEY_TIME_ZONE: only takes effect when using JDBC native connection. In the time zone used by the client, the default value is the system's current time zone.
|
||||
- TSDBDriver.HTTP_CONNECT_TIMEOUT: REST connection timeout in milliseconds, the default value is 5000 ms. It only takes effect when using JDBC REST connection.
|
||||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket timeout in milliseconds, the default value is 5000 ms. It only takes effect when using JDBC REST connection and batchfetch is false.
|
||||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: message transmission timeout in milliseconds, the default value is 3000 ms. It only takes effect when using JDBC REST connection and batchfetch is true.
|
||||
- TSDBDriver.HTTP_CONNECT_TIMEOUT: REST connection timeout in milliseconds, the default value is 60000 ms. It only takes effect when using JDBC REST connection.
|
||||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket timeout in milliseconds, the default value is 60000 ms. It only takes effect when using JDBC REST connection and batchfetch is false.
|
||||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: message transmission timeout in milliseconds, the default value is 60000 ms. It only takes effect when using JDBC REST connection and batchfetch is true.
|
||||
- TSDBDriver.PROPERTY_KEY_USE_SSL: connecting Securely Using SSL. true: using SSL connection, false: not using SSL connection. It only takes effect when using JDBC REST connection.
|
||||
- TSDBDriver.HTTP_POOL_SIZE: size of REST concurrent requests. The default value is 20.
|
||||
For JDBC native connections, you can specify other parameters, such as log level, SQL length, etc., by specifying URL and Properties. For more detailed configuration, please refer to [Client Configuration](/reference/config/#Client-Only).
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,21 +31,57 @@ Websocket connections are supported on all platforms that can run Go.
|
|||
|
||||
| connector-rust version | TDengine version | major features |
|
||||
| :----------------: | :--------------: | :--------------------------------------------------: |
|
||||
| v0.8.10 | 3.0.5.0 or later | TMQ: Get consuming progress and seek offset to consume. |
|
||||
| v0.8.12 | 3.0.5.0 or later | TMQ: Get consuming progress and seek offset to consume. |
|
||||
| v0.8.0 | 3.0.4.0 | Support schemaless insert. |
|
||||
| v0.7.6 | 3.0.3.0 | Support req_id in query. |
|
||||
| v0.6.0 | 3.0.0.0 | Base features. |
|
||||
|
||||
The Rust Connector is still under rapid development and is not guaranteed to be backward compatible before 1.0. We recommend using TDengine version 3.0 or higher to avoid known issues.
|
||||
|
||||
## Installation
|
||||
## Handling exceptions
|
||||
|
||||
After the error is reported, the specific information of the error can be obtained:
|
||||
|
||||
```rust
|
||||
match conn.exec(sql) {
|
||||
Ok(_) => {
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: {:?}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## TDengine DataType vs. Rust DataType
|
||||
|
||||
TDengine currently supports timestamp, number, character, Boolean type, and the corresponding type conversion with Rust is as follows:
|
||||
|
||||
| TDengine DataType | Rust DataType |
|
||||
| ----------------- | ----------------- |
|
||||
| TIMESTAMP | Timestamp |
|
||||
| INT | i32 |
|
||||
| BIGINT | i64 |
|
||||
| FLOAT | f32 |
|
||||
| DOUBLE | f64 |
|
||||
| SMALLINT | i16 |
|
||||
| TINYINT | i8 |
|
||||
| BOOL | bool |
|
||||
| BINARY | Vec<u8\> |
|
||||
| NCHAR | String |
|
||||
| JSON | serde_json::Value |
|
||||
|
||||
Note: Only TAG supports JSON types
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### Pre-installation preparation
|
||||
|
||||
* Install the Rust development toolchain
|
||||
* If using the native connection, please install the TDengine client driver. Please refer to [install client driver](/reference/connector#install-client-driver)
|
||||
|
||||
### Add taos dependency
|
||||
### Install the connectors
|
||||
|
||||
Depending on the connection method, add the [taos][taos] dependency in your Rust project as follows:
|
||||
|
||||
|
@ -146,7 +182,8 @@ let builder = TaosBuilder::from_dsn("taos://localhost:6030")?;
|
|||
let conn1 = builder.build();
|
||||
|
||||
// use websocket protocol.
|
||||
let conn2 = TaosBuilder::from_dsn("taos+ws://localhost:6041")?;
|
||||
let builder2 = TaosBuilder::from_dsn("taos+ws://localhost:6041")?;
|
||||
let conn2 = builder2.build();
|
||||
```
|
||||
|
||||
After the connection is established, you can perform operations on your database.
|
||||
|
@ -228,41 +265,191 @@ There are two ways to query data: Using built-in types or the [serde](https://se
|
|||
|
||||
## Usage examples
|
||||
|
||||
### Write data
|
||||
### Create database and tables
|
||||
|
||||
#### SQL Write
|
||||
```rust
|
||||
use taos::*;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let dsn = "taos://localhost:6030";
|
||||
let builder = TaosBuilder::from_dsn(dsn)?;
|
||||
|
||||
let taos = builder.build()?;
|
||||
|
||||
let db = "query";
|
||||
|
||||
// create database
|
||||
taos.exec_many([
|
||||
format!("DROP DATABASE IF EXISTS `{db}`"),
|
||||
format!("CREATE DATABASE `{db}`"),
|
||||
format!("USE `{db}`"),
|
||||
])
|
||||
.await?;
|
||||
|
||||
// create table
|
||||
taos.exec_many([
|
||||
// create super table
|
||||
"CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) \
|
||||
TAGS (`groupid` INT, `location` BINARY(16))",
|
||||
// create child table
|
||||
"CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')",
|
||||
]).await?;
|
||||
}
|
||||
```
|
||||
|
||||
> The query is consistent with operating a relational database. When using subscripts to get the contents of the returned fields, you have to start from 1. However, we recommend using the field names to get the values of the fields in the result set.
|
||||
|
||||
### Insert data
|
||||
|
||||
<RustInsert />
|
||||
|
||||
#### STMT Write
|
||||
|
||||
<RustBind />
|
||||
|
||||
#### Schemaless Write
|
||||
|
||||
<RustSml />
|
||||
|
||||
### Query data
|
||||
|
||||
<RustQuery />
|
||||
|
||||
## API Reference
|
||||
### execute SQL with req_id
|
||||
|
||||
### Connector Constructor
|
||||
|
||||
You create a connector constructor by using a DSN.
|
||||
This req_id can be used to request link tracing.
|
||||
|
||||
```rust
|
||||
let cfg = TaosBuilder::default().build()?;
|
||||
let rs = taos.query_with_req_id("select * from stable where tag1 is null", 1)?;
|
||||
```
|
||||
|
||||
You use the builder object to create multiple connections.
|
||||
### Writing data via parameter binding
|
||||
|
||||
TDengine has significantly improved the bind APIs to support data writing (INSERT) scenarios. Writing data in this way avoids the resource consumption of SQL syntax parsing, resulting in significant write performance improvements in many cases.
|
||||
|
||||
Parameter binding details see [API Reference](#stmt-api)
|
||||
|
||||
<RustBind />
|
||||
|
||||
### Schemaless Writing
|
||||
|
||||
TDengine supports schemaless writing. It is compatible with InfluxDB's Line Protocol, OpenTSDB's telnet line protocol, and OpenTSDB's JSON format protocol. For more information, see [Schemaless Writing](../../schemaless).
|
||||
|
||||
<RustSml />
|
||||
|
||||
### Schemaless with req_id
|
||||
|
||||
This req_id can be used to request link tracing.
|
||||
|
||||
```rust
|
||||
let conn: Taos = cfg.build();
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.data(data)
|
||||
.req_id(100u64)
|
||||
.build()?;
|
||||
|
||||
client.put(&sml_data)?
|
||||
```
|
||||
|
||||
### Connection pooling
|
||||
### Data Subscription
|
||||
|
||||
TDengine starts subscriptions through [TMQ](../../../taos-sql/tmq/).
|
||||
|
||||
#### Create a Topic
|
||||
|
||||
```rust
|
||||
taos.exec_many([
|
||||
// create topic for subscription
|
||||
format!("CREATE TOPIC tmq_meters with META AS DATABASE {db}")
|
||||
])
|
||||
.await?;
|
||||
```
|
||||
|
||||
#### Create a Consumer
|
||||
|
||||
You create a TMQ connector by using a DSN.
|
||||
|
||||
```rust
|
||||
let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?;
|
||||
```
|
||||
|
||||
Create a consumer:
|
||||
|
||||
```rust
|
||||
let mut consumer = tmq.build()?;
|
||||
```
|
||||
|
||||
#### Subscribe to consume data
|
||||
|
||||
A single consumer can subscribe to one or more topics.
|
||||
|
||||
```rust
|
||||
consumer.subscribe(["tmq_meters"]).await?;
|
||||
```
|
||||
|
||||
The TMQ is of [futures::Stream](https://docs.rs/futures/latest/futures/stream/index.html) type. You can use the corresponding API to consume each message in the queue and then use `.commit` to mark them as consumed.
|
||||
|
||||
```rust
|
||||
{
|
||||
let mut stream = consumer.stream();
|
||||
|
||||
while let Some((offset, message)) = stream.try_next().await? {
|
||||
// get information from offset
|
||||
|
||||
// the topic
|
||||
let topic = offset.topic();
|
||||
// the vgroup id, like partition id in kafka.
|
||||
let vgroup_id = offset.vgroup_id();
|
||||
println!("* in vgroup id {vgroup_id} of topic {topic}\n");
|
||||
|
||||
if let Some(data) = message.into_data() {
|
||||
while let Some(block) = data.fetch_raw_block().await? {
|
||||
// one block for one table, get table name if needed
|
||||
let name = block.table_name();
|
||||
let records: Vec<Record> = block.deserialize().try_collect()?;
|
||||
println!(
|
||||
"** table: {}, got {} records: {:#?}\n",
|
||||
name.unwrap(),
|
||||
records.len(),
|
||||
records
|
||||
);
|
||||
}
|
||||
}
|
||||
consumer.commit(offset).await?;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Get assignments:
|
||||
|
||||
Version requirements connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
let assignments = consumer.assignments().await.unwrap();
|
||||
```
|
||||
|
||||
#### Assignment subscription Offset
|
||||
|
||||
Seek offset:
|
||||
|
||||
Version requirements connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
consumer.offset_seek(topic, vgroup_id, offset).await;
|
||||
```
|
||||
|
||||
#### Close subscriptions
|
||||
|
||||
```rust
|
||||
consumer.unsubscribe().await;
|
||||
```
|
||||
|
||||
The following parameters can be configured for the TMQ DSN. Only `group.id` is mandatory.
|
||||
|
||||
- `group.id`: Within a consumer group, load balancing is implemented by consuming messages on an at-least-once basis.
|
||||
- `client.id`: Subscriber client ID.
|
||||
- `auto.offset.reset`: Initial point of subscription. *earliest* subscribes from the beginning, and *latest* subscribes from the newest message. The default is earliest. Note: This parameter is set per consumer group.
|
||||
- `enable.auto.commit`: Automatically commits. This can be enabled when data consistency is not essential.
|
||||
- `auto.commit.interval.ms`: Interval for automatic commits.
|
||||
|
||||
#### Full Sample Code
|
||||
|
||||
For more information, see [GitHub sample file](https://github.com/taosdata/TDengine/blob/3.0/docs/examples/rust/nativeexample/examples/subscribe_demo.rs).
|
||||
|
||||
### Use with connection pool
|
||||
|
||||
In complex applications, we recommend enabling connection pools. [taos] implements connection pools based on [r2d2].
|
||||
|
||||
|
@ -292,7 +479,17 @@ In the application code, use `pool.get()? ` to get a connection object [Taos].
|
|||
let taos = pool.get()?;
|
||||
```
|
||||
|
||||
### Connectors
|
||||
### More sample programs
|
||||
|
||||
The source code of the sample application is under `TDengine/examples/rust` :
|
||||
|
||||
[rust example](https://github.com/taosdata/TDengine/tree/3.0/examples/rust)
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
For additional troubleshooting, see [FAQ](../../../train-faq/faq).
|
||||
|
||||
## API Reference
|
||||
|
||||
The [Taos][struct.Taos] object provides an API to perform operations on multiple databases.
|
||||
|
||||
|
@ -378,9 +575,13 @@ Note that Rust asynchronous functions and an asynchronous runtime are required.
|
|||
- `.create_database(database: &str)`: Executes the `CREATE DATABASE` statement.
|
||||
- `.use_database(database: &str)`: Executes the `USE` statement.
|
||||
|
||||
In addition, this structure is also the entry point for [Parameter Binding](#Parameter Binding Interface) and [Line Protocol Interface](#Line Protocol Interface). Please refer to the specific API descriptions for usage.
|
||||
In addition, this structure is also the entry point for Parameter Binding and Line Protocol Interface. Please refer to the specific API descriptions for usage.
|
||||
|
||||
### Bind Interface
|
||||
<p>
|
||||
<a id="stmt-api" style={{color:'#141414'}}>
|
||||
Bind Interface
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Similar to the C interface, Rust provides the bind interface's wrapping. First, the [Taos][struct.taos] object creates a parameter binding object [Stmt] for an SQL statement.
|
||||
|
||||
|
@ -391,7 +592,7 @@ stmt.prepare("INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)")?;
|
|||
|
||||
The bind object provides a set of interfaces for implementing parameter binding.
|
||||
|
||||
#### `.set_tbname(name)`
|
||||
`.set_tbname(name)`
|
||||
|
||||
To bind table names.
|
||||
|
||||
|
@ -400,7 +601,7 @@ let mut stmt = taos.stmt("insert into ? values(? ,?)")?;
|
|||
stmt.set_tbname("d0")?;
|
||||
```
|
||||
|
||||
#### `.set_tags(&[tag])`
|
||||
`.set_tags(&[tag])`
|
||||
|
||||
Bind sub-table table names and tag values when the SQL statement uses a super table.
|
||||
|
||||
|
@ -410,7 +611,7 @@ stmt.set_tbname("d0")?;
|
|||
stmt.set_tags(&[Value::VarChar("taos".to_string())])?;
|
||||
```
|
||||
|
||||
#### `.bind(&[column])`
|
||||
`.bind(&[column])`
|
||||
|
||||
Bind value types. Use the [ColumnView] structure to create and bind the required types.
|
||||
|
||||
|
@ -434,7 +635,7 @@ let params = vec![
|
|||
let rows = stmt.bind(¶ms)?.add_batch()?.execute()?;
|
||||
```
|
||||
|
||||
#### `.execute()`
|
||||
`.execute()`
|
||||
|
||||
Execute SQL. [Stmt] objects can be reused, re-binded, and executed after execution. Before execution, ensure that all data has been added to the queue with `.add_batch`.
|
||||
|
||||
|
@ -449,92 +650,6 @@ stmt.execute()?;
|
|||
|
||||
For a working example, see [GitHub](https://github.com/taosdata/taos-connector-rust/blob/main/examples/bind.rs).
|
||||
|
||||
### Subscriptions
|
||||
|
||||
TDengine starts subscriptions through [TMQ](../../../taos-sql/tmq/).
|
||||
|
||||
You create a TMQ connector by using a DSN.
|
||||
|
||||
```rust
|
||||
let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?;
|
||||
```
|
||||
|
||||
Create a consumer:
|
||||
|
||||
```rust
|
||||
let mut consumer = tmq.build()?;
|
||||
```
|
||||
|
||||
A single consumer can subscribe to one or more topics.
|
||||
|
||||
```rust
|
||||
consumer.subscribe(["tmq_meters"]).await?;
|
||||
```
|
||||
|
||||
The TMQ is of [futures::Stream](https://docs.rs/futures/latest/futures/stream/index.html) type. You can use the corresponding API to consume each message in the queue and then use `.commit` to mark them as consumed.
|
||||
|
||||
```rust
|
||||
{
|
||||
let mut stream = consumer.stream();
|
||||
|
||||
while let Some((offset, message)) = stream.try_next().await? {
|
||||
// get information from offset
|
||||
|
||||
// the topic
|
||||
let topic = offset.topic();
|
||||
// the vgroup id, like partition id in kafka.
|
||||
let vgroup_id = offset.vgroup_id();
|
||||
println!("* in vgroup id {vgroup_id} of topic {topic}\n");
|
||||
|
||||
if let Some(data) = message.into_data() {
|
||||
while let Some(block) = data.fetch_raw_block().await? {
|
||||
// one block for one table, get table name if needed
|
||||
let name = block.table_name();
|
||||
let records: Vec<Record> = block.deserialize().try_collect()?;
|
||||
println!(
|
||||
"** table: {}, got {} records: {:#?}\n",
|
||||
name.unwrap(),
|
||||
records.len(),
|
||||
records
|
||||
);
|
||||
}
|
||||
}
|
||||
consumer.commit(offset).await?;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Get assignments:
|
||||
|
||||
Version requirements connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
let assignments = consumer.assignments().await.unwrap();
|
||||
```
|
||||
|
||||
Seek offset:
|
||||
|
||||
Version requirements connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
consumer.offset_seek(topic, vgroup_id, offset).await;
|
||||
```
|
||||
|
||||
Unsubscribe:
|
||||
|
||||
```rust
|
||||
consumer.unsubscribe().await;
|
||||
```
|
||||
|
||||
The following parameters can be configured for the TMQ DSN. Only `group.id` is mandatory.
|
||||
|
||||
- `group.id`: Within a consumer group, load balancing is implemented by consuming messages on an at-least-once basis.
|
||||
- `client.id`: Subscriber client ID.
|
||||
- `auto.offset.reset`: Initial point of subscription. *earliest* subscribes from the beginning, and *latest* subscribes from the newest message. The default is earliest. Note: This parameter is set per consumer group.
|
||||
- `enable.auto.commit`: Automatically commits. This can be enabled when data consistency is not essential.
|
||||
- `auto.commit.interval.ms`: Interval for automatic commits.
|
||||
|
||||
For more information, see [GitHub sample file](https://github.com/taosdata/TDengine/blob/3.0/docs/examples/rust/nativeexample/examples/subscribe_demo.rs).
|
||||
|
||||
For information about other structure APIs, see the [Rust documentation](https://docs.rs/taos).
|
||||
|
||||
|
|
|
@ -20,10 +20,25 @@ The source code for the Python connector is hosted on [GitHub](https://github.co
|
|||
- The [supported platforms](/reference/connector/#supported-platforms) for the native connection are the same as the ones supported by the TDengine client.
|
||||
- REST connections are supported on all platforms that can run Python.
|
||||
|
||||
### Supported features
|
||||
|
||||
- Native connections support all the core features of TDengine, including connection management, SQL execution, bind interface, subscriptions, and schemaless writing.
|
||||
- REST connections support features such as connection management and SQL execution. (SQL execution allows you to: manage databases, tables, and supertables, write data, query data, create continuous queries, etc.).
|
||||
|
||||
## Version selection
|
||||
|
||||
We recommend using the latest version of `taospy`, regardless of the version of TDengine.
|
||||
|
||||
|Python Connector Version|major changes|
|
||||
|:-------------------:|:----:|
|
||||
|2.7.9|support for getting assignment and seek function on subscription|
|
||||
|2.7.8|add `execute_many` method|
|
||||
|
||||
|Python Websocket Connector Version|major changes|
|
||||
|:----------------------------:|:-----:|
|
||||
|0.2.5|1. support for getting assignment and seek function on subscription <br/> 2. support schemaless <br/> 3. support STMT|
|
||||
|0.2.4|support `unsubscribe` on subscription|
|
||||
|
||||
## Handling Exceptions
|
||||
|
||||
There are 4 types of exception in python connector.
|
||||
|
@ -54,10 +69,23 @@ All exceptions from the Python Connector are thrown directly. Applications shoul
|
|||
{{#include docs/examples/python/handle_exception.py}}
|
||||
```
|
||||
|
||||
## Supported features
|
||||
## TDengine DataType vs. Python DataType
|
||||
|
||||
- Native connections support all the core features of TDengine, including connection management, SQL execution, bind interface, subscriptions, and schemaless writing.
|
||||
- REST connections support features such as connection management and SQL execution. (SQL execution allows you to: manage databases, tables, and supertables, write data, query data, create continuous queries, etc.).
|
||||
TDengine currently supports timestamp, number, character, Boolean type, and the corresponding type conversion with Python is as follows:
|
||||
|
||||
|TDengine DataType|Python DataType|
|
||||
|:---------------:|:-------------:|
|
||||
|TIMESTAMP|datetime|
|
||||
|INT|int|
|
||||
|BIGINT|int|
|
||||
|FLOAT|float|
|
||||
|DOUBLE|int|
|
||||
|SMALLINT|int|
|
||||
|TINYINT|int|
|
||||
|BOOL|bool|
|
||||
|BINARY|str|
|
||||
|NCHAR|str|
|
||||
|JSON|str|
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -534,7 +562,7 @@ Connector support data subscription. For more information about subscroption, pl
|
|||
|
||||
The `consumer` in the connector contains the subscription api.
|
||||
|
||||
#### Create Consumer
|
||||
##### Create Consumer
|
||||
|
||||
The syntax for creating a consumer is `consumer = Consumer(configs)`. For more subscription api parameters, please refer to [Data Subscription](../../../develop/tmq/).
|
||||
|
||||
|
@ -544,7 +572,7 @@ from taos.tmq import Consumer
|
|||
consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"})
|
||||
```
|
||||
|
||||
#### Subscribe topics
|
||||
##### Subscribe topics
|
||||
|
||||
The `subscribe` function is used to subscribe to a list of topics.
|
||||
|
||||
|
@ -552,7 +580,7 @@ The `subscribe` function is used to subscribe to a list of topics.
|
|||
consumer.subscribe(['topic1', 'topic2'])
|
||||
```
|
||||
|
||||
#### Consume
|
||||
##### Consume
|
||||
|
||||
The `poll` function is used to consume data in tmq. The parameter of the `poll` function is a value of type float representing the timeout in seconds. It returns a `Message` before timing out, or `None` on timing out. You have to handle error messages in response data.
|
||||
|
||||
|
@ -570,7 +598,7 @@ while True:
|
|||
print(block.fetchall())
|
||||
```
|
||||
|
||||
#### assignment
|
||||
##### assignment
|
||||
|
||||
The `assignment` function is used to get the assignment of the topic.
|
||||
|
||||
|
@ -578,7 +606,7 @@ The `assignment` function is used to get the assignment of the topic.
|
|||
assignments = consumer.assignment()
|
||||
```
|
||||
|
||||
#### Seek
|
||||
##### Seek
|
||||
|
||||
The `seek` function is used to reset the assignment of the topic.
|
||||
|
||||
|
@ -587,7 +615,7 @@ tp = TopicPartition(topic='topic1', partition=0, offset=0)
|
|||
consumer.seek(tp)
|
||||
```
|
||||
|
||||
#### After consuming data
|
||||
##### After consuming data
|
||||
|
||||
You should unsubscribe to the topics and close the consumer after consuming.
|
||||
|
||||
|
@ -596,13 +624,13 @@ consumer.unsubscribe()
|
|||
consumer.close()
|
||||
```
|
||||
|
||||
#### Tmq subscription example
|
||||
##### Tmq subscription example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_example.py}}
|
||||
```
|
||||
|
||||
#### assignment and seek example
|
||||
##### assignment and seek example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_assignment_example.py:taos_get_assignment_and_seek_demo}}
|
||||
|
@ -614,7 +642,7 @@ consumer.close()
|
|||
|
||||
In addition to native connections, the connector also supports subscriptions via websockets.
|
||||
|
||||
#### Create Consumer
|
||||
##### Create Consumer
|
||||
|
||||
The syntax for creating a consumer is "consumer = consumer = Consumer(conf=configs)". You need to specify that the `td.connect.websocket.scheme` parameter is set to "ws" in the configuration. For more subscription api parameters, please refer to [Data Subscription](../../../develop/tmq/#create-a-consumer).
|
||||
|
||||
|
@ -624,7 +652,7 @@ import taosws
|
|||
consumer = taosws.(conf={"group.id": "local", "td.connect.websocket.scheme": "ws"})
|
||||
```
|
||||
|
||||
#### subscribe topics
|
||||
##### subscribe topics
|
||||
|
||||
The `subscribe` function is used to subscribe to a list of topics.
|
||||
|
||||
|
@ -632,7 +660,7 @@ The `subscribe` function is used to subscribe to a list of topics.
|
|||
consumer.subscribe(['topic1', 'topic2'])
|
||||
```
|
||||
|
||||
#### Consume
|
||||
##### Consume
|
||||
|
||||
The `poll` function is used to consume data in tmq. The parameter of the `poll` function is a value of type float representing the timeout in seconds. It returns a `Message` before timing out, or `None` on timing out. You have to handle error messages in response data.
|
||||
|
||||
|
@ -649,7 +677,7 @@ while True:
|
|||
print(row)
|
||||
```
|
||||
|
||||
#### assignment
|
||||
##### assignment
|
||||
|
||||
The `assignment` function is used to get the assignment of the topic.
|
||||
|
||||
|
@ -657,7 +685,7 @@ The `assignment` function is used to get the assignment of the topic.
|
|||
assignments = consumer.assignment()
|
||||
```
|
||||
|
||||
#### Seek
|
||||
##### Seek
|
||||
|
||||
The `seek` function is used to reset the assignment of the topic.
|
||||
|
||||
|
@ -665,7 +693,7 @@ The `seek` function is used to reset the assignment of the topic.
|
|||
consumer.seek(topic='topic1', partition=0, offset=0)
|
||||
```
|
||||
|
||||
#### After consuming data
|
||||
##### After consuming data
|
||||
|
||||
You should unsubscribe to the topics and close the consumer after consuming.
|
||||
|
||||
|
@ -674,13 +702,13 @@ consumer.unsubscribe()
|
|||
consumer.close()
|
||||
```
|
||||
|
||||
#### Subscription example
|
||||
##### Subscription example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_websocket_example.py}}
|
||||
```
|
||||
|
||||
#### Assignment and seek example
|
||||
##### Assignment and seek example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_websocket_assgnment_example.py:taosws_get_assignment_and_seek_demo}}
|
||||
|
@ -696,19 +724,19 @@ Connector support schemaless insert.
|
|||
<Tabs defaultValue="list">
|
||||
<TabItem value="list" label="List Insert">
|
||||
|
||||
Simple insert
|
||||
##### Simple insert
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert.py}}
|
||||
```
|
||||
|
||||
Insert with ttl argument
|
||||
##### Insert with ttl argument
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_ttl.py}}
|
||||
```
|
||||
|
||||
Insert with req_id argument
|
||||
##### Insert with req_id argument
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_req_id.py}}
|
||||
|
@ -718,19 +746,19 @@ Insert with req_id argument
|
|||
|
||||
<TabItem value="raw" label="Raw Insert">
|
||||
|
||||
Simple insert
|
||||
##### Simple insert
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw.py}}
|
||||
```
|
||||
|
||||
Insert with ttl argument
|
||||
##### Insert with ttl argument
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw_ttl.py}}
|
||||
```
|
||||
|
||||
Insert with req_id argument
|
||||
##### Insert with req_id argument
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw_req_id.py}}
|
||||
|
@ -746,7 +774,7 @@ The Python connector provides a parameter binding api for inserting data. Simila
|
|||
<Tabs>
|
||||
<TabItem value="native" label="native connection">
|
||||
|
||||
#### Create Stmt
|
||||
##### Create Stmt
|
||||
|
||||
Call the `statement` method in `Connection` to create the `stmt` for parameter binding.
|
||||
|
||||
|
@ -757,7 +785,7 @@ conn = taos.connect()
|
|||
stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
```
|
||||
|
||||
#### parameter binding
|
||||
##### parameter binding
|
||||
|
||||
Call the `new_multi_binds` function to create the parameter list for parameter bindings.
|
||||
|
||||
|
@ -787,7 +815,7 @@ Call the `bind_param` (for a single row) method or the `bind_param_batch` (for m
|
|||
stmt.bind_param_batch(params)
|
||||
```
|
||||
|
||||
#### execute sql
|
||||
##### execute sql
|
||||
|
||||
Call `execute` method to execute sql.
|
||||
|
||||
|
@ -795,13 +823,13 @@ Call `execute` method to execute sql.
|
|||
stmt.execute()
|
||||
```
|
||||
|
||||
#### Close Stmt
|
||||
##### Close Stmt
|
||||
|
||||
```
|
||||
stmt.close()
|
||||
```
|
||||
|
||||
#### Example
|
||||
##### Example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/stmt_example.py}}
|
||||
|
@ -810,7 +838,7 @@ stmt.close()
|
|||
|
||||
<TabItem value="websocket" label="WebSocket connection">
|
||||
|
||||
#### Create Stmt
|
||||
##### Create Stmt
|
||||
|
||||
Call the `statement` method in `Connection` to create the `stmt` for parameter binding.
|
||||
|
||||
|
@ -821,7 +849,7 @@ conn = taosws.connect('taosws://localhost:6041/test')
|
|||
stmt = conn.statement()
|
||||
```
|
||||
|
||||
#### Prepare sql
|
||||
##### Prepare sql
|
||||
|
||||
Call `prepare` method in stmt to prepare sql.
|
||||
|
||||
|
@ -829,7 +857,7 @@ Call `prepare` method in stmt to prepare sql.
|
|||
stmt.prepare("insert into t1 values (?, ?, ?, ?)")
|
||||
```
|
||||
|
||||
#### parameter binding
|
||||
##### parameter binding
|
||||
|
||||
Call the `bind_param` method to bind parameters.
|
||||
|
||||
|
@ -848,7 +876,7 @@ Call the `add_batch` method to add parameters to the batch.
|
|||
stmt.add_batch()
|
||||
```
|
||||
|
||||
#### execute sql
|
||||
##### execute sql
|
||||
|
||||
Call `execute` method to execute sql.
|
||||
|
||||
|
@ -856,13 +884,13 @@ Call `execute` method to execute sql.
|
|||
stmt.execute()
|
||||
```
|
||||
|
||||
#### Close Stmt
|
||||
##### Close Stmt
|
||||
|
||||
```
|
||||
stmt.close()
|
||||
```
|
||||
|
||||
#### Example
|
||||
##### Example
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/stmt_websocket_example.py}}
|
||||
|
|
|
@ -10,6 +10,10 @@ For TDengine 2.x installation packages by version, please visit [here](https://w
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.6.0
|
||||
|
||||
<Release type="tdengine" version="3.0.6.0" />
|
||||
|
||||
## 3.0.5.1
|
||||
|
||||
<Release type="tdengine" version="3.0.5.1" />
|
||||
|
|
|
@ -243,6 +243,7 @@ TDengine 使用 SQL 创建一个 topic:
|
|||
```sql
|
||||
CREATE TOPIC topic_name AS SELECT ts, c1, c2, c3 FROM tmqdb.stb WHERE c1 > 1;
|
||||
```
|
||||
- topic创建个数有上限,通过参数 tmqMaxTopicNum 控制,默认 20 个
|
||||
|
||||
TMQ 支持多种订阅类型:
|
||||
|
||||
|
@ -265,14 +266,15 @@ CREATE TOPIC topic_name as subquery
|
|||
语法:
|
||||
|
||||
```sql
|
||||
CREATE TOPIC topic_name AS STABLE stb_name
|
||||
CREATE TOPIC topic_name [with meta] AS STABLE stb_name [where_condition]
|
||||
```
|
||||
|
||||
与 `SELECT * from stbName` 订阅的区别是:
|
||||
|
||||
- 不会限制用户的表结构变更。
|
||||
- 返回的是非结构化的数据:返回数据的结构会随之超级表的表结构变化而变化。
|
||||
- 用户对于要处理的每一个数据块都可能有不同的表结构。
|
||||
- with meta 参数可选,选择时将返回创建超级表,子表等语句,主要用于taosx做超级表迁移
|
||||
- where_condition 参数可选,选择时将用来过滤符合条件的子表,订阅这些子表。where 条件里不能有普通列,只能是tag或tbname,where条件里可以用函数,用来过滤tag,但是不能是聚合函数,因为子表tag值无法做聚合。也可以是常量表达式,比如 2 > 1(订阅全部子表),或者 false(订阅0个子表)
|
||||
- 返回数据不包含标签。
|
||||
|
||||
### 数据库订阅
|
||||
|
@ -280,11 +282,13 @@ CREATE TOPIC topic_name AS STABLE stb_name
|
|||
语法:
|
||||
|
||||
```sql
|
||||
CREATE TOPIC topic_name AS DATABASE db_name;
|
||||
CREATE TOPIC topic_name [with meta] AS DATABASE db_name;
|
||||
```
|
||||
|
||||
通过该语句可创建一个包含数据库所有表数据的订阅
|
||||
|
||||
- with meta 参数可选,选择时将返回创建数据库里所有超级表,子表的语句,主要用于taosx做数据库迁移
|
||||
|
||||
## 创建消费者 *consumer*
|
||||
|
||||
消费者需要通过一系列配置选项创建,基础配置项如下表所示:
|
||||
|
@ -295,7 +299,7 @@ CREATE TOPIC topic_name AS DATABASE db_name;
|
|||
| `td.connect.user` | string | 用户名 | |
|
||||
| `td.connect.pass` | string | 密码 | |
|
||||
| `td.connect.port` | integer | 服务端的端口号 | |
|
||||
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192。 |
|
||||
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | <br />**必填项**。最大长度:192。<br />每个topic最多可建立100个 consumer group |
|
||||
| `client.id` | string | 客户端 ID | 最大长度:192。 |
|
||||
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default;从头开始订阅; <br/>`latest`: 仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 |
|
||||
| `enable.auto.commit` | boolean | 是否启用消费位点自动提交,true: 自动提交,客户端应用无需commit;false:客户端应用需要自行commit | 默认值为 true |
|
||||
|
|
|
@ -17,7 +17,7 @@ TDengine 支持通过 C/Python 语言进行 UDF 定义。接下来结合示例
|
|||
- 聚合函数需要实现聚合接口函数 aggfn_start , aggfn , aggfn_finish。
|
||||
- 如果需要初始化,实现 udf_init;如果需要清理工作,实现udf_destroy。
|
||||
|
||||
接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(_start, _finish, _init, _destroy)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。
|
||||
接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(`_start`, `_finish`, `_init`, `_destroy`)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。
|
||||
|
||||
### 用 C 语言实现标量函数
|
||||
标量函数实现模板如下
|
||||
|
|
|
@ -36,14 +36,15 @@ REST 连接支持所有能运行 Java 的平台。
|
|||
|
||||
| taos-jdbcdriver 版本 | 主要变化 | TDengine 版本 |
|
||||
| :------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------: |
|
||||
| 3.2.3 | 修复 ResultSet 在一些情况数据解析失败 | - |
|
||||
| 3.2.2 | 新增功能:数据订阅支持 seek 功能。 | 3.0.5.0 及更高版本 |
|
||||
| 3.2.1 | 新增功能:WebSocket 连接支持 schemaless 与 prepareStatement 写入。变更:consumer poll 返回结果集为 ConsumerRecord,可通过 value() 获取指定结果集数据。 | 3.0.3.0 及更高版本 |
|
||||
| 3.2.0 | 存在连接问题,不推荐使用 | - |
|
||||
| 3.1.0 | WebSocket 连接支持订阅功能 | - |
|
||||
| 3.0.1 - 3.0.4 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用其他版本 | - |
|
||||
| 3.0.0 | 支持 TDengine 3.0 | 3.0.0.0 及更高版本 |
|
||||
| 2.0.42 | 修在 WebSocket 连接中 wasNull 接口返回值 | - |
|
||||
| 2.0.41 | 修正 REST 连接中用户名和密码转码方式 | - |
|
||||
| 2.0.42 | 修复 WebSocket 连接中 wasNull 接口返回值 | - |
|
||||
| 2.0.41 | 修复 REST 连接中用户名和密码转码方式 | - |
|
||||
| 2.0.39 - 2.0.40 | 增加 REST 连接/请求 超时设置 | - |
|
||||
| 2.0.38 | JDBC REST 连接增加批量拉取功能 | - |
|
||||
| 2.0.37 | 增加对 json tag 支持 | - |
|
||||
|
@ -287,9 +288,9 @@ url 中的配置参数如下:
|
|||
- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTP,WebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。
|
||||
- charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。
|
||||
- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。
|
||||
- httpConnectTimeout: 连接超时时间,单位 ms, 默认值为 5000。
|
||||
- httpSocketTimeout: socket 超时时间,单位 ms,默认值为 5000。仅在 batchfetch 设置为 false 时生效。
|
||||
- messageWaitTimeout: 消息超时时间, 单位 ms, 默认值为 3000。 仅在 batchfetch 设置为 true 时生效。
|
||||
- httpConnectTimeout: 连接超时时间,单位 ms, 默认值为 60000。
|
||||
- httpSocketTimeout: socket 超时时间,单位 ms,默认值为 60000。仅在 batchfetch 设置为 false 时生效。
|
||||
- messageWaitTimeout: 消息超时时间, 单位 ms, 默认值为 60000。 仅在 batchfetch 设置为 true 时生效。
|
||||
- useSSL: 连接中是否使用 SSL。
|
||||
- httpPoolSize: REST 并发请求大小,默认 20。
|
||||
|
||||
|
@ -355,9 +356,9 @@ properties 中的配置参数如下:
|
|||
- TSDBDriver.PROPERTY_KEY_CHARSET:客户端使用的字符集,默认值为系统字符集。
|
||||
- TSDBDriver.PROPERTY_KEY_LOCALE:仅在使用 JDBC 原生连接时生效。 客户端语言环境,默认值系统当前 locale。
|
||||
- TSDBDriver.PROPERTY_KEY_TIME_ZONE:仅在使用 JDBC 原生连接时生效。 客户端使用的时区,默认值为系统当前时区。
|
||||
- TSDBDriver.HTTP_CONNECT_TIMEOUT: 连接超时时间,单位 ms, 默认值为 5000。仅在 REST 连接时生效。
|
||||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket 超时时间,单位 ms,默认值为 5000。仅在 REST 连接且 batchfetch 设置为 false 时生效。
|
||||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: 消息超时时间, 单位 ms, 默认值为 3000。 仅在 REST 连接且 batchfetch 设置为 true 时生效。
|
||||
- TSDBDriver.HTTP_CONNECT_TIMEOUT: 连接超时时间,单位 ms, 默认值为 60000。仅在 REST 连接时生效。
|
||||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket 超时时间,单位 ms,默认值为 60000。仅在 REST 连接且 batchfetch 设置为 false 时生效。
|
||||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: 消息超时时间, 单位 ms, 默认值为 60000。 仅在 REST 连接且 batchfetch 设置为 true 时生效。
|
||||
- TSDBDriver.PROPERTY_KEY_USE_SSL: 连接中是否使用 SSL。仅在 REST 连接时生效。
|
||||
- TSDBDriver.HTTP_POOL_SIZE: REST 并发请求大小,默认 20。
|
||||
此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数,比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](/reference/config/#仅客户端适用)。
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,21 +30,57 @@ Websocket 连接支持所有能运行 Rust 的平台。
|
|||
|
||||
| Rust 连接器版本 | TDengine 版本 | 主要功能 |
|
||||
| :----------------: | :--------------: | :--------------------------------------------------: |
|
||||
| v0.8.10 | 3.0.5.0 or later | 消息订阅:获取消费进度及按照指定进度开始消费。 |
|
||||
| v0.8.12 | 3.0.5.0 or later | 消息订阅:获取消费进度及按照指定进度开始消费。 |
|
||||
| v0.8.0 | 3.0.4.0 | 支持无模式写入。 |
|
||||
| v0.7.6 | 3.0.3.0 | 支持在请求中使用 req_id。 |
|
||||
| v0.6.0 | 3.0.0.0 | 基础功能。 |
|
||||
|
||||
Rust 连接器仍然在快速开发中,1.0 之前无法保证其向后兼容。建议使用 3.0 版本以上的 TDengine,以避免已知问题。
|
||||
|
||||
## 安装
|
||||
## 处理错误
|
||||
|
||||
在报错后,可以获取到错误的具体信息:
|
||||
|
||||
```rust
|
||||
match conn.exec(sql) {
|
||||
Ok(_) => {
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: {:?}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## TDengine DataType 和 Rust DataType
|
||||
|
||||
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Rust 对应类型转换如下:
|
||||
|
||||
| TDengine DataType | Rust DataType |
|
||||
| ----------------- | ----------------- |
|
||||
| TIMESTAMP | Timestamp |
|
||||
| INT | i32 |
|
||||
| BIGINT | i64 |
|
||||
| FLOAT | f32 |
|
||||
| DOUBLE | f64 |
|
||||
| SMALLINT | i16 |
|
||||
| TINYINT | i8 |
|
||||
| BOOL | bool |
|
||||
| BINARY | Vec<u8\> |
|
||||
| NCHAR | String |
|
||||
| JSON | serde_json::Value |
|
||||
|
||||
**注意**:JSON 类型仅在 tag 中支持。
|
||||
|
||||
## 安装步骤
|
||||
|
||||
### 安装前准备
|
||||
|
||||
* 安装 Rust 开发工具链
|
||||
* 如果使用原生连接,请安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](../#安装客户端驱动)
|
||||
|
||||
### 添加 taos 依赖
|
||||
### 安装连接器
|
||||
|
||||
根据选择的连接方式,按照如下说明在 [Rust](https://rust-lang.org) 项目中添加 [taos][taos] 依赖:
|
||||
|
||||
|
@ -151,7 +187,8 @@ let builder = TaosBuilder::from_dsn("taos://localhost:6030")?;
|
|||
let conn1 = builder.build();
|
||||
|
||||
// use websocket protocol.
|
||||
let conn2 = TaosBuilder::from_dsn("taos+ws://localhost:6041")?;
|
||||
let builder2 = TaosBuilder::from_dsn("taos+ws://localhost:6041")?;
|
||||
let conn2 = builder2.build();
|
||||
```
|
||||
|
||||
建立连接后,您可以进行相关数据库操作:
|
||||
|
@ -233,41 +270,191 @@ async fn demo(taos: &Taos, db: &str) -> Result<(), Error> {
|
|||
|
||||
## 使用示例
|
||||
|
||||
### 写入数据
|
||||
### 创建数据库和表
|
||||
|
||||
#### SQL 写入
|
||||
```rust
|
||||
use taos::*;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let dsn = "taos://localhost:6030";
|
||||
let builder = TaosBuilder::from_dsn(dsn)?;
|
||||
|
||||
let taos = builder.build()?;
|
||||
|
||||
let db = "query";
|
||||
|
||||
// create database
|
||||
taos.exec_many([
|
||||
format!("DROP DATABASE IF EXISTS `{db}`"),
|
||||
format!("CREATE DATABASE `{db}`"),
|
||||
format!("USE `{db}`"),
|
||||
])
|
||||
.await?;
|
||||
|
||||
// create table
|
||||
taos.exec_many([
|
||||
// create super table
|
||||
"CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) \
|
||||
TAGS (`groupid` INT, `location` BINARY(16))",
|
||||
// create child table
|
||||
"CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')",
|
||||
]).await?;
|
||||
}
|
||||
```
|
||||
|
||||
> **注意**:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
|
||||
|
||||
### 插入数据
|
||||
|
||||
<RustInsert />
|
||||
|
||||
#### STMT 写入
|
||||
|
||||
<RustBind />
|
||||
|
||||
#### Schemaless 写入
|
||||
|
||||
<RustSml />
|
||||
|
||||
### 查询数据
|
||||
|
||||
<RustQuery />
|
||||
|
||||
## API 参考
|
||||
### 执行带有 req_id 的 SQL
|
||||
|
||||
### 连接构造器
|
||||
|
||||
通过 DSN 来构建一个连接器构造器。
|
||||
此 req_id 可用于请求链路追踪。
|
||||
|
||||
```rust
|
||||
let cfg = TaosBuilder::default().build()?;
|
||||
let rs = taos.query_with_req_id("select * from stable where tag1 is null", 1)?;
|
||||
```
|
||||
|
||||
使用 `builder` 对象创建多个连接:
|
||||
### 通过参数绑定写入数据
|
||||
|
||||
TDengine 的 Rust 连接器实现了参数绑定方式对数据写入(INSERT)场景的支持。采用这种方式写入数据时,能避免 SQL 语法解析的资源消耗,从而在很多情况下显著提升写入性能。
|
||||
|
||||
参数绑定接口详见[API参考](#stmt-api)
|
||||
|
||||
<RustBind />
|
||||
|
||||
### 无模式写入
|
||||
|
||||
TDengine 支持无模式写入功能。无模式写入兼容 InfluxDB 的 行协议(Line Protocol)、OpenTSDB 的 telnet 行协议和 OpenTSDB 的 JSON 格式协议。详情请参见[无模式写入](../../reference/schemaless/)。
|
||||
|
||||
<RustSml />
|
||||
|
||||
### 执行带有 req_id 的无模式写入
|
||||
|
||||
此 req_id 可用于请求链路追踪。
|
||||
|
||||
```rust
|
||||
let conn: Taos = cfg.build();
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.data(data)
|
||||
.req_id(100u64)
|
||||
.build()?;
|
||||
|
||||
client.put(&sml_data)?
|
||||
```
|
||||
|
||||
### 连接池
|
||||
### 数据订阅
|
||||
|
||||
TDengine 通过消息队列 [TMQ](../../../taos-sql/tmq/) 启动一个订阅。
|
||||
|
||||
#### 创建 Topic
|
||||
|
||||
```rust
|
||||
taos.exec_many([
|
||||
// create topic for subscription
|
||||
format!("CREATE TOPIC tmq_meters with META AS DATABASE {db}")
|
||||
])
|
||||
.await?;
|
||||
```
|
||||
|
||||
#### 创建 Consumer
|
||||
|
||||
从 DSN 开始,构建一个 TMQ 连接器。
|
||||
|
||||
```rust
|
||||
let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?;
|
||||
```
|
||||
|
||||
创建消费者:
|
||||
|
||||
```rust
|
||||
let mut consumer = tmq.build()?;
|
||||
```
|
||||
|
||||
#### 订阅消费数据
|
||||
|
||||
消费者可订阅一个或多个 `TOPIC`。
|
||||
|
||||
```rust
|
||||
consumer.subscribe(["tmq_meters"]).await?;
|
||||
```
|
||||
|
||||
TMQ 消息队列是一个 [futures::Stream](https://docs.rs/futures/latest/futures/stream/index.html) 类型,可以使用相应 API 对每个消息进行消费,并通过 `.commit` 进行已消费标记。
|
||||
|
||||
```rust
|
||||
{
|
||||
let mut stream = consumer.stream();
|
||||
|
||||
while let Some((offset, message)) = stream.try_next().await? {
|
||||
// get information from offset
|
||||
|
||||
// the topic
|
||||
let topic = offset.topic();
|
||||
// the vgroup id, like partition id in kafka.
|
||||
let vgroup_id = offset.vgroup_id();
|
||||
println!("* in vgroup id {vgroup_id} of topic {topic}\n");
|
||||
|
||||
if let Some(data) = message.into_data() {
|
||||
while let Some(block) = data.fetch_raw_block().await? {
|
||||
// one block for one table, get table name if needed
|
||||
let name = block.table_name();
|
||||
let records: Vec<Record> = block.deserialize().try_collect()?;
|
||||
println!(
|
||||
"** table: {}, got {} records: {:#?}\n",
|
||||
name.unwrap(),
|
||||
records.len(),
|
||||
records
|
||||
);
|
||||
}
|
||||
}
|
||||
consumer.commit(offset).await?;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
获取消费进度:
|
||||
|
||||
版本要求 connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
let assignments = consumer.assignments().await.unwrap();
|
||||
```
|
||||
|
||||
#### 指定订阅 Offset
|
||||
|
||||
按照指定的进度消费:
|
||||
|
||||
版本要求 connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
consumer.offset_seek(topic, vgroup_id, offset).await;
|
||||
```
|
||||
|
||||
#### 关闭订阅
|
||||
|
||||
```rust
|
||||
consumer.unsubscribe().await;
|
||||
```
|
||||
|
||||
对于 TMQ DSN, 有以下配置项可以进行设置,需要注意的是,`group.id` 是必须的。
|
||||
|
||||
- `group.id`: 同一个消费者组,将以至少消费一次的方式进行消息负载均衡。
|
||||
- `client.id`: 可选的订阅客户端识别项。
|
||||
- `auto.offset.reset`: 可选初始化订阅起点, *earliest* 为从头开始订阅, *latest* 为仅从最新数据开始订阅,默认为从头订阅。注意,此选项在同一个 `group.id` 中仅生效一次。
|
||||
- `enable.auto.commit`: 当设置为 `true` 时,将启用自动标记模式,当对数据一致性不敏感时,可以启用此方式。
|
||||
- `auto.commit.interval.ms`: 自动标记的时间间隔。
|
||||
|
||||
#### 完整示例
|
||||
|
||||
完整订阅示例参见 [GitHub 示例文件](https://github.com/taosdata/TDengine/blob/3.0/docs/examples/rust/nativeexample/examples/subscribe_demo.rs).
|
||||
|
||||
### 与连接池使用
|
||||
|
||||
在复杂应用中,建议启用连接池。[taos] 的连接池默认(异步模式)使用 [deadpool] 实现。
|
||||
|
||||
|
@ -295,7 +482,17 @@ let pool: Pool<TaosBuilder> = Pool::builder(Manager::from_dsn(self.dsn.clone()).
|
|||
let taos = pool.get()?;
|
||||
```
|
||||
|
||||
### 连接
|
||||
### 更多示例程序
|
||||
|
||||
示例程序源码位于 `TDengine/examples/rust` 下:
|
||||
|
||||
请参考:[rust example](https://github.com/taosdata/TDengine/tree/3.0/examples/rust)
|
||||
|
||||
## 常见问题
|
||||
|
||||
请参考 [FAQ](../../../train-faq/faq)
|
||||
|
||||
## API 参考
|
||||
|
||||
[Taos][struct.Taos] 对象提供了多个数据库操作的 API:
|
||||
|
||||
|
@ -381,9 +578,13 @@ let taos = pool.get()?;
|
|||
- `.create_database(database: &str)`: 执行 `CREATE DATABASE` 语句。
|
||||
- `.use_database(database: &str)`: 执行 `USE` 语句。
|
||||
|
||||
除此之外,该结构也是 [参数绑定](#参数绑定接口) 和 [行协议接口](#行协议接口) 的入口,使用方法请参考具体的 API 说明。
|
||||
除此之外,该结构也是参数绑定和行协议接口的入口,使用方法请参考具体的 API 说明。
|
||||
|
||||
### 参数绑定接口
|
||||
<p>
|
||||
<a id="stmt-api" style={{color:'#141414'}}>
|
||||
参数绑定接口
|
||||
</a>
|
||||
</p>
|
||||
|
||||
与 C 接口类似,Rust 提供参数绑定接口。首先,通过 [Taos][struct.Taos] 对象创建一个 SQL 语句的参数绑定对象 [Stmt]:
|
||||
|
||||
|
@ -394,7 +595,7 @@ stmt.prepare("INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)")?;
|
|||
|
||||
参数绑定对象提供了一组接口用于实现参数绑定:
|
||||
|
||||
#### `.set_tbname(name)`
|
||||
`.set_tbname(name)`
|
||||
|
||||
用于绑定表名。
|
||||
|
||||
|
@ -403,7 +604,7 @@ let mut stmt = taos.stmt("insert into ? values(? ,?)")?;
|
|||
stmt.set_tbname("d0")?;
|
||||
```
|
||||
|
||||
#### `.set_tags(&[tag])`
|
||||
`.set_tags(&[tag])`
|
||||
|
||||
当 SQL 语句使用超级表时,用于绑定子表表名和标签值:
|
||||
|
||||
|
@ -413,7 +614,7 @@ stmt.set_tbname("d0")?;
|
|||
stmt.set_tags(&[Value::VarChar("涛思".to_string())])?;
|
||||
```
|
||||
|
||||
#### `.bind(&[column])`
|
||||
`.bind(&[column])`
|
||||
|
||||
用于绑定值类型。使用 [ColumnView] 结构体构建需要的类型并绑定:
|
||||
|
||||
|
@ -437,7 +638,7 @@ let params = vec![
|
|||
let rows = stmt.bind(¶ms)?.add_batch()?.execute()?;
|
||||
```
|
||||
|
||||
#### `.execute()`
|
||||
`.execute()`
|
||||
|
||||
执行 SQL。[Stmt] 对象可以复用,在执行后可以重新绑定并执行。执行前请确保所有数据已通过 `.add_batch` 加入到执行队列中。
|
||||
|
||||
|
@ -452,92 +653,6 @@ stmt.execute()?;
|
|||
|
||||
一个可运行的示例请见 [GitHub 上的示例](https://github.com/taosdata/taos-connector-rust/blob/main/examples/bind.rs)。
|
||||
|
||||
### 订阅
|
||||
|
||||
TDengine 通过消息队列 [TMQ](../../../taos-sql/tmq/) 启动一个订阅。
|
||||
|
||||
从 DSN 开始,构建一个 TMQ 连接器。
|
||||
|
||||
```rust
|
||||
let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?;
|
||||
```
|
||||
|
||||
创建消费者:
|
||||
|
||||
```rust
|
||||
let mut consumer = tmq.build()?;
|
||||
```
|
||||
|
||||
消费者可订阅一个或多个 `TOPIC`。
|
||||
|
||||
```rust
|
||||
consumer.subscribe(["tmq_meters"]).await?;
|
||||
```
|
||||
|
||||
TMQ 消息队列是一个 [futures::Stream](https://docs.rs/futures/latest/futures/stream/index.html) 类型,可以使用相应 API 对每个消息进行消费,并通过 `.commit` 进行已消费标记。
|
||||
|
||||
```rust
|
||||
{
|
||||
let mut stream = consumer.stream();
|
||||
|
||||
while let Some((offset, message)) = stream.try_next().await? {
|
||||
// get information from offset
|
||||
|
||||
// the topic
|
||||
let topic = offset.topic();
|
||||
// the vgroup id, like partition id in kafka.
|
||||
let vgroup_id = offset.vgroup_id();
|
||||
println!("* in vgroup id {vgroup_id} of topic {topic}\n");
|
||||
|
||||
if let Some(data) = message.into_data() {
|
||||
while let Some(block) = data.fetch_raw_block().await? {
|
||||
// one block for one table, get table name if needed
|
||||
let name = block.table_name();
|
||||
let records: Vec<Record> = block.deserialize().try_collect()?;
|
||||
println!(
|
||||
"** table: {}, got {} records: {:#?}\n",
|
||||
name.unwrap(),
|
||||
records.len(),
|
||||
records
|
||||
);
|
||||
}
|
||||
}
|
||||
consumer.commit(offset).await?;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
获取消费进度:
|
||||
|
||||
版本要求 connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
let assignments = consumer.assignments().await.unwrap();
|
||||
```
|
||||
|
||||
按照指定的进度消费:
|
||||
|
||||
版本要求 connector-rust >= v0.8.8, TDengine >= 3.0.5.0
|
||||
|
||||
```rust
|
||||
consumer.offset_seek(topic, vgroup_id, offset).await;
|
||||
```
|
||||
|
||||
停止订阅:
|
||||
|
||||
```rust
|
||||
consumer.unsubscribe().await;
|
||||
```
|
||||
|
||||
对于 TMQ DSN, 有以下配置项可以进行设置,需要注意的是,`group.id` 是必须的。
|
||||
|
||||
- `group.id`: 同一个消费者组,将以至少消费一次的方式进行消息负载均衡。
|
||||
- `client.id`: 可选的订阅客户端识别项。
|
||||
- `auto.offset.reset`: 可选初始化订阅起点, *earliest* 为从头开始订阅, *latest* 为仅从最新数据开始订阅,默认为从头订阅。注意,此选项在同一个 `group.id` 中仅生效一次。
|
||||
- `enable.auto.commit`: 当设置为 `true` 时,将启用自动标记模式,当对数据一致性不敏感时,可以启用此方式。
|
||||
- `auto.commit.interval.ms`: 自动标记的时间间隔。
|
||||
|
||||
完整订阅示例参见 [GitHub 示例文件](https://github.com/taosdata/TDengine/blob/3.0/docs/examples/rust/nativeexample/examples/subscribe_demo.rs).
|
||||
|
||||
其他相关结构体 API 使用说明请移步 Rust 文档托管网页:<https://docs.rs/taos>。
|
||||
|
||||
|
|
|
@ -21,10 +21,25 @@ Python 连接器的源码托管在 [GitHub](https://github.com/taosdata/taos-con
|
|||
- 原生连接[支持的平台](../#支持的平台)和 TDengine 客户端支持的平台一致。
|
||||
- REST 连接支持所有能运行 Python 的平台。
|
||||
|
||||
## 版本选择
|
||||
### 支持的功能
|
||||
|
||||
- 原生连接支持 TDengine 的所有核心功能, 包括: 连接管理、执行 SQL、参数绑定、订阅、无模式写入(schemaless)。
|
||||
- REST 连接支持的功能包括:连接管理、执行 SQL。 (通过执行 SQL 可以: 管理数据库、管理表和超级表、写入数据、查询数据、创建连续查询等)。
|
||||
|
||||
## 历史版本
|
||||
|
||||
无论使用什么版本的 TDengine 都建议使用最新版本的 `taospy`。
|
||||
|
||||
|Python Connector 版本|主要变化|
|
||||
|:-------------------:|:----:|
|
||||
|2.7.9|数据订阅支持获取消费进度和重置消费进度|
|
||||
|2.7.8|新增 `execute_many`|
|
||||
|
||||
|Python Websocket Connector 版本|主要变化|
|
||||
|:----------------------------:|:-----:|
|
||||
|0.2.5|1. 数据订阅支持获取消费进度和重置消费进度 <br/> 2. 支持 schemaless <br/> 3. 支持 STMT|
|
||||
|0.2.4|数据订阅新增取消订阅方法|
|
||||
|
||||
## 处理异常
|
||||
|
||||
Python 连接器可能会产生 4 种异常:
|
||||
|
@ -55,12 +70,25 @@ Python Connector 的所有数据库操作如果出现异常,都会直接抛出
|
|||
{{#include docs/examples/python/handle_exception.py}}
|
||||
```
|
||||
|
||||
## 支持的功能
|
||||
TDengine DataType 和 Python DataType
|
||||
|
||||
- 原生连接支持 TDengine 的所有核心功能, 包括: 连接管理、执行 SQL、参数绑定、订阅、无模式写入(schemaless)。
|
||||
- REST 连接支持的功能包括:连接管理、执行 SQL。 (通过执行 SQL 可以: 管理数据库、管理表和超级表、写入数据、查询数据、创建连续查询等)。
|
||||
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Python 对应类型转换如下:
|
||||
|
||||
## 安装
|
||||
|TDengine DataType|Python DataType|
|
||||
|:---------------:|:-------------:|
|
||||
|TIMESTAMP|datetime|
|
||||
|INT|int|
|
||||
|BIGINT|int|
|
||||
|FLOAT|float|
|
||||
|DOUBLE|int|
|
||||
|SMALLINT|int|
|
||||
|TINYINT|int|
|
||||
|BOOL|bool|
|
||||
|BINARY|str|
|
||||
|NCHAR|str|
|
||||
|JSON|str|
|
||||
|
||||
## 安装步骤
|
||||
|
||||
### 安装前准备
|
||||
|
||||
|
@ -373,7 +401,7 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
</TabItem>
|
||||
<TabItem value="websocket" label="WebSocket 连接">
|
||||
|
||||
#### Connection 类的使用
|
||||
##### Connection 类的使用
|
||||
|
||||
`Connection` 类既包含对 PEP249 Connection 接口的实现(如:cursor方法和 close 方法),也包含很多扩展功能(如: execute、 query、schemaless_insert 和 subscribe 方法。
|
||||
|
||||
|
@ -537,7 +565,7 @@ RestClient 类是对于 REST API 的直接封装。它只包含一个 sql() 方
|
|||
|
||||
`Consumer` 提供了 Python 连接器订阅 TMQ 数据的 API。
|
||||
|
||||
#### 创建 Consumer
|
||||
##### 创建 Consumer
|
||||
|
||||
创建 Consumer 语法为 `consumer = Consumer(configs)`,参数定义请参考 [数据订阅文档](../../develop/tmq/#%E5%88%9B%E5%BB%BA%E6%B6%88%E8%B4%B9%E8%80%85-consumer)。
|
||||
|
||||
|
@ -547,15 +575,15 @@ from taos.tmq import Consumer
|
|||
consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"})
|
||||
```
|
||||
|
||||
#### 订阅 topics
|
||||
##### 订阅 topics
|
||||
|
||||
Comsumer API 的 `subscribe` 方法用于订阅 topics,consumer 支持同时订阅多个 topic。
|
||||
Consumer API 的 `subscribe` 方法用于订阅 topics,consumer 支持同时订阅多个 topic。
|
||||
|
||||
```python
|
||||
consumer.subscribe(['topic1', 'topic2'])
|
||||
```
|
||||
|
||||
#### 消费数据
|
||||
##### 消费数据
|
||||
|
||||
Consumer API 的 `poll` 方法用于消费数据,`poll` 方法接收一个 float 类型的超时时间,超时时间单位为秒(s),`poll` 方法在超时之前返回一条 Message 类型的数据或超时返回 `None`。消费者必须通过 Message 的 `error()` 方法校验返回数据的 error 信息。
|
||||
|
||||
|
@ -573,7 +601,7 @@ while True:
|
|||
print(block.fetchall())
|
||||
```
|
||||
|
||||
#### 获取消费进度
|
||||
##### 获取消费进度
|
||||
|
||||
Consumer API 的 `assignment` 方法用于获取 Consumer 订阅的所有 topic 的消费进度,返回结果类型为 TopicPartition 列表。
|
||||
|
||||
|
@ -581,7 +609,7 @@ Consumer API 的 `assignment` 方法用于获取 Consumer 订阅的所有 topic
|
|||
assignments = consumer.assignment()
|
||||
```
|
||||
|
||||
#### 重置消费进度
|
||||
##### 指定订阅 Offset
|
||||
|
||||
Consumer API 的 `seek` 方法用于重置 Consumer 的消费进度到指定位置,方法参数类型为 TopicPartition。
|
||||
|
||||
|
@ -590,7 +618,7 @@ tp = TopicPartition(topic='topic1', partition=0, offset=0)
|
|||
consumer.seek(tp)
|
||||
```
|
||||
|
||||
#### 结束消费
|
||||
##### 关闭订阅
|
||||
|
||||
消费结束后,应当取消订阅,并关闭 Consumer。
|
||||
|
||||
|
@ -599,13 +627,13 @@ consumer.unsubscribe()
|
|||
consumer.close()
|
||||
```
|
||||
|
||||
#### tmq 订阅示例代码
|
||||
##### 完整示例
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_example.py}}
|
||||
```
|
||||
|
||||
#### 获取和重置消费进度示例代码
|
||||
##### 获取和重置消费进度示例代码
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_assignment_example.py:taos_get_assignment_and_seek_demo}}
|
||||
|
@ -619,7 +647,7 @@ consumer.close()
|
|||
|
||||
taosws `Consumer` API 提供了基于 Websocket 订阅 TMQ 数据的 API。
|
||||
|
||||
#### 创建 Consumer
|
||||
##### 创建 Consumer
|
||||
|
||||
创建 Consumer 语法为 `consumer = Consumer(conf=configs)`,使用时需要指定 `td.connect.websocket.scheme` 参数值为 "ws",参数定义请参考 [数据订阅文档](../../develop/tmq/#%E5%88%9B%E5%BB%BA%E6%B6%88%E8%B4%B9%E8%80%85-consumer)。
|
||||
|
||||
|
@ -629,15 +657,15 @@ import taosws
|
|||
consumer = taosws.(conf={"group.id": "local", "td.connect.websocket.scheme": "ws"})
|
||||
```
|
||||
|
||||
#### 订阅 topics
|
||||
##### 订阅 topics
|
||||
|
||||
Comsumer API 的 `subscribe` 方法用于订阅 topics,consumer 支持同时订阅多个 topic。
|
||||
Consumer API 的 `subscribe` 方法用于订阅 topics,consumer 支持同时订阅多个 topic。
|
||||
|
||||
```python
|
||||
consumer.subscribe(['topic1', 'topic2'])
|
||||
```
|
||||
|
||||
#### 消费数据
|
||||
##### 消费数据
|
||||
|
||||
Consumer API 的 `poll` 方法用于消费数据,`poll` 方法接收一个 float 类型的超时时间,超时时间单位为秒(s),`poll` 方法在超时之前返回一条 Message 类型的数据或超时返回 `None`。消费者必须通过 Message 的 `error()` 方法校验返回数据的 error 信息。
|
||||
|
||||
|
@ -654,7 +682,7 @@ while True:
|
|||
print(row)
|
||||
```
|
||||
|
||||
#### 获取消费进度
|
||||
##### 获取消费进度
|
||||
|
||||
Consumer API 的 `assignment` 方法用于获取 Consumer 订阅的所有 topic 的消费进度,返回结果类型为 TopicPartition 列表。
|
||||
|
||||
|
@ -662,7 +690,7 @@ Consumer API 的 `assignment` 方法用于获取 Consumer 订阅的所有 topic
|
|||
assignments = consumer.assignment()
|
||||
```
|
||||
|
||||
#### 重置消费进度
|
||||
##### 重置消费进度
|
||||
|
||||
Consumer API 的 `seek` 方法用于重置 Consumer 的消费进度到指定位置。
|
||||
|
||||
|
@ -670,7 +698,7 @@ Consumer API 的 `seek` 方法用于重置 Consumer 的消费进度到指定位
|
|||
consumer.seek(topic='topic1', partition=0, offset=0)
|
||||
```
|
||||
|
||||
#### 结束消费
|
||||
##### 结束消费
|
||||
|
||||
消费结束后,应当取消订阅,并关闭 Consumer。
|
||||
|
||||
|
@ -679,7 +707,7 @@ consumer.unsubscribe()
|
|||
consumer.close()
|
||||
```
|
||||
|
||||
#### tmq 订阅示例代码
|
||||
##### tmq 订阅示例代码
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_websocket_example.py}}
|
||||
|
@ -687,7 +715,7 @@ consumer.close()
|
|||
|
||||
连接器提供了 `assignment` 接口,用于获取 topic assignment 的功能,可以查询订阅的 topic 的消费进度,并提供 `seek` 接口,用于重置 topic 的消费进度。
|
||||
|
||||
#### 获取和重置消费进度示例代码
|
||||
##### 获取和重置消费进度示例代码
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/tmq_websocket_assgnment_example.py:taosws_get_assignment_and_seek_demo}}
|
||||
|
@ -703,19 +731,19 @@ consumer.close()
|
|||
<Tabs defaultValue="list">
|
||||
<TabItem value="list" label="List 写入">
|
||||
|
||||
简单写入
|
||||
##### 简单写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert.py}}
|
||||
```
|
||||
|
||||
带有 ttl 参数的写入
|
||||
##### 带有 ttl 参数的写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_ttl.py}}
|
||||
```
|
||||
|
||||
带有 req_id 参数的写入
|
||||
##### 带有 req_id 参数的写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_req_id.py}}
|
||||
|
@ -725,19 +753,19 @@ consumer.close()
|
|||
|
||||
<TabItem value="raw" label="Raw 写入">
|
||||
|
||||
简单写入
|
||||
##### 简单写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw.py}}
|
||||
```
|
||||
|
||||
带有 ttl 参数的写入
|
||||
##### 带有 ttl 参数的写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw_ttl.py}}
|
||||
```
|
||||
|
||||
带有 req_id 参数的写入
|
||||
##### 带有 req_id 参数的写入
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/schemaless_insert_raw_req_id.py}}
|
||||
|
@ -753,7 +781,7 @@ TDengine 的 Python 连接器支持参数绑定风格的 Prepare API 方式写
|
|||
<Tabs>
|
||||
<TabItem value="native" label="原生连接">
|
||||
|
||||
#### 创建 stmt
|
||||
##### 创建 stmt
|
||||
|
||||
Python 连接器的 `Connection` 提供了 `statement` 方法用于创建参数绑定对象 stmt,该方法接收 sql 字符串作为参数,sql 字符串目前仅支持用 `?` 来代表绑定的参数。
|
||||
|
||||
|
@ -764,7 +792,7 @@ conn = taos.connect()
|
|||
stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
```
|
||||
|
||||
#### 参数绑定
|
||||
##### 参数绑定
|
||||
|
||||
调用 `new_multi_binds` 函数创建 params 列表,用于参数绑定。
|
||||
|
||||
|
@ -794,7 +822,7 @@ params[15].timestamp([None, None, 1626861392591])
|
|||
stmt.bind_param_batch(params)
|
||||
```
|
||||
|
||||
#### 执行 sql
|
||||
##### 执行 sql
|
||||
|
||||
调用 stmt 的 `execute` 方法执行 sql
|
||||
|
||||
|
@ -802,7 +830,7 @@ stmt.bind_param_batch(params)
|
|||
stmt.execute()
|
||||
```
|
||||
|
||||
#### 关闭 stmt
|
||||
##### 关闭 stmt
|
||||
|
||||
最后需要关闭 stmt。
|
||||
|
||||
|
@ -810,7 +838,7 @@ stmt.execute()
|
|||
stmt.close()
|
||||
```
|
||||
|
||||
#### 示例代码
|
||||
##### 示例代码
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/stmt_example.py}}
|
||||
|
@ -819,7 +847,7 @@ stmt.close()
|
|||
|
||||
<TabItem value="websocket" label="WebSocket 连接">
|
||||
|
||||
#### 创建 stmt
|
||||
##### 创建 stmt
|
||||
|
||||
Python WebSocket 连接器的 `Connection` 提供了 `statement` 方法用于创建参数绑定对象 stmt,该方法接收 sql 字符串作为参数,sql 字符串目前仅支持用 `?` 来代表绑定的参数。
|
||||
|
||||
|
@ -830,7 +858,7 @@ conn = taosws.connect('taosws://localhost:6041/test')
|
|||
stmt = conn.statement()
|
||||
```
|
||||
|
||||
#### 解析 sql
|
||||
##### 解析 sql
|
||||
|
||||
调用 stmt 的 `prepare` 方法来解析 insert 语句。
|
||||
|
||||
|
@ -838,7 +866,7 @@ stmt = conn.statement()
|
|||
stmt.prepare("insert into t1 values (?, ?, ?, ?)")
|
||||
```
|
||||
|
||||
#### 参数绑定
|
||||
##### 参数绑定
|
||||
|
||||
调用 stmt 的 `bind_param` 方法绑定参数。
|
||||
|
||||
|
@ -857,7 +885,7 @@ stmt.bind_param([
|
|||
stmt.add_batch()
|
||||
```
|
||||
|
||||
#### 执行 sql
|
||||
##### 执行 sql
|
||||
|
||||
调用 stmt 的 `execute` 方法执行 sql
|
||||
|
||||
|
@ -865,7 +893,7 @@ stmt.add_batch()
|
|||
stmt.execute()
|
||||
```
|
||||
|
||||
#### 关闭 stmt
|
||||
##### 关闭 stmt
|
||||
|
||||
最后需要关闭 stmt。
|
||||
|
||||
|
@ -873,7 +901,7 @@ stmt.execute()
|
|||
stmt.close()
|
||||
```
|
||||
|
||||
#### 示例代码
|
||||
##### 示例代码
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/stmt_websocket_example.py}}
|
||||
|
|
|
@ -991,18 +991,14 @@ SAMPLE(expr, k)
|
|||
|
||||
**功能说明**: 获取数据的 k 个采样值。参数 k 的合法输入范围是 1≤ k ≤ 1000。
|
||||
|
||||
**返回结果类型**: 同原始数据类型, 返回结果中带有该行记录的时间戳。
|
||||
**返回结果类型**: 同原始数据类型。
|
||||
|
||||
**适用数据类型**: 在超级表查询中使用时,不能应用在标签之上。
|
||||
**适用数据类型**: 全部类型字段。
|
||||
|
||||
**嵌套子查询支持**: 适用于内层查询和外层查询。
|
||||
|
||||
**适用于**:表和超级表。
|
||||
|
||||
**使用说明**:
|
||||
|
||||
- 不能参与表达式计算;该函数可以应用在普通表和超级表上;
|
||||
|
||||
|
||||
### TAIL
|
||||
|
||||
|
@ -1047,11 +1043,11 @@ TOP(expr, k)
|
|||
UNIQUE(expr)
|
||||
```
|
||||
|
||||
**功能说明**:返回该列的数值首次出现的值。该函数功能与 distinct 相似,但是可以匹配标签和时间戳信息。可以针对除时间列以外的字段进行查询,可以匹配标签和时间戳,其中的标签和时间戳是第一次出现时刻的标签和时间戳。
|
||||
**功能说明**:返回该列数据首次出现的值。该函数功能与 distinct 相似。
|
||||
|
||||
**返回数据类型**:同应用的字段。
|
||||
|
||||
**适用数据类型**:适合于除时间类型以外的字段。
|
||||
**适用数据类型**:全部类型字段。
|
||||
|
||||
**适用于**: 表和超级表。
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ SHOW CONNECTIONS;
|
|||
SHOW CONSUMERS;
|
||||
```
|
||||
|
||||
显示当前数据库下所有活跃的消费者的信息。
|
||||
显示当前数据库下所有消费者的信息。
|
||||
|
||||
## SHOW CREATE DATABASE
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.6.0
|
||||
|
||||
<Release type="tdengine" version="3.0.6.0" />
|
||||
|
||||
## 3.0.5.1
|
||||
|
||||
<Release type="tdengine" version="3.0.5.1" />
|
||||
|
|
|
@ -54,6 +54,11 @@ typedef struct SSessionKey {
|
|||
uint64_t groupId;
|
||||
} SSessionKey;
|
||||
|
||||
typedef struct SVersionRange {
|
||||
uint64_t minVer;
|
||||
uint64_t maxVer;
|
||||
} SVersionRange;
|
||||
|
||||
static inline int winKeyCmprImpl(const void* pKey1, const void* pKey2) {
|
||||
SWinKey* pWin1 = (SWinKey*)pKey1;
|
||||
SWinKey* pWin2 = (SWinKey*)pKey2;
|
||||
|
@ -131,10 +136,10 @@ static inline int STupleKeyCmpr(const void* pKey1, int kLen1, const void* pKey2,
|
|||
|
||||
enum {
|
||||
TMQ_MSG_TYPE__DUMMY = 0,
|
||||
TMQ_MSG_TYPE__POLL_RSP,
|
||||
TMQ_MSG_TYPE__POLL_DATA_RSP,
|
||||
TMQ_MSG_TYPE__POLL_META_RSP,
|
||||
TMQ_MSG_TYPE__EP_RSP,
|
||||
TMQ_MSG_TYPE__TAOSX_RSP,
|
||||
TMQ_MSG_TYPE__POLL_DATA_META_RSP,
|
||||
TMQ_MSG_TYPE__WALINFO_RSP,
|
||||
TMQ_MSG_TYPE__END_RSP,
|
||||
};
|
||||
|
|
|
@ -177,7 +177,6 @@ static FORCE_INLINE void colDataSetDouble(SColumnInfoData* pColumnInfoData, uint
|
|||
int32_t getJsonValueLen(const char* data);
|
||||
|
||||
int32_t colDataSetVal(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull);
|
||||
int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull);
|
||||
int32_t colDataReassignVal(SColumnInfoData* pColumnInfoData, uint32_t dstRowIdx, uint32_t srcRowIdx, const char* pData);
|
||||
int32_t colDataSetNItems(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, uint32_t numOfRows, bool trimValue);
|
||||
int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int32_t* capacity,
|
||||
|
@ -187,6 +186,8 @@ int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* p
|
|||
int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex);
|
||||
|
||||
int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows);
|
||||
|
||||
int32_t colDataGetRowLength(const SColumnInfoData* pColumnInfoData, int32_t rowIdx);
|
||||
void colDataTrim(SColumnInfoData* pColumnInfoData);
|
||||
|
||||
size_t blockDataGetNumOfCols(const SSDataBlock* pBlock);
|
||||
|
@ -207,7 +208,6 @@ double blockDataGetSerialRowSize(const SSDataBlock* pBlock);
|
|||
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, uint32_t numOfRows, bool clearPayload);
|
||||
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows);
|
||||
|
@ -236,11 +236,10 @@ int32_t blockDataAppendColInfo(SSDataBlock* pBlock, SColumnInfoData* pColIn
|
|||
SColumnInfoData createColumnInfoData(int16_t type, int32_t bytes, int16_t colId);
|
||||
SColumnInfoData* bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index);
|
||||
|
||||
int32_t blockGetEncodeSize(const SSDataBlock* pBlock);
|
||||
int32_t blockEncode(const SSDataBlock* pBlock, char* data, int32_t numOfCols);
|
||||
const char* blockDecode(SSDataBlock* pBlock, const char* pData);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -250,9 +249,7 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq2** pReq, const SSDataBlock* pData
|
|||
char* buildCtbNameByGroupId(const char* stbName, uint64_t groupId);
|
||||
int32_t buildCtbNameByGroupIdImpl(const char* stbName, uint64_t groupId, char* pBuf);
|
||||
|
||||
static FORCE_INLINE int32_t blockGetEncodeSize(const SSDataBlock* pBlock) {
|
||||
return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
|
||||
}
|
||||
void trimDataBlock(SSDataBlock* pBlock, int32_t totalRows, const bool* pBoolList);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -164,6 +164,8 @@ extern char tsSmlTagName[];
|
|||
// extern bool tsSmlDataFormat;
|
||||
// extern int32_t tsSmlBatchSize;
|
||||
|
||||
extern int32_t tmqMaxTopicNum;
|
||||
|
||||
// wal
|
||||
extern int64_t tsWalFsyncDataSizeLimit;
|
||||
|
||||
|
@ -184,6 +186,7 @@ extern int64_t tsStreamBufferSize;
|
|||
extern int64_t tsCheckpointInterval;
|
||||
extern bool tsFilterScalarMode;
|
||||
extern int32_t tsMaxStreamBackendCache;
|
||||
extern int32_t tsPQSortMemThreshold;
|
||||
|
||||
// #define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
|
||||
|
||||
|
|
|
@ -2909,6 +2909,12 @@ enum {
|
|||
TMQ_OFFSET__SNAPSHOT_META = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
WITH_DATA = 0,
|
||||
WITH_META = 1,
|
||||
ONLY_META = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
union {
|
||||
|
|
|
@ -145,7 +145,7 @@ enum {
|
|||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_DROP_TOPIC, "drop-topic", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_SUBSCRIBE, "subscribe", SCMSubscribeReq, SCMSubscribeRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_ASK_EP, "ask-ep", SMqAskEpReq, SMqAskEpRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_CONSUMER_LOST, "consumer-lost", SMqConsumerLostMsg, NULL)
|
||||
// TD_DEF_MSG_TYPE(TDMT_MND_TMQ_CONSUMER_LOST, "consumer-lost", SMqConsumerLostMsg, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_CONSUMER_RECOVER, "consumer-recover", SMqConsumerRecoverMsg, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_HB, "consumer-hb", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_TMQ_DO_REBALANCE, "do-rebalance", SMqDoRebalanceMsg, NULL)
|
||||
|
@ -253,7 +253,9 @@ enum {
|
|||
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_DISPATCH, "stream-task-dispatch", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_UNUSED1, "stream-unused1", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_RETRIEVE, "stream-retrieve", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_RECOVER_FINISH, "stream-recover-finish", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_SCAN_HISTORY, "stream-scan-history", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_SCAN_HISTORY_FINISH, "stream-scan-history-finish", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_TRANSFER_STATE, "stream-transfer-state", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_CHECK, "stream-task-check", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_CHECKPOINT, "stream-checkpoint", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_REPORT_CHECKPOINT, "stream-report-checkpoint", NULL, NULL)
|
||||
|
@ -298,8 +300,7 @@ enum {
|
|||
|
||||
TD_NEW_MSG_SEG(TDMT_VND_STREAM_MSG)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TRIGGER, "vnode-stream-trigger", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_RECOVER_NONBLOCKING_STAGE, "vnode-stream-recover1", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE, "vnode-stream-recover2", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_SCAN_HISTORY, "vnode-stream-scan-history", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_CHECK_POINT_SOURCE, "vnode-stream-checkpoint-source", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_MAX_MSG, "vnd-stream-max", NULL, NULL)
|
||||
|
||||
|
|
|
@ -193,165 +193,167 @@
|
|||
#define TK_INTERVAL 175
|
||||
#define TK_COUNT 176
|
||||
#define TK_LAST_ROW 177
|
||||
#define TK_TOPIC 178
|
||||
#define TK_META 179
|
||||
#define TK_CONSUMER 180
|
||||
#define TK_GROUP 181
|
||||
#define TK_DESC 182
|
||||
#define TK_DESCRIBE 183
|
||||
#define TK_RESET 184
|
||||
#define TK_QUERY 185
|
||||
#define TK_CACHE 186
|
||||
#define TK_EXPLAIN 187
|
||||
#define TK_ANALYZE 188
|
||||
#define TK_VERBOSE 189
|
||||
#define TK_NK_BOOL 190
|
||||
#define TK_RATIO 191
|
||||
#define TK_NK_FLOAT 192
|
||||
#define TK_OUTPUTTYPE 193
|
||||
#define TK_AGGREGATE 194
|
||||
#define TK_BUFSIZE 195
|
||||
#define TK_LANGUAGE 196
|
||||
#define TK_REPLACE 197
|
||||
#define TK_STREAM 198
|
||||
#define TK_INTO 199
|
||||
#define TK_PAUSE 200
|
||||
#define TK_RESUME 201
|
||||
#define TK_TRIGGER 202
|
||||
#define TK_AT_ONCE 203
|
||||
#define TK_WINDOW_CLOSE 204
|
||||
#define TK_IGNORE 205
|
||||
#define TK_EXPIRED 206
|
||||
#define TK_FILL_HISTORY 207
|
||||
#define TK_UPDATE 208
|
||||
#define TK_SUBTABLE 209
|
||||
#define TK_UNTREATED 210
|
||||
#define TK_KILL 211
|
||||
#define TK_CONNECTION 212
|
||||
#define TK_TRANSACTION 213
|
||||
#define TK_BALANCE 214
|
||||
#define TK_VGROUP 215
|
||||
#define TK_LEADER 216
|
||||
#define TK_MERGE 217
|
||||
#define TK_REDISTRIBUTE 218
|
||||
#define TK_SPLIT 219
|
||||
#define TK_DELETE 220
|
||||
#define TK_INSERT 221
|
||||
#define TK_NULL 222
|
||||
#define TK_NK_QUESTION 223
|
||||
#define TK_NK_ARROW 224
|
||||
#define TK_ROWTS 225
|
||||
#define TK_QSTART 226
|
||||
#define TK_QEND 227
|
||||
#define TK_QDURATION 228
|
||||
#define TK_WSTART 229
|
||||
#define TK_WEND 230
|
||||
#define TK_WDURATION 231
|
||||
#define TK_IROWTS 232
|
||||
#define TK_ISFILLED 233
|
||||
#define TK_CAST 234
|
||||
#define TK_NOW 235
|
||||
#define TK_TODAY 236
|
||||
#define TK_TIMEZONE 237
|
||||
#define TK_CLIENT_VERSION 238
|
||||
#define TK_SERVER_VERSION 239
|
||||
#define TK_SERVER_STATUS 240
|
||||
#define TK_CURRENT_USER 241
|
||||
#define TK_CASE 242
|
||||
#define TK_WHEN 243
|
||||
#define TK_THEN 244
|
||||
#define TK_ELSE 245
|
||||
#define TK_BETWEEN 246
|
||||
#define TK_IS 247
|
||||
#define TK_NK_LT 248
|
||||
#define TK_NK_GT 249
|
||||
#define TK_NK_LE 250
|
||||
#define TK_NK_GE 251
|
||||
#define TK_NK_NE 252
|
||||
#define TK_MATCH 253
|
||||
#define TK_NMATCH 254
|
||||
#define TK_CONTAINS 255
|
||||
#define TK_IN 256
|
||||
#define TK_JOIN 257
|
||||
#define TK_INNER 258
|
||||
#define TK_SELECT 259
|
||||
#define TK_DISTINCT 260
|
||||
#define TK_WHERE 261
|
||||
#define TK_PARTITION 262
|
||||
#define TK_BY 263
|
||||
#define TK_SESSION 264
|
||||
#define TK_STATE_WINDOW 265
|
||||
#define TK_EVENT_WINDOW 266
|
||||
#define TK_SLIDING 267
|
||||
#define TK_FILL 268
|
||||
#define TK_VALUE 269
|
||||
#define TK_VALUE_F 270
|
||||
#define TK_NONE 271
|
||||
#define TK_PREV 272
|
||||
#define TK_NULL_F 273
|
||||
#define TK_LINEAR 274
|
||||
#define TK_NEXT 275
|
||||
#define TK_HAVING 276
|
||||
#define TK_RANGE 277
|
||||
#define TK_EVERY 278
|
||||
#define TK_ORDER 279
|
||||
#define TK_SLIMIT 280
|
||||
#define TK_SOFFSET 281
|
||||
#define TK_LIMIT 282
|
||||
#define TK_OFFSET 283
|
||||
#define TK_ASC 284
|
||||
#define TK_NULLS 285
|
||||
#define TK_ABORT 286
|
||||
#define TK_AFTER 287
|
||||
#define TK_ATTACH 288
|
||||
#define TK_BEFORE 289
|
||||
#define TK_BEGIN 290
|
||||
#define TK_BITAND 291
|
||||
#define TK_BITNOT 292
|
||||
#define TK_BITOR 293
|
||||
#define TK_BLOCKS 294
|
||||
#define TK_CHANGE 295
|
||||
#define TK_COMMA 296
|
||||
#define TK_CONCAT 297
|
||||
#define TK_CONFLICT 298
|
||||
#define TK_COPY 299
|
||||
#define TK_DEFERRED 300
|
||||
#define TK_DELIMITERS 301
|
||||
#define TK_DETACH 302
|
||||
#define TK_DIVIDE 303
|
||||
#define TK_DOT 304
|
||||
#define TK_EACH 305
|
||||
#define TK_FAIL 306
|
||||
#define TK_FILE 307
|
||||
#define TK_FOR 308
|
||||
#define TK_GLOB 309
|
||||
#define TK_ID 310
|
||||
#define TK_IMMEDIATE 311
|
||||
#define TK_IMPORT 312
|
||||
#define TK_INITIALLY 313
|
||||
#define TK_INSTEAD 314
|
||||
#define TK_ISNULL 315
|
||||
#define TK_KEY 316
|
||||
#define TK_MODULES 317
|
||||
#define TK_NK_BITNOT 318
|
||||
#define TK_NK_SEMI 319
|
||||
#define TK_NOTNULL 320
|
||||
#define TK_OF 321
|
||||
#define TK_PLUS 322
|
||||
#define TK_PRIVILEGE 323
|
||||
#define TK_RAISE 324
|
||||
#define TK_RESTRICT 325
|
||||
#define TK_ROW 326
|
||||
#define TK_SEMI 327
|
||||
#define TK_STAR 328
|
||||
#define TK_STATEMENT 329
|
||||
#define TK_STRICT 330
|
||||
#define TK_STRING 331
|
||||
#define TK_TIMES 332
|
||||
#define TK_VALUES 333
|
||||
#define TK_VARIABLE 334
|
||||
#define TK_VIEW 335
|
||||
#define TK_WAL 336
|
||||
#define TK_META 178
|
||||
#define TK_ONLY 179
|
||||
#define TK_TOPIC 180
|
||||
#define TK_CONSUMER 181
|
||||
#define TK_GROUP 182
|
||||
#define TK_DESC 183
|
||||
#define TK_DESCRIBE 184
|
||||
#define TK_RESET 185
|
||||
#define TK_QUERY 186
|
||||
#define TK_CACHE 187
|
||||
#define TK_EXPLAIN 188
|
||||
#define TK_ANALYZE 189
|
||||
#define TK_VERBOSE 190
|
||||
#define TK_NK_BOOL 191
|
||||
#define TK_RATIO 192
|
||||
#define TK_NK_FLOAT 193
|
||||
#define TK_OUTPUTTYPE 194
|
||||
#define TK_AGGREGATE 195
|
||||
#define TK_BUFSIZE 196
|
||||
#define TK_LANGUAGE 197
|
||||
#define TK_REPLACE 198
|
||||
#define TK_STREAM 199
|
||||
#define TK_INTO 200
|
||||
#define TK_PAUSE 201
|
||||
#define TK_RESUME 202
|
||||
#define TK_TRIGGER 203
|
||||
#define TK_AT_ONCE 204
|
||||
#define TK_WINDOW_CLOSE 205
|
||||
#define TK_IGNORE 206
|
||||
#define TK_EXPIRED 207
|
||||
#define TK_FILL_HISTORY 208
|
||||
#define TK_UPDATE 209
|
||||
#define TK_SUBTABLE 210
|
||||
#define TK_UNTREATED 211
|
||||
#define TK_KILL 212
|
||||
#define TK_CONNECTION 213
|
||||
#define TK_TRANSACTION 214
|
||||
#define TK_BALANCE 215
|
||||
#define TK_VGROUP 216
|
||||
#define TK_LEADER 217
|
||||
#define TK_MERGE 218
|
||||
#define TK_REDISTRIBUTE 219
|
||||
#define TK_SPLIT 220
|
||||
#define TK_DELETE 221
|
||||
#define TK_INSERT 222
|
||||
#define TK_NULL 223
|
||||
#define TK_NK_QUESTION 224
|
||||
#define TK_NK_ARROW 225
|
||||
#define TK_ROWTS 226
|
||||
#define TK_QSTART 227
|
||||
#define TK_QEND 228
|
||||
#define TK_QDURATION 229
|
||||
#define TK_WSTART 230
|
||||
#define TK_WEND 231
|
||||
#define TK_WDURATION 232
|
||||
#define TK_IROWTS 233
|
||||
#define TK_ISFILLED 234
|
||||
#define TK_CAST 235
|
||||
#define TK_NOW 236
|
||||
#define TK_TODAY 237
|
||||
#define TK_TIMEZONE 238
|
||||
#define TK_CLIENT_VERSION 239
|
||||
#define TK_SERVER_VERSION 240
|
||||
#define TK_SERVER_STATUS 241
|
||||
#define TK_CURRENT_USER 242
|
||||
#define TK_CASE 243
|
||||
#define TK_WHEN 244
|
||||
#define TK_THEN 245
|
||||
#define TK_ELSE 246
|
||||
#define TK_BETWEEN 247
|
||||
#define TK_IS 248
|
||||
#define TK_NK_LT 249
|
||||
#define TK_NK_GT 250
|
||||
#define TK_NK_LE 251
|
||||
#define TK_NK_GE 252
|
||||
#define TK_NK_NE 253
|
||||
#define TK_MATCH 254
|
||||
#define TK_NMATCH 255
|
||||
#define TK_CONTAINS 256
|
||||
#define TK_IN 257
|
||||
#define TK_JOIN 258
|
||||
#define TK_INNER 259
|
||||
#define TK_SELECT 260
|
||||
#define TK_DISTINCT 261
|
||||
#define TK_WHERE 262
|
||||
#define TK_PARTITION 263
|
||||
#define TK_BY 264
|
||||
#define TK_SESSION 265
|
||||
#define TK_STATE_WINDOW 266
|
||||
#define TK_EVENT_WINDOW 267
|
||||
#define TK_SLIDING 268
|
||||
#define TK_FILL 269
|
||||
#define TK_VALUE 270
|
||||
#define TK_VALUE_F 271
|
||||
#define TK_NONE 272
|
||||
#define TK_PREV 273
|
||||
#define TK_NULL_F 274
|
||||
#define TK_LINEAR 275
|
||||
#define TK_NEXT 276
|
||||
#define TK_HAVING 277
|
||||
#define TK_RANGE 278
|
||||
#define TK_EVERY 279
|
||||
#define TK_ORDER 280
|
||||
#define TK_SLIMIT 281
|
||||
#define TK_SOFFSET 282
|
||||
#define TK_LIMIT 283
|
||||
#define TK_OFFSET 284
|
||||
#define TK_ASC 285
|
||||
#define TK_NULLS 286
|
||||
#define TK_ABORT 287
|
||||
#define TK_AFTER 288
|
||||
#define TK_ATTACH 289
|
||||
#define TK_BEFORE 290
|
||||
#define TK_BEGIN 291
|
||||
#define TK_BITAND 292
|
||||
#define TK_BITNOT 293
|
||||
#define TK_BITOR 294
|
||||
#define TK_BLOCKS 295
|
||||
#define TK_CHANGE 296
|
||||
#define TK_COMMA 297
|
||||
#define TK_CONCAT 298
|
||||
#define TK_CONFLICT 299
|
||||
#define TK_COPY 300
|
||||
#define TK_DEFERRED 301
|
||||
#define TK_DELIMITERS 302
|
||||
#define TK_DETACH 303
|
||||
#define TK_DIVIDE 304
|
||||
#define TK_DOT 305
|
||||
#define TK_EACH 306
|
||||
#define TK_FAIL 307
|
||||
#define TK_FILE 308
|
||||
#define TK_FOR 309
|
||||
#define TK_GLOB 310
|
||||
#define TK_ID 311
|
||||
#define TK_IMMEDIATE 312
|
||||
#define TK_IMPORT 313
|
||||
#define TK_INITIALLY 314
|
||||
#define TK_INSTEAD 315
|
||||
#define TK_ISNULL 316
|
||||
#define TK_KEY 317
|
||||
#define TK_MODULES 318
|
||||
#define TK_NK_BITNOT 319
|
||||
#define TK_NK_SEMI 320
|
||||
#define TK_NOTNULL 321
|
||||
#define TK_OF 322
|
||||
#define TK_PLUS 323
|
||||
#define TK_PRIVILEGE 324
|
||||
#define TK_RAISE 325
|
||||
#define TK_RESTRICT 326
|
||||
#define TK_ROW 327
|
||||
#define TK_SEMI 328
|
||||
#define TK_STAR 329
|
||||
#define TK_STATEMENT 330
|
||||
#define TK_STRICT 331
|
||||
#define TK_STRING 332
|
||||
#define TK_TIMES 333
|
||||
#define TK_VALUES 334
|
||||
#define TK_VARIABLE 335
|
||||
#define TK_VIEW 336
|
||||
#define TK_WAL 337
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ typedef struct {
|
|||
|
||||
void* pStateBackend;
|
||||
struct SStorageAPI api;
|
||||
|
||||
int8_t fillHistory;
|
||||
STimeWindow winRange;
|
||||
} SReadHandle;
|
||||
|
||||
// in queue mode, data streams are seperated by msg
|
||||
|
@ -193,14 +196,6 @@ int32_t qDeserializeTaskStatus(qTaskInfo_t tinfo, const char* pInput, int32_t le
|
|||
void getNextTimeWindow(const SInterval* pInterval, STimeWindow* tw, int32_t order);
|
||||
void getInitialStartTimeWindow(SInterval* pInterval, TSKEY ts, STimeWindow* w, bool ascQuery);
|
||||
STimeWindow getAlignQueryTimeWindow(const SInterval* pInterval, int64_t key);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
SArray* qGetQueriedTableListInfo(qTaskInfo_t tinfo);
|
||||
|
||||
|
@ -220,15 +215,22 @@ void* qExtractReaderFromStreamScanner(void* scanner);
|
|||
|
||||
int32_t qExtractStreamScanner(qTaskInfo_t tinfo, void** scanner);
|
||||
|
||||
int32_t qStreamSetParamForRecover(qTaskInfo_t tinfo);
|
||||
int32_t qStreamSourceRecoverStep1(qTaskInfo_t tinfo, int64_t ver);
|
||||
int32_t qStreamSourceRecoverStep2(qTaskInfo_t tinfo, int64_t ver);
|
||||
int32_t qSetStreamOperatorOptionForScanHistory(qTaskInfo_t tinfo);
|
||||
int32_t qStreamSourceScanParamForHistoryScanStep1(qTaskInfo_t tinfo, SVersionRange *pVerRange, STimeWindow* pWindow);
|
||||
int32_t qStreamSourceScanParamForHistoryScanStep2(qTaskInfo_t tinfo, SVersionRange *pVerRange, STimeWindow* pWindow);
|
||||
int32_t qStreamRecoverFinish(qTaskInfo_t tinfo);
|
||||
int32_t qStreamRestoreParam(qTaskInfo_t tinfo);
|
||||
int32_t qRestoreStreamOperatorOption(qTaskInfo_t tinfo);
|
||||
bool qStreamRecoverScanFinished(qTaskInfo_t tinfo);
|
||||
void qStreamCloseTsdbReader(void* task);
|
||||
bool qStreamRecoverScanStep1Finished(qTaskInfo_t tinfo);
|
||||
bool qStreamRecoverScanStep2Finished(qTaskInfo_t tinfo);
|
||||
int32_t qStreamRecoverSetAllStepFinished(qTaskInfo_t tinfo);
|
||||
void resetTaskInfo(qTaskInfo_t tinfo);
|
||||
|
||||
void qResetStreamInfoTimeWindow(qTaskInfo_t tinfo);
|
||||
|
||||
int32_t qStreamOperatorReleaseState(qTaskInfo_t tInfo);
|
||||
int32_t qStreamOperatorReloadState(qTaskInfo_t tInfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -123,8 +123,8 @@ typedef struct SSnapContext {
|
|||
SHashObj* suidInfo;
|
||||
SArray* idList;
|
||||
int32_t index;
|
||||
bool withMeta;
|
||||
bool queryMeta; // true-get meta, false-get data
|
||||
int8_t withMeta;
|
||||
int8_t queryMeta; // true-get meta, false-get data
|
||||
} SSnapContext;
|
||||
|
||||
typedef struct {
|
||||
|
@ -234,29 +234,6 @@ typedef struct SStoreSnapshotFn {
|
|||
int32_t (*getTableInfoFromSnapshot)(SSnapContext* ctx, void** pBuf, int32_t* contLen, int16_t* type, int64_t* uid);
|
||||
} SStoreSnapshotFn;
|
||||
|
||||
/**
|
||||
void metaReaderInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags);
|
||||
void metaReaderReleaseLock(SMetaReader *pReader);
|
||||
void metaReaderClear(SMetaReader *pReader);
|
||||
int32_t metaReaderGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid);
|
||||
int32_t metaReaderGetTableEntryByUidCache(SMetaReader *pReader, tb_uid_t uid);
|
||||
int32_t metaGetTableTags(SMeta *pMeta, uint64_t suid, SArray *uidList);
|
||||
const void *metaGetTableTagVal(void *tag, int16_t type, STagVal *tagVal);
|
||||
int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
|
||||
|
||||
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
||||
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
||||
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
||||
int32_t metaGetCachedTableUidList(SMeta *pMeta, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList,
|
||||
bool *acquired);
|
||||
int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
||||
int32_t payloadLen, double selectivityRatio);
|
||||
tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name);
|
||||
int32_t metaGetCachedTbGroup(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList);
|
||||
int32_t metaPutTbGroupToCache(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t
|
||||
payloadLen);
|
||||
*/
|
||||
|
||||
typedef struct SStoreMeta {
|
||||
SMTbCursor* (*openTableMetaCursor)(void* pVnode); // metaOpenTbCursor
|
||||
void (*closeTableMetaCursor)(SMTbCursor* pTbCur); // metaCloseTbCursor
|
||||
|
@ -403,7 +380,7 @@ typedef struct SStateStore {
|
|||
SStreamStateCur* (*streamStateSessionSeekKeyCurrentNext)(SStreamState* pState, const SSessionKey* key);
|
||||
|
||||
struct SStreamFileState* (*streamFileStateInit)(int64_t memSize, uint32_t keySize, uint32_t rowSize,
|
||||
uint32_t selectRowSize, GetTsFun fp, void* pFile, TSKEY delMark);
|
||||
uint32_t selectRowSize, GetTsFun fp, void* pFile, TSKEY delMark, const char*id);
|
||||
|
||||
void (*streamFileStateDestroy)(struct SStreamFileState* pFileState);
|
||||
void (*streamFileStateClear)(struct SStreamFileState* pFileState);
|
||||
|
@ -415,6 +392,7 @@ typedef struct SStateStore {
|
|||
int32_t (*streamStateCommit)(SStreamState* pState);
|
||||
void (*streamStateDestroy)(SStreamState* pState, bool remove);
|
||||
int32_t (*streamStateDeleteCheckPoint)(SStreamState* pState, TSKEY mark);
|
||||
void (*streamStateReloadInfo)(SStreamState* pState, TSKEY ts);
|
||||
} SStateStore;
|
||||
|
||||
typedef struct SStorageAPI {
|
||||
|
|
|
@ -129,22 +129,30 @@ typedef struct SSerializeDataHandle {
|
|||
} SSerializeDataHandle;
|
||||
|
||||
// incremental state storage
|
||||
typedef struct STdbState {
|
||||
|
||||
typedef struct SBackendCfWrapper {
|
||||
void *rocksdb;
|
||||
void **pHandle;
|
||||
void *writeOpts;
|
||||
void *readOpts;
|
||||
void **cfOpts;
|
||||
void *dbOpt;
|
||||
struct SStreamTask *pOwner;
|
||||
void *param;
|
||||
void *env;
|
||||
SListNode *pComparNode;
|
||||
void *pBackend;
|
||||
char idstr[64];
|
||||
void *compactFactory;
|
||||
TdThreadRwlock rwLock;
|
||||
bool remove;
|
||||
int64_t backendId;
|
||||
char idstr[64];
|
||||
} SBackendCfWrapper;
|
||||
typedef struct STdbState {
|
||||
SBackendCfWrapper *pBackendCfWrapper;
|
||||
int64_t backendCfWrapperId;
|
||||
char idstr[64];
|
||||
|
||||
struct SStreamTask *pOwner;
|
||||
void *db;
|
||||
void *pStateDb;
|
||||
void *pFuncStateDb;
|
||||
|
|
|
@ -111,6 +111,12 @@ int32_t udfStartUdfd(int32_t startDnodeId);
|
|||
*/
|
||||
int32_t udfStopUdfd();
|
||||
|
||||
/**
|
||||
* get udfd pid
|
||||
*
|
||||
*/
|
||||
int32_t udfGetUdfdPid(int32_t* pUdfdPid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -362,7 +362,7 @@ typedef struct SCreateTopicStmt {
|
|||
char subDbName[TSDB_DB_NAME_LEN];
|
||||
char subSTbName[TSDB_TABLE_NAME_LEN];
|
||||
bool ignoreExists;
|
||||
bool withMeta;
|
||||
int8_t withMeta;
|
||||
SNode* pQuery;
|
||||
SNode* pWhere;
|
||||
} SCreateTopicStmt;
|
||||
|
|
|
@ -246,6 +246,7 @@ typedef struct SSortLogicNode {
|
|||
SLogicNode node;
|
||||
SNodeList* pSortKeys;
|
||||
bool groupSort;
|
||||
int64_t maxRows;
|
||||
} SSortLogicNode;
|
||||
|
||||
typedef struct SPartitionLogicNode {
|
||||
|
@ -523,6 +524,7 @@ typedef struct SSortPhysiNode {
|
|||
SNodeList* pExprs; // these are expression list of order_by_clause and parameter expression of aggregate function
|
||||
SNodeList* pSortKeys; // element is SOrderByExprNode, and SOrderByExprNode::pExpr is SColumnNode
|
||||
SNodeList* pTargets;
|
||||
int64_t maxRows;
|
||||
} SSortPhysiNode;
|
||||
|
||||
typedef SSortPhysiNode SGroupSortPhysiNode;
|
||||
|
|
|
@ -138,6 +138,8 @@ int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur);
|
|||
int32_t streamStatePutParName(SStreamState* pState, int64_t groupId, const char* tbname);
|
||||
int32_t streamStateGetParName(SStreamState* pState, int64_t groupId, void** pVal);
|
||||
|
||||
void streamStateReloadInfo(SStreamState* pState, TSKEY ts);
|
||||
|
||||
/***compare func **/
|
||||
|
||||
typedef struct SStateChekpoint {
|
||||
|
|
|
@ -44,10 +44,8 @@ enum {
|
|||
TASK_STATUS__DROPPING,
|
||||
TASK_STATUS__FAIL,
|
||||
TASK_STATUS__STOP,
|
||||
TASK_STATUS__WAIT_DOWNSTREAM,
|
||||
TASK_STATUS__RECOVER_PREPARE,
|
||||
TASK_STATUS__RECOVER1,
|
||||
TASK_STATUS__RECOVER2,
|
||||
TASK_STATUS__SCAN_HISTORY, // stream task scan history data by using tsdbread in the stream scanner
|
||||
TASK_STATUS__HALT, // stream task will handle all data in the input queue, and then paused
|
||||
TASK_STATUS__PAUSE,
|
||||
};
|
||||
|
||||
|
@ -133,7 +131,6 @@ typedef struct {
|
|||
// ref data block, for delete
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
int64_t ver;
|
||||
SSDataBlock* pBlock;
|
||||
} SStreamRefDataBlock;
|
||||
|
||||
|
@ -203,13 +200,11 @@ static FORCE_INLINE void streamQueueProcessFail(SStreamQueue* queue) {
|
|||
atomic_store_8(&queue->status, STREAM_QUEUE__FAILED);
|
||||
}
|
||||
|
||||
void* streamQueueNextItem(SStreamQueue* queue);
|
||||
void* streamQueueNextItem(SStreamQueue* pQueue);
|
||||
|
||||
SStreamDataSubmit* streamDataSubmitNew(SPackedData* pData, int32_t type);
|
||||
void streamDataSubmitDestroy(SStreamDataSubmit* pDataSubmit);
|
||||
|
||||
SStreamDataSubmit* streamSubmitBlockClone(SStreamDataSubmit* pSubmit);
|
||||
|
||||
typedef struct {
|
||||
char* qmsg;
|
||||
void* pExecutor; // not applicable to encoder and decoder
|
||||
|
@ -251,7 +246,7 @@ typedef struct {
|
|||
int8_t reserved;
|
||||
} STaskSinkFetch;
|
||||
|
||||
typedef struct {
|
||||
typedef struct SStreamChildEpInfo {
|
||||
int32_t nodeId;
|
||||
int32_t childId;
|
||||
int32_t taskId;
|
||||
|
@ -272,28 +267,52 @@ typedef struct SCheckpointInfo {
|
|||
|
||||
typedef struct SStreamStatus {
|
||||
int8_t taskStatus;
|
||||
int8_t downstreamReady; // downstream tasks are all ready now, if this flag is set
|
||||
int8_t schedStatus;
|
||||
int8_t keepTaskStatus;
|
||||
bool transferState;
|
||||
int8_t timerActive; // timer is active
|
||||
} SStreamStatus;
|
||||
|
||||
typedef struct SHistDataRange {
|
||||
SVersionRange range;
|
||||
STimeWindow window;
|
||||
} SHistDataRange;
|
||||
|
||||
typedef struct SSTaskBasicInfo {
|
||||
int32_t nodeId; // vgroup id or snode id
|
||||
SEpSet epSet;
|
||||
int32_t selfChildId;
|
||||
int32_t totalLevel;
|
||||
int8_t taskLevel;
|
||||
int8_t fillHistory; // is fill history task or not
|
||||
} SSTaskBasicInfo;
|
||||
|
||||
typedef struct SDispatchMsgInfo {
|
||||
void* pData; // current dispatch data
|
||||
int16_t msgType; // dispatch msg type
|
||||
int32_t retryCount; // retry send data count
|
||||
int64_t blockingTs; // output blocking timestamp
|
||||
} SDispatchMsgInfo;
|
||||
|
||||
typedef struct {
|
||||
int8_t outputType;
|
||||
int8_t outputStatus;
|
||||
SStreamQueue* outputQueue;
|
||||
} SSTaskOutputInfo;
|
||||
|
||||
struct SStreamTask {
|
||||
SStreamId id;
|
||||
int32_t totalLevel;
|
||||
int8_t taskLevel;
|
||||
SSTaskBasicInfo info;
|
||||
int8_t outputType;
|
||||
int16_t dispatchMsgType;
|
||||
SDispatchMsgInfo msgInfo;
|
||||
SStreamStatus status;
|
||||
int32_t selfChildId;
|
||||
int32_t nodeId; // vgroup id
|
||||
SEpSet epSet;
|
||||
SCheckpointInfo chkInfo;
|
||||
STaskExec exec;
|
||||
int8_t fillHistory; // fill history
|
||||
int64_t ekey; // end ts key
|
||||
int64_t endVer; // end version
|
||||
|
||||
// children info
|
||||
SArray* childEpInfo; // SArray<SStreamChildEpInfo*>
|
||||
SHistDataRange dataRange;
|
||||
SStreamId historyTaskId;
|
||||
SStreamId streamTaskId;
|
||||
SArray* pUpstreamEpInfoList; // SArray<SStreamChildEpInfo*>, // children info
|
||||
int32_t nextCheckId;
|
||||
SArray* checkpointInfo; // SArray<SStreamCheckpointInfo>
|
||||
|
||||
|
@ -314,13 +333,14 @@ struct SStreamTask {
|
|||
// trigger
|
||||
int8_t triggerStatus;
|
||||
int64_t triggerParam;
|
||||
void* timer;
|
||||
void* schedTimer;
|
||||
void* launchTaskTimer;
|
||||
SMsgCb* pMsgCb; // msg handle
|
||||
SStreamState* pState; // state backend
|
||||
|
||||
// the followings attributes don't be serialized
|
||||
int32_t recoverTryingDownstream;
|
||||
int32_t recoverWaitingUpstream;
|
||||
int32_t notReadyTasks;
|
||||
int32_t numOfWaitingUpstream;
|
||||
int64_t checkReqId;
|
||||
SArray* checkReqIds; // shuffle
|
||||
int32_t refCnt;
|
||||
|
@ -346,8 +366,10 @@ typedef struct SStreamMeta {
|
|||
int32_t walScanCounter;
|
||||
void* streamBackend;
|
||||
int64_t streamBackendRid;
|
||||
int64_t checkpointTs;
|
||||
SHashObj* pTaskBackendUnique;
|
||||
TdThreadMutex backendMutex;
|
||||
|
||||
int64_t checkpointTs;
|
||||
SArray* checkpointSaved;
|
||||
SArray* checkpointInUse;
|
||||
int32_t checkpointCap;
|
||||
|
@ -436,16 +458,17 @@ typedef struct {
|
|||
SMsgHead msgHead;
|
||||
int64_t streamId;
|
||||
int32_t taskId;
|
||||
} SStreamRecoverStep1Req, SStreamRecoverStep2Req;
|
||||
int8_t igUntreated;
|
||||
} SStreamScanHistoryReq;
|
||||
|
||||
typedef struct {
|
||||
int64_t streamId;
|
||||
int32_t taskId;
|
||||
int32_t childId;
|
||||
} SStreamRecoverFinishReq;
|
||||
} SStreamRecoverFinishReq, SStreamTransferReq;
|
||||
|
||||
int32_t tEncodeSStreamRecoverFinishReq(SEncoder* pEncoder, const SStreamRecoverFinishReq* pReq);
|
||||
int32_t tDecodeSStreamRecoverFinishReq(SDecoder* pDecoder, SStreamRecoverFinishReq* pReq);
|
||||
int32_t tEncodeStreamRecoverFinishReq(SEncoder* pEncoder, const SStreamRecoverFinishReq* pReq);
|
||||
int32_t tDecodeStreamRecoverFinishReq(SDecoder* pDecoder, SStreamRecoverFinishReq* pReq);
|
||||
|
||||
typedef struct {
|
||||
int64_t streamId;
|
||||
|
@ -514,11 +537,11 @@ typedef struct {
|
|||
SArray* checkpointVer; // SArray<SStreamCheckpointInfo>
|
||||
} SStreamRecoverDownstreamRsp;
|
||||
|
||||
int32_t tEncodeSStreamTaskCheckReq(SEncoder* pEncoder, const SStreamTaskCheckReq* pReq);
|
||||
int32_t tDecodeSStreamTaskCheckReq(SDecoder* pDecoder, SStreamTaskCheckReq* pReq);
|
||||
int32_t tEncodeStreamTaskCheckReq(SEncoder* pEncoder, const SStreamTaskCheckReq* pReq);
|
||||
int32_t tDecodeStreamTaskCheckReq(SDecoder* pDecoder, SStreamTaskCheckReq* pReq);
|
||||
|
||||
int32_t tEncodeSStreamTaskCheckRsp(SEncoder* pEncoder, const SStreamTaskCheckRsp* pRsp);
|
||||
int32_t tDecodeSStreamTaskCheckRsp(SDecoder* pDecoder, SStreamTaskCheckRsp* pRsp);
|
||||
int32_t tEncodeStreamTaskCheckRsp(SEncoder* pEncoder, const SStreamTaskCheckRsp* pRsp);
|
||||
int32_t tDecodeStreamTaskCheckRsp(SDecoder* pDecoder, SStreamTaskCheckRsp* pRsp);
|
||||
|
||||
int32_t tEncodeSStreamTaskRecoverReq(SEncoder* pEncoder, const SStreamRecoverDownstreamReq* pReq);
|
||||
int32_t tDecodeSStreamTaskRecoverReq(SDecoder* pDecoder, SStreamRecoverDownstreamReq* pReq);
|
||||
|
@ -530,9 +553,11 @@ int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq);
|
|||
int32_t tDecodeStreamRetrieveReq(SDecoder* pDecoder, SStreamRetrieveReq* pReq);
|
||||
void tDeleteStreamRetrieveReq(SStreamRetrieveReq* pReq);
|
||||
|
||||
int32_t tInitStreamDispatchReq(SStreamDispatchReq* pReq, const SStreamTask* pTask, int32_t vgId, int32_t numOfBlocks,
|
||||
int64_t dstTaskId);
|
||||
void tDeleteStreamDispatchReq(SStreamDispatchReq* pReq);
|
||||
|
||||
int32_t streamSetupTrigger(SStreamTask* pTask);
|
||||
int32_t streamSetupScheduleTrigger(SStreamTask* pTask);
|
||||
|
||||
int32_t streamProcessRunReq(SStreamTask* pTask);
|
||||
int32_t streamProcessDispatchMsg(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pMsg, bool exec);
|
||||
|
@ -547,30 +572,44 @@ int32_t streamSchedExec(SStreamTask* pTask);
|
|||
int32_t streamTaskOutputResultBlock(SStreamTask* pTask, SStreamDataBlock* pBlock);
|
||||
bool streamTaskShouldStop(const SStreamStatus* pStatus);
|
||||
bool streamTaskShouldPause(const SStreamStatus* pStatus);
|
||||
bool streamTaskIsIdle(const SStreamTask* pTask);
|
||||
|
||||
int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz);
|
||||
|
||||
char* createStreamTaskIdStr(int64_t streamId, int32_t taskId);
|
||||
|
||||
// recover and fill history
|
||||
int32_t streamTaskCheckDownstream(SStreamTask* pTask, int64_t version);
|
||||
int32_t streamTaskLaunchRecover(SStreamTask* pTask, int64_t version);
|
||||
void streamPrepareNdoCheckDownstream(SStreamTask* pTask);
|
||||
int32_t streamTaskCheckDownstreamTasks(SStreamTask* pTask);
|
||||
int32_t streamTaskLaunchScanHistory(SStreamTask* pTask);
|
||||
int32_t streamTaskCheckStatus(SStreamTask* pTask);
|
||||
int32_t streamProcessTaskCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRsp, int64_t version);
|
||||
int32_t streamProcessCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRsp);
|
||||
int32_t streamCheckHistoryTaskDownstrem(SStreamTask* pTask);
|
||||
int32_t streamTaskScanHistoryDataComplete(SStreamTask* pTask);
|
||||
int32_t streamStartRecoverTask(SStreamTask* pTask, int8_t igUntreated);
|
||||
bool streamTaskRecoverScanStep1Finished(SStreamTask* pTask);
|
||||
bool streamTaskRecoverScanStep2Finished(SStreamTask* pTask);
|
||||
int32_t streamTaskRecoverSetAllStepFinished(SStreamTask* pTask);
|
||||
|
||||
// common
|
||||
int32_t streamSetParamForRecover(SStreamTask* pTask);
|
||||
int32_t streamSetParamForScanHistoryData(SStreamTask* pTask);
|
||||
int32_t streamRestoreParam(SStreamTask* pTask);
|
||||
int32_t streamSetStatusNormal(SStreamTask* pTask);
|
||||
const char* streamGetTaskStatusStr(int32_t status);
|
||||
|
||||
// source level
|
||||
int32_t streamSourceRecoverPrepareStep1(SStreamTask* pTask, int64_t ver);
|
||||
int32_t streamBuildSourceRecover1Req(SStreamTask* pTask, SStreamRecoverStep1Req* pReq);
|
||||
int32_t streamSourceRecoverScanStep1(SStreamTask* pTask);
|
||||
int32_t streamBuildSourceRecover2Req(SStreamTask* pTask, SStreamRecoverStep2Req* pReq);
|
||||
int32_t streamSourceRecoverScanStep2(SStreamTask* pTask, int64_t ver);
|
||||
int32_t streamDispatchRecoverFinishReq(SStreamTask* pTask);
|
||||
int32_t streamSetParamForStreamScannerStep1(SStreamTask* pTask, SVersionRange* pVerRange, STimeWindow* pWindow);
|
||||
int32_t streamSetParamForStreamScannerStep2(SStreamTask* pTask, SVersionRange* pVerRange, STimeWindow* pWindow);
|
||||
int32_t streamBuildSourceRecover1Req(SStreamTask* pTask, SStreamScanHistoryReq* pReq, int8_t igUntreated);
|
||||
int32_t streamSourceScanHistoryData(SStreamTask* pTask);
|
||||
// int32_t streamSourceRecoverScanStep2(SStreamTask* pTask, int64_t ver);
|
||||
int32_t streamDispatchScanHistoryFinishMsg(SStreamTask* pTask);
|
||||
|
||||
int32_t streamDispatchTransferStateMsg(SStreamTask* pTask);
|
||||
|
||||
// agg level
|
||||
int32_t streamAggRecoverPrepare(SStreamTask* pTask);
|
||||
// int32_t streamAggChildrenRecoverFinish(SStreamTask* pTask);
|
||||
int32_t streamProcessRecoverFinishReq(SStreamTask* pTask, int32_t childId);
|
||||
int32_t streamProcessRecoverFinishReq(SStreamTask* pTask, int32_t taskId, int32_t childId);
|
||||
|
||||
void streamMetaInit();
|
||||
void streamMetaCleanup();
|
||||
|
@ -597,6 +636,9 @@ int32_t streamProcessCheckpointSourceReq(SStreamMeta* pMeta, SStreamTask* pTask,
|
|||
int32_t streamProcessCheckpointReq(SStreamMeta* pMeta, SStreamTask* pTask, SStreamCheckpointReq* pReq);
|
||||
int32_t streamProcessCheckpointRsp(SStreamMeta* pMeta, SStreamTask* pTask, SStreamCheckpointRsp* pRsp);
|
||||
|
||||
int32_t streamTaskReleaseState(SStreamTask* pTask);
|
||||
int32_t streamTaskReloadState(SStreamTask* pTask);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,11 +28,10 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct SStreamFileState SStreamFileState;
|
||||
|
||||
typedef SList SStreamSnapshot;
|
||||
|
||||
SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_t rowSize, uint32_t selectRowSize,
|
||||
GetTsFun fp, void* pFile, TSKEY delMark);
|
||||
GetTsFun fp, void* pFile, TSKEY delMark, const char* id);
|
||||
void streamFileStateDestroy(SStreamFileState* pFileState);
|
||||
void streamFileStateClear(SStreamFileState* pFileState);
|
||||
bool needClearDiskBuff(SStreamFileState* pFileState);
|
||||
|
@ -50,6 +49,7 @@ int32_t recoverSnapshot(SStreamFileState* pFileState);
|
|||
int32_t getSnapshotIdList(SStreamFileState* pFileState, SArray* list);
|
||||
int32_t deleteExpiredCheckPoint(SStreamFileState* pFileState, TSKEY mark);
|
||||
int32_t streamFileStateGeSelectRowSize(SStreamFileState* pFileState);
|
||||
void streamFileStateReloadInfo(SStreamFileState* pFileState, TSKEY ts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -516,6 +516,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_QRY_JSON_IN_GROUP_ERROR TAOS_DEF_ERROR_CODE(0, 0x072E)
|
||||
#define TSDB_CODE_QRY_JOB_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x072F)
|
||||
#define TSDB_CODE_QRY_QWORKER_QUIT TAOS_DEF_ERROR_CODE(0, 0x0730)
|
||||
#define TSDB_CODE_QRY_GEO_NOT_SUPPORT_ERROR TAOS_DEF_ERROR_CODE(0, 0x0731)
|
||||
|
||||
// grant
|
||||
#define TSDB_CODE_GRANT_EXPIRED TAOS_DEF_ERROR_CODE(0, 0x0800)
|
||||
|
@ -768,6 +769,8 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_TMQ_CONSUMER_MISMATCH TAOS_DEF_ERROR_CODE(0, 0x4001)
|
||||
#define TSDB_CODE_TMQ_CONSUMER_CLOSED TAOS_DEF_ERROR_CODE(0, 0x4002)
|
||||
#define TSDB_CODE_TMQ_CONSUMER_ERROR TAOS_DEF_ERROR_CODE(0, 0x4003)
|
||||
#define TSDB_CODE_TMQ_TOPIC_OUT_OF_RANGE TAOS_DEF_ERROR_CODE(0, 0x4004)
|
||||
#define TSDB_CODE_TMQ_GROUP_OUT_OF_RANGE TAOS_DEF_ERROR_CODE(0, 0x4005)
|
||||
|
||||
// stream
|
||||
#define TSDB_CODE_STREAM_TASK_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x4100)
|
||||
|
|
|
@ -79,6 +79,7 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight);
|
|||
|
||||
int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight);
|
||||
int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight);
|
||||
int32_t compareLenBinaryVal(const void *pLeft, const void *pRight);
|
||||
|
||||
int32_t comparestrRegexMatch(const void *pLeft, const void *pRight);
|
||||
int32_t comparestrRegexNMatch(const void *pLeft, const void *pRight);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#define _TD_UTIL_HEAP_H_
|
||||
|
||||
#include "os.h"
|
||||
#include "tarray.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -58,6 +59,48 @@ void heapDequeue(Heap* heap);
|
|||
|
||||
size_t heapSize(Heap* heap);
|
||||
|
||||
typedef bool (*pq_comp_fn)(void* l, void* r, void* param);
|
||||
|
||||
typedef struct PriorityQueueNode {
|
||||
void* data;
|
||||
} PriorityQueueNode;
|
||||
|
||||
typedef struct PriorityQueue PriorityQueue;
|
||||
|
||||
PriorityQueue* createPriorityQueue(pq_comp_fn fn, FDelete deleteFn, void* param);
|
||||
|
||||
void taosPQSetFn(PriorityQueue* pq, pq_comp_fn fn);
|
||||
|
||||
void destroyPriorityQueue(PriorityQueue* pq);
|
||||
|
||||
PriorityQueueNode* taosPQTop(PriorityQueue* pq);
|
||||
|
||||
size_t taosPQSize(PriorityQueue* pq);
|
||||
|
||||
void taosPQPush(PriorityQueue* pq, const PriorityQueueNode* node);
|
||||
|
||||
void taosPQPop(PriorityQueue* pq);
|
||||
|
||||
typedef struct BoundedQueue BoundedQueue;
|
||||
|
||||
BoundedQueue* createBoundedQueue(uint32_t maxSize, pq_comp_fn fn, FDelete deleteFn, void* param);
|
||||
|
||||
void taosBQSetFn(BoundedQueue* q, pq_comp_fn fn);
|
||||
|
||||
void destroyBoundedQueue(BoundedQueue* q);
|
||||
|
||||
void taosBQPush(BoundedQueue* q, PriorityQueueNode* n);
|
||||
|
||||
PriorityQueueNode* taosBQTop(BoundedQueue* q);
|
||||
|
||||
size_t taosBQSize(BoundedQueue* q);
|
||||
|
||||
size_t taosBQMaxSize(BoundedQueue* q);
|
||||
|
||||
void taosBQBuildHeap(BoundedQueue* q);
|
||||
|
||||
void taosBQPop(BoundedQueue* q);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -152,7 +152,7 @@ function wgetFile {
|
|||
file=$1
|
||||
versionPath=$2
|
||||
sourceP=$3
|
||||
nasServerIP="192.168.1.131"
|
||||
nasServerIP="192.168.1.213"
|
||||
packagePath="/nas/TDengine/v${versionPath}/${verMode}"
|
||||
if [ -f ${file} ];then
|
||||
echoColor YD "${file} already exists ,it will delete it and download it again "
|
||||
|
|
|
@ -749,6 +749,9 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
|||
pReq.suid = pTableMeta->uid;
|
||||
pReq.source = TD_REQ_FROM_TAOX;
|
||||
pSql = (action == SCHEMA_ACTION_ADD_COLUMN) ? "sml_add_column" : "sml_modify_column_size";
|
||||
} else{
|
||||
uError("SML:0x%" PRIx64 " invalid action:%d", info->id, action);
|
||||
goto end;
|
||||
}
|
||||
|
||||
code = buildRequest(info->taos->id, pSql, strlen(pSql), NULL, false, &pRequest, 0);
|
||||
|
|
|
@ -939,8 +939,6 @@ int stmtClose(TAOS_STMT* stmt) {
|
|||
stmtCleanSQLInfo(pStmt);
|
||||
taosMemoryFree(stmt);
|
||||
|
||||
STMT_DLOG_E("stmt freed");
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -652,7 +652,7 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, int32_t type, tm
|
|||
int32_t j = 0;
|
||||
int32_t numOfVgroups = taosArrayGetSize(pTopic->vgs);
|
||||
for (j = 0; j < numOfVgroups; j++) {
|
||||
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
|
||||
SMqClientVg* pVg = (SMqClientVg*)taosArrayGet(pTopic->vgs, j);
|
||||
if (pVg->vgId == vgId) {
|
||||
break;
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, int32_t type, tm
|
|||
return;
|
||||
}
|
||||
|
||||
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
|
||||
SMqClientVg* pVg = (SMqClientVg*)taosArrayGet(pTopic->vgs, j);
|
||||
if (pVg->offsetInfo.currentOffset.type > 0 && !tOffsetEqual(&pVg->offsetInfo.currentOffset, &pVg->offsetInfo.committedOffset)) {
|
||||
code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups, type);
|
||||
|
||||
|
@ -742,13 +742,15 @@ static void asyncCommitAllOffsets(tmq_t* tmq, tmq_commit_cb* pCommitFp, void* us
|
|||
|
||||
static void generateTimedTask(int64_t refId, int32_t type) {
|
||||
tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId);
|
||||
if (tmq != NULL) {
|
||||
if(tmq == NULL) return;
|
||||
|
||||
int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM, 0);
|
||||
if(pTaskType == NULL) return;
|
||||
|
||||
*pTaskType = type;
|
||||
taosWriteQitem(tmq->delayedTask, pTaskType);
|
||||
tsem_post(&tmq->rspSem);
|
||||
taosReleaseRef(tmqMgmt.rsetId, refId);
|
||||
}
|
||||
}
|
||||
|
||||
void tmqAssignAskEpTask(void* param, void* tmrId) {
|
||||
|
@ -763,19 +765,19 @@ void tmqAssignDelayedCommitTask(void* param, void* tmrId) {
|
|||
taosMemoryFree(param);
|
||||
}
|
||||
|
||||
void tmqAssignDelayedReportTask(void* param, void* tmrId) {
|
||||
int64_t refId = *(int64_t*)param;
|
||||
tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId);
|
||||
if (tmq != NULL) {
|
||||
int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM, 0);
|
||||
*pTaskType = TMQ_DELAYED_TASK__REPORT;
|
||||
taosWriteQitem(tmq->delayedTask, pTaskType);
|
||||
tsem_post(&tmq->rspSem);
|
||||
}
|
||||
|
||||
taosReleaseRef(tmqMgmt.rsetId, refId);
|
||||
taosMemoryFree(param);
|
||||
}
|
||||
//void tmqAssignDelayedReportTask(void* param, void* tmrId) {
|
||||
// int64_t refId = *(int64_t*)param;
|
||||
// tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId);
|
||||
// if (tmq != NULL) {
|
||||
// int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM, 0);
|
||||
// *pTaskType = TMQ_DELAYED_TASK__REPORT;
|
||||
// taosWriteQitem(tmq->delayedTask, pTaskType);
|
||||
// tsem_post(&tmq->rspSem);
|
||||
// }
|
||||
//
|
||||
// taosReleaseRef(tmqMgmt.rsetId, refId);
|
||||
// taosMemoryFree(param);
|
||||
//}
|
||||
|
||||
int32_t tmqHbCb(void* param, SDataBuf* pMsg, int32_t code) {
|
||||
if (pMsg) {
|
||||
|
@ -813,7 +815,7 @@ void tmqSendHbReq(void* param, void* tmrId) {
|
|||
offRows->offset = pVg->offsetInfo.currentOffset;
|
||||
char buf[TSDB_OFFSET_LEN] = {0};
|
||||
tFormatOffset(buf, TSDB_OFFSET_LEN, &offRows->offset);
|
||||
tscInfo("report offset: vgId:%d, offset:%s, rows:%"PRId64, offRows->vgId, buf, offRows->rows);
|
||||
tscInfo("consumer:0x%" PRIx64 ",report offset: vgId:%d, offset:%s, rows:%"PRId64, tmq->consumerId, offRows->vgId, buf, offRows->rows);
|
||||
}
|
||||
}
|
||||
// tmq->needReportOffsetRows = false;
|
||||
|
@ -917,7 +919,7 @@ static void* tmqFreeRspWrapper(SMqRspWrapper* rspWrapper) {
|
|||
} else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__EP_RSP) {
|
||||
SMqAskEpRspWrapper* pEpRspWrapper = (SMqAskEpRspWrapper*)rspWrapper;
|
||||
tDeleteSMqAskEpRsp(&pEpRspWrapper->msg);
|
||||
} else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
} else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_DATA_RSP) {
|
||||
SMqPollRspWrapper* pRsp = (SMqPollRspWrapper*)rspWrapper;
|
||||
taosMemoryFreeClear(pRsp->pEpset);
|
||||
|
||||
|
@ -930,7 +932,7 @@ static void* tmqFreeRspWrapper(SMqRspWrapper* rspWrapper) {
|
|||
taosMemoryFreeClear(pRsp->pEpset);
|
||||
|
||||
taosMemoryFree(pRsp->metaRsp.metaRsp);
|
||||
} else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
} else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
SMqPollRspWrapper* pRsp = (SMqPollRspWrapper*)rspWrapper;
|
||||
taosMemoryFreeClear(pRsp->pEpset);
|
||||
|
||||
|
@ -1405,7 +1407,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
strcpy(pRspWrapper->topicName, pParam->topicName);
|
||||
|
||||
pMsg->pEpSet = NULL;
|
||||
if (rspType == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
if (rspType == TMQ_MSG_TYPE__POLL_DATA_RSP) {
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
|
||||
tDecodeMqDataRsp(&decoder, &pRspWrapper->dataRsp);
|
||||
|
@ -1422,7 +1424,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
tDecodeMqMetaRsp(&decoder, &pRspWrapper->metaRsp);
|
||||
tDecoderClear(&decoder);
|
||||
memcpy(&pRspWrapper->metaRsp, pMsg->pData, sizeof(SMqRspHead));
|
||||
} else if (rspType == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
} else if (rspType == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
|
||||
tDecodeSTaosxRsp(&decoder, &pRspWrapper->taosxRsp);
|
||||
|
@ -1489,7 +1491,8 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
|
|||
makeTopicVgroupKey(vgKey, pTopic->topicName, pVgEp->vgId);
|
||||
SVgroupSaveInfo* pInfo = taosHashGet(pVgOffsetHashMap, vgKey, strlen(vgKey));
|
||||
|
||||
STqOffsetVal offsetNew = {.type = tmq->resetOffsetCfg};
|
||||
STqOffsetVal offsetNew = {0};
|
||||
offsetNew.type = tmq->resetOffsetCfg;
|
||||
|
||||
SMqClientVg clientVg = {
|
||||
.pollCnt = 0,
|
||||
|
@ -1881,7 +1884,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET;
|
||||
tscError("consumer:0x%" PRIx64 " unexpected rsp from poll, code:%s", tmq->consumerId, tstrerror(terrno));
|
||||
return NULL;
|
||||
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_DATA_RSP) {
|
||||
SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper;
|
||||
|
||||
int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
|
||||
|
@ -1981,7 +1984,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
pRspWrapper = tmqFreeRspWrapper(pRspWrapper);
|
||||
taosFreeQitem(pollRspWrapper);
|
||||
}
|
||||
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper;
|
||||
int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
|
||||
|
||||
|
@ -2023,7 +2026,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
void* pRsp = NULL;
|
||||
int64_t numOfRows = 0;
|
||||
if (pollRspWrapper->taosxRsp.createTableNum == 0) {
|
||||
pRsp = tmqBuildRspFromWrapper(pollRspWrapper, pVg, &numOfRows);
|
||||
tscError("consumer:0x%" PRIx64" createTableNum should > 0 if rsp type is data_meta", tmq->consumerId);
|
||||
} else {
|
||||
pRsp = tmqBuildTaosxRspFromWrapper(pollRspWrapper, pVg, &numOfRows);
|
||||
}
|
||||
|
|
|
@ -160,9 +160,9 @@ static const SSysDbTableSchema streamSchema[] = {
|
|||
|
||||
static const SSysDbTableSchema streamTaskSchema[] = {
|
||||
{.name = "stream_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "task_id", .bytes = 8, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "task_id", .bytes = 32, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "node_type", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "node_id", .bytes = 8, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "node_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "level", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "status", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
};
|
||||
|
@ -290,7 +290,7 @@ static const SSysDbTableSchema subscriptionSchema[] = {
|
|||
{.name = "topic_name", .bytes = TSDB_TOPIC_FNAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "consumer_group", .bytes = TSDB_CGROUP_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "vgroup_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "consumer_id", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT, .sysInfo = false},
|
||||
{.name = "consumer_id", .bytes = 32, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "offset", .bytes = TSDB_OFFSET_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "rows", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT, .sysInfo = false},
|
||||
};
|
||||
|
@ -352,7 +352,7 @@ static const SSysDbTableSchema connectionsSchema[] = {
|
|||
|
||||
|
||||
static const SSysDbTableSchema consumerSchema[] = {
|
||||
{.name = "consumer_id", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT, .sysInfo = false},
|
||||
{.name = "consumer_id", .bytes = 32, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "consumer_group", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "client_id", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "status", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
|
|
|
@ -47,6 +47,16 @@ int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRo
|
|||
}
|
||||
}
|
||||
|
||||
int32_t colDataGetRowLength(const SColumnInfoData* pColumnInfoData, int32_t rowIdx) {
|
||||
if (colDataIsNull_s(pColumnInfoData, rowIdx)) return 0;
|
||||
|
||||
if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) return pColumnInfoData->info.bytes;
|
||||
if (pColumnInfoData->info.type == TSDB_DATA_TYPE_JSON)
|
||||
return getJsonValueLen(colDataGetData(pColumnInfoData, rowIdx));
|
||||
else
|
||||
return varDataTLen(colDataGetData(pColumnInfoData, rowIdx));
|
||||
}
|
||||
|
||||
int32_t colDataGetFullLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows) {
|
||||
if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
|
||||
return pColumnInfoData->varmeta.length + sizeof(int32_t) * numOfRows;
|
||||
|
@ -56,10 +66,6 @@ int32_t colDataGetFullLength(const SColumnInfoData* pColumnInfoData, int32_t num
|
|||
}
|
||||
}
|
||||
|
||||
void colDataTrim(SColumnInfoData* pColumnInfoData) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
int32_t getJsonValueLen(const char* data) {
|
||||
int32_t dataLen = 0;
|
||||
if (*data == TSDB_DATA_TYPE_NULL) {
|
||||
|
@ -78,10 +84,6 @@ int32_t getJsonValueLen(const char* data) {
|
|||
return dataLen;
|
||||
}
|
||||
|
||||
int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
|
||||
return colDataSetVal(pColumnInfoData, rowIndex, pData, isNull);
|
||||
}
|
||||
|
||||
int32_t colDataSetVal(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
|
||||
if (isNull) {
|
||||
// There is a placehold for each NULL value of binary or nchar type.
|
||||
|
@ -163,7 +165,7 @@ int32_t colDataReassignVal(SColumnInfoData* pColumnInfoData, uint32_t dstRowIdx,
|
|||
}
|
||||
|
||||
|
||||
int32_t colDataReserve(SColumnInfoData* pColumnInfoData, size_t newSize) {
|
||||
static int32_t colDataReserve(SColumnInfoData* pColumnInfoData, size_t newSize) {
|
||||
if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -871,41 +873,8 @@ int32_t dataBlockCompar(const void* p1, const void* p2, const void* param) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t doAssignOneTuple(SColumnInfoData* pDstCols, int32_t numOfRows, const SSDataBlock* pSrcBlock,
|
||||
int32_t tupleIndex) {
|
||||
int32_t code = 0;
|
||||
size_t numOfCols = taosArrayGetSize(pSrcBlock->pDataBlock);
|
||||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumnInfoData* pDst = &pDstCols[i];
|
||||
SColumnInfoData* pSrc = taosArrayGet(pSrcBlock->pDataBlock, i);
|
||||
|
||||
if (pSrc->hasNull && colDataIsNull(pSrc, pSrcBlock->info.rows, tupleIndex, pSrcBlock->pBlockAgg[i])) {
|
||||
code = colDataSetVal(pDst, numOfRows, NULL, true);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
char* p = colDataGetData(pSrc, tupleIndex);
|
||||
code = colDataSetVal(pDst, numOfRows, p, false);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
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]);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumnInfoData* pDst = &pCols[i];
|
||||
|
@ -930,7 +899,7 @@ static int32_t blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataB
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1090,114 +1059,6 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct SHelper {
|
||||
int32_t index;
|
||||
union {
|
||||
char* pData;
|
||||
int64_t i64;
|
||||
double d64;
|
||||
};
|
||||
} SHelper;
|
||||
|
||||
SHelper* createTupleIndex_rv(int32_t numOfRows, SArray* pOrderInfo, SSDataBlock* pBlock) {
|
||||
int32_t sortValLengthPerRow = 0;
|
||||
int32_t numOfCols = taosArrayGetSize(pOrderInfo);
|
||||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SBlockOrderInfo* pInfo = taosArrayGet(pOrderInfo, i);
|
||||
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pInfo->slotId);
|
||||
pInfo->pColData = pColInfo;
|
||||
sortValLengthPerRow += pColInfo->info.bytes;
|
||||
}
|
||||
|
||||
size_t len = sortValLengthPerRow * pBlock->info.rows;
|
||||
|
||||
char* buf = taosMemoryCalloc(1, len);
|
||||
SHelper* phelper = taosMemoryCalloc(numOfRows, sizeof(SHelper));
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
phelper[i].index = i;
|
||||
phelper[i].pData = buf + sortValLengthPerRow * i;
|
||||
}
|
||||
|
||||
int32_t offset = 0;
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SBlockOrderInfo* pInfo = taosArrayGet(pOrderInfo, i);
|
||||
for (int32_t j = 0; j < numOfRows; ++j) {
|
||||
phelper[j].i64 = *(int32_t*)pInfo->pColData->pData + pInfo->pColData->info.bytes * j;
|
||||
// memcpy(phelper[j].pData + offset, pInfo->pColData->pData + pInfo->pColData->info.bytes * j,
|
||||
// pInfo->pColData->info.bytes);
|
||||
}
|
||||
|
||||
offset += pInfo->pColData->info.bytes;
|
||||
}
|
||||
|
||||
taosMemoryFree(buf);
|
||||
return phelper;
|
||||
}
|
||||
|
||||
int32_t dataBlockCompar_rv(const void* p1, const void* p2, const void* param) {
|
||||
const SSDataBlockSortHelper* pHelper = (const SSDataBlockSortHelper*)param;
|
||||
|
||||
SHelper* left = (SHelper*)p1;
|
||||
SHelper* right = (SHelper*)p2;
|
||||
|
||||
SArray* pInfo = pHelper->orderInfo;
|
||||
|
||||
int32_t offset = 0;
|
||||
int32_t leftx = *(int32_t*)left->pData; //*(int32_t*)(left->pData + offset);
|
||||
int32_t rightx = *(int32_t*)right->pData; //*(int32_t*)(right->pData + offset);
|
||||
|
||||
if (leftx == rightx) {
|
||||
return 0;
|
||||
} else {
|
||||
return (leftx < rightx) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blockDataSort_rv(SSDataBlock* pDataBlock, SArray* pOrderInfo, bool nullFirst) {
|
||||
// Allocate the additional buffer.
|
||||
int64_t p0 = taosGetTimestampUs();
|
||||
|
||||
SSDataBlockSortHelper helper = {.pDataBlock = pDataBlock, .orderInfo = pOrderInfo};
|
||||
|
||||
uint32_t rows = pDataBlock->info.rows;
|
||||
SHelper* index = createTupleIndex_rv(rows, helper.orderInfo, pDataBlock);
|
||||
if (index == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
taosqsort(index, rows, sizeof(SHelper), &helper, dataBlockCompar_rv);
|
||||
|
||||
int64_t p1 = taosGetTimestampUs();
|
||||
SColumnInfoData* pCols = createHelpColInfoData(pDataBlock);
|
||||
if (pCols == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
int64_t p2 = taosGetTimestampUs();
|
||||
|
||||
// int32_t code = blockDataAssign(pCols, pDataBlock, index);
|
||||
// if (code != TSDB_CODE_SUCCESS) {
|
||||
// terrno = code;
|
||||
// return code;
|
||||
// }
|
||||
|
||||
int64_t p3 = taosGetTimestampUs();
|
||||
|
||||
copyBackToBlock(pDataBlock, pCols);
|
||||
int64_t p4 = taosGetTimestampUs();
|
||||
|
||||
printf("sort:%" PRId64 ", create:%" PRId64 ", assign:%" PRId64 ", copyback:%" PRId64 ", rows:%d\n", p1 - p0, p2 - p1,
|
||||
p3 - p2, p4 - p3, rows);
|
||||
// destroyTupleIndex(index);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void blockDataCleanup(SSDataBlock* pDataBlock) {
|
||||
blockDataEmpty(pDataBlock);
|
||||
SDataBlockInfo* pInfo = &pDataBlock->info;
|
||||
|
@ -1334,8 +1195,7 @@ void blockDataFreeRes(SSDataBlock* pBlock) {
|
|||
colDataDestroy(pColInfoData);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pBlock->pDataBlock);
|
||||
pBlock->pDataBlock = NULL;
|
||||
pBlock->pDataBlock = taosArrayDestroy(pBlock->pDataBlock);
|
||||
taosMemoryFreeClear(pBlock->pBlockAgg);
|
||||
memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
|
||||
}
|
||||
|
@ -1350,6 +1210,7 @@ void* blockDataDestroy(SSDataBlock* pBlock) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// todo remove it
|
||||
int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
|
||||
dst->info = src->info;
|
||||
dst->info.rows = 0;
|
||||
|
@ -1748,16 +1609,6 @@ static void colDataKeepFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_
|
|||
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
|
||||
// pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, 0, n);
|
||||
memset(&pColInfoData->varmeta.offset[n], 0, total - n);
|
||||
} else { // reset the bitmap value
|
||||
/*int32_t stopIndex = BitmapLen(n) * 8;
|
||||
for(int32_t i = n; i < stopIndex; ++i) {
|
||||
colDataClearNull_f(pColInfoData->nullbitmap, i);
|
||||
}
|
||||
|
||||
int32_t remain = BitmapLen(total) - BitmapLen(n);
|
||||
if (remain > 0) {
|
||||
memset(pColInfoData->nullbitmap+BitmapLen(n), 0, remain);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1864,32 +1715,6 @@ void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) {
|
|||
return (void*)buf;
|
||||
}
|
||||
|
||||
int32_t tEncodeDataBlocks(void** buf, const SArray* blocks) {
|
||||
int32_t tlen = 0;
|
||||
int32_t sz = taosArrayGetSize(blocks);
|
||||
tlen += taosEncodeFixedI32(buf, sz);
|
||||
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SSDataBlock* pBlock = taosArrayGet(blocks, i);
|
||||
tlen += tEncodeDataBlock(buf, pBlock);
|
||||
}
|
||||
|
||||
return tlen;
|
||||
}
|
||||
|
||||
void* tDecodeDataBlocks(const void* buf, SArray** blocks) {
|
||||
int32_t sz;
|
||||
buf = taosDecodeFixedI32(buf, &sz);
|
||||
|
||||
*blocks = taosArrayInit(sz, sizeof(SSDataBlock));
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SSDataBlock pBlock = {0};
|
||||
buf = tDecodeDataBlock(buf, &pBlock);
|
||||
taosArrayPush(*blocks, &pBlock);
|
||||
}
|
||||
return (void*)buf;
|
||||
}
|
||||
|
||||
static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
||||
time_t tt;
|
||||
int32_t ms = 0;
|
||||
|
@ -1939,101 +1764,6 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
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);
|
||||
size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
|
||||
|
||||
int32_t rows = pDataBlock->info.rows;
|
||||
printf("%s |block ver %" PRIi64 " |block type %d |child id %d|group id %" PRIu64 "\n", flag,
|
||||
pDataBlock->info.version, (int32_t)pDataBlock->info.type, pDataBlock->info.childId,
|
||||
pDataBlock->info.id.groupId);
|
||||
for (int32_t j = 0; j < rows; j++) {
|
||||
printf("%s |", flag);
|
||||
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 (k == 0) {
|
||||
printf("cols:%d |", (int32_t)numOfCols);
|
||||
}
|
||||
if (colDataIsNull(pColInfoData, rows, j, NULL)) {
|
||||
printf(" %15s |", "NULL");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pColInfoData->info.type) {
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
formatTimestamp(pBuf, *(uint64_t*)var, TSDB_TIME_PRECISION_MILLI);
|
||||
printf(" %25s |", pBuf);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
printf(" %15" PRIi8 " |", *(int8_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
printf(" %15" PRIi8 " |", *(int8_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
printf(" %15" PRIi16 " |", *(int16_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
printf(" %15d |", *(int32_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
printf(" %15" PRIu8 " |", *(uint8_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
printf(" %15" PRIu16 " |", *(uint16_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
printf(" %15u |", *(uint32_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
printf(" %15" PRId64 " |", *(int64_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
printf(" %15" PRIu64 " |", *(uint64_t*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
printf(" %15f |", *(float*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
printf(" %15lf |", *(double*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf) - 1, varDataLen(pData));
|
||||
memset(pBuf, 0, dataSize + 1);
|
||||
strncpy(pBuf, varDataVal(pData), dataSize);
|
||||
printf(" %15s |", pBuf);
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
|
||||
memset(pBuf, 0, dataSize);
|
||||
(void)taosUcs4ToMbs((TdUcs4*)varDataVal(pData), dataSize, pBuf);
|
||||
printf(" %15s |", pBuf);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// for debug
|
||||
char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) {
|
||||
int32_t size = 2048*1024;
|
||||
|
@ -2142,182 +1872,6 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
|
|||
return dumpBuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TODO: Assume that the final generated result it less than 3M
|
||||
*
|
||||
* @param pReq
|
||||
* @param pDataBlocks
|
||||
* @param vgId
|
||||
* @param suid
|
||||
*
|
||||
*/
|
||||
#if 0
|
||||
int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataBlock, STSchema* pTSchema, int32_t vgId,
|
||||
tb_uid_t suid) {
|
||||
int32_t bufSize = sizeof(SSubmitReq);
|
||||
int32_t sz = 1;
|
||||
for (int32_t i = 0; i < sz; ++i) {
|
||||
const SDataBlockInfo* pBlkInfo = &pDataBlock->info;
|
||||
|
||||
int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
|
||||
bufSize += pBlkInfo->rows * (TD_ROW_HEAD_LEN + pBlkInfo->rowSize + BitmapLen(colNum));
|
||||
bufSize += sizeof(SSubmitBlk);
|
||||
}
|
||||
|
||||
*pReq = taosMemoryCalloc(1, bufSize);
|
||||
if (!(*pReq)) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
void* pDataBuf = *pReq;
|
||||
|
||||
int32_t msgLen = sizeof(SSubmitReq);
|
||||
int32_t numOfBlks = 0;
|
||||
SRowBuilder rb = {0};
|
||||
tdSRowInit(&rb, pTSchema->version);
|
||||
|
||||
for (int32_t i = 0; i < sz; ++i) {
|
||||
int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
|
||||
int32_t rows = pDataBlock->info.rows;
|
||||
|
||||
if (colNum <= 1) {
|
||||
// invalid if only with TS col
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rb.nCols != colNum) {
|
||||
tdSRowSetTpInfo(&rb, colNum, pTSchema->flen);
|
||||
}
|
||||
|
||||
SSubmitBlk* pSubmitBlk = POINTER_SHIFT(pDataBuf, msgLen);
|
||||
pSubmitBlk->suid = suid;
|
||||
pSubmitBlk->uid = pDataBlock->info.id.groupId;
|
||||
pSubmitBlk->numOfRows = rows;
|
||||
pSubmitBlk->sversion = pTSchema->version;
|
||||
|
||||
msgLen += sizeof(SSubmitBlk);
|
||||
int32_t dataLen = 0;
|
||||
for (int32_t j = 0; j < rows; ++j) { // iterate by row
|
||||
tdSRowResetBuf(&rb, POINTER_SHIFT(pDataBuf, msgLen + dataLen)); // 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);
|
||||
continue; // offset should keep 0 for next column
|
||||
|
||||
} else if (colDataIsNull_s(pColInfoData, j)) {
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, TSDB_DATA_TYPE_TIMESTAMP, TD_VTYPE_NULL, NULL,
|
||||
false, 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:
|
||||
case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (colDataIsNull_s(pColInfoData, j)) {
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pColInfoData->info.type, TD_VTYPE_NULL, NULL,
|
||||
false, offset, k);
|
||||
} else {
|
||||
void* data = colDataGetData(pColInfoData, j);
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pColInfoData->info.type, TD_VTYPE_NORM, data,
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) {
|
||||
if (colDataIsNull_s(pColInfoData, j)) {
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pCol->type, TD_VTYPE_NULL, NULL, false,
|
||||
offset, k);
|
||||
} else 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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
offset += TYPE_BYTES[pCol->type]; // sum/avg would convert to int64_t/uint64_t/double during aggregation
|
||||
}
|
||||
tdSRowEnd(&rb);
|
||||
dataLen += TD_ROW_LEN(rb.pBuf);
|
||||
#ifdef TD_DEBUG_PRINT_ROW
|
||||
tdSRowPrint(rb.pBuf, pTSchema, __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
++numOfBlks;
|
||||
|
||||
pSubmitBlk->dataLen = dataLen;
|
||||
msgLen += pSubmitBlk->dataLen;
|
||||
}
|
||||
|
||||
if (numOfBlks > 0) {
|
||||
(*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->sversion = htonl(blk->sversion);
|
||||
blk->dataLen = htonl(blk->dataLen);
|
||||
blk->schemaLen = htonl(blk->schemaLen);
|
||||
blk->numOfRows = htonl(blk->numOfRows);
|
||||
blk = (SSubmitBlk*)(blk->data + dataLen);
|
||||
}
|
||||
} else {
|
||||
// no valid rows
|
||||
taosMemoryFreeClear(*pReq);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDataBlock, const STSchema* pTSchema,
|
||||
int64_t uid, int32_t vgId, tb_uid_t suid) {
|
||||
SSubmitReq2* pReq = *ppReq;
|
||||
|
@ -2721,3 +2275,149 @@ const char* blockDecode(SSDataBlock* pBlock, const char* pData) {
|
|||
ASSERT(pStart - pData == dataLen);
|
||||
return pStart;
|
||||
}
|
||||
|
||||
void trimDataBlock(SSDataBlock* pBlock, int32_t totalRows, const bool* pBoolList) {
|
||||
// int32_t totalRows = pBlock->info.rows;
|
||||
int32_t bmLen = BitmapLen(totalRows);
|
||||
char* pBitmap = NULL;
|
||||
int32_t maxRows = 0;
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
|
||||
for (int32_t i = 0; i < numOfCols; ++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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t numOfRows = 0;
|
||||
if (IS_VAR_DATA_TYPE(pDst->info.type)) {
|
||||
int32_t j = 0;
|
||||
pDst->varmeta.length = 0;
|
||||
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (colDataIsNull_var(pDst, j)) {
|
||||
colDataSetNull_var(pDst, numOfRows);
|
||||
} else {
|
||||
// fix address sanitizer error. p1 may point to memory that will change during realloc of colDataSetVal, first copy it to p2
|
||||
char* p1 = colDataGetVarData(pDst, j);
|
||||
int32_t len = 0;
|
||||
if (pDst->info.type == TSDB_DATA_TYPE_JSON) {
|
||||
len = getJsonValueLen(p1);
|
||||
} else {
|
||||
len = varDataTLen(p1);
|
||||
}
|
||||
char* p2 = taosMemoryMalloc(len);
|
||||
memcpy(p2, p1, len);
|
||||
colDataSetVal(pDst, numOfRows, p2, false);
|
||||
taosMemoryFree(p2);
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
if (maxRows < numOfRows) {
|
||||
maxRows = numOfRows;
|
||||
}
|
||||
} else {
|
||||
if (pBitmap == NULL) {
|
||||
pBitmap = taosMemoryCalloc(1, bmLen);
|
||||
}
|
||||
|
||||
memcpy(pBitmap, pDst->nullbitmap, bmLen);
|
||||
memset(pDst->nullbitmap, 0, bmLen);
|
||||
|
||||
int32_t j = 0;
|
||||
|
||||
switch (pDst->info.type) {
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (colDataIsNull_f(pBitmap, j)) {
|
||||
colDataSetNull_f(pDst->nullbitmap, numOfRows);
|
||||
} else {
|
||||
((int64_t*)pDst->pData)[numOfRows] = ((int64_t*)pDst->pData)[j];
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
if (colDataIsNull_f(pBitmap, j)) {
|
||||
colDataSetNull_f(pDst->nullbitmap, numOfRows);
|
||||
} else {
|
||||
((int32_t*)pDst->pData)[numOfRows] = ((int32_t*)pDst->pData)[j];
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
if (colDataIsNull_f(pBitmap, j)) {
|
||||
colDataSetNull_f(pDst->nullbitmap, numOfRows);
|
||||
} else {
|
||||
((int16_t*)pDst->pData)[numOfRows] = ((int16_t*)pDst->pData)[j];
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
if (colDataIsNull_f(pBitmap, j)) {
|
||||
colDataSetNull_f(pDst->nullbitmap, numOfRows);
|
||||
} else {
|
||||
((int8_t*)pDst->pData)[numOfRows] = ((int8_t*)pDst->pData)[j];
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxRows < numOfRows) {
|
||||
maxRows = numOfRows;
|
||||
}
|
||||
}
|
||||
|
||||
pBlock->info.rows = maxRows;
|
||||
if (pBitmap != NULL) {
|
||||
taosMemoryFree(pBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t blockGetEncodeSize(const SSDataBlock* pBlock) {
|
||||
return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
|
||||
}
|
|
@ -62,6 +62,7 @@ int32_t tsNumOfQnodeFetchThreads = 1;
|
|||
int32_t tsNumOfSnodeStreamThreads = 4;
|
||||
int32_t tsNumOfSnodeWriteThreads = 1;
|
||||
int32_t tsMaxStreamBackendCache = 128; // M
|
||||
int32_t tsPQSortMemThreshold = 16; // M
|
||||
|
||||
// sync raft
|
||||
int32_t tsElectInterval = 25 * 1000;
|
||||
|
@ -104,11 +105,13 @@ char tsSmlChildTableName[TSDB_TABLE_NAME_LEN] = ""; // user defined child table
|
|||
// bool tsSmlDataFormat = false;
|
||||
// int32_t tsSmlBatchSize = 10000;
|
||||
|
||||
// tmq
|
||||
int32_t tmqMaxTopicNum = 20;
|
||||
// query
|
||||
int32_t tsQueryPolicy = 1;
|
||||
int32_t tsQueryRspPolicy = 0;
|
||||
int64_t tsQueryMaxConcurrentTables = 200; // unit is TSDB_TABLE_NUM_UNIT
|
||||
bool tsEnableQueryHb = false;
|
||||
bool tsEnableQueryHb = true;
|
||||
bool tsEnableScience = false; // on taos-cli show float and doulbe with scientific notation if true
|
||||
bool tsTtlChangeOnWrite = false; // ttl delete time changes on last write if true
|
||||
int32_t tsQuerySmaOptimize = 0;
|
||||
|
@ -510,6 +513,8 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
if (cfgAddString(pCfg, "telemetryServer", tsTelemServer, 0) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "telemetryPort", tsTelemPort, 1, 65056, 0) != 0) return -1;
|
||||
|
||||
if (cfgAddInt32(pCfg, "tmqMaxTopicNum", tmqMaxTopicNum, 1, 10000, 1) != 0) return -1;
|
||||
|
||||
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;
|
||||
|
@ -533,6 +538,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
|
||||
if (cfgAddBool(pCfg, "filterScalarMode", tsFilterScalarMode, 0) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "maxStreamBackendCache", tsMaxStreamBackendCache, 16, 1024, 0) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "pqSortMemThreshold", tsPQSortMemThreshold, 1, 10240, 0) != 0) return -1;
|
||||
|
||||
GRANT_CFG_ADD;
|
||||
return 0;
|
||||
|
@ -880,6 +886,8 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
|||
tstrncpy(tsTelemServer, cfgGetItem(pCfg, "telemetryServer")->str, TSDB_FQDN_LEN);
|
||||
tsTelemPort = (uint16_t)cfgGetItem(pCfg, "telemetryPort")->i32;
|
||||
|
||||
tmqMaxTopicNum= cfgGetItem(pCfg, "tmqMaxTopicNum")->i32;
|
||||
|
||||
tsTransPullupInterval = cfgGetItem(pCfg, "transPullupInterval")->i32;
|
||||
tsMqRebalanceInterval = cfgGetItem(pCfg, "mqRebalanceInterval")->i32;
|
||||
tsTtlUnit = cfgGetItem(pCfg, "ttlUnit")->i32;
|
||||
|
@ -914,6 +922,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
|||
|
||||
tsFilterScalarMode = cfgGetItem(pCfg, "filterScalarMode")->bval;
|
||||
tsMaxStreamBackendCache = cfgGetItem(pCfg, "maxStreamBackendCache")->i32;
|
||||
tsPQSortMemThreshold = cfgGetItem(pCfg, "pqSortMemThreshold")->i32;
|
||||
|
||||
GRANT_CFG_GET;
|
||||
return 0;
|
||||
|
|
|
@ -6982,8 +6982,11 @@ int32_t tDecodeSVAlterTbReqSetCtime(SDecoder* pDecoder, SVAlterTbReq* pReq, int6
|
|||
if (tStartDecode(pDecoder) < 0) return -1;
|
||||
if (tDecodeSVAlterTbReqCommon(pDecoder, pReq) < 0) return -1;
|
||||
|
||||
pReq->ctimeMs = 0;
|
||||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
*(int64_t *)(pDecoder->data + pDecoder->pos) = ctimeMs;
|
||||
if (tDecodeI64(pDecoder, &pReq->ctimeMs) < 0) return -1;
|
||||
}
|
||||
|
||||
tEndDecode(pDecoder);
|
||||
return 0;
|
||||
|
@ -7541,8 +7544,11 @@ int32_t tDecodeSBatchDeleteReq(SDecoder *pDecoder, SBatchDeleteReq *pReq) {
|
|||
int32_t tDecodeSBatchDeleteReqSetCtime(SDecoder *pDecoder, SBatchDeleteReq *pReq, int64_t ctimeMs) {
|
||||
if (tDecodeSBatchDeleteReqCommon(pDecoder, pReq)) return -1;
|
||||
|
||||
pReq->ctimeMs = 0;
|
||||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
*(int64_t *)(pDecoder->data + pDecoder->pos) = ctimeMs;
|
||||
if (tDecodeI64(pDecoder, &pReq->ctimeMs) < 0) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -969,7 +969,7 @@ void taosFormatUtcTime(char* buf, int32_t bufLen, int64_t t, int32_t precision)
|
|||
|
||||
default:
|
||||
fractionLen = 0;
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (taosLocalTime(", &ptm, buf) == NULL) {
|
||||
|
|
|
@ -76,6 +76,9 @@ SArray *smGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_RETRIEVE_RSP, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_PAUSE, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RESUME, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECK, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECK_RSP, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_SCAN_HISTORY_FINISH, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_CHECK_POINT_SOURCE, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
|
||||
code = 0;
|
||||
|
|
|
@ -743,9 +743,10 @@ SArray *vmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DISPATCH_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_STREAM_RECOVER_FINISH, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_SCAN_HISTORY_FINISH, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TRANSFER_STATE, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECK, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECK_RSP, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECK_RSP, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TRIGGER, vmPutMsgToStreamQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_PAUSE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RESUME, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
|
|
|
@ -92,7 +92,7 @@ static void vmProcessStreamQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
|||
const STraceId *trace = &pMsg->info.traceId;
|
||||
|
||||
dGTrace("vgId:%d, msg:%p get from vnode-stream queue", pVnode->vgId, pMsg);
|
||||
int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
|
||||
int32_t code = vnodeProcessStreamMsg(pVnode->pImpl, pMsg, pInfo);
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dGError("vgId:%d, msg:%p failed to process stream msg %s since %s", pVnode->vgId, pMsg, TMSG_INFO(pMsg->msgType),
|
||||
|
|
|
@ -25,14 +25,15 @@ extern "C" {
|
|||
enum {
|
||||
MQ_CONSUMER_STATUS_REBALANCE = 1,
|
||||
// MQ_CONSUMER_STATUS__MODIFY_IN_REB, // this value is not used anymore
|
||||
MQ_CONSUMER_STATUS__READY,
|
||||
MQ_CONSUMER_STATUS__LOST,
|
||||
MQ_CONSUMER_STATUS_READY,
|
||||
MQ_CONSUMER_STATUS_LOST,
|
||||
// MQ_CONSUMER_STATUS__LOST_IN_REB, // this value is not used anymore
|
||||
MQ_CONSUMER_STATUS__LOST_REBD,
|
||||
};
|
||||
// MQ_CONSUMER_STATUS__LOST_REBD,
|
||||
};\
|
||||
|
||||
int32_t mndInitConsumer(SMnode *pMnode);
|
||||
void mndCleanupConsumer(SMnode *pMnode);
|
||||
void mndDropConsumerFromSdb(SMnode *pMnode, int64_t consumerId);
|
||||
|
||||
SMqConsumerObj *mndAcquireConsumer(SMnode *pMnode, int64_t consumerId);
|
||||
void mndReleaseConsumer(SMnode *pMnode, SMqConsumerObj *pConsumer);
|
||||
|
|
|
@ -137,12 +137,12 @@ typedef enum {
|
|||
} EDndReason;
|
||||
|
||||
typedef enum {
|
||||
CONSUMER_UPDATE__TOUCH = 1, // rebalance req do not need change consume topic
|
||||
CONSUMER_UPDATE__ADD,
|
||||
CONSUMER_UPDATE__REMOVE,
|
||||
CONSUMER_UPDATE__LOST,
|
||||
CONSUMER_UPDATE__RECOVER,
|
||||
CONSUMER_UPDATE__REBALANCE, // subscribe req need change consume topic
|
||||
CONSUMER_UPDATE_REB_MODIFY_NOTOPIC = 1, // topic do not need modified after rebalance
|
||||
CONSUMER_UPDATE_REB_MODIFY_TOPIC, // topic need modified after rebalance
|
||||
CONSUMER_UPDATE_REB_MODIFY_REMOVE, // topic need removed after rebalance
|
||||
// CONSUMER_UPDATE_TIMER_LOST,
|
||||
CONSUMER_UPDATE_RECOVER,
|
||||
CONSUMER_UPDATE_SUB_MODIFY, // modify after subscribe req
|
||||
} ECsmUpdateType;
|
||||
|
||||
typedef struct {
|
||||
|
@ -549,7 +549,7 @@ typedef struct {
|
|||
// data for display
|
||||
int32_t pid;
|
||||
SEpSet ep;
|
||||
int64_t upTime;
|
||||
int64_t createTime;
|
||||
int64_t subscribeTime;
|
||||
int64_t rebalanceTime;
|
||||
|
||||
|
@ -560,7 +560,7 @@ typedef struct {
|
|||
} SMqConsumerObj;
|
||||
|
||||
SMqConsumerObj* tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_LEN]);
|
||||
void tDeleteSMqConsumerObj(SMqConsumerObj* pConsumer);
|
||||
void tDeleteSMqConsumerObj(SMqConsumerObj* pConsumer, bool delete);
|
||||
int32_t tEncodeSMqConsumerObj(void** buf, const SMqConsumerObj* pConsumer);
|
||||
void* tDecodeSMqConsumerObj(const void* buf, SMqConsumerObj* pConsumer, int8_t sver);
|
||||
|
||||
|
@ -647,6 +647,14 @@ typedef struct {
|
|||
// SMqSubActionLogEntry* pLogEntry;
|
||||
} SMqRebOutputObj;
|
||||
|
||||
typedef struct SStreamConf {
|
||||
int8_t igExpired;
|
||||
int8_t trigger;
|
||||
int8_t fillHistory;
|
||||
int64_t triggerParam;
|
||||
int64_t watermark;
|
||||
} SStreamConf;
|
||||
|
||||
typedef struct {
|
||||
char name[TSDB_STREAM_FNAME_LEN];
|
||||
// ctl
|
||||
|
@ -660,12 +668,7 @@ typedef struct {
|
|||
// info
|
||||
int64_t uid;
|
||||
int8_t status;
|
||||
// config
|
||||
int8_t igExpired;
|
||||
int8_t trigger;
|
||||
int8_t fillHistory;
|
||||
int64_t triggerParam;
|
||||
int64_t watermark;
|
||||
SStreamConf conf;
|
||||
// source and target
|
||||
int64_t sourceDbUid;
|
||||
int64_t targetDbUid;
|
||||
|
@ -683,6 +686,10 @@ typedef struct {
|
|||
char* ast;
|
||||
char* physicalPlan;
|
||||
SArray* tasks; // SArray<SArray<SStreamTask>>
|
||||
|
||||
SArray* pHTasksList; // generate the results for already stored ts data
|
||||
int64_t hTaskUid; // stream task for history ts data
|
||||
|
||||
SSchemaWrapper outputSchema;
|
||||
SSchemaWrapper tagSchema;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib
|
|||
int32_t mndConvertRsmaTask(char** pDst, int32_t* pDstLen, const char* ast, int64_t uid, int8_t triggerType,
|
||||
int64_t watermark, int64_t deleteMark);
|
||||
|
||||
int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream);
|
||||
int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream, int64_t nextWindowSkey);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ extern "C" {
|
|||
int32_t mndInitSubscribe(SMnode *pMnode);
|
||||
void mndCleanupSubscribe(SMnode *pMnode);
|
||||
|
||||
int32_t mndGetGroupNumByTopic(SMnode *pMnode, const char *topicName);
|
||||
SMqSubscribeObj *mndAcquireSubscribe(SMnode *pMnode, const char *CGroup, const char *topicName);
|
||||
SMqSubscribeObj *mndAcquireSubscribeByKey(SMnode *pMnode, const char *key);
|
||||
void mndReleaseSubscribe(SMnode *pMnode, SMqSubscribeObj *pSub);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define MND_CONSUMER_VER_NUMBER 2
|
||||
#define MND_CONSUMER_RESERVE_SIZE 64
|
||||
|
||||
#define MND_MAX_GROUP_PER_TOPIC 100
|
||||
#define MND_CONSUMER_LOST_HB_CNT 6
|
||||
#define MND_CONSUMER_LOST_CLEAR_THRESHOLD 43200
|
||||
|
||||
|
@ -63,7 +64,7 @@ int32_t mndInitConsumer(SMnode *pMnode) {
|
|||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_HB, mndProcessMqHbReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_ASK_EP, mndProcessAskEpReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_TIMER, mndProcessMqTimerMsg);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_CONSUMER_LOST, mndProcessConsumerLostMsg);
|
||||
// mndSetMsgHandle(pMnode, TDMT_MND_TMQ_CONSUMER_LOST, mndProcessConsumerLostMsg);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_CONSUMER_RECOVER, mndProcessConsumerRecoverMsg);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, mndProcessConsumerClearMsg);
|
||||
|
||||
|
@ -75,6 +76,22 @@ int32_t mndInitConsumer(SMnode *pMnode) {
|
|||
|
||||
void mndCleanupConsumer(SMnode *pMnode) {}
|
||||
|
||||
void mndDropConsumerFromSdb(SMnode *pMnode, int64_t consumerId){
|
||||
SMqConsumerClearMsg *pClearMsg = rpcMallocCont(sizeof(SMqConsumerClearMsg));
|
||||
if (pClearMsg == NULL) {
|
||||
mError("consumer:0x%"PRIx64" failed to clear consumer due to out of memory. alloc size:%d", consumerId, (int32_t)sizeof(SMqConsumerClearMsg));
|
||||
return;
|
||||
}
|
||||
|
||||
pClearMsg->consumerId = consumerId;
|
||||
SRpcMsg rpcMsg = {
|
||||
.msgType = TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, .pCont = pClearMsg, .contLen = sizeof(SMqConsumerClearMsg)};
|
||||
|
||||
mInfo("consumer:0x%" PRIx64 " drop from sdb", consumerId);
|
||||
tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
bool mndRebTryStart() {
|
||||
int32_t old = atomic_val_compare_exchange_32(&mqRebInExecCnt, 0, 1);
|
||||
mDebug("tq timer, rebalance counter old val:%d", old);
|
||||
|
@ -105,50 +122,48 @@ void mndRebCntDec() {
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) {
|
||||
SMnode *pMnode = pMsg->info.node;
|
||||
SMqConsumerLostMsg *pLostMsg = pMsg->pCont;
|
||||
SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pLostMsg->consumerId);
|
||||
if (pConsumer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mInfo("process consumer lost msg, consumer:0x%" PRIx64 " status:%d(%s)", pLostMsg->consumerId, pConsumer->status,
|
||||
mndConsumerStatusName(pConsumer->status));
|
||||
|
||||
if (pConsumer->status != MQ_CONSUMER_STATUS__READY) {
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumer->consumerId, pConsumer->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__LOST;
|
||||
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
|
||||
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "lost-csm");
|
||||
if (pTrans == NULL) {
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) {
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
mndTransDrop(pTrans);
|
||||
return 0;
|
||||
FAIL:
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
//static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) {
|
||||
// SMnode *pMnode = pMsg->info.node;
|
||||
// SMqConsumerLostMsg *pLostMsg = pMsg->pCont;
|
||||
// SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pLostMsg->consumerId);
|
||||
// if (pConsumer == NULL) {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// mInfo("process consumer lost msg, consumer:0x%" PRIx64 " status:%d(%s)", pLostMsg->consumerId, pConsumer->status,
|
||||
// mndConsumerStatusName(pConsumer->status));
|
||||
//
|
||||
// if (pConsumer->status != MQ_CONSUMER_STATUS_READY) {
|
||||
// mndReleaseConsumer(pMnode, pConsumer);
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumer->consumerId, pConsumer->cgroup);
|
||||
// pConsumerNew->updateType = CONSUMER_UPDATE_TIMER_LOST;
|
||||
//
|
||||
// mndReleaseConsumer(pMnode, pConsumer);
|
||||
//
|
||||
// STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "lost-csm");
|
||||
// if (pTrans == NULL) {
|
||||
// goto FAIL;
|
||||
// }
|
||||
//
|
||||
// if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) {
|
||||
// goto FAIL;
|
||||
// }
|
||||
//
|
||||
// if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
// goto FAIL;
|
||||
// }
|
||||
//
|
||||
// tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
// mndTransDrop(pTrans);
|
||||
// return 0;
|
||||
//FAIL:
|
||||
// tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
// mndTransDrop(pTrans);
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) {
|
||||
SMnode *pMnode = pMsg->info.node;
|
||||
|
@ -162,14 +177,14 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) {
|
|||
mInfo("receive consumer recover msg, consumer:0x%" PRIx64 " status:%d(%s)", pRecoverMsg->consumerId,
|
||||
pConsumer->status, mndConsumerStatusName(pConsumer->status));
|
||||
|
||||
if (pConsumer->status != MQ_CONSUMER_STATUS__LOST_REBD) {
|
||||
if (pConsumer->status != MQ_CONSUMER_STATUS_LOST) {
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
terrno = TSDB_CODE_MND_CONSUMER_NOT_READY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumer->consumerId, pConsumer->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__RECOVER;
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE_RECOVER;
|
||||
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
|
||||
|
@ -181,13 +196,13 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) {
|
|||
if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL;
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return 0;
|
||||
FAIL:
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
@ -206,13 +221,13 @@ static int32_t mndProcessConsumerClearMsg(SRpcMsg *pMsg) {
|
|||
mInfo("consumer:0x%" PRIx64 " needs to be cleared, status %s", pClearMsg->consumerId,
|
||||
mndConsumerStatusName(pConsumer->status));
|
||||
|
||||
if (pConsumer->status != MQ_CONSUMER_STATUS__LOST_REBD) {
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
return -1;
|
||||
}
|
||||
// if (pConsumer->status != MQ_CONSUMER_STATUS_LOST) {
|
||||
// mndReleaseConsumer(pMnode, pConsumer);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumer->consumerId, pConsumer->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__LOST;
|
||||
// pConsumerNew->updateType = CONSUMER_UPDATE_TIMER_LOST;
|
||||
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
|
||||
|
@ -223,14 +238,14 @@ static int32_t mndProcessConsumerClearMsg(SRpcMsg *pMsg) {
|
|||
if (mndSetConsumerDropLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL;
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return 0;
|
||||
|
||||
FAIL:
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
@ -297,46 +312,14 @@ static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) {
|
|||
int32_t hbStatus = atomic_add_fetch_32(&pConsumer->hbStatus, 1);
|
||||
int32_t status = atomic_load_32(&pConsumer->status);
|
||||
|
||||
mDebug("check for consumer:0x%" PRIx64 " status:%d(%s), sub-time:%" PRId64 ", uptime:%" PRId64 ", hbstatus:%d",
|
||||
pConsumer->consumerId, status, mndConsumerStatusName(status), pConsumer->subscribeTime, pConsumer->upTime,
|
||||
mDebug("check for consumer:0x%" PRIx64 " status:%d(%s), sub-time:%" PRId64 ", createTime:%" PRId64 ", hbstatus:%d",
|
||||
pConsumer->consumerId, status, mndConsumerStatusName(status), pConsumer->subscribeTime, pConsumer->createTime,
|
||||
hbStatus);
|
||||
|
||||
if (status == MQ_CONSUMER_STATUS__READY) {
|
||||
if (hbStatus > MND_CONSUMER_LOST_HB_CNT) {
|
||||
SMqConsumerLostMsg *pLostMsg = rpcMallocCont(sizeof(SMqConsumerLostMsg));
|
||||
if (pLostMsg == NULL) {
|
||||
mError("consumer:0x%"PRIx64" failed to transfer consumer status to lost due to out of memory. alloc size:%d",
|
||||
pConsumer->consumerId, (int32_t)sizeof(SMqConsumerLostMsg));
|
||||
continue;
|
||||
}
|
||||
|
||||
pLostMsg->consumerId = pConsumer->consumerId;
|
||||
SRpcMsg rpcMsg = {
|
||||
.msgType = TDMT_MND_TMQ_CONSUMER_LOST, .pCont = pLostMsg, .contLen = sizeof(SMqConsumerLostMsg)};
|
||||
|
||||
mDebug("consumer:0x%"PRIx64" hb not received beyond threshold %d, set to lost", pConsumer->consumerId,
|
||||
MND_CONSUMER_LOST_HB_CNT);
|
||||
tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
|
||||
}
|
||||
} else if (status == MQ_CONSUMER_STATUS__LOST_REBD) {
|
||||
// if the client is lost longer than one day, clear it. Otherwise, do nothing about the lost consumers.
|
||||
if (hbStatus > MND_CONSUMER_LOST_CLEAR_THRESHOLD) {
|
||||
SMqConsumerClearMsg *pClearMsg = rpcMallocCont(sizeof(SMqConsumerClearMsg));
|
||||
if (pClearMsg == NULL) {
|
||||
mError("consumer:0x%"PRIx64" failed to clear consumer due to out of memory. alloc size:%d",
|
||||
pConsumer->consumerId, (int32_t)sizeof(SMqConsumerClearMsg));
|
||||
continue;
|
||||
}
|
||||
|
||||
pClearMsg->consumerId = pConsumer->consumerId;
|
||||
SRpcMsg rpcMsg = {
|
||||
.msgType = TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, .pCont = pClearMsg, .contLen = sizeof(SMqConsumerClearMsg)};
|
||||
|
||||
mDebug("consumer:0x%" PRIx64 " lost beyond threshold %d, clear it", pConsumer->consumerId,
|
||||
MND_CONSUMER_LOST_CLEAR_THRESHOLD);
|
||||
tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
|
||||
}
|
||||
} else if (status == MQ_CONSUMER_STATUS__LOST) {
|
||||
if (status == MQ_CONSUMER_STATUS_READY) {
|
||||
if (taosArrayGetSize(pConsumer->assignedTopics) == 0) { // unsubscribe or close
|
||||
mndDropConsumerFromSdb(pMnode, pConsumer->consumerId);
|
||||
} else if (hbStatus > MND_CONSUMER_LOST_HB_CNT) {
|
||||
taosRLockLatch(&pConsumer->lock);
|
||||
int32_t topicNum = taosArrayGetSize(pConsumer->currentTopics);
|
||||
for (int32_t i = 0; i < topicNum; i++) {
|
||||
|
@ -347,6 +330,11 @@ static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) {
|
|||
taosArrayPush(pRebSub->removedConsumers, &pConsumer->consumerId);
|
||||
}
|
||||
taosRUnLockLatch(&pConsumer->lock);
|
||||
}
|
||||
} else if (status == MQ_CONSUMER_STATUS_LOST) {
|
||||
if (hbStatus > MND_CONSUMER_LOST_CLEAR_THRESHOLD) { // clear consumer if lost a day
|
||||
mndDropConsumerFromSdb(pMnode, pConsumer->consumerId);
|
||||
}
|
||||
} else { // MQ_CONSUMER_STATUS_REBALANCE
|
||||
taosRLockLatch(&pConsumer->lock);
|
||||
|
||||
|
@ -413,7 +401,7 @@ static int32_t mndProcessMqHbReq(SRpcMsg *pMsg) {
|
|||
|
||||
int32_t status = atomic_load_32(&pConsumer->status);
|
||||
|
||||
if (status == MQ_CONSUMER_STATUS__LOST_REBD) {
|
||||
if (status == MQ_CONSUMER_STATUS_LOST) {
|
||||
mInfo("try to recover consumer:0x%" PRIx64 "", consumerId);
|
||||
SMqConsumerRecoverMsg *pRecoverMsg = rpcMallocCont(sizeof(SMqConsumerRecoverMsg));
|
||||
|
||||
|
@ -475,7 +463,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
|
|||
mError("consumer:0x%" PRIx64 " group:%s not consistent with data in sdb, saved cgroup:%s", consumerId, req.cgroup,
|
||||
pConsumer->cgroup);
|
||||
terrno = TSDB_CODE_MND_CONSUMER_NOT_EXIST;
|
||||
return -1;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
atomic_store_32(&pConsumer->hbStatus, 0);
|
||||
|
@ -483,7 +471,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
|
|||
// 1. check consumer status
|
||||
int32_t status = atomic_load_32(&pConsumer->status);
|
||||
|
||||
if (status == MQ_CONSUMER_STATUS__LOST_REBD) {
|
||||
if (status == MQ_CONSUMER_STATUS_LOST) {
|
||||
mInfo("try to recover consumer:0x%" PRIx64, consumerId);
|
||||
SMqConsumerRecoverMsg *pRecoverMsg = rpcMallocCont(sizeof(SMqConsumerRecoverMsg));
|
||||
|
||||
|
@ -497,10 +485,10 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
|
|||
tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &pRpcMsg);
|
||||
}
|
||||
|
||||
if (status != MQ_CONSUMER_STATUS__READY) {
|
||||
if (status != MQ_CONSUMER_STATUS_READY) {
|
||||
mInfo("consumer:0x%" PRIx64 " not ready, status: %s", consumerId, mndConsumerStatusName(status));
|
||||
terrno = TSDB_CODE_MND_CONSUMER_NOT_READY;
|
||||
return -1;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
int32_t serverEpoch = atomic_load_32(&pConsumer->epoch);
|
||||
|
@ -582,7 +570,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
|
|||
void *buf = rpcMallocCont(tlen);
|
||||
if (buf == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
SMqRspHead* pHead = buf;
|
||||
|
@ -669,6 +657,7 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
char *cgroup = subscribe.cgroup;
|
||||
SMqConsumerObj *pExistedConsumer = NULL;
|
||||
SMqConsumerObj *pConsumerNew = NULL;
|
||||
STrans *pTrans = NULL;
|
||||
|
||||
int32_t code = -1;
|
||||
SArray *pTopicList = subscribe.topicNames;
|
||||
|
@ -676,9 +665,17 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
taosArrayRemoveDuplicate(pTopicList, taosArrayCompareString, freeItem);
|
||||
|
||||
int32_t newTopicNum = taosArrayGetSize(pTopicList);
|
||||
for(int i = 0; i < newTopicNum; i++){
|
||||
int32_t gNum = mndGetGroupNumByTopic(pMnode, (const char*)taosArrayGetP(pTopicList, i));
|
||||
if(gNum >= MND_MAX_GROUP_PER_TOPIC){
|
||||
terrno = TSDB_CODE_TMQ_GROUP_OUT_OF_RANGE;
|
||||
code = terrno;
|
||||
goto _over;
|
||||
}
|
||||
}
|
||||
|
||||
// check topic existence
|
||||
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg, "subscribe");
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg, "subscribe");
|
||||
if (pTrans == NULL) {
|
||||
goto _over;
|
||||
}
|
||||
|
@ -701,8 +698,7 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
pConsumerNew->autoCommitInterval = subscribe.autoCommitInterval;
|
||||
pConsumerNew->resetOffsetCfg = subscribe.resetOffsetCfg;
|
||||
|
||||
// set the update type
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__REBALANCE;
|
||||
// pConsumerNew->updateType = CONSUMER_UPDATE_SUB_MODIFY; // use insert logic
|
||||
taosArrayDestroy(pConsumerNew->assignedTopics);
|
||||
pConsumerNew->assignedTopics = taosArrayDup(pTopicList, topicNameDup);
|
||||
|
||||
|
@ -721,7 +717,7 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
" cgroup:%s, current status:%d(%s), subscribe topic num: %d",
|
||||
consumerId, subscribe.cgroup, status, mndConsumerStatusName(status), newTopicNum);
|
||||
|
||||
if (status != MQ_CONSUMER_STATUS__READY) {
|
||||
if (status != MQ_CONSUMER_STATUS_READY) {
|
||||
terrno = TSDB_CODE_MND_CONSUMER_NOT_READY;
|
||||
goto _over;
|
||||
}
|
||||
|
@ -732,11 +728,11 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
}
|
||||
|
||||
// set the update type
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__REBALANCE;
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE_SUB_MODIFY;
|
||||
taosArrayDestroy(pConsumerNew->assignedTopics);
|
||||
pConsumerNew->assignedTopics = taosArrayDup(pTopicList, topicNameDup);
|
||||
|
||||
int32_t oldTopicNum = (pExistedConsumer->currentTopics) ? taosArrayGetSize(pExistedConsumer->currentTopics) : 0;
|
||||
int32_t oldTopicNum = taosArrayGetSize(pExistedConsumer->currentTopics);
|
||||
|
||||
int32_t i = 0, j = 0;
|
||||
while (i < oldTopicNum || j < newTopicNum) {
|
||||
|
@ -791,10 +787,7 @@ _over:
|
|||
mndReleaseConsumer(pMnode, pExistedConsumer);
|
||||
}
|
||||
|
||||
if (pConsumerNew) {
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
}
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
// TODO: replace with destroy subscribe msg
|
||||
taosArrayDestroyP(subscribe.topicNames, (FDelete)taosMemoryFree);
|
||||
|
@ -894,17 +887,17 @@ CM_DECODE_OVER:
|
|||
}
|
||||
|
||||
static int32_t mndConsumerActionInsert(SSdb *pSdb, SMqConsumerObj *pConsumer) {
|
||||
mDebug("consumer:0x%" PRIx64 " cgroup:%s status:%d(%s) epoch:%d load from sdb, perform insert action",
|
||||
mInfo("consumer:0x%" PRIx64 " sub insert, cgroup:%s status:%d(%s) epoch:%d",
|
||||
pConsumer->consumerId, pConsumer->cgroup, pConsumer->status, mndConsumerStatusName(pConsumer->status),
|
||||
pConsumer->epoch);
|
||||
pConsumer->subscribeTime = pConsumer->upTime;
|
||||
pConsumer->subscribeTime = taosGetTimestampMs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndConsumerActionDelete(SSdb *pSdb, SMqConsumerObj *pConsumer) {
|
||||
mDebug("consumer:0x%" PRIx64 " perform delete action, status:(%d)%s", pConsumer->consumerId, pConsumer->status,
|
||||
mInfo("consumer:0x%" PRIx64 " perform delete action, status:(%d)%s", pConsumer->consumerId, pConsumer->status,
|
||||
mndConsumerStatusName(pConsumer->status));
|
||||
tDeleteSMqConsumerObj(pConsumer);
|
||||
tDeleteSMqConsumerObj(pConsumer, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -913,10 +906,9 @@ static void updateConsumerStatus(SMqConsumerObj *pConsumer) {
|
|||
|
||||
if (taosArrayGetSize(pConsumer->rebNewTopics) == 0 && taosArrayGetSize(pConsumer->rebRemovedTopics) == 0) {
|
||||
if (status == MQ_CONSUMER_STATUS_REBALANCE) {
|
||||
pConsumer->status = MQ_CONSUMER_STATUS__READY;
|
||||
} else if (status == MQ_CONSUMER_STATUS__LOST) {
|
||||
ASSERT(taosArrayGetSize(pConsumer->currentTopics) == 0);
|
||||
pConsumer->status = MQ_CONSUMER_STATUS__LOST_REBD;
|
||||
pConsumer->status = MQ_CONSUMER_STATUS_READY;
|
||||
} else if (status == MQ_CONSUMER_STATUS_READY) {
|
||||
pConsumer->status = MQ_CONSUMER_STATUS_LOST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -930,7 +922,7 @@ static void removeFromNewTopicList(SMqConsumerObj *pConsumer, const char *pTopic
|
|||
taosArrayRemove(pConsumer->rebNewTopics, i);
|
||||
taosMemoryFree(p);
|
||||
|
||||
mDebug("consumer:0x%" PRIx64 " remove new topic:%s in the topic list, remain newTopics:%d", pConsumer->consumerId,
|
||||
mInfo("consumer:0x%" PRIx64 " remove new topic:%s in the topic list, remain newTopics:%d", pConsumer->consumerId,
|
||||
pTopic, (int)taosArrayGetSize(pConsumer->rebNewTopics));
|
||||
break;
|
||||
}
|
||||
|
@ -946,7 +938,7 @@ static void removeFromRemoveTopicList(SMqConsumerObj *pConsumer, const char *pTo
|
|||
taosArrayRemove(pConsumer->rebRemovedTopics, i);
|
||||
taosMemoryFree(p);
|
||||
|
||||
mDebug("consumer:0x%" PRIx64 " remove topic:%s in the removed topic list, remain removedTopics:%d",
|
||||
mInfo("consumer:0x%" PRIx64 " remove topic:%s in the removed topic list, remain removedTopics:%d",
|
||||
pConsumer->consumerId, pTopic, (int)taosArrayGetSize(pConsumer->rebRemovedTopics));
|
||||
break;
|
||||
}
|
||||
|
@ -961,7 +953,7 @@ static void removeFromCurrentTopicList(SMqConsumerObj *pConsumer, const char *pT
|
|||
taosArrayRemove(pConsumer->currentTopics, i);
|
||||
taosMemoryFree(topic);
|
||||
|
||||
mDebug("consumer:0x%" PRIx64 " remove topic:%s in the current topic list, remain currentTopics:%d",
|
||||
mInfo("consumer:0x%" PRIx64 " remove topic:%s in the current topic list, remain currentTopics:%d",
|
||||
pConsumer->consumerId, pTopic, (int)taosArrayGetSize(pConsumer->currentTopics));
|
||||
break;
|
||||
}
|
||||
|
@ -984,47 +976,46 @@ static bool existInCurrentTopicList(const SMqConsumerObj* pConsumer, const char*
|
|||
}
|
||||
|
||||
static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer, SMqConsumerObj *pNewConsumer) {
|
||||
mDebug("consumer:0x%" PRIx64 " perform update action, update type:%d, subscribe-time:%" PRId64 ", uptime:%" PRId64,
|
||||
pOldConsumer->consumerId, pNewConsumer->updateType, pOldConsumer->subscribeTime, pOldConsumer->upTime);
|
||||
mInfo("consumer:0x%" PRIx64 " perform update action, update type:%d, subscribe-time:%" PRId64 ", createTime:%" PRId64,
|
||||
pOldConsumer->consumerId, pNewConsumer->updateType, pOldConsumer->subscribeTime, pOldConsumer->createTime);
|
||||
|
||||
taosWLockLatch(&pOldConsumer->lock);
|
||||
|
||||
if (pNewConsumer->updateType == CONSUMER_UPDATE__REBALANCE) {
|
||||
if (pNewConsumer->updateType == CONSUMER_UPDATE_SUB_MODIFY) {
|
||||
TSWAP(pOldConsumer->rebNewTopics, pNewConsumer->rebNewTopics);
|
||||
TSWAP(pOldConsumer->rebRemovedTopics, pNewConsumer->rebRemovedTopics);
|
||||
TSWAP(pOldConsumer->assignedTopics, pNewConsumer->assignedTopics);
|
||||
|
||||
pOldConsumer->subscribeTime = pNewConsumer->upTime;
|
||||
pOldConsumer->subscribeTime = taosGetTimestampMs();
|
||||
pOldConsumer->status = MQ_CONSUMER_STATUS_REBALANCE;
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE__LOST) {
|
||||
int32_t sz = taosArrayGetSize(pOldConsumer->currentTopics);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
char *topic = taosStrdup(taosArrayGetP(pOldConsumer->currentTopics, i));
|
||||
taosArrayPush(pOldConsumer->rebRemovedTopics, &topic);
|
||||
}
|
||||
|
||||
pOldConsumer->rebalanceTime = pNewConsumer->upTime;
|
||||
|
||||
int32_t prevStatus = pOldConsumer->status;
|
||||
pOldConsumer->status = MQ_CONSUMER_STATUS__LOST;
|
||||
mDebug("consumer:0x%" PRIx64 " state %s -> %s, reb-time:%" PRId64 ", reb-removed-topics:%d",
|
||||
pOldConsumer->consumerId, mndConsumerStatusName(prevStatus), mndConsumerStatusName(pOldConsumer->status),
|
||||
pOldConsumer->rebalanceTime, (int)taosArrayGetSize(pOldConsumer->rebRemovedTopics));
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE__RECOVER) {
|
||||
mInfo("consumer:0x%" PRIx64 " sub update, modify existed consumer",pOldConsumer->consumerId);
|
||||
// } else if (pNewConsumer->updateType == CONSUMER_UPDATE_TIMER_LOST) {
|
||||
// int32_t sz = taosArrayGetSize(pOldConsumer->currentTopics);
|
||||
// for (int32_t i = 0; i < sz; i++) {
|
||||
// char *topic = taosStrdup(taosArrayGetP(pOldConsumer->currentTopics, i));
|
||||
// taosArrayPush(pOldConsumer->rebRemovedTopics, &topic);
|
||||
// }
|
||||
//
|
||||
// int32_t prevStatus = pOldConsumer->status;
|
||||
// pOldConsumer->status = MQ_CONSUMER_STATUS_LOST;
|
||||
// mInfo("consumer:0x%" PRIx64 " timer update, timer lost. state %s -> %s, reb-time:%" PRId64 ", reb-removed-topics:%d",
|
||||
// pOldConsumer->consumerId, mndConsumerStatusName(prevStatus), mndConsumerStatusName(pOldConsumer->status),
|
||||
// pOldConsumer->rebalanceTime, (int)taosArrayGetSize(pOldConsumer->rebRemovedTopics));
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE_RECOVER) {
|
||||
int32_t sz = taosArrayGetSize(pOldConsumer->assignedTopics);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
char *topic = taosStrdup(taosArrayGetP(pOldConsumer->assignedTopics, i));
|
||||
taosArrayPush(pOldConsumer->rebNewTopics, &topic);
|
||||
}
|
||||
|
||||
pOldConsumer->rebalanceTime = pNewConsumer->upTime;
|
||||
pOldConsumer->status = MQ_CONSUMER_STATUS_REBALANCE;
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE__TOUCH) {
|
||||
mInfo("consumer:0x%" PRIx64 " timer update, timer recover",pOldConsumer->consumerId);
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE_REB_MODIFY_NOTOPIC) {
|
||||
atomic_add_fetch_32(&pOldConsumer->epoch, 1);
|
||||
|
||||
pOldConsumer->rebalanceTime = pNewConsumer->upTime;
|
||||
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE__ADD) {
|
||||
pOldConsumer->rebalanceTime = taosGetTimestampMs();
|
||||
mInfo("consumer:0x%" PRIx64 " reb update, only rebalance time", pOldConsumer->consumerId);
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE_REB_MODIFY_TOPIC) {
|
||||
char *pNewTopic = taosStrdup(taosArrayGetP(pNewConsumer->rebNewTopics, 0));
|
||||
|
||||
// check if exist in current topic
|
||||
|
@ -1033,6 +1024,7 @@ static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer,
|
|||
// add to current topic
|
||||
bool existing = existInCurrentTopicList(pOldConsumer, pNewTopic);
|
||||
if (existing) {
|
||||
mError("consumer:0x%" PRIx64 "new topic:%s should not in currentTopics", pOldConsumer->consumerId, pNewTopic);
|
||||
taosMemoryFree(pNewTopic);
|
||||
} else { // added into current topic list
|
||||
taosArrayPush(pOldConsumer->currentTopics, &pNewTopic);
|
||||
|
@ -1044,17 +1036,17 @@ static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer,
|
|||
updateConsumerStatus(pOldConsumer);
|
||||
|
||||
// the re-balance is triggered when the new consumer is launched.
|
||||
pOldConsumer->rebalanceTime = pNewConsumer->upTime;
|
||||
pOldConsumer->rebalanceTime = taosGetTimestampMs();
|
||||
|
||||
atomic_add_fetch_32(&pOldConsumer->epoch, 1);
|
||||
mDebug("consumer:0x%" PRIx64 " state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64
|
||||
mInfo("consumer:0x%" PRIx64 " reb update add, state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64
|
||||
", current topics:%d, newTopics:%d, removeTopics:%d",
|
||||
pOldConsumer->consumerId, status, mndConsumerStatusName(status), pOldConsumer->status,
|
||||
mndConsumerStatusName(pOldConsumer->status), pOldConsumer->epoch, pOldConsumer->rebalanceTime,
|
||||
(int)taosArrayGetSize(pOldConsumer->currentTopics), (int)taosArrayGetSize(pOldConsumer->rebNewTopics),
|
||||
(int)taosArrayGetSize(pOldConsumer->rebRemovedTopics));
|
||||
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE__REMOVE) {
|
||||
} else if (pNewConsumer->updateType == CONSUMER_UPDATE_REB_MODIFY_REMOVE) {
|
||||
char *removedTopic = taosArrayGetP(pNewConsumer->rebRemovedTopics, 0);
|
||||
|
||||
// remove from removed topic
|
||||
|
@ -1067,10 +1059,10 @@ static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer,
|
|||
int32_t status = pOldConsumer->status;
|
||||
updateConsumerStatus(pOldConsumer);
|
||||
|
||||
pOldConsumer->rebalanceTime = pNewConsumer->upTime;
|
||||
pOldConsumer->rebalanceTime = taosGetTimestampMs();
|
||||
atomic_add_fetch_32(&pOldConsumer->epoch, 1);
|
||||
|
||||
mDebug("consumer:0x%" PRIx64 " state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64
|
||||
mInfo("consumer:0x%" PRIx64 " reb update remove, state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64
|
||||
", current topics:%d, newTopics:%d, removeTopics:%d",
|
||||
pOldConsumer->consumerId, status, mndConsumerStatusName(status), pOldConsumer->status,
|
||||
mndConsumerStatusName(pOldConsumer->status), pOldConsumer->epoch, pOldConsumer->rebalanceTime,
|
||||
|
@ -1133,8 +1125,12 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *
|
|||
int32_t cols = 0;
|
||||
|
||||
// consumer id
|
||||
char consumerIdHex[32] = {0};
|
||||
sprintf(varDataVal(consumerIdHex), "0x%"PRIx64, pConsumer->consumerId);
|
||||
varDataSetLen(consumerIdHex, strlen(varDataVal(consumerIdHex)));
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->consumerId, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)consumerIdHex, false);
|
||||
|
||||
// consumer group
|
||||
char cgroup[TSDB_CGROUP_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
|
@ -1175,7 +1171,7 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *
|
|||
|
||||
// up time
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->upTime, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->createTime, false);
|
||||
|
||||
// subscribe time
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
|
@ -1190,7 +1186,7 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *
|
|||
tFormatOffset(buf, TSDB_OFFSET_LEN, &pVal);
|
||||
|
||||
char parasStr[64 + TSDB_OFFSET_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
sprintf(varDataVal(parasStr), "tbname:%d,commit:%d,interval:%d,reset:%s", pConsumer->withTbName, pConsumer->autoCommit, pConsumer->autoCommitInterval, buf);
|
||||
sprintf(varDataVal(parasStr), "tbname:%d,commit:%d,interval:%dms,reset:%s", pConsumer->withTbName, pConsumer->autoCommit, pConsumer->autoCommitInterval, buf);
|
||||
varDataSetLen(parasStr, strlen(varDataVal(parasStr)));
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
|
@ -1216,10 +1212,9 @@ static void mndCancelGetNextConsumer(SMnode *pMnode, void *pIter) {
|
|||
|
||||
static const char *mndConsumerStatusName(int status) {
|
||||
switch (status) {
|
||||
case MQ_CONSUMER_STATUS__READY:
|
||||
case MQ_CONSUMER_STATUS_READY:
|
||||
return "ready";
|
||||
case MQ_CONSUMER_STATUS__LOST:
|
||||
case MQ_CONSUMER_STATUS__LOST_REBD:
|
||||
case MQ_CONSUMER_STATUS_LOST:
|
||||
return "lost";
|
||||
case MQ_CONSUMER_STATUS_REBALANCE:
|
||||
return "rebalancing";
|
||||
|
|
|
@ -30,11 +30,11 @@ 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->igExpired) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->trigger) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->fillHistory) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->triggerParam) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->watermark) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->conf.igExpired) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->conf.trigger) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->conf.fillHistory) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->conf.triggerParam) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->conf.watermark) < 0) return -1;
|
||||
|
||||
if (tEncodeI64(pEncoder, pObj->sourceDbUid) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->targetDbUid) < 0) return -1;
|
||||
|
@ -100,11 +100,11 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj, int32_t sver) {
|
|||
if (tDecodeI64(pDecoder, &pObj->uid) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->status) < 0) return -1;
|
||||
|
||||
if (tDecodeI8(pDecoder, &pObj->igExpired) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->trigger) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->fillHistory) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->triggerParam) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->watermark) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->conf.igExpired) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->conf.trigger) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->conf.fillHistory) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->conf.triggerParam) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->conf.watermark) < 0) return -1;
|
||||
|
||||
if (tDecodeI64(pDecoder, &pObj->sourceDbUid) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->targetDbUid) < 0) return -1;
|
||||
|
@ -160,18 +160,10 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj, int32_t sver) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tFreeStreamObj(SStreamObj *pStream) {
|
||||
taosMemoryFree(pStream->sql);
|
||||
taosMemoryFree(pStream->ast);
|
||||
taosMemoryFree(pStream->physicalPlan);
|
||||
|
||||
if (pStream->outputSchema.nCols) {
|
||||
taosMemoryFree(pStream->outputSchema.pSchema);
|
||||
}
|
||||
|
||||
int32_t sz = taosArrayGetSize(pStream->tasks);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pStream->tasks, i);
|
||||
static void* freeStreamTasks(SArray* pTaskLevel) {
|
||||
int32_t numOfLevel = taosArrayGetSize(pTaskLevel);
|
||||
for (int32_t i = 0; i < numOfLevel; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pTaskLevel, i);
|
||||
int32_t taskSz = taosArrayGetSize(pLevel);
|
||||
for (int32_t j = 0; j < taskSz; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, j);
|
||||
|
@ -181,7 +173,20 @@ void tFreeStreamObj(SStreamObj *pStream) {
|
|||
taosArrayDestroy(pLevel);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pStream->tasks);
|
||||
return taosArrayDestroy(pTaskLevel);
|
||||
}
|
||||
|
||||
void tFreeStreamObj(SStreamObj *pStream) {
|
||||
taosMemoryFree(pStream->sql);
|
||||
taosMemoryFree(pStream->ast);
|
||||
taosMemoryFree(pStream->physicalPlan);
|
||||
|
||||
if (pStream->outputSchema.nCols || pStream->outputSchema.pSchema) {
|
||||
taosMemoryFree(pStream->outputSchema.pSchema);
|
||||
}
|
||||
|
||||
pStream->tasks = freeStreamTasks(pStream->tasks);
|
||||
pStream->pHTasksList = freeStreamTasks(pStream->pHTasksList);
|
||||
|
||||
// tagSchema.pSchema
|
||||
if (pStream->tagSchema.nCols > 0) {
|
||||
|
@ -224,7 +229,7 @@ void *tDecodeSMqVgEp(const void *buf, SMqVgEp *pVgEp, int8_t sver) {
|
|||
return (void *)buf;
|
||||
}
|
||||
|
||||
SMqConsumerObj *tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_LEN]) {
|
||||
SMqConsumerObj *tNewSMqConsumerObj(int64_t consumerId, char* cgroup) {
|
||||
SMqConsumerObj *pConsumer = taosMemoryCalloc(1, sizeof(SMqConsumerObj));
|
||||
if (pConsumer == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
@ -255,16 +260,20 @@ SMqConsumerObj *tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_L
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pConsumer->upTime = taosGetTimestampMs();
|
||||
pConsumer->createTime = taosGetTimestampMs();
|
||||
|
||||
return pConsumer;
|
||||
}
|
||||
|
||||
void tDeleteSMqConsumerObj(SMqConsumerObj *pConsumer) {
|
||||
void tDeleteSMqConsumerObj(SMqConsumerObj *pConsumer, bool delete) {
|
||||
if(pConsumer == NULL) return;
|
||||
taosArrayDestroyP(pConsumer->currentTopics, (FDelete)taosMemoryFree);
|
||||
taosArrayDestroyP(pConsumer->rebNewTopics, (FDelete)taosMemoryFree);
|
||||
taosArrayDestroyP(pConsumer->rebRemovedTopics, (FDelete)taosMemoryFree);
|
||||
taosArrayDestroyP(pConsumer->assignedTopics, (FDelete)taosMemoryFree);
|
||||
if(delete){
|
||||
taosMemoryFree(pConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tEncodeSMqConsumerObj(void **buf, const SMqConsumerObj *pConsumer) {
|
||||
|
@ -279,7 +288,7 @@ int32_t tEncodeSMqConsumerObj(void **buf, const SMqConsumerObj *pConsumer) {
|
|||
|
||||
tlen += taosEncodeFixedI32(buf, pConsumer->pid);
|
||||
tlen += taosEncodeSEpSet(buf, &pConsumer->ep);
|
||||
tlen += taosEncodeFixedI64(buf, pConsumer->upTime);
|
||||
tlen += taosEncodeFixedI64(buf, pConsumer->createTime);
|
||||
tlen += taosEncodeFixedI64(buf, pConsumer->subscribeTime);
|
||||
tlen += taosEncodeFixedI64(buf, pConsumer->rebalanceTime);
|
||||
|
||||
|
@ -349,7 +358,7 @@ void *tDecodeSMqConsumerObj(const void *buf, SMqConsumerObj *pConsumer, int8_t s
|
|||
|
||||
buf = taosDecodeFixedI32(buf, &pConsumer->pid);
|
||||
buf = taosDecodeSEpSet(buf, &pConsumer->ep);
|
||||
buf = taosDecodeFixedI64(buf, &pConsumer->upTime);
|
||||
buf = taosDecodeFixedI64(buf, &pConsumer->createTime);
|
||||
buf = taosDecodeFixedI64(buf, &pConsumer->subscribeTime);
|
||||
buf = taosDecodeFixedI64(buf, &pConsumer->rebalanceTime);
|
||||
|
||||
|
|
|
@ -367,10 +367,10 @@ void dumpStream(SSdb *pSdb, SJson *json) {
|
|||
tjsonAddStringToObject(item, "smaId", i642str(pObj->smaId));
|
||||
tjsonAddStringToObject(item, "uid", i642str(pObj->uid));
|
||||
tjsonAddStringToObject(item, "status", i642str(pObj->status));
|
||||
tjsonAddStringToObject(item, "igExpired", i642str(pObj->igExpired));
|
||||
tjsonAddStringToObject(item, "trigger", i642str(pObj->trigger));
|
||||
tjsonAddStringToObject(item, "triggerParam", i642str(pObj->triggerParam));
|
||||
tjsonAddStringToObject(item, "watermark", i642str(pObj->watermark));
|
||||
tjsonAddStringToObject(item, "igExpired", i642str(pObj->conf.igExpired));
|
||||
tjsonAddStringToObject(item, "trigger", i642str(pObj->conf.trigger));
|
||||
tjsonAddStringToObject(item, "triggerParam", i642str(pObj->conf.triggerParam));
|
||||
tjsonAddStringToObject(item, "watermark", i642str(pObj->conf.watermark));
|
||||
tjsonAddStringToObject(item, "sourceDbUid", i642str(pObj->sourceDbUid));
|
||||
tjsonAddStringToObject(item, "targetDbUid", i642str(pObj->targetDbUid));
|
||||
tjsonAddStringToObject(item, "sourceDb", mndGetDbStr(pObj->sourceDb));
|
||||
|
|
|
@ -542,32 +542,32 @@ int32_t mndRetrieveTagIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, i
|
|||
STR_TO_VARSTR(n3, (char *)tNameGetTableName(&stbName));
|
||||
|
||||
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)n1, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)n1, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)n2, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)n2, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)n3, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)n3, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)&invalid, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&invalid, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)&pIdx->createdTime, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pIdx->createdTime, false);
|
||||
|
||||
char col[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
STR_TO_VARSTR(col, (char *)pIdx->colName);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)col, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)col, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
|
||||
char tag[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
STR_TO_VARSTR(tag, (char *)"tag_index");
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)tag, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)tag, false);
|
||||
|
||||
numOfRows++;
|
||||
sdbRelease(pSdb, pIdx);
|
||||
|
|
|
@ -233,7 +233,6 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) {
|
|||
}
|
||||
|
||||
code = -1;
|
||||
|
||||
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());
|
||||
|
@ -271,6 +270,7 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) {
|
|||
}
|
||||
}
|
||||
|
||||
_CONNECT:
|
||||
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) {
|
||||
|
@ -842,7 +842,7 @@ static int32_t packQueriesIntoBlock(SShowObj* pShow, SConnObj* pConn, SSDataBloc
|
|||
}
|
||||
varDataLen(subStatus) = strlen(&subStatus[VARSTR_HEADER_SIZE]);
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, curRowIndex, subStatus, false);
|
||||
colDataSetVal(pColInfo, curRowIndex, subStatus, (varDataLen(subStatus) == 0) ? true : false);
|
||||
|
||||
char sql[TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
STR_TO_VARSTR(sql, pQuery->sql);
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
#include "tname.h"
|
||||
#include "tuuid.h"
|
||||
|
||||
#define SINK_NODE_LEVEL (0)
|
||||
extern bool tsDeployOnSnode;
|
||||
|
||||
static int32_t mndAddSinkTaskToStream(SStreamObj* pStream, SMnode* pMnode, int32_t vgId, SVgObj* pVgroup);
|
||||
static int32_t mndAddSinkTaskToStream(SStreamObj* pStream, SArray* pTaskList, SMnode* pMnode, int32_t vgId,
|
||||
SVgObj* pVgroup, int32_t fillHistory);
|
||||
static void setFixedDownstreamEpInfo(SStreamTask* pDstTask, const SStreamTask* pTask);
|
||||
|
||||
int32_t mndConvertRsmaTask(char** pDst, int32_t* pDstLen, const char* ast, int64_t uid, int8_t triggerType,
|
||||
|
@ -100,18 +102,16 @@ int32_t mndSetSinkTaskInfo(SStreamObj* pStream, SStreamTask* pTask) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define SINK_NODE_LEVEL (0)
|
||||
|
||||
int32_t mndAddDispatcherForInnerTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask) {
|
||||
int32_t mndAddDispatcherForInternalTask(SMnode* pMnode, SStreamObj* pStream, SArray* pSinkNodeList,
|
||||
SStreamTask* pTask) {
|
||||
bool isShuffle = false;
|
||||
|
||||
if (pStream->fixedSinkVgId == 0) {
|
||||
SDbObj* pDb = mndAcquireDb(pMnode, pStream->targetDb);
|
||||
if (pDb != NULL && pDb->cfg.numOfVgroups > 1) {
|
||||
|
||||
isShuffle = true;
|
||||
pTask->outputType = TASK_OUTPUT__SHUFFLE_DISPATCH;
|
||||
pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
pTask->msgInfo.msgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
if (mndExtractDbInfo(pMnode, pDb, &pTask->shuffleDispatcher.dbInfo, NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -120,7 +120,6 @@ int32_t mndAddDispatcherForInnerTask(SMnode* pMnode, SStreamObj* pStream, SStrea
|
|||
sdbRelease(pMnode->pSdb, pDb);
|
||||
}
|
||||
|
||||
SArray* pSinkNodeList = taosArrayGetP(pStream->tasks, SINK_NODE_LEVEL);
|
||||
int32_t numOfSinkNodes = taosArrayGetSize(pSinkNodeList);
|
||||
|
||||
if (isShuffle) {
|
||||
|
@ -133,7 +132,7 @@ int32_t mndAddDispatcherForInnerTask(SMnode* pMnode, SStreamObj* pStream, SStrea
|
|||
|
||||
for (int32_t j = 0; j < numOfSinkNodes; j++) {
|
||||
SStreamTask* pSinkTask = taosArrayGetP(pSinkNodeList, j);
|
||||
if (pSinkTask->nodeId == pVgInfo->vgId) {
|
||||
if (pSinkTask->info.nodeId == pVgInfo->vgId) {
|
||||
pVgInfo->taskId = pSinkTask->id.taskId;
|
||||
break;
|
||||
}
|
||||
|
@ -150,11 +149,11 @@ int32_t mndAddDispatcherForInnerTask(SMnode* pMnode, SStreamObj* pStream, SStrea
|
|||
int32_t mndAssignStreamTaskToVgroup(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, const SVgObj* pVgroup) {
|
||||
int32_t msgLen;
|
||||
|
||||
pTask->nodeId = pVgroup->vgId;
|
||||
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
|
||||
pTask->info.nodeId = pVgroup->vgId;
|
||||
pTask->info.epSet = mndGetVgroupEpset(pMnode, pVgroup);
|
||||
|
||||
plan->execNode.nodeId = pTask->nodeId;
|
||||
plan->execNode.epSet = pTask->epSet;
|
||||
plan->execNode.nodeId = pTask->info.nodeId;
|
||||
plan->execNode.epSet = pTask->info.epSet;
|
||||
if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
|
@ -171,14 +170,15 @@ SSnodeObj* mndSchedFetchOneSnode(SMnode* pMnode) {
|
|||
return pObj;
|
||||
}
|
||||
|
||||
int32_t mndAssignTaskToSnode(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, const SSnodeObj* pSnode) {
|
||||
int32_t mndAssignStreamTaskToSnode(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, const SSnodeObj* pSnode) {
|
||||
int32_t msgLen;
|
||||
|
||||
pTask->nodeId = SNODE_HANDLE;
|
||||
pTask->epSet = mndAcquireEpFromSnode(pMnode, pSnode);
|
||||
pTask->info.nodeId = SNODE_HANDLE;
|
||||
pTask->info.epSet = mndAcquireEpFromSnode(pMnode, pSnode);
|
||||
|
||||
plan->execNode.nodeId = SNODE_HANDLE;
|
||||
plan->execNode.epSet = pTask->epSet;
|
||||
plan->execNode.epSet = pTask->info.epSet;
|
||||
mDebug("s-task:0x%x set the agg task to snode:%d", pTask->id.taskId, SNODE_HANDLE);
|
||||
|
||||
if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
|
@ -187,6 +187,7 @@ int32_t mndAssignTaskToSnode(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// todo random choose a node to do compute
|
||||
SVgObj* mndSchedFetchOneVg(SMnode* pMnode, int64_t dbUid) {
|
||||
void* pIter = NULL;
|
||||
SVgObj* pVgroup = NULL;
|
||||
|
@ -203,7 +204,7 @@ SVgObj* mndSchedFetchOneVg(SMnode* pMnode, int64_t dbUid) {
|
|||
}
|
||||
|
||||
// create sink node for each vgroup.
|
||||
int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) {
|
||||
int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SArray* pTaskList, SStreamObj* pStream, int32_t fillHistory) {
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
void* pIter = NULL;
|
||||
|
||||
|
@ -219,43 +220,45 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
continue;
|
||||
}
|
||||
|
||||
mndAddSinkTaskToStream(pStream, pMnode, pVgroup->vgId, pVgroup);
|
||||
mndAddSinkTaskToStream(pStream, pTaskList, pMnode, pVgroup->vgId, pVgroup, fillHistory);
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndAddSinkTaskToStream(SStreamObj* pStream, SMnode* pMnode, int32_t vgId, SVgObj* pVgroup) {
|
||||
SArray* pTaskList = taosArrayGetP(pStream->tasks, SINK_NODE_LEVEL);
|
||||
|
||||
SStreamTask* pTask = tNewStreamTask(pStream->uid, TASK_LEVEL__SINK, pStream->fillHistory, 0, pTaskList);
|
||||
int32_t mndAddSinkTaskToStream(SStreamObj* pStream, SArray* pTaskList, SMnode* pMnode, int32_t vgId, SVgObj* pVgroup,
|
||||
int32_t fillHistory) {
|
||||
SStreamTask* pTask = tNewStreamTask(pStream->uid, TASK_LEVEL__SINK, fillHistory, 0, pTaskList);
|
||||
if (pTask == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pTask->nodeId = vgId;
|
||||
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
|
||||
pTask->info.nodeId = vgId;
|
||||
pTask->info.epSet = mndGetVgroupEpset(pMnode, pVgroup);
|
||||
mndSetSinkTaskInfo(pStream, pTask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndScheduleFillHistoryStreamTask(SMnode* pMnode, SStreamObj* pStream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t addSourceStreamTask(SMnode* pMnode, SVgObj* pVgroup, SArray* pTaskList, SStreamObj* pStream,
|
||||
SSubplan* plan, uint64_t uid, int8_t taskLevel, int8_t fillHistory,
|
||||
bool hasExtraSink) {
|
||||
SStreamTask* pTask = tNewStreamTask(uid, taskLevel, fillHistory, pStream->triggerParam, pTaskList);
|
||||
static int32_t addSourceStreamTask(SMnode* pMnode, SVgObj* pVgroup, SArray* pTaskList, SArray* pSinkTaskList,
|
||||
SStreamObj* pStream, SSubplan* plan, uint64_t uid, int8_t fillHistory,
|
||||
bool hasExtraSink, int64_t firstWindowSkey) {
|
||||
SStreamTask* pTask = tNewStreamTask(uid, TASK_LEVEL__SOURCE, fillHistory, pStream->conf.triggerParam, pTaskList);
|
||||
if (pTask == NULL) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
// todo set the correct ts, which should be last key of queried table.
|
||||
STimeWindow* pWindow = &pTask->dataRange.window;
|
||||
|
||||
pWindow->skey = INT64_MIN;
|
||||
pWindow->ekey = firstWindowSkey - 1;
|
||||
mDebug("add source task 0x%x window:%" PRId64 " - %" PRId64, pTask->id.taskId, pWindow->skey, pWindow->ekey);
|
||||
|
||||
// sink or dispatch
|
||||
if (hasExtraSink) {
|
||||
mndAddDispatcherForInnerTask(pMnode, pStream, pTask);
|
||||
mndAddDispatcherForInternalTask(pMnode, pStream, pSinkTaskList, pTask);
|
||||
} else {
|
||||
mndSetSinkTaskInfo(pStream, pTask);
|
||||
}
|
||||
|
@ -274,9 +277,9 @@ static SStreamChildEpInfo* createStreamTaskEpInfo(SStreamTask* pTask) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pEpInfo->childId = pTask->selfChildId;
|
||||
pEpInfo->epSet = pTask->epSet;
|
||||
pEpInfo->nodeId = pTask->nodeId;
|
||||
pEpInfo->childId = pTask->info.selfChildId;
|
||||
pEpInfo->epSet = pTask->info.epSet;
|
||||
pEpInfo->nodeId = pTask->info.nodeId;
|
||||
pEpInfo->taskId = pTask->id.taskId;
|
||||
|
||||
return pEpInfo;
|
||||
|
@ -285,182 +288,61 @@ static SStreamChildEpInfo* createStreamTaskEpInfo(SStreamTask* pTask) {
|
|||
void setFixedDownstreamEpInfo(SStreamTask* pDstTask, const SStreamTask* pTask) {
|
||||
STaskDispatcherFixedEp* pDispatcher = &pDstTask->fixedEpDispatcher;
|
||||
pDispatcher->taskId = pTask->id.taskId;
|
||||
pDispatcher->nodeId = pTask->nodeId;
|
||||
pDispatcher->epSet = pTask->epSet;
|
||||
pDispatcher->nodeId = pTask->info.nodeId;
|
||||
pDispatcher->epSet = pTask->info.epSet;
|
||||
|
||||
pDstTask->outputType = TASK_OUTPUT__FIXED_DISPATCH;
|
||||
pDstTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
pDstTask->msgInfo.msgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
}
|
||||
|
||||
int32_t appendToUpstream(SStreamTask* pTask, SStreamTask* pUpstream) {
|
||||
int32_t setEpToDownstreamTask(SStreamTask* pTask, SStreamTask* pDownstream) {
|
||||
SStreamChildEpInfo* pEpInfo = createStreamTaskEpInfo(pTask);
|
||||
if (pEpInfo == NULL) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(pUpstream->childEpInfo == NULL) {
|
||||
pUpstream->childEpInfo = taosArrayInit(4, POINTER_BYTES);
|
||||
if (pDownstream->pUpstreamEpInfoList == NULL) {
|
||||
pDownstream->pUpstreamEpInfoList = taosArrayInit(4, POINTER_BYTES);
|
||||
}
|
||||
|
||||
taosArrayPush(pUpstream->childEpInfo, &pEpInfo);
|
||||
taosArrayPush(pDownstream->pUpstreamEpInfoList, &pEpInfo);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
||||
static SArray* addNewTaskList(SArray* pTasksList) {
|
||||
SArray* pTaskList = taosArrayInit(0, POINTER_BYTES);
|
||||
taosArrayPush(pTasksList, &pTaskList);
|
||||
return pTaskList;
|
||||
}
|
||||
|
||||
// set the history task id
|
||||
static void setHTasksId(SArray* pTaskList, const SArray* pHTaskList) {
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pTaskList); ++i) {
|
||||
SStreamTask** pStreamTask = taosArrayGet(pTaskList, i);
|
||||
SStreamTask** pHTask = taosArrayGet(pHTaskList, i);
|
||||
|
||||
(*pStreamTask)->historyTaskId.taskId = (*pHTask)->id.taskId;
|
||||
(*pStreamTask)->historyTaskId.streamId = (*pHTask)->id.streamId;
|
||||
|
||||
(*pHTask)->streamTaskId.taskId = (*pStreamTask)->id.taskId;
|
||||
(*pHTask)->streamTaskId.streamId = (*pStreamTask)->id.streamId;
|
||||
|
||||
mDebug("s-task:0x%x related history task:0x%x, level:%d", (*pStreamTask)->id.taskId, (*pHTask)->id.taskId,
|
||||
(*pHTask)->info.taskLevel);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t addSourceTasksForOneLevelStream(SMnode* pMnode, const SQueryPlan* pPlan, SStreamObj* pStream,
|
||||
bool hasExtraSink, int64_t nextWindowSkey) {
|
||||
// create exec stream task, since only one level, the exec task is also the source task
|
||||
SArray* pTaskList = addNewTaskList(pStream->tasks);
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
|
||||
SQueryPlan* pPlan = qStringToQueryPlan(pStream->physicalPlan);
|
||||
if (pPlan == NULL) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
SArray* pHTaskList = NULL;
|
||||
if (pStream->conf.fillHistory) {
|
||||
pHTaskList = addNewTaskList(pStream->pHTasksList);
|
||||
}
|
||||
|
||||
int32_t planTotLevel = LIST_LENGTH(pPlan->pSubplans);
|
||||
pStream->tasks = taosArrayInit(planTotLevel, POINTER_BYTES);
|
||||
|
||||
bool hasExtraSink = false;
|
||||
bool externalTargetDB = strcmp(pStream->sourceDb, pStream->targetDb) != 0;
|
||||
SDbObj* pDbObj = mndAcquireDb(pMnode, pStream->targetDb);
|
||||
if (pDbObj == NULL) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool multiTarget = (pDbObj->cfg.numOfVgroups > 1);
|
||||
sdbRelease(pSdb, pDbObj);
|
||||
|
||||
if (planTotLevel == 2 || externalTargetDB || multiTarget || pStream->fixedSinkVgId) {
|
||||
SArray* taskOneLevel = taosArrayInit(0, POINTER_BYTES);
|
||||
taosArrayPush(pStream->tasks, &taskOneLevel);
|
||||
|
||||
// add extra sink
|
||||
hasExtraSink = true;
|
||||
if (pStream->fixedSinkVgId == 0) {
|
||||
if (mndAddShuffleSinkTasksToStream(pMnode, pStream) < 0) {
|
||||
// TODO free
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (mndAddSinkTaskToStream(pStream, pMnode, pStream->fixedSinkVgId, &pStream->fixedSinkVg) < 0) {
|
||||
// TODO free
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pStream->totalLevel = planTotLevel + hasExtraSink;
|
||||
|
||||
if (planTotLevel > 1) {
|
||||
SStreamTask* pInnerTask;
|
||||
// inner level
|
||||
{
|
||||
SArray* taskInnerLevel = taosArrayInit(0, POINTER_BYTES);
|
||||
taosArrayPush(pStream->tasks, &taskInnerLevel);
|
||||
|
||||
SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0);
|
||||
SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0);
|
||||
if (plan->subplanType != SUBPLAN_TYPE_MERGE) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pInnerTask = tNewStreamTask(pStream->uid, TASK_LEVEL__AGG, pStream->fillHistory, pStream->triggerParam, taskInnerLevel);
|
||||
if (pInnerTask == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// dispatch
|
||||
if (mndAddDispatcherForInnerTask(pMnode, pStream, pInnerTask) < 0) {
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tsDeployOnSnode) {
|
||||
SSnodeObj* pSnode = mndSchedFetchOneSnode(pMnode);
|
||||
if (pSnode == NULL) {
|
||||
SVgObj* pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
|
||||
if (mndAssignStreamTaskToVgroup(pMnode, pInnerTask, plan, pVgroup) < 0) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
} else {
|
||||
if (mndAssignTaskToSnode(pMnode, pInnerTask, plan, pSnode) < 0) {
|
||||
sdbRelease(pSdb, pSnode);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SVgObj* pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
|
||||
if (mndAssignStreamTaskToVgroup(pMnode, pInnerTask, plan, pVgroup) < 0) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
}
|
||||
|
||||
// source level
|
||||
SArray* taskSourceLevel = taosArrayInit(0, POINTER_BYTES);
|
||||
taosArrayPush(pStream->tasks, &taskSourceLevel);
|
||||
|
||||
SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 1);
|
||||
SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0);
|
||||
if (plan->subplanType != SUBPLAN_TYPE_SCAN) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* pIter = NULL;
|
||||
while (1) {
|
||||
SVgObj* pVgroup;
|
||||
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
|
||||
if (pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mndVgroupInDb(pVgroup, pStream->sourceDbUid)) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
continue;
|
||||
}
|
||||
|
||||
SStreamTask* pTask = tNewStreamTask(pStream->uid, TASK_LEVEL__SOURCE, pStream->fillHistory, 0, taskSourceLevel);
|
||||
if (pTask == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// all the source tasks dispatch result to a single agg node.
|
||||
setFixedDownstreamEpInfo(pTask, pInnerTask);
|
||||
|
||||
if (mndAssignStreamTaskToVgroup(pMnode, pTask, plan, pVgroup) < 0) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t code = appendToUpstream(pTask, pInnerTask);
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
terrno = code;
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (planTotLevel == 1) {
|
||||
// create exec stream task, since only one level, the exec task is also the source task
|
||||
SArray* pTaskList = taosArrayInit(0, POINTER_BYTES);
|
||||
taosArrayPush(pStream->tasks, &pTaskList);
|
||||
|
||||
SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0);
|
||||
if (LIST_LENGTH(inner->pNodeList) != 1) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
|
@ -487,20 +369,296 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
}
|
||||
|
||||
// new stream task
|
||||
int32_t code = addSourceStreamTask(pMnode, pVgroup, pTaskList, pStream, plan, pStream->uid, TASK_LEVEL__SOURCE, pStream->fillHistory, hasExtraSink);
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
|
||||
SArray** pSinkTaskList = taosArrayGet(pStream->tasks, SINK_NODE_LEVEL);
|
||||
int32_t code = addSourceStreamTask(pMnode, pVgroup, pTaskList, *pSinkTaskList, pStream, plan, pStream->uid, 0,
|
||||
hasExtraSink, nextWindowSkey);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pStream->conf.fillHistory) {
|
||||
SArray** pHSinkTaskList = taosArrayGet(pStream->pHTasksList, SINK_NODE_LEVEL);
|
||||
code = addSourceStreamTask(pMnode, pVgroup, pHTaskList, *pHSinkTaskList, pStream, plan, pStream->hTaskUid,
|
||||
1, hasExtraSink, nextWindowSkey);
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pStream->conf.fillHistory) {
|
||||
setHTasksId(pTaskList, pHTaskList);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t doAddSourceTask(SArray* pTaskList, int8_t fillHistory, int64_t uid, SStreamTask* pDownstreamTask,
|
||||
SMnode* pMnode, SSubplan* pPlan, SVgObj* pVgroup, int64_t nextWindowSkey) {
|
||||
SStreamTask* pTask = tNewStreamTask(uid, TASK_LEVEL__SOURCE, fillHistory, 0, pTaskList);
|
||||
if (pTask == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// todo set the correct ts, which should be last key of queried table.
|
||||
STimeWindow* pWindow = &pTask->dataRange.window;
|
||||
pWindow->skey = INT64_MIN;
|
||||
pWindow->ekey = nextWindowSkey - 1;
|
||||
|
||||
mDebug("s-task:0x%x level:%d set time window:%" PRId64 " - %" PRId64, pTask->id.taskId, pTask->info.taskLevel,
|
||||
pWindow->skey, pWindow->ekey);
|
||||
|
||||
// all the source tasks dispatch result to a single agg node.
|
||||
setFixedDownstreamEpInfo(pTask, pDownstreamTask);
|
||||
if (mndAssignStreamTaskToVgroup(pMnode, pTask, pPlan, pVgroup) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setEpToDownstreamTask(pTask, pDownstreamTask);
|
||||
}
|
||||
|
||||
static int32_t doAddAggTask(uint64_t uid, SArray* pTaskList, SArray* pSinkNodeList, SMnode* pMnode, SStreamObj* pStream,
|
||||
int32_t fillHistory, SStreamTask** pAggTask) {
|
||||
*pAggTask = tNewStreamTask(uid, TASK_LEVEL__AGG, fillHistory, pStream->conf.triggerParam, pTaskList);
|
||||
if (*pAggTask == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// dispatch
|
||||
if (mndAddDispatcherForInternalTask(pMnode, pStream, pSinkNodeList, *pAggTask) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
qDestroyQueryPlan(pPlan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t addAggTask(SStreamObj* pStream, SMnode* pMnode, SQueryPlan* pPlan, SStreamTask** pAggTask,
|
||||
SStreamTask** pHAggTask) {
|
||||
SArray* pAggTaskList = addNewTaskList(pStream->tasks);
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
|
||||
SNodeListNode* pInnerNode = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0);
|
||||
SSubplan* plan = (SSubplan*)nodesListGetNode(pInnerNode->pNodeList, 0);
|
||||
if (plan->subplanType != SUBPLAN_TYPE_MERGE) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pAggTask = NULL;
|
||||
SArray* pSinkNodeList = taosArrayGetP(pStream->tasks, SINK_NODE_LEVEL);
|
||||
|
||||
int32_t code = doAddAggTask(pStream->uid, pAggTaskList, pSinkNodeList, pMnode, pStream, 0, pAggTask);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SVgObj* pVgroup = NULL;
|
||||
SSnodeObj* pSnode = NULL;
|
||||
|
||||
if (tsDeployOnSnode) {
|
||||
pSnode = mndSchedFetchOneSnode(pMnode);
|
||||
if (pSnode == NULL) {
|
||||
pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
|
||||
}
|
||||
} else {
|
||||
pVgroup = mndSchedFetchOneVg(pMnode, pStream->sourceDbUid);
|
||||
}
|
||||
|
||||
if (pSnode != NULL) {
|
||||
code = mndAssignStreamTaskToSnode(pMnode, *pAggTask, plan, pSnode);
|
||||
} else {
|
||||
code = mndAssignStreamTaskToVgroup(pMnode, *pAggTask, plan, pVgroup);
|
||||
}
|
||||
|
||||
if (pStream->conf.fillHistory) {
|
||||
SArray* pHAggTaskList = addNewTaskList(pStream->pHTasksList);
|
||||
SArray* pHSinkNodeList = taosArrayGetP(pStream->pHTasksList, SINK_NODE_LEVEL);
|
||||
|
||||
*pHAggTask = NULL;
|
||||
code = doAddAggTask(pStream->hTaskUid, pHAggTaskList, pHSinkNodeList, pMnode, pStream, pStream->conf.fillHistory,
|
||||
pHAggTask);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
if (pSnode != NULL) {
|
||||
sdbRelease(pSdb, pSnode);
|
||||
} else {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pSnode != NULL) {
|
||||
code = mndAssignStreamTaskToSnode(pMnode, *pHAggTask, plan, pSnode);
|
||||
} else {
|
||||
code = mndAssignStreamTaskToVgroup(pMnode, *pHAggTask, plan, pVgroup);
|
||||
}
|
||||
|
||||
setHTasksId(pAggTaskList, pHAggTaskList);
|
||||
}
|
||||
|
||||
if (pSnode != NULL) {
|
||||
sdbRelease(pSdb, pSnode);
|
||||
} else {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t addSourceTasksForMultiLevelStream(SMnode* pMnode, SQueryPlan* pPlan, SStreamObj* pStream,
|
||||
SStreamTask* pDownstreamTask, SStreamTask* pHDownstreamTask, int64_t nextWindowSkey) {
|
||||
SArray* pSourceTaskList = addNewTaskList(pStream->tasks);
|
||||
|
||||
SArray* pHSourceTaskList = NULL;
|
||||
if (pStream->conf.fillHistory) {
|
||||
pHSourceTaskList = addNewTaskList(pStream->pHTasksList);
|
||||
}
|
||||
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 1);
|
||||
SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0);
|
||||
if (plan->subplanType != SUBPLAN_TYPE_SCAN) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* pIter = NULL;
|
||||
while (1) {
|
||||
SVgObj* pVgroup;
|
||||
pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup);
|
||||
if (pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mndVgroupInDb(pVgroup, pStream->sourceDbUid)) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t code =
|
||||
doAddSourceTask(pSourceTaskList, 0, pStream->uid, pDownstreamTask, pMnode, plan, pVgroup, nextWindowSkey);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
terrno = code;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pStream->conf.fillHistory) {
|
||||
code = doAddSourceTask(pHSourceTaskList, 1, pStream->hTaskUid, pHDownstreamTask, pMnode, plan, pVgroup,
|
||||
nextWindowSkey);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
|
||||
if (pStream->conf.fillHistory) {
|
||||
setHTasksId(pSourceTaskList, pHSourceTaskList);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t addSinkTasks(SArray* pTasksList, SMnode* pMnode, SStreamObj* pStream, SArray** pCreatedTaskList,
|
||||
int32_t fillHistory) {
|
||||
SArray* pSinkTaskList = addNewTaskList(pTasksList);
|
||||
if (pStream->fixedSinkVgId == 0) {
|
||||
if (mndAddShuffleSinkTasksToStream(pMnode, pSinkTaskList, pStream, fillHistory) < 0) {
|
||||
// TODO free
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (mndAddSinkTaskToStream(pStream, pSinkTaskList, pMnode, pStream->fixedSinkVgId, &pStream->fixedSinkVg,
|
||||
fillHistory) < 0) {
|
||||
// TODO free
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*pCreatedTaskList = pSinkTaskList;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t doScheduleStream(SStreamObj* pStream, SMnode* pMnode, SQueryPlan* pPlan, int64_t nextWindowSkey) {
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
int32_t numOfPlanLevel = LIST_LENGTH(pPlan->pSubplans);
|
||||
|
||||
bool hasExtraSink = false;
|
||||
bool externalTargetDB = strcmp(pStream->sourceDb, pStream->targetDb) != 0;
|
||||
SDbObj* pDbObj = mndAcquireDb(pMnode, pStream->targetDb);
|
||||
if (pDbObj == NULL) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool multiTarget = (pDbObj->cfg.numOfVgroups > 1);
|
||||
sdbRelease(pSdb, pDbObj);
|
||||
|
||||
pStream->tasks = taosArrayInit(numOfPlanLevel + 1, POINTER_BYTES);
|
||||
pStream->pHTasksList = taosArrayInit(numOfPlanLevel + 1, POINTER_BYTES);
|
||||
|
||||
if (numOfPlanLevel == 2 || externalTargetDB || multiTarget || pStream->fixedSinkVgId) {
|
||||
// add extra sink
|
||||
hasExtraSink = true;
|
||||
|
||||
SArray* pSinkTaskList = NULL;
|
||||
int32_t code = addSinkTasks(pStream->tasks, pMnode, pStream, &pSinkTaskList, 0);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// check for fill history
|
||||
if (pStream->conf.fillHistory) {
|
||||
SArray* pHSinkTaskList = NULL;
|
||||
code = addSinkTasks(pStream->pHTasksList, pMnode, pStream, &pHSinkTaskList, 1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
setHTasksId(pSinkTaskList, pHSinkTaskList);
|
||||
}
|
||||
}
|
||||
|
||||
pStream->totalLevel = numOfPlanLevel + hasExtraSink;
|
||||
|
||||
if (numOfPlanLevel > 1) {
|
||||
SStreamTask* pAggTask = NULL;
|
||||
SStreamTask* pHAggTask = NULL;
|
||||
|
||||
int32_t code = addAggTask(pStream, pMnode, pPlan, &pAggTask, &pHAggTask);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// source level
|
||||
return addSourceTasksForMultiLevelStream(pMnode, pPlan, pStream, pAggTask, pHAggTask, nextWindowSkey);
|
||||
} else if (numOfPlanLevel == 1) {
|
||||
return addSourceTasksForOneLevelStream(pMnode, pPlan, pStream, hasExtraSink, nextWindowSkey);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream, int64_t nextWindowSkey) {
|
||||
SQueryPlan* pPlan = qStringToQueryPlan(pStream->physicalPlan);
|
||||
if (pPlan == NULL) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t code = doScheduleStream(pStream, pMnode, pPlan, nextWindowSkey);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscribeObj* pSub) {
|
||||
SSdb* pSdb = pMnode->pSdb;
|
||||
SVgObj* pVgroup = NULL;
|
||||
|
@ -513,8 +671,8 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib
|
|||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
}else if(pTopic->subType == TOPIC_SUB_TYPE__TABLE && pTopic->ast != NULL){
|
||||
SNode *pAst = NULL;
|
||||
} else if (pTopic->subType == TOPIC_SUB_TYPE__TABLE && pTopic->ast != NULL) {
|
||||
SNode* pAst = NULL;
|
||||
if (nodesStringToNode(pTopic->ast, &pAst) != 0) {
|
||||
mError("topic:%s, failed to create since %s", pTopic->name, terrstr());
|
||||
return -1;
|
||||
|
@ -529,7 +687,7 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib
|
|||
nodesDestroyNode(pAst);
|
||||
}
|
||||
|
||||
if(pPlan){
|
||||
if (pPlan) {
|
||||
int32_t levelNum = LIST_LENGTH(pPlan->pSubplans);
|
||||
if (levelNum != 1) {
|
||||
qDestroyQueryPlan(pPlan);
|
||||
|
|
|
@ -555,20 +555,20 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
|
|||
streamObj.version = 1;
|
||||
streamObj.sql = taosStrdup(pCreate->sql);
|
||||
streamObj.smaId = smaObj.uid;
|
||||
streamObj.watermark = pCreate->watermark;
|
||||
streamObj.conf.watermark = pCreate->watermark;
|
||||
streamObj.deleteMark = pCreate->deleteMark;
|
||||
streamObj.fillHistory = STREAM_FILL_HISTORY_ON;
|
||||
streamObj.trigger = STREAM_TRIGGER_WINDOW_CLOSE;
|
||||
streamObj.triggerParam = pCreate->maxDelay;
|
||||
streamObj.conf.fillHistory = STREAM_FILL_HISTORY_ON;
|
||||
streamObj.conf.trigger = STREAM_TRIGGER_WINDOW_CLOSE;
|
||||
streamObj.conf.triggerParam = pCreate->maxDelay;
|
||||
streamObj.ast = taosStrdup(smaObj.ast);
|
||||
|
||||
// check the maxDelay
|
||||
if (streamObj.triggerParam < TSDB_MIN_ROLLUP_MAX_DELAY) {
|
||||
if (streamObj.conf.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;
|
||||
streamObj.conf.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 (streamObj.conf.triggerParam > TSDB_MAX_ROLLUP_MAX_DELAY) {
|
||||
streamObj.conf.triggerParam = TSDB_MAX_ROLLUP_MAX_DELAY;
|
||||
}
|
||||
|
||||
if (mndAllocSmaVgroup(pMnode, pDb, &streamObj.fixedSinkVg) != 0) {
|
||||
|
@ -597,8 +597,8 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
|
|||
.pAstRoot = pAst,
|
||||
.topicQuery = false,
|
||||
.streamQuery = true,
|
||||
.triggerType = streamObj.trigger,
|
||||
.watermark = streamObj.watermark,
|
||||
.triggerType = streamObj.conf.trigger,
|
||||
.watermark = streamObj.conf.watermark,
|
||||
.deleteMark = streamObj.deleteMark,
|
||||
};
|
||||
|
||||
|
@ -633,7 +633,7 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
|
|||
if (mndSetCreateSmaVgroupCommitLogs(pMnode, pTrans, &streamObj.fixedSinkVg) != 0) goto _OVER;
|
||||
if (mndSetUpdateSmaStbCommitLogs(pMnode, pTrans, pStb) != 0) goto _OVER;
|
||||
if (mndSetCreateSmaVgroupRedoActions(pMnode, pTrans, pDb, &streamObj.fixedSinkVg, &smaObj) != 0) goto _OVER;
|
||||
if (mndScheduleStream(pMnode, &streamObj) != 0) goto _OVER;
|
||||
if (mndScheduleStream(pMnode, &streamObj, 1685959190000) != 0) goto _OVER;
|
||||
if (mndPersistStream(pMnode, pTrans, &streamObj) != 0) goto _OVER;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
|
||||
|
||||
|
@ -1278,13 +1278,13 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
|
|||
STR_TO_VARSTR(col, (char *)"");
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)col, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)col, false);
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
|
||||
char tag[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
STR_TO_VARSTR(tag, (char *)"sma_index");
|
||||
colDataAppend(pColInfo, numOfRows, (const char *)tag, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)tag, false);
|
||||
|
||||
numOfRows++;
|
||||
sdbRelease(pSdb, pSma);
|
||||
|
|
|
@ -244,7 +244,7 @@ static void mndShowStreamStatus(char *dst, SStreamObj *pStream) {
|
|||
}
|
||||
|
||||
static void mndShowStreamTrigger(char *dst, SStreamObj *pStream) {
|
||||
int8_t trigger = pStream->trigger;
|
||||
int8_t trigger = pStream->conf.trigger;
|
||||
if (trigger == STREAM_TRIGGER_AT_ONCE) {
|
||||
strcpy(dst, "at once");
|
||||
} else if (trigger == STREAM_TRIGGER_WINDOW_CLOSE) {
|
||||
|
@ -304,13 +304,18 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj,
|
|||
pObj->smaId = 0;
|
||||
|
||||
pObj->uid = mndGenerateUid(pObj->name, strlen(pObj->name));
|
||||
|
||||
char p[TSDB_STREAM_FNAME_LEN + 32] = {0};
|
||||
snprintf(p, tListLen(p), "%s_%s", pObj->name, "fillhistory");
|
||||
|
||||
pObj->hTaskUid = mndGenerateUid(pObj->name, strlen(pObj->name));
|
||||
pObj->status = 0;
|
||||
|
||||
pObj->igExpired = pCreate->igExpired;
|
||||
pObj->trigger = pCreate->triggerType;
|
||||
pObj->triggerParam = pCreate->maxDelay;
|
||||
pObj->watermark = pCreate->watermark;
|
||||
pObj->fillHistory = pCreate->fillHistory;
|
||||
pObj->conf.igExpired = pCreate->igExpired;
|
||||
pObj->conf.trigger = pCreate->triggerType;
|
||||
pObj->conf.triggerParam = pCreate->maxDelay;
|
||||
pObj->conf.watermark = pCreate->watermark;
|
||||
pObj->conf.fillHistory = pCreate->fillHistory;
|
||||
pObj->deleteMark = pCreate->deleteMark;
|
||||
pObj->igCheckUpdate = pCreate->igUpdate;
|
||||
|
||||
|
@ -392,9 +397,9 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj,
|
|||
.pAstRoot = pAst,
|
||||
.topicQuery = false,
|
||||
.streamQuery = true,
|
||||
.triggerType = pObj->trigger == STREAM_TRIGGER_MAX_DELAY ? STREAM_TRIGGER_WINDOW_CLOSE : pObj->trigger,
|
||||
.watermark = pObj->watermark,
|
||||
.igExpired = pObj->igExpired,
|
||||
.triggerType = pObj->conf.trigger == STREAM_TRIGGER_MAX_DELAY ? STREAM_TRIGGER_WINDOW_CLOSE : pObj->conf.trigger,
|
||||
.watermark = pObj->conf.watermark,
|
||||
.igExpired = pObj->conf.igExpired,
|
||||
.deleteMark = pObj->deleteMark,
|
||||
.igCheckUpdate = pObj->igCheckUpdate,
|
||||
};
|
||||
|
@ -433,30 +438,37 @@ int32_t mndPersistTaskDeployReq(STrans *pTrans, const SStreamTask *pTask) {
|
|||
SEncoder encoder;
|
||||
tEncoderInit(&encoder, NULL, 0);
|
||||
tEncodeStreamTask(&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(pTask->nodeId);
|
||||
|
||||
((SMsgHead *)buf)->vgId = htonl(pTask->info.nodeId);
|
||||
|
||||
void *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
||||
tEncoderInit(&encoder, abuf, size);
|
||||
|
||||
tEncodeStreamTask(&encoder, pTask);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
STransAction action = {0};
|
||||
action.mTraceId = pTrans->mTraceId;
|
||||
memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
|
||||
memcpy(&action.epSet, &pTask->info.epSet, sizeof(SEpSet));
|
||||
action.pCont = buf;
|
||||
action.contLen = tlen;
|
||||
action.msgType = TDMT_STREAM_TASK_DEPLOY;
|
||||
|
||||
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
|
||||
taosMemoryFree(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -464,14 +476,33 @@ int32_t mndPersistStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStrea
|
|||
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++) {
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pLevel);
|
||||
for (int32_t j = 0; j < numOfTasks; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, j);
|
||||
if (mndPersistTaskDeployReq(pTrans, pTask) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// persistent stream task for already stored ts data
|
||||
if (pStream->conf.fillHistory) {
|
||||
level = taosArrayGetSize(pStream->pHTasksList);
|
||||
|
||||
for (int32_t i = 0; i < level; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pStream->pHTasksList, i);
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pLevel);
|
||||
for (int32_t j = 0; j < numOfTasks; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, j);
|
||||
if (mndPersistTaskDeployReq(pTrans, pTask) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -479,11 +510,13 @@ int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
|
|||
if (mndPersistStreamTasks(pMnode, pTrans, pStream) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
(void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
return 0;
|
||||
}
|
||||
|
@ -495,6 +528,7 @@ int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStr
|
|||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
|
||||
return 0;
|
||||
}
|
||||
|
@ -608,16 +642,17 @@ _OVER:
|
|||
|
||||
static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) {
|
||||
// vnode
|
||||
/*if (pTask->nodeId > 0) {*/
|
||||
/*if (pTask->info.nodeId > 0) {*/
|
||||
SVDropStreamTaskReq *pReq = taosMemoryCalloc(1, sizeof(SVDropStreamTaskReq));
|
||||
if (pReq == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pReq->head.vgId = htonl(pTask->nodeId);
|
||||
|
||||
pReq->head.vgId = htonl(pTask->info.nodeId);
|
||||
pReq->taskId = pTask->id.taskId;
|
||||
STransAction action = {0};
|
||||
memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
|
||||
memcpy(&action.epSet, &pTask->info.epSet, sizeof(SEpSet));
|
||||
action.pCont = pReq;
|
||||
action.contLen = sizeof(SVDropStreamTaskReq);
|
||||
action.msgType = TDMT_STREAM_TASK_DROP;
|
||||
|
@ -737,6 +772,7 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
|
|||
mError("stream:%s, failed to create since %s", createStreamReq.name, terrstr());
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
mInfo("trans:%d, used to create stream:%s", pTrans->id, createStreamReq.name);
|
||||
|
||||
mndTransSetDbName(pTrans, createStreamReq.sourceDB, streamObj.targetDb);
|
||||
|
@ -753,7 +789,7 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
|
|||
}
|
||||
|
||||
// schedule stream task for stream obj
|
||||
if (mndScheduleStream(pMnode, &streamObj) < 0) {
|
||||
if (mndScheduleStream(pMnode, &streamObj, createStreamReq.lastTs) < 0) {
|
||||
mError("stream:%s, failed to schedule since %s", createStreamReq.name, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
goto _OVER;
|
||||
|
@ -865,7 +901,7 @@ static int32_t mndBuildStreamCheckpointSourceReq(void **pBuf, int32_t *pLen, con
|
|||
SMStreamDoCheckpointMsg *pMsg) {
|
||||
SStreamCheckpointSourceReq req = {0};
|
||||
req.checkpointId = pMsg->checkpointId;
|
||||
req.nodeId = pTask->nodeId;
|
||||
req.nodeId = pTask->info.nodeId;
|
||||
req.expireTime = -1;
|
||||
req.streamId = pTask->id.streamId;
|
||||
req.taskId = pTask->id.taskId;
|
||||
|
@ -894,7 +930,7 @@ static int32_t mndBuildStreamCheckpointSourceReq(void **pBuf, int32_t *pLen, con
|
|||
|
||||
SMsgHead *pMsgHead = (SMsgHead *)buf;
|
||||
pMsgHead->contLen = htonl(tlen);
|
||||
pMsgHead->vgId = htonl(pTask->nodeId);
|
||||
pMsgHead->vgId = htonl(pTask->info.nodeId);
|
||||
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
|
@ -966,12 +1002,12 @@ static int32_t mndProcessStreamCheckpointTrans(SMnode *pMnode, SStreamObj *pStre
|
|||
for (int32_t i = 0; i < totLevel; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pStream->tasks, i);
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, 0);
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
int32_t sz = taosArrayGetSize(pLevel);
|
||||
for (int32_t j = 0; j < sz; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, j);
|
||||
/*A(pTask->nodeId > 0);*/
|
||||
SVgObj *pVgObj = mndAcquireVgroup(pMnode, pTask->nodeId);
|
||||
/*A(pTask->info.nodeId > 0);*/
|
||||
SVgObj *pVgObj = mndAcquireVgroup(pMnode, pTask->info.nodeId);
|
||||
if (pVgObj == NULL) {
|
||||
taosRUnLockLatch(&pStream->lock);
|
||||
mndTransDrop(pTrans);
|
||||
|
@ -1067,8 +1103,6 @@ static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq) {
|
|||
static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
SStreamObj *pStream = NULL;
|
||||
/*SDbObj *pDb = NULL;*/
|
||||
/*SUserObj *pUser = NULL;*/
|
||||
|
||||
SMDropStreamReq dropReq = {0};
|
||||
if (tDeserializeSMDropStreamReq(pReq->pCont, pReq->contLen, &dropReq) < 0) {
|
||||
|
@ -1259,7 +1293,7 @@ static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB
|
|||
}
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->watermark, false);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->conf.watermark, false);
|
||||
|
||||
char trigger[20 + VARSTR_HEADER_SIZE] = {0};
|
||||
char trigger2[20] = {0};
|
||||
|
@ -1289,12 +1323,16 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock
|
|||
|
||||
while (numOfRows < rowsCapacity) {
|
||||
pShow->pIter = sdbFetch(pSdb, SDB_STREAM, pShow->pIter, (void **)&pStream);
|
||||
if (pShow->pIter == NULL) break;
|
||||
if (pShow->pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
// lock
|
||||
taosRLockLatch(&pStream->lock);
|
||||
|
||||
// count task num
|
||||
int32_t sz = taosArrayGetSize(pStream->tasks);
|
||||
|
||||
int32_t count = 0;
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pStream->tasks, i);
|
||||
|
@ -1304,10 +1342,12 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock
|
|||
if (numOfRows + count > rowsCapacity) {
|
||||
blockDataEnsureCapacity(pBlock, numOfRows + count);
|
||||
}
|
||||
|
||||
// add row for each task
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SArray *pLevel = taosArrayGetP(pStream->tasks, i);
|
||||
int32_t levelCnt = taosArrayGetSize(pLevel);
|
||||
|
||||
for (int32_t j = 0; j < levelCnt; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pLevel, j);
|
||||
|
||||
|
@ -1317,18 +1357,25 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock
|
|||
// stream name
|
||||
char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName));
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)streamName, false);
|
||||
|
||||
// task id
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&pTask->id.taskId, false);
|
||||
|
||||
char idstr[128] = {0};
|
||||
int32_t len = tintToHex(pTask->id.taskId, &idstr[4]);
|
||||
idstr[2] = '0';
|
||||
idstr[3] = 'x';
|
||||
varDataSetLen(idstr, len + 2);
|
||||
colDataSetVal(pColInfo, numOfRows, idstr, false);
|
||||
|
||||
// node type
|
||||
char nodeType[20 + VARSTR_HEADER_SIZE] = {0};
|
||||
varDataSetLen(nodeType, 5);
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
if (pTask->nodeId > 0) {
|
||||
if (pTask->info.nodeId > 0) {
|
||||
memcpy(varDataVal(nodeType), "vnode", 5);
|
||||
} else {
|
||||
memcpy(varDataVal(nodeType), "snode", 5);
|
||||
|
@ -1337,30 +1384,50 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock
|
|||
|
||||
// node id
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
int64_t nodeId = TMAX(pTask->nodeId, 0);
|
||||
int64_t nodeId = TMAX(pTask->info.nodeId, 0);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&nodeId, false);
|
||||
|
||||
// level
|
||||
char level[20 + VARSTR_HEADER_SIZE] = {0};
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
memcpy(varDataVal(level), "source", 6);
|
||||
varDataSetLen(level, 6);
|
||||
} else if (pTask->taskLevel == TASK_LEVEL__AGG) {
|
||||
} else if (pTask->info.taskLevel == TASK_LEVEL__AGG) {
|
||||
memcpy(varDataVal(level), "agg", 3);
|
||||
varDataSetLen(level, 3);
|
||||
} else if (pTask->taskLevel == TASK_LEVEL__SINK) {
|
||||
} else if (pTask->info.taskLevel == TASK_LEVEL__SINK) {
|
||||
memcpy(varDataVal(level), "sink", 4);
|
||||
varDataSetLen(level, 4);
|
||||
} else if (pTask->taskLevel == TASK_LEVEL__SINK) {
|
||||
}
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&level, false);
|
||||
|
||||
// status
|
||||
char status[20 + VARSTR_HEADER_SIZE] = {0};
|
||||
char status2[20] = {0};
|
||||
strcpy(status, "normal");
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status));
|
||||
int8_t taskStatus = atomic_load_8(&pTask->status.taskStatus);
|
||||
if (taskStatus == TASK_STATUS__NORMAL) {
|
||||
memcpy(varDataVal(status), "normal", 6);
|
||||
varDataSetLen(status, 6);
|
||||
} else if (taskStatus == TASK_STATUS__DROPPING) {
|
||||
memcpy(varDataVal(status), "dropping", 8);
|
||||
varDataSetLen(status, 8);
|
||||
} else if (taskStatus == TASK_STATUS__FAIL) {
|
||||
memcpy(varDataVal(status), "fail", 4);
|
||||
varDataSetLen(status, 4);
|
||||
} else if (taskStatus == TASK_STATUS__STOP) {
|
||||
memcpy(varDataVal(status), "stop", 4);
|
||||
varDataSetLen(status, 4);
|
||||
} else if (taskStatus == TASK_STATUS__SCAN_HISTORY) {
|
||||
memcpy(varDataVal(status), "history", 7);
|
||||
varDataSetLen(status, 7);
|
||||
} else if (taskStatus == TASK_STATUS__HALT) {
|
||||
memcpy(varDataVal(status), "halt", 4);
|
||||
varDataSetLen(status, 4);
|
||||
} else if (taskStatus == TASK_STATUS__PAUSE) {
|
||||
memcpy(varDataVal(status), "pause", 5);
|
||||
varDataSetLen(status, 5);
|
||||
}
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)&status, false);
|
||||
|
||||
|
@ -1389,10 +1456,10 @@ static int32_t mndPauseStreamTask(STrans *pTrans, SStreamTask *pTask) {
|
|||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pReq->head.vgId = htonl(pTask->nodeId);
|
||||
pReq->head.vgId = htonl(pTask->info.nodeId);
|
||||
pReq->taskId = pTask->id.taskId;
|
||||
STransAction action = {0};
|
||||
memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
|
||||
memcpy(&action.epSet, &pTask->info.epSet, sizeof(SEpSet));
|
||||
action.pCont = pReq;
|
||||
action.contLen = sizeof(SVPauseStreamTaskReq);
|
||||
action.msgType = TDMT_STREAM_TASK_PAUSE;
|
||||
|
@ -1403,21 +1470,36 @@ static int32_t mndPauseStreamTask(STrans *pTrans, SStreamTask *pTask) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndPauseAllStreamTasks(STrans *pTrans, SStreamObj *pStream) {
|
||||
int32_t size = taosArrayGetSize(pStream->tasks);
|
||||
int32_t mndPauseAllStreamTaskImpl(STrans *pTrans, SArray* tasks) {
|
||||
int32_t size = taosArrayGetSize(tasks);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
SArray *pTasks = taosArrayGetP(pStream->tasks, i);
|
||||
SArray *pTasks = taosArrayGetP(tasks, i);
|
||||
int32_t sz = taosArrayGetSize(pTasks);
|
||||
for (int32_t j = 0; j < sz; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pTasks, j);
|
||||
if (pTask->taskLevel != TASK_LEVEL__SINK && mndPauseStreamTask(pTrans, pTask) < 0) {
|
||||
if (pTask->info.taskLevel != TASK_LEVEL__SINK && mndPauseStreamTask(pTrans, pTask) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (atomic_load_8(&pTask->status.taskStatus) != TASK_STATUS__PAUSE) {
|
||||
atomic_store_8(&pTask->status.keepTaskStatus, pTask->status.taskStatus);
|
||||
atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__PAUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndPauseAllStreamTasks(STrans *pTrans, SStreamObj *pStream) {
|
||||
int32_t code = mndPauseAllStreamTaskImpl(pTrans, pStream->tasks);
|
||||
if (code != 0) {
|
||||
return code;
|
||||
}
|
||||
// pStream->pHTasksList is null
|
||||
// code = mndPauseAllStreamTaskImpl(pTrans, pStream->pHTasksList);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mndPersistStreamLog(STrans *pTrans, const SStreamObj *pStream, int8_t status) {
|
||||
SStreamObj streamObj = {0};
|
||||
memcpy(streamObj.name, pStream->name, TSDB_STREAM_FNAME_LEN);
|
||||
|
@ -1457,6 +1539,10 @@ static int32_t mndProcessPauseStreamReq(SRpcMsg *pReq) {
|
|||
}
|
||||
}
|
||||
|
||||
if (pStream->status == STREAM_STATUS__PAUSE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
|
||||
sdbRelease(pMnode->pSdb, pStream);
|
||||
return -1;
|
||||
|
@ -1511,11 +1597,11 @@ static int32_t mndResumeStreamTask(STrans *pTrans, SStreamTask *pTask, int8_t ig
|
|||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pReq->head.vgId = htonl(pTask->nodeId);
|
||||
pReq->head.vgId = htonl(pTask->info.nodeId);
|
||||
pReq->taskId = pTask->id.taskId;
|
||||
pReq->igUntreated = igUntreated;
|
||||
STransAction action = {0};
|
||||
memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
|
||||
memcpy(&action.epSet, &pTask->info.epSet, sizeof(SEpSet));
|
||||
action.pCont = pReq;
|
||||
action.contLen = sizeof(SVResumeStreamTaskReq);
|
||||
action.msgType = TDMT_STREAM_TASK_RESUME;
|
||||
|
@ -1533,11 +1619,16 @@ int32_t mndResumeAllStreamTasks(STrans *pTrans, SStreamObj *pStream, int8_t igUn
|
|||
int32_t sz = taosArrayGetSize(pTasks);
|
||||
for (int32_t j = 0; j < sz; j++) {
|
||||
SStreamTask *pTask = taosArrayGetP(pTasks, j);
|
||||
if (pTask->taskLevel != TASK_LEVEL__SINK && mndResumeStreamTask(pTrans, pTask, igUntreated) < 0) {
|
||||
if (pTask->info.taskLevel != TASK_LEVEL__SINK && mndResumeStreamTask(pTrans, pTask, igUntreated) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__PAUSE) {
|
||||
atomic_store_8(&pTask->status.taskStatus, pTask->status.keepTaskStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
// pStream->pHTasksList is null
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1564,6 +1655,10 @@ static int32_t mndProcessResumeStreamReq(SRpcMsg *pReq) {
|
|||
}
|
||||
}
|
||||
|
||||
if (pStream->status != STREAM_STATUS__PAUSE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
|
||||
sdbRelease(pMnode->pSdb, pStream);
|
||||
return -1;
|
||||
|
|
|
@ -160,10 +160,10 @@ static int32_t mndBuildSubChangeReq(void **pBuf, int32_t *pLen, SMqSubscribeObj
|
|||
|
||||
static int32_t mndPersistSubChangeVgReq(SMnode *pMnode, STrans *pTrans, SMqSubscribeObj *pSub,
|
||||
const SMqRebOutputVg *pRebVg, SSubplan* pPlan) {
|
||||
// if (pRebVg->oldConsumerId == pRebVg->newConsumerId) {
|
||||
// terrno = TSDB_CODE_MND_INVALID_SUB_OPTION;
|
||||
// return -1;
|
||||
// }
|
||||
if (pRebVg->oldConsumerId == pRebVg->newConsumerId) {
|
||||
terrno = TSDB_CODE_MND_INVALID_SUB_OPTION;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buf;
|
||||
int32_t tlen;
|
||||
|
@ -175,7 +175,7 @@ static int32_t mndPersistSubChangeVgReq(SMnode *pMnode, STrans *pTrans, SMqSubsc
|
|||
SVgObj *pVgObj = mndAcquireVgroup(pMnode, vgId);
|
||||
if (pVgObj == NULL) {
|
||||
taosMemoryFree(buf);
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -296,17 +296,17 @@ static void addUnassignedVgroups(SMqRebOutputObj *pOutput, SHashObj *pHash) {
|
|||
}
|
||||
}
|
||||
|
||||
static void putNoTransferToOutput(SMqRebOutputObj *pOutput, SMqConsumerEp *pConsumerEp){
|
||||
for(int i = 0; i < taosArrayGetSize(pConsumerEp->vgs); i++){
|
||||
SMqVgEp *pVgEp = (SMqVgEp *)taosArrayGetP(pConsumerEp->vgs, i);
|
||||
SMqRebOutputVg outputVg = {
|
||||
.oldConsumerId = pConsumerEp->consumerId,
|
||||
.newConsumerId = pConsumerEp->consumerId,
|
||||
.pVgEp = pVgEp,
|
||||
};
|
||||
taosArrayPush(pOutput->rebVgs, &outputVg);
|
||||
}
|
||||
}
|
||||
//static void putNoTransferToOutput(SMqRebOutputObj *pOutput, SMqConsumerEp *pConsumerEp){
|
||||
// for(int i = 0; i < taosArrayGetSize(pConsumerEp->vgs); i++){
|
||||
// SMqVgEp *pVgEp = (SMqVgEp *)taosArrayGetP(pConsumerEp->vgs, i);
|
||||
// SMqRebOutputVg outputVg = {
|
||||
// .oldConsumerId = pConsumerEp->consumerId,
|
||||
// .newConsumerId = pConsumerEp->consumerId,
|
||||
// .pVgEp = pVgEp,
|
||||
// };
|
||||
// taosArrayPush(pOutput->rebVgs, &outputVg);
|
||||
// }
|
||||
//}
|
||||
|
||||
static void transferVgroupsForConsumers(SMqRebOutputObj *pOutput, SHashObj *pHash, int32_t minVgCnt,
|
||||
int32_t imbConsumerNum) {
|
||||
|
@ -357,7 +357,7 @@ static void transferVgroupsForConsumers(SMqRebOutputObj *pOutput, SHashObj *pHas
|
|||
}
|
||||
}
|
||||
}
|
||||
putNoTransferToOutput(pOutput, pConsumerEp);
|
||||
// putNoTransferToOutput(pOutput, pConsumerEp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,40 +468,51 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR
|
|||
}
|
||||
}
|
||||
|
||||
if(taosHashGetSize(pOutput->pSub->consumerHash) == 0) { // if all consumer is removed
|
||||
// if(taosHashGetSize(pOutput->pSub->consumerHash) == 0) { // if all consumer is removed
|
||||
SMqSubscribeObj *pSub = mndAcquireSubscribeByKey(pMnode, pInput->pRebInfo->key); // put all offset rows
|
||||
if (pSub) {
|
||||
taosRLockLatch(&pSub->lock);
|
||||
bool init = false;
|
||||
if (pOutput->pSub->offsetRows == NULL) {
|
||||
pOutput->pSub->offsetRows = taosArrayInit(4, sizeof(OffsetRows));
|
||||
init = true;
|
||||
}
|
||||
pIter = NULL;
|
||||
while (1) {
|
||||
pIter = taosHashIterate(pSub->consumerHash, pIter);
|
||||
if (pIter == NULL) break;
|
||||
SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter;
|
||||
if (init) {
|
||||
taosArrayAddAll(pOutput->pSub->offsetRows, pConsumerEp->offsetRows);
|
||||
// mDebug("pSub->offsetRows is init");
|
||||
} else {
|
||||
SMqConsumerEp *pConsumerEpNew = taosHashGet(pOutput->pSub->consumerHash, &pConsumerEp->consumerId, sizeof(int64_t));
|
||||
|
||||
for (int j = 0; j < taosArrayGetSize(pConsumerEp->offsetRows); j++) {
|
||||
OffsetRows *d1 = taosArrayGet(pConsumerEp->offsetRows, j);
|
||||
bool jump = false;
|
||||
for (int i = 0; pConsumerEpNew && i < taosArrayGetSize(pConsumerEpNew->vgs); i++){
|
||||
SMqVgEp *pVgEp = taosArrayGetP(pConsumerEpNew->vgs, i);
|
||||
if(pVgEp->vgId == d1->vgId){
|
||||
jump = true;
|
||||
mInfo("pSub->offsetRows jump, because consumer id:%"PRIx64 " and vgId:%d not change", pConsumerEp->consumerId, pVgEp->vgId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(jump) continue;
|
||||
bool find = false;
|
||||
for (int i = 0; i < taosArrayGetSize(pOutput->pSub->offsetRows); i++) {
|
||||
OffsetRows *d2 = taosArrayGet(pOutput->pSub->offsetRows, i);
|
||||
if (d1->vgId == d2->vgId) {
|
||||
d2->rows += d1->rows;
|
||||
d2->offset = d1->offset;
|
||||
// mDebug("pSub->offsetRows add vgId:%d, after:%"PRId64", before:%"PRId64, d2->vgId, d2->rows, d1->rows);
|
||||
find = true;
|
||||
mInfo("pSub->offsetRows add vgId:%d, after:%"PRId64", before:%"PRId64, d2->vgId, d2->rows, d1->rows);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!find){
|
||||
taosArrayPush(pOutput->pSub->offsetRows, d1);
|
||||
}
|
||||
}
|
||||
}
|
||||
taosRUnLockLatch(&pSub->lock);
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
// 8. generate logs
|
||||
|
@ -576,50 +587,44 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu
|
|||
return -1;
|
||||
}
|
||||
|
||||
char topic[TSDB_TOPIC_FNAME_LEN] = {0};
|
||||
char cgroup[TSDB_CGROUP_LEN] = {0};
|
||||
mndSplitSubscribeKey(pOutput->pSub->key, topic, cgroup, true);
|
||||
|
||||
// 3. commit log: consumer to update status and epoch
|
||||
// 3.1 set touched consumer
|
||||
int32_t consumerNum = taosArrayGetSize(pOutput->modifyConsumers);
|
||||
for (int32_t i = 0; i < consumerNum; i++) {
|
||||
int64_t consumerId = *(int64_t *)taosArrayGet(pOutput->modifyConsumers, i);
|
||||
SMqConsumerObj *pConsumerOld = mndAcquireConsumer(pMnode, consumerId);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumerOld->consumerId, pConsumerOld->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__TOUCH;
|
||||
mndReleaseConsumer(pMnode, pConsumerOld);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE_REB_MODIFY_NOTOPIC;
|
||||
if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) {
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
}
|
||||
|
||||
// 3.2 set new consumer
|
||||
consumerNum = taosArrayGetSize(pOutput->newConsumers);
|
||||
for (int32_t i = 0; i < consumerNum; i++) {
|
||||
int64_t consumerId = *(int64_t *)taosArrayGet(pOutput->newConsumers, i);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE_REB_MODIFY_TOPIC;
|
||||
|
||||
SMqConsumerObj *pConsumerOld = mndAcquireConsumer(pMnode, consumerId);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumerOld->consumerId, pConsumerOld->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__ADD;
|
||||
char *topic = taosMemoryCalloc(1, TSDB_TOPIC_FNAME_LEN);
|
||||
char cgroup[TSDB_CGROUP_LEN];
|
||||
mndSplitSubscribeKey(pOutput->pSub->key, topic, cgroup, true);
|
||||
taosArrayPush(pConsumerNew->rebNewTopics, &topic);
|
||||
mndReleaseConsumer(pMnode, pConsumerOld);
|
||||
char* topicTmp = taosStrdup(topic);
|
||||
taosArrayPush(pConsumerNew->rebNewTopics, &topicTmp);
|
||||
if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) {
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
}
|
||||
|
||||
// 3.3 set removed consumer
|
||||
|
@ -627,24 +632,19 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu
|
|||
for (int32_t i = 0; i < consumerNum; i++) {
|
||||
int64_t consumerId = *(int64_t *)taosArrayGet(pOutput->removedConsumers, i);
|
||||
|
||||
SMqConsumerObj *pConsumerOld = mndAcquireConsumer(pMnode, consumerId);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumerOld->consumerId, pConsumerOld->cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE__REMOVE;
|
||||
char *topic = taosMemoryCalloc(1, TSDB_TOPIC_FNAME_LEN);
|
||||
char cgroup[TSDB_CGROUP_LEN];
|
||||
mndSplitSubscribeKey(pOutput->pSub->key, topic, cgroup, true);
|
||||
taosArrayPush(pConsumerNew->rebRemovedTopics, &topic);
|
||||
mndReleaseConsumer(pMnode, pConsumerOld);
|
||||
SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup);
|
||||
pConsumerNew->updateType = CONSUMER_UPDATE_REB_MODIFY_REMOVE;
|
||||
|
||||
char* topicTmp = taosStrdup(topic);
|
||||
taosArrayPush(pConsumerNew->rebRemovedTopics, &topicTmp);
|
||||
if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) {
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tDeleteSMqConsumerObj(pConsumerNew);
|
||||
taosMemoryFree(pConsumerNew);
|
||||
tDeleteSMqConsumerObj(pConsumerNew, true);
|
||||
}
|
||||
|
||||
// 4. TODO commit log: modification log
|
||||
|
@ -773,6 +773,8 @@ static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg) {
|
|||
static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg) {
|
||||
SMnode *pMnode = pMsg->info.node;
|
||||
SMDropCgroupReq dropReq = {0};
|
||||
STrans *pTrans = NULL;
|
||||
int32_t code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
|
||||
if (tDeserializeSMDropCgroupReq(pMsg->pCont, pMsg->contLen, &dropReq) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
|
@ -791,38 +793,54 @@ static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg) {
|
|||
}
|
||||
}
|
||||
|
||||
taosWLockLatch(&pSub->lock);
|
||||
if (taosHashGetSize(pSub->consumerHash) != 0) {
|
||||
terrno = TSDB_CODE_MND_CGROUP_USED;
|
||||
mError("cgroup:%s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr());
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
return -1;
|
||||
code = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "drop-cgroup");
|
||||
void *pIter = NULL;
|
||||
SMqConsumerObj *pConsumer;
|
||||
while (1) {
|
||||
pIter = sdbFetch(pMnode->pSdb, SDB_CONSUMER, pIter, (void **)&pConsumer);
|
||||
if (pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(dropReq.cgroup, pConsumer->cgroup) == 0) {
|
||||
mndDropConsumerFromSdb(pMnode, pConsumer->consumerId);
|
||||
}
|
||||
sdbRelease(pMnode->pSdb, pConsumer);
|
||||
}
|
||||
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "drop-cgroup");
|
||||
if (pTrans == NULL) {
|
||||
mError("cgroup: %s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr());
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
code = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
mInfo("trans:%d, used to drop cgroup:%s on topic %s", pTrans->id, dropReq.cgroup, dropReq.topic);
|
||||
|
||||
if (mndSetDropSubCommitLogs(pMnode, pTrans, pSub) < 0) {
|
||||
mError("cgroup %s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr());
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
code = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) < 0) {
|
||||
code = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
taosWUnLockLatch(&pSub->lock);
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
mndReleaseSubscribe(pMnode, pSub);
|
||||
|
||||
return TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
void mndCleanupSubscribe(SMnode *pMnode) {}
|
||||
|
@ -989,6 +1007,32 @@ SMqSubscribeObj *mndAcquireSubscribeByKey(SMnode *pMnode, const char *key) {
|
|||
return pSub;
|
||||
}
|
||||
|
||||
int32_t mndGetGroupNumByTopic(SMnode *pMnode, const char *topicName) {
|
||||
int32_t num = 0;
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
|
||||
void *pIter = NULL;
|
||||
SMqSubscribeObj *pSub = NULL;
|
||||
while (1) {
|
||||
pIter = sdbFetch(pSdb, SDB_SUBSCRIBE, pIter, (void **)&pSub);
|
||||
if (pIter == NULL) break;
|
||||
|
||||
|
||||
char topic[TSDB_TOPIC_FNAME_LEN];
|
||||
char cgroup[TSDB_CGROUP_LEN];
|
||||
mndSplitSubscribeKey(pSub->key, topic, cgroup, true);
|
||||
if (strcmp(topic, topicName) != 0) {
|
||||
sdbRelease(pSdb, pSub);
|
||||
continue;
|
||||
}
|
||||
|
||||
num++;
|
||||
sdbRelease(pSdb, pSub);
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
void mndReleaseSubscribe(SMnode *pMnode, SMqSubscribeObj *pSub) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
sdbRelease(pSdb, pSub);
|
||||
|
@ -1114,8 +1158,12 @@ static int32_t buildResult(SSDataBlock *pBlock, int32_t* numOfRows, int64_t cons
|
|||
colDataSetVal(pColInfo, *numOfRows, (const char *)&pVgEp->vgId, false);
|
||||
|
||||
// consumer id
|
||||
char consumerIdHex[32] = {0};
|
||||
sprintf(varDataVal(consumerIdHex), "0x%"PRIx64, consumerId);
|
||||
varDataSetLen(consumerIdHex, strlen(varDataVal(consumerIdHex)));
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, *numOfRows, (const char *)&consumerId, consumerId == -1);
|
||||
colDataSetVal(pColInfo, *numOfRows, (const char *)consumerIdHex, consumerId == -1);
|
||||
|
||||
mDebug("mnd show subscriptions: topic %s, consumer:0x%" PRIx64 " cgroup %s vgid %d", varDataVal(topic),
|
||||
consumerId, varDataVal(cgroup), pVgEp->vgId);
|
||||
|
|
|
@ -569,6 +569,11 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) {
|
|||
SMqTopicObj *pTopic = NULL;
|
||||
SDbObj *pDb = NULL;
|
||||
SCMCreateTopicReq createTopicReq = {0};
|
||||
if (sdbGetSize(pMnode->pSdb, SDB_TOPIC) >= tmqMaxTopicNum){
|
||||
terrno = TSDB_CODE_TMQ_TOPIC_OUT_OF_RANGE;
|
||||
mError("topic num out of range");
|
||||
return code;
|
||||
}
|
||||
|
||||
if (tDeserializeSCMCreateTopicReq(pReq->pCont, pReq->contLen, &createTopicReq) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
|
@ -681,7 +686,11 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (pConsumer->status == MQ_CONSUMER_STATUS__LOST_REBD) continue;
|
||||
if (pConsumer->status == MQ_CONSUMER_STATUS_LOST){
|
||||
mndDropConsumerFromSdb(pMnode, pConsumer->consumerId);
|
||||
mndReleaseConsumer(pMnode, pConsumer);
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t sz = taosArrayGetSize(pConsumer->assignedTopics);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
|
|
|
@ -875,7 +875,7 @@ static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p
|
|||
// if (pDb == NULL || pDb->compactStartTime <= 0) {
|
||||
// colDataSetNULL(pColInfo, numOfRows);
|
||||
// } else {
|
||||
// colDataAppend(pColInfo, numOfRows, (const char *)&pDb->compactStartTime, false);
|
||||
// colDataSetVal(pColInfo, numOfRows, (const char *)&pDb->compactStartTime, false);
|
||||
// }
|
||||
|
||||
numOfRows++;
|
||||
|
|
|
@ -52,23 +52,21 @@ void sndEnqueueStreamDispatch(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
|
||||
FAIL:
|
||||
if (pMsg->info.handle == NULL) return;
|
||||
SRpcMsg rsp = {
|
||||
.code = code,
|
||||
.info = pMsg->info,
|
||||
};
|
||||
SRpcMsg rsp = { .code = code, .info = pMsg->info};
|
||||
tmsgSendRsp(&rsp);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
|
||||
int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t ver) {
|
||||
ASSERT(pTask->taskLevel == TASK_LEVEL__AGG && taosArrayGetSize(pTask->childEpInfo) != 0);
|
||||
ASSERT(pTask->info.taskLevel == TASK_LEVEL__AGG && taosArrayGetSize(pTask->pUpstreamEpInfoList) != 0);
|
||||
|
||||
pTask->refCnt = 1;
|
||||
pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE;
|
||||
pTask->id.idStr = createStreamTaskIdStr(pTask->id.streamId, pTask->id.taskId);
|
||||
|
||||
pTask->inputQueue = streamQueueOpen(0);
|
||||
pTask->outputQueue = streamQueueOpen(0);
|
||||
pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE;
|
||||
pTask->inputQueue = streamQueueOpen(512 << 10);
|
||||
pTask->outputQueue = streamQueueOpen(512 << 10);
|
||||
|
||||
if (pTask->inputQueue == NULL || pTask->outputQueue == NULL) {
|
||||
return -1;
|
||||
|
@ -85,14 +83,18 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t ver) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int32_t numOfChildEp = taosArrayGetSize(pTask->childEpInfo);
|
||||
SReadHandle handle = {.vnode = NULL, .numOfVgroups = numOfChildEp, .pStateBackend = pTask->pState};
|
||||
int32_t numOfChildEp = taosArrayGetSize(pTask->pUpstreamEpInfoList);
|
||||
SReadHandle handle = { .vnode = NULL, .numOfVgroups = numOfChildEp, .pStateBackend = pTask->pState, .fillHistory = pTask->info.fillHistory };
|
||||
initStreamStateAPI(&handle.api);
|
||||
|
||||
pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, 0);
|
||||
ASSERT(pTask->exec.pExecutor);
|
||||
|
||||
streamSetupTrigger(pTask);
|
||||
streamSetupScheduleTrigger(pTask);
|
||||
|
||||
qDebug("snode:%d expand stream task on snode, s-task:%s, checkpoint ver:%" PRId64 " child id:%d, level:%d", SNODE_HANDLE,
|
||||
pTask->id.idStr, pTask->chkInfo.version, pTask->info.selfChildId, pTask->info.taskLevel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -149,9 +151,10 @@ int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
|||
taosMemoryFree(pTask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
ASSERT(pTask->taskLevel == TASK_LEVEL__AGG);
|
||||
ASSERT(pTask->info.taskLevel == TASK_LEVEL__AGG);
|
||||
|
||||
// 2.save task
|
||||
taosWLockLatch(&pSnode->pMeta->lock);
|
||||
|
@ -161,19 +164,20 @@ int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int32_t numOfTasks = streamMetaGetNumOfTasks(pSnode->pMeta);
|
||||
taosWUnLockLatch(&pSnode->pMeta->lock);
|
||||
|
||||
// 3.go through recover steps to fill history
|
||||
if (pTask->fillHistory) {
|
||||
streamSetParamForRecover(pTask);
|
||||
streamAggRecoverPrepare(pTask);
|
||||
}
|
||||
streamPrepareNdoCheckDownstream(pTask);
|
||||
qDebug("snode:%d s-task:%s is deployed on snode and add into meta, status:%s, numOfTasks:%d", SNODE_HANDLE, pTask->id.idStr,
|
||||
streamGetTaskStatusStr(pTask->status.taskStatus), numOfTasks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessTaskDropReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
||||
SVDropStreamTaskReq *pReq = (SVDropStreamTaskReq *)msg;
|
||||
qDebug("snode:%d receive msg to drop stream task:0x%x", pSnode->pMeta->vgId, pReq->taskId);
|
||||
|
||||
streamMetaRemoveTask(pSnode->pMeta, pReq->taskId);
|
||||
return 0;
|
||||
}
|
||||
|
@ -255,13 +259,15 @@ int32_t sndProcessTaskRetrieveRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
}
|
||||
|
||||
int32_t sndProcessWriteMsg(SSnode *pSnode, SRpcMsg *pMsg, SRpcMsg *pRsp) {
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_DEPLOY: {
|
||||
void *pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_DEPLOY:
|
||||
return sndProcessTaskDeployReq(pSnode, pReq, len);
|
||||
}
|
||||
|
||||
case TDMT_STREAM_TASK_DROP:
|
||||
return sndProcessTaskDropReq(pSnode, pReq, len);
|
||||
return sndProcessTaskDropReq(pSnode, pMsg->pCont, pMsg->contLen);
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
@ -277,7 +283,7 @@ int32_t sndProcessTaskRecoverFinishReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, msg, msgLen);
|
||||
tDecodeSStreamRecoverFinishReq(&decoder, &req);
|
||||
tDecodeStreamRecoverFinishReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
// find task
|
||||
|
@ -286,7 +292,7 @@ int32_t sndProcessTaskRecoverFinishReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
// do process request
|
||||
if (streamProcessRecoverFinishReq(pTask, req.childId) < 0) {
|
||||
if (streamProcessRecoverFinishReq(pTask, req.taskId, req.childId) < 0) {
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
return -1;
|
||||
}
|
||||
|
@ -300,6 +306,102 @@ int32_t sndProcessTaskRecoverFinishRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamTaskCheckReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
char *msgStr = pMsg->pCont;
|
||||
char *msgBody = POINTER_SHIFT(msgStr, sizeof(SMsgHead));
|
||||
int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
||||
SStreamTaskCheckReq req;
|
||||
SDecoder decoder;
|
||||
|
||||
tDecoderInit(&decoder, (uint8_t *)msgBody, msgLen);
|
||||
tDecodeStreamTaskCheckReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
int32_t taskId = req.downstreamTaskId;
|
||||
|
||||
SStreamTaskCheckRsp rsp = {
|
||||
.reqId = req.reqId,
|
||||
.streamId = req.streamId,
|
||||
.childId = req.childId,
|
||||
.downstreamNodeId = req.downstreamNodeId,
|
||||
.downstreamTaskId = req.downstreamTaskId,
|
||||
.upstreamNodeId = req.upstreamNodeId,
|
||||
.upstreamTaskId = req.upstreamTaskId,
|
||||
};
|
||||
|
||||
SStreamTask *pTask = streamMetaAcquireTask(pSnode->pMeta, taskId);
|
||||
|
||||
if (pTask != NULL) {
|
||||
rsp.status = streamTaskCheckStatus(pTask);
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
|
||||
qDebug("s-task:%s recv task check req(reqId:0x%" PRIx64 ") task:0x%x (vgId:%d), status:%s, rsp status %d",
|
||||
pTask->id.idStr, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId,
|
||||
streamGetTaskStatusStr(pTask->status.taskStatus), rsp.status);
|
||||
} else {
|
||||
rsp.status = 0;
|
||||
qDebug("tq recv task check(taskId:0x%x not built yet) req(reqId:0x%" PRIx64
|
||||
") from task:0x%x (vgId:%d), rsp status %d",
|
||||
taskId, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
}
|
||||
|
||||
SEncoder encoder;
|
||||
int32_t code;
|
||||
int32_t len;
|
||||
|
||||
tEncodeSize(tEncodeStreamTaskCheckRsp, &rsp, len, code);
|
||||
if (code < 0) {
|
||||
qError("vgId:%d failed to encode task check rsp, task:0x%x", pSnode->pMeta->vgId, taskId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buf = rpcMallocCont(sizeof(SMsgHead) + len);
|
||||
((SMsgHead *)buf)->vgId = htonl(req.upstreamNodeId);
|
||||
|
||||
void *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
||||
tEncoderInit(&encoder, (uint8_t *)abuf, len);
|
||||
tEncodeStreamTaskCheckRsp(&encoder, &rsp);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
SRpcMsg rspMsg = {.code = 0, .pCont = buf, .contLen = sizeof(SMsgHead) + len, .info = pMsg->info};
|
||||
|
||||
tmsgSendRsp(&rspMsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamTaskCheckRsp(SSnode* pSnode, SRpcMsg* pMsg) {
|
||||
char* pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
||||
int32_t code;
|
||||
SStreamTaskCheckRsp rsp;
|
||||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)pReq, len);
|
||||
code = tDecodeStreamTaskCheckRsp(&decoder, &rsp);
|
||||
|
||||
if (code < 0) {
|
||||
tDecoderClear(&decoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
qDebug("tq task:0x%x (vgId:%d) recv check rsp(reqId:0x%" PRIx64 ") from 0x%x (vgId:%d) status %d",
|
||||
rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.status);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pSnode->pMeta, rsp.upstreamTaskId);
|
||||
if (pTask == NULL) {
|
||||
qError("tq failed to locate the stream task:0x%x (vgId:%d), it may have been destroyed", rsp.upstreamTaskId,
|
||||
pSnode->pMeta->vgId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
code = streamProcessCheckRsp(pTask, &rsp);
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamMsg(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_RUN:
|
||||
|
@ -312,10 +414,14 @@ int32_t sndProcessStreamMsg(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
return sndProcessTaskRetrieveReq(pSnode, pMsg);
|
||||
case TDMT_STREAM_RETRIEVE_RSP:
|
||||
return sndProcessTaskRetrieveRsp(pSnode, pMsg);
|
||||
case TDMT_STREAM_RECOVER_FINISH:
|
||||
case TDMT_STREAM_SCAN_HISTORY_FINISH:
|
||||
return sndProcessTaskRecoverFinishReq(pSnode, pMsg);
|
||||
case TDMT_STREAM_RECOVER_FINISH_RSP:
|
||||
case TDMT_STREAM_SCAN_HISTORY_FINISH_RSP:
|
||||
return sndProcessTaskRecoverFinishRsp(pSnode, pMsg);
|
||||
case TDMT_STREAM_TASK_CHECK:
|
||||
return sndProcessStreamTaskCheckReq(pSnode, pMsg);
|
||||
case TDMT_STREAM_TASK_CHECK_RSP:
|
||||
return sndProcessStreamTaskCheckRsp(pSnode, pMsg);
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamStateCommit = streamStateCommit;
|
||||
pStore->streamStateDestroy= streamStateDestroy;
|
||||
pStore->streamStateDeleteCheckPoint = streamStateDeleteCheckPoint;
|
||||
pStore->streamStateReloadInfo = streamStateReloadInfo;
|
||||
}
|
||||
|
||||
void initFunctionStateStore(SFunctionStateStore* pStore) {
|
||||
|
|
|
@ -96,6 +96,7 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
|
|||
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);
|
||||
int32_t vnodeProcessStreamMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo);
|
||||
void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
|
||||
void vnodeApplyWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs);
|
||||
void vnodeProposeCommitOnNeed(SVnode *pVnode, bool atExit);
|
||||
|
@ -126,8 +127,6 @@ int32_t metaGetCachedTbGroup(void *pVnode, tb_uid_t suid, const uint8_t *pKey,
|
|||
int32_t metaPutTbGroupToCache(void* pVnode, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
||||
int32_t payloadLen);
|
||||
|
||||
int64_t metaGetTbNum(SMeta *pMeta);
|
||||
|
||||
int32_t metaGetStbStats(void *pVnode, int64_t uid, int64_t *numOfTables);
|
||||
|
||||
// tsdb
|
||||
|
@ -235,7 +234,7 @@ int32_t vnodeSnapWriterOpen(SVnode *pVnode, int64_t sver, int64_t ever, SVSnapWr
|
|||
int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback, SSnapshot *pSnapshot);
|
||||
int32_t vnodeSnapWrite(SVSnapWriter *pWriter, uint8_t *pData, uint32_t nData);
|
||||
|
||||
int32_t buildSnapContext(SVnode *pVnode, int64_t snapVersion, int64_t suid, int8_t subType, bool withMeta,
|
||||
int32_t buildSnapContext(SVnode *pVnode, int64_t snapVersion, int64_t suid, int8_t subType, int8_t withMeta,
|
||||
SSnapContext **ctxRet);
|
||||
int32_t getTableInfoFromSnapshot(SSnapContext *ctx, void **pBuf, int32_t *contLen, int16_t *type, int64_t *uid);
|
||||
SMetaTableInfo getMetaTableInfoFromSnapshot(SSnapContext *ctx);
|
||||
|
|
|
@ -45,27 +45,10 @@ extern "C" {
|
|||
typedef struct STqOffsetStore STqOffsetStore;
|
||||
|
||||
// tqPush
|
||||
|
||||
// typedef struct {
|
||||
// // msg info
|
||||
// int64_t consumerId;
|
||||
// int64_t reqOffset;
|
||||
// int64_t processedVer;
|
||||
// int32_t epoch;
|
||||
// // rpc info
|
||||
// int64_t reqId;
|
||||
// SRpcHandleInfo rpcInfo;
|
||||
// tmr_h timerId;
|
||||
// int8_t tmrStopped;
|
||||
// // exec
|
||||
// int8_t inputStatus;
|
||||
// int8_t execStatus;
|
||||
// SStreamQueue inputQ;
|
||||
// SRWLatch lock;
|
||||
// } STqPushHandle;
|
||||
#define EXTRACT_DATA_FROM_WAL_ID (-1)
|
||||
#define STREAM_TASK_STATUS_CHECK_ID (-2)
|
||||
|
||||
// tqExec
|
||||
|
||||
typedef struct {
|
||||
char* qmsg; // SubPlanToString
|
||||
} STqExecCol;
|
||||
|
@ -187,10 +170,10 @@ int32_t tqOffsetRestoreFromFile(STqOffsetStore* pStore, const char* fname);
|
|||
// tqStream
|
||||
int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver);
|
||||
int32_t tqStreamTasksScanWal(STQ* pTq);
|
||||
int32_t tqStreamTasksStatusCheck(STQ* pTq);
|
||||
|
||||
// tq util
|
||||
int32_t extractDelDataBlock(const void* pData, int32_t len, int64_t ver, SStreamRefDataBlock** pRefBlock);
|
||||
char* createStreamTaskIdStr(int64_t streamId, int32_t taskId);
|
||||
int32_t tqAddInputBlockNLaunchTask(SStreamTask* pTask, SStreamQueueItem* pQueueItem);
|
||||
int32_t tqExtractDataForMq(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg);
|
||||
int32_t tqDoSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch, int64_t consumerId,
|
||||
|
|
|
@ -64,7 +64,6 @@ typedef struct STsdbReadSnap STsdbReadSnap;
|
|||
typedef struct SBlockInfo SBlockInfo;
|
||||
typedef struct SSmaInfo SSmaInfo;
|
||||
typedef struct SBlockCol SBlockCol;
|
||||
typedef struct SVersionRange SVersionRange;
|
||||
typedef struct SLDataIter SLDataIter;
|
||||
typedef struct SDiskCol SDiskCol;
|
||||
typedef struct SDiskData SDiskData;
|
||||
|
@ -383,11 +382,6 @@ struct TSDBKEY {
|
|||
TSKEY ts;
|
||||
};
|
||||
|
||||
struct SVersionRange {
|
||||
uint64_t minVer;
|
||||
uint64_t maxVer;
|
||||
};
|
||||
|
||||
typedef struct SMemSkipListNode SMemSkipListNode;
|
||||
struct SMemSkipListNode {
|
||||
int8_t level;
|
||||
|
|
|
@ -179,7 +179,8 @@ SArray* metaGetSmaTbUids(SMeta* pMeta);
|
|||
void* metaGetIdx(SMeta* pMeta);
|
||||
void* metaGetIvtIdx(SMeta* pMeta);
|
||||
|
||||
void metaReaderInit(SMetaReader* pReader, SMeta* pMeta, int32_t flags);
|
||||
int64_t metaGetTbNum(SMeta *pMeta);
|
||||
void metaReaderDoInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags);
|
||||
|
||||
int32_t metaCreateTSma(SMeta* pMeta, int64_t version, SSmaCfg* pCfg);
|
||||
int32_t metaDropTSma(SMeta* pMeta, int64_t indexUid);
|
||||
|
@ -219,6 +220,7 @@ int tqRegisterPushHandle(STQ* pTq, void* handle, SRpcMsg* pMsg);
|
|||
int tqUnregisterPushHandle(STQ* pTq, void* pHandle);
|
||||
int tqStartStreamTasks(STQ* pTq); // restore all stream tasks after vnode launching completed.
|
||||
int32_t tqProcessStreamCheckPointReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen);
|
||||
int32_t tqCheckStreamStatus(STQ* pTq);
|
||||
|
||||
int tqCommit(STQ*);
|
||||
int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd);
|
||||
|
@ -240,14 +242,14 @@ int32_t tqProcessTaskDropReq(STQ* pTq, int64_t version, char* msg, int32_t msgLe
|
|||
int32_t tqProcessTaskPauseReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
|
||||
int32_t tqProcessTaskResumeReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
|
||||
int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
|
||||
int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg, bool exec);
|
||||
int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRetrieveReq(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRetrieveRsp(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRecover1Req(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
|
||||
int32_t tqProcessTaskScanHistory(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskTransferStateReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
|
||||
int32_t tqProcessTaskRecoverFinishReq(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskRecoverFinishRsp(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqCheckLogInWal(STQ* pTq, int64_t version);
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
#include "osMemory.h"
|
||||
#include "tencode.h"
|
||||
|
||||
void _metaReaderInit(SMetaReader *pReader, void *pVnode, int32_t flags, SStoreMeta *pAPI) {
|
||||
SMeta *pMeta = ((SVnode *)pVnode)->pMeta;
|
||||
metaReaderInit(pReader, pMeta, flags);
|
||||
void _metaReaderInit(SMetaReader* pReader, void* pVnode, int32_t flags, SStoreMeta* pAPI) {
|
||||
SMeta* pMeta = ((SVnode*)pVnode)->pMeta;
|
||||
metaReaderDoInit(pReader, pMeta, flags);
|
||||
pReader->pAPI = pAPI;
|
||||
}
|
||||
|
||||
void metaReaderInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags) {
|
||||
void metaReaderDoInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags) {
|
||||
memset(pReader, 0, sizeof(*pReader));
|
||||
pReader->pMeta = pMeta;
|
||||
pReader->flags = flags;
|
||||
|
@ -143,7 +143,7 @@ tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name) {
|
|||
int metaGetTableNameByUid(void *pVnode, uint64_t uid, char *tbName) {
|
||||
int code = 0;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, ((SVnode *)pVnode)->pMeta, 0);
|
||||
metaReaderDoInit(&mr, ((SVnode*)pVnode)->pMeta, 0);
|
||||
code = metaReaderGetTableEntryByUid(&mr, uid);
|
||||
if (code < 0) {
|
||||
metaReaderClear(&mr);
|
||||
|
@ -159,7 +159,7 @@ int metaGetTableNameByUid(void *pVnode, uint64_t uid, char *tbName) {
|
|||
int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName) {
|
||||
int code = 0;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, (SMeta *)meta, 0);
|
||||
metaReaderDoInit(&mr, (SMeta *)meta, 0);
|
||||
code = metaReaderGetTableEntryByUid(&mr, uid);
|
||||
if (code < 0) {
|
||||
metaReaderClear(&mr);
|
||||
|
@ -174,7 +174,7 @@ int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName) {
|
|||
int metaGetTableUidByName(void *pVnode, char *tbName, uint64_t *uid) {
|
||||
int code = 0;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, ((SVnode *)pVnode)->pMeta, 0);
|
||||
metaReaderDoInit(&mr, ((SVnode *)pVnode)->pMeta, 0);
|
||||
|
||||
SMetaReader *pReader = &mr;
|
||||
|
||||
|
@ -195,7 +195,7 @@ int metaGetTableUidByName(void *pVnode, char *tbName, uint64_t *uid) {
|
|||
int metaGetTableTypeByName(void *pVnode, char *tbName, ETableType *tbType) {
|
||||
int code = 0;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, ((SVnode *)pVnode)->pMeta, 0);
|
||||
metaReaderDoInit(&mr, ((SVnode*)pVnode)->pMeta, 0);
|
||||
|
||||
code = metaGetTableEntryByName(&mr, tbName);
|
||||
if (code == 0) *tbType = mr.me.type;
|
||||
|
@ -215,7 +215,7 @@ int metaReadNext(SMetaReader *pReader) {
|
|||
int metaGetTableTtlByUid(void *meta, uint64_t uid, int64_t *ttlDays) {
|
||||
int code = -1;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, (SMeta *)meta, 0);
|
||||
metaReaderDoInit(&mr, (SMeta *)meta, 0);
|
||||
code = metaReaderGetTableEntryByUid(&mr, uid);
|
||||
if (code < 0) {
|
||||
goto _exit;
|
||||
|
@ -244,9 +244,7 @@ SMTbCursor *metaOpenTbCursor(void *pVnode) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SVnode *pVnodeObj = pVnode;
|
||||
// metaReaderInit(&pTbCur->mr, pVnodeObj->pMeta, 0);
|
||||
|
||||
SVnode* pVnodeObj = pVnode;
|
||||
// tdbTbcMoveToFirst((TBC *)pTbCur->pDbc);
|
||||
pTbCur->pMeta = pVnodeObj->pMeta;
|
||||
pTbCur->paused = 1;
|
||||
|
@ -277,7 +275,7 @@ void metaPauseTbCursor(SMTbCursor *pTbCur) {
|
|||
}
|
||||
void metaResumeTbCursor(SMTbCursor *pTbCur, int8_t first) {
|
||||
if (pTbCur->paused) {
|
||||
metaReaderInit(&pTbCur->mr, pTbCur->pMeta, 0);
|
||||
metaReaderDoInit(&pTbCur->mr, pTbCur->pMeta, 0);
|
||||
|
||||
tdbTbcOpen(((SMeta *)pTbCur->pMeta)->pUidIdx, (TBC **)&pTbCur->pDbc, NULL);
|
||||
|
||||
|
@ -784,7 +782,7 @@ STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid, bool deepCopy) {
|
|||
}
|
||||
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pMeta, 0);
|
||||
metaReaderDoInit(&mr, pMeta, 0);
|
||||
int64_t smaId;
|
||||
int smaIdx = 0;
|
||||
STSma *pTSma = NULL;
|
||||
|
@ -839,7 +837,7 @@ _err:
|
|||
STSma *metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid) {
|
||||
STSma *pTSma = NULL;
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pMeta, 0);
|
||||
metaReaderDoInit(&mr, pMeta, 0);
|
||||
if (metaReaderGetTableEntryByUid(&mr, indexUid) < 0) {
|
||||
metaWarn("vgId:%d, failed to get table entry for smaId:%" PRIi64, TD_VID(pMeta->pVnode), indexUid);
|
||||
metaReaderClear(&mr);
|
||||
|
|
|
@ -37,7 +37,7 @@ int32_t metaCreateTSma(SMeta *pMeta, int64_t version, SSmaCfg *pCfg) {
|
|||
|
||||
// validate req
|
||||
// save smaIndex
|
||||
metaReaderInit(&mr, pMeta, 0);
|
||||
metaReaderDoInit(&mr, pMeta, 0);
|
||||
if (metaReaderGetTableEntryByUidCache(&mr, pCfg->indexUid) == 0) {
|
||||
#if 1
|
||||
terrno = TSDB_CODE_TSMA_ALREADY_EXIST;
|
||||
|
|
|
@ -260,7 +260,7 @@ static void saveSuperTableInfoForChildTable(SMetaEntry* me, SHashObj* suidInfo)
|
|||
taosHashPut(suidInfo, &me->uid, sizeof(tb_uid_t), &dataTmp, sizeof(STableInfoForChildTable));
|
||||
}
|
||||
|
||||
int32_t buildSnapContext(SVnode* pVnode, int64_t snapVersion, int64_t suid, int8_t subType, bool withMeta,
|
||||
int32_t buildSnapContext(SVnode* pVnode, int64_t snapVersion, int64_t suid, int8_t subType, int8_t withMeta,
|
||||
SSnapContext** ctxRet) {
|
||||
SSnapContext* ctx = taosMemoryCalloc(1, sizeof(SSnapContext));
|
||||
if (ctx == NULL) return -1;
|
||||
|
@ -476,7 +476,7 @@ int32_t getTableInfoFromSnapshot(SSnapContext* ctx, void** pBuf, int32_t* contLe
|
|||
if (ctx->index >= taosArrayGetSize(ctx->idList)) {
|
||||
metaDebug("tmqsnap get meta end");
|
||||
ctx->index = 0;
|
||||
ctx->queryMeta = false; // change to get data
|
||||
ctx->queryMeta = 0; // change to get data
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -709,7 +709,7 @@ int metaCreateTable(SMeta *pMeta, int64_t ver, SVCreateTbReq *pReq, STableMetaRs
|
|||
}
|
||||
|
||||
// validate req
|
||||
metaReaderInit(&mr, pMeta, 0);
|
||||
metaReaderDoInit(&mr, pMeta, 0);
|
||||
if (metaGetTableEntryByName(&mr, pReq->name) == 0) {
|
||||
if (pReq->type == TSDB_CHILD_TABLE && pReq->ctb.suid != mr.me.ctbEntry.suid) {
|
||||
terrno = TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
|
||||
|
@ -1980,6 +1980,11 @@ static int metaUpdateTtl(SMeta *pMeta, const SMetaEntry *pME) {
|
|||
int metaUpdateChangeTime(SMeta *pMeta, tb_uid_t uid, int64_t changeTimeMs) {
|
||||
if (!tsTtlChangeOnWrite) return 0;
|
||||
|
||||
if (changeTimeMs <= 0) {
|
||||
metaWarn("Skip to change ttl deletetion time on write, uid: %" PRId64, uid);
|
||||
return TSDB_CODE_VERSION_NOT_COMPATIBLE;
|
||||
}
|
||||
|
||||
STtlUpdCtimeCtx ctx = {.uid = uid, .changeTimeMs = changeTimeMs};
|
||||
|
||||
return ttlMgrUpdateChangeTime(pMeta->pTtlMgr, &ctx);
|
||||
|
|
|
@ -358,7 +358,8 @@ int ttlMgrFlush(STtlManger *pTtlMgr, TXN *pTxn) {
|
|||
|
||||
STtlCacheEntry *cacheEntry = taosHashGet(pTtlMgr->pTtlCache, pUid, sizeof(*pUid));
|
||||
if (cacheEntry == NULL) {
|
||||
metaError("ttlMgr flush failed to get ttl cache since %s", tstrerror(terrno));
|
||||
metaError("ttlMgr flush failed to get ttl cache since %s, uid: %" PRId64 ", type: %d", tstrerror(terrno), *pUid,
|
||||
pEntry->type);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
|
|
|
@ -896,7 +896,7 @@ static int32_t tdRSmaInfoClone(SSma *pSma, SRSmaInfo *pInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
metaReaderInit(&mr, SMA_META(pSma), 0);
|
||||
metaReaderDoInit(&mr, SMA_META(pSma), 0);
|
||||
smaDebug("vgId:%d, rsma clone qTaskInfo for suid:%" PRIi64, SMA_VID(pSma), pInfo->suid);
|
||||
if (metaReaderGetTableEntryByUidCache(&mr, pInfo->suid) < 0) {
|
||||
code = terrno;
|
||||
|
@ -1116,7 +1116,7 @@ static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) {
|
|||
}
|
||||
|
||||
int64_t nRsmaTables = 0;
|
||||
metaReaderInit(&mr, SMA_META(pSma), 0);
|
||||
metaReaderDoInit(&mr, SMA_META(pSma), 0);
|
||||
if (!(uidStore.tbUids = taosArrayInit(1024, sizeof(tb_uid_t)))) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
// 0: not init
|
||||
// 1: already inited
|
||||
// 2: wait to be inited or cleaup
|
||||
#define WAL_READ_TASKS_ID (-1)
|
||||
|
||||
static int32_t tqInitialize(STQ* pTq);
|
||||
|
||||
static FORCE_INLINE bool tqIsHandleExec(STqHandle* pHandle) { return TMQ_HANDLE_STATUS_EXEC == pHandle->status; }
|
||||
|
@ -158,6 +156,29 @@ void tqClose(STQ* pTq) {
|
|||
taosMemoryFree(pTq);
|
||||
}
|
||||
|
||||
static bool hasStreamTaskInTimer(SStreamMeta* pMeta) {
|
||||
bool inTimer = false;
|
||||
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
|
||||
void* pIter = NULL;
|
||||
while(1) {
|
||||
pIter = taosHashIterate(pMeta->pTasks, pIter);
|
||||
if (pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
SStreamTask* pTask = *(SStreamTask**)pIter;
|
||||
if (pTask->status.timerActive == 1) {
|
||||
inTimer = true;
|
||||
}
|
||||
}
|
||||
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
|
||||
return inTimer;
|
||||
}
|
||||
|
||||
void tqNotifyClose(STQ* pTq) {
|
||||
if (pTq != NULL) {
|
||||
taosWLockLatch(&pTq->pStreamMeta->lock);
|
||||
|
@ -170,77 +191,90 @@ void tqNotifyClose(STQ* pTq) {
|
|||
}
|
||||
|
||||
SStreamTask* pTask = *(SStreamTask**)pIter;
|
||||
tqDebug("vgId:%d s-task:%s set dropping flag", pTq->pStreamMeta->vgId, pTask->id.idStr);
|
||||
tqDebug("vgId:%d s-task:%s set closing flag", pTq->pStreamMeta->vgId, pTask->id.idStr);
|
||||
pTask->status.taskStatus = TASK_STATUS__STOP;
|
||||
|
||||
int64_t st = taosGetTimestampMs();
|
||||
qKillTask(pTask->exec.pExecutor, TSDB_CODE_SUCCESS);
|
||||
|
||||
int64_t el = taosGetTimestampMs() - st;
|
||||
tqDebug("vgId:%d s-task:%s is closed in %" PRId64 " ms", pTq->pStreamMeta->vgId, pTask->id.idStr, el);
|
||||
}
|
||||
|
||||
taosWUnLockLatch(&pTq->pStreamMeta->lock);
|
||||
|
||||
tqDebug("vgId:%d start to check all tasks", pTq->pStreamMeta->vgId);
|
||||
|
||||
int64_t st = taosGetTimestampMs();
|
||||
|
||||
while(hasStreamTaskInTimer(pTq->pStreamMeta)) {
|
||||
tqDebug("vgId:%d some tasks in timer, wait for 100ms and recheck", pTq->pStreamMeta->vgId);
|
||||
taosMsleep(100);
|
||||
}
|
||||
|
||||
int64_t el = taosGetTimestampMs() - st;
|
||||
tqDebug("vgId:%d all stream tasks are not in timer, continue close, elapsed time:%"PRId64" ms", pTq->pStreamMeta->vgId, el);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t doSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch,
|
||||
int64_t consumerId, int32_t type) {
|
||||
int32_t len = 0;
|
||||
int32_t code = 0;
|
||||
|
||||
if (type == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
tEncodeSize(tEncodeMqDataRsp, pRsp, len, code);
|
||||
} else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code);
|
||||
}
|
||||
|
||||
if (code < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tlen = sizeof(SMqRspHead) + len;
|
||||
void* buf = rpcMallocCont(tlen);
|
||||
if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
((SMqRspHead*)buf)->mqMsgType = type;
|
||||
((SMqRspHead*)buf)->epoch = epoch;
|
||||
((SMqRspHead*)buf)->consumerId = consumerId;
|
||||
|
||||
void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
|
||||
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, abuf, len);
|
||||
|
||||
if (type == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
tEncodeMqDataRsp(&encoder, pRsp);
|
||||
} else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp);
|
||||
}
|
||||
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
SRpcMsg rsp = {
|
||||
.info = *pRpcHandleInfo,
|
||||
.pCont = buf,
|
||||
.contLen = tlen,
|
||||
.code = 0,
|
||||
};
|
||||
|
||||
tmsgSendRsp(&rsp);
|
||||
return 0;
|
||||
}
|
||||
//static int32_t doSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch,
|
||||
// int64_t consumerId, int32_t type) {
|
||||
// int32_t len = 0;
|
||||
// int32_t code = 0;
|
||||
//
|
||||
// if (type == TMQ_MSG_TYPE__POLL_DATA_RSP) {
|
||||
// tEncodeSize(tEncodeMqDataRsp, pRsp, len, code);
|
||||
// } else if (type == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
// tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code);
|
||||
// }
|
||||
//
|
||||
// if (code < 0) {
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// int32_t tlen = sizeof(SMqRspHead) + len;
|
||||
// void* buf = rpcMallocCont(tlen);
|
||||
// if (buf == NULL) {
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// ((SMqRspHead*)buf)->mqMsgType = type;
|
||||
// ((SMqRspHead*)buf)->epoch = epoch;
|
||||
// ((SMqRspHead*)buf)->consumerId = consumerId;
|
||||
//
|
||||
// void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
|
||||
//
|
||||
// SEncoder encoder = {0};
|
||||
// tEncoderInit(&encoder, abuf, len);
|
||||
//
|
||||
// if (type == TMQ_MSG_TYPE__POLL_DATA_RSP) {
|
||||
// tEncodeMqDataRsp(&encoder, pRsp);
|
||||
// } else if (type == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
// tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp);
|
||||
// }
|
||||
//
|
||||
// tEncoderClear(&encoder);
|
||||
//
|
||||
// SRpcMsg rsp = {
|
||||
// .info = *pRpcHandleInfo,
|
||||
// .pCont = buf,
|
||||
// .contLen = tlen,
|
||||
// .code = 0,
|
||||
// };
|
||||
//
|
||||
// tmsgSendRsp(&rsp);
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
int32_t tqPushDataRsp(STqHandle* pHandle, int32_t vgId) {
|
||||
SMqDataRsp dataRsp = {0};
|
||||
dataRsp.head.consumerId = pHandle->consumerId;
|
||||
dataRsp.head.epoch = pHandle->epoch;
|
||||
dataRsp.head.mqMsgType = TMQ_MSG_TYPE__POLL_RSP;
|
||||
dataRsp.head.mqMsgType = TMQ_MSG_TYPE__POLL_DATA_RSP;
|
||||
|
||||
int64_t sver = 0, ever = 0;
|
||||
walReaderValidVersionRange(pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
|
||||
tqDoSendDataRsp(&pHandle->msg->info, &dataRsp, pHandle->epoch, pHandle->consumerId, TMQ_MSG_TYPE__POLL_RSP, sver,
|
||||
tqDoSendDataRsp(&pHandle->msg->info, &dataRsp, pHandle->epoch, pHandle->consumerId, TMQ_MSG_TYPE__POLL_DATA_RSP, sver,
|
||||
ever);
|
||||
|
||||
char buf1[TSDB_OFFSET_LEN] = {0};
|
||||
|
@ -771,19 +805,32 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) {
|
|||
pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL;
|
||||
pTask->pMsgCb = &pTq->pVnode->msgCb;
|
||||
pTask->pMeta = pTq->pStreamMeta;
|
||||
|
||||
pTask->chkInfo.version = ver;
|
||||
pTask->chkInfo.currentVer = ver;
|
||||
|
||||
// expand executor
|
||||
pTask->status.taskStatus = (pTask->fillHistory) ? TASK_STATUS__WAIT_DOWNSTREAM : TASK_STATUS__NORMAL;
|
||||
pTask->dataRange.range.maxVer = ver;
|
||||
pTask->dataRange.range.minVer = ver;
|
||||
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pTask, false, -1, -1);
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
SStreamTask* pSateTask = pTask;
|
||||
SStreamTask task = {0};
|
||||
if (pTask->info.fillHistory) {
|
||||
task.id = pTask->streamTaskId;
|
||||
task.pMeta = pTask->pMeta;
|
||||
pSateTask = &task;
|
||||
}
|
||||
|
||||
pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pSateTask, false, -1, -1);
|
||||
if (pTask->pState == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SReadHandle handle = {.vnode = pTq->pVnode, .initTqReader = 1, .pStateBackend = pTask->pState};
|
||||
SReadHandle handle = {.vnode = pTq->pVnode,
|
||||
.initTqReader = 1,
|
||||
.pStateBackend = pTask->pState,
|
||||
.fillHistory = pTask->info.fillHistory,
|
||||
.winRange = pTask->dataRange.window};
|
||||
initStorageAPI(&handle.api);
|
||||
|
||||
pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, vgId);
|
||||
|
@ -792,14 +839,25 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) {
|
|||
}
|
||||
|
||||
qSetTaskId(pTask->exec.pExecutor, pTask->id.taskId, pTask->id.streamId);
|
||||
} else if (pTask->taskLevel == TASK_LEVEL__AGG) {
|
||||
pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pTask, false, -1, -1);
|
||||
} else if (pTask->info.taskLevel == TASK_LEVEL__AGG) {
|
||||
SStreamTask* pSateTask = pTask;
|
||||
SStreamTask task = {0};
|
||||
if (pTask->info.fillHistory) {
|
||||
task.id = pTask->streamTaskId;
|
||||
task.pMeta = pTask->pMeta;
|
||||
pSateTask = &task;
|
||||
}
|
||||
pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pSateTask, false, -1, -1);
|
||||
if (pTask->pState == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTask->childEpInfo);
|
||||
SReadHandle handle = {.vnode = NULL, .numOfVgroups = numOfVgroups, .pStateBackend = pTask->pState};
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTask->pUpstreamEpInfoList);
|
||||
SReadHandle handle = {.vnode = NULL,
|
||||
.numOfVgroups = numOfVgroups,
|
||||
.pStateBackend = pTask->pState,
|
||||
.fillHistory = pTask->info.fillHistory,
|
||||
.winRange = pTask->dataRange.window};
|
||||
initStorageAPI(&handle.api);
|
||||
|
||||
pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, vgId);
|
||||
|
@ -834,15 +892,17 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) {
|
|||
tSimpleHashSetFreeFp(pTask->tbSink.pTblInfo, freePtr);
|
||||
}
|
||||
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
SWalFilterCond cond = {.deleteMsg = 1}; // delete msg also extract from wal files
|
||||
pTask->exec.pWalReader = walOpenReader(pTq->pVnode->pWal, &cond);
|
||||
}
|
||||
|
||||
streamSetupTrigger(pTask);
|
||||
streamSetupScheduleTrigger(pTask);
|
||||
|
||||
tqInfo("vgId:%d expand stream task, s-task:%s, checkpoint ver:%" PRId64 " child id:%d, level:%d", vgId,
|
||||
pTask->id.idStr, pTask->chkInfo.version, pTask->selfChildId, pTask->taskLevel);
|
||||
tqInfo("vgId:%d expand stream task, s-task:%s, checkpoint ver:%" PRId64
|
||||
" child id:%d, level:%d, scan-history:%d, trigger:%" PRId64 " ms",
|
||||
vgId, pTask->id.idStr, pTask->chkInfo.version, pTask->info.selfChildId, pTask->info.taskLevel,
|
||||
pTask->info.fillHistory, pTask->triggerParam);
|
||||
|
||||
// next valid version will add one
|
||||
pTask->chkInfo.version += 1;
|
||||
|
@ -858,10 +918,11 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
SDecoder decoder;
|
||||
|
||||
tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen);
|
||||
tDecodeSStreamTaskCheckReq(&decoder, &req);
|
||||
tDecodeStreamTaskCheckReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
int32_t taskId = req.downstreamTaskId;
|
||||
|
||||
SStreamTaskCheckRsp rsp = {
|
||||
.reqId = req.reqId,
|
||||
.streamId = req.streamId,
|
||||
|
@ -878,23 +939,20 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
rsp.status = streamTaskCheckStatus(pTask);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
|
||||
tqDebug("s-task:%s recv task check req(reqId:0x%" PRIx64
|
||||
") %d at node %d task status:%d, check req from task %d at node %d, rsp status %d",
|
||||
pTask->id.idStr, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, pTask->status.taskStatus,
|
||||
rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
tqDebug("s-task:%s recv task check req(reqId:0x%" PRIx64 ") task:0x%x (vgId:%d), status:%s, rsp status %d",
|
||||
pTask->id.idStr, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId,
|
||||
streamGetTaskStatusStr(pTask->status.taskStatus), rsp.status);
|
||||
} else {
|
||||
rsp.status = 0;
|
||||
tqDebug("tq recv task check(taskId:0x%x not built yet) req(reqId:0x%" PRIx64
|
||||
") %d at node %d, check req from task:0x%x at node %d, rsp status %d",
|
||||
taskId, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.upstreamTaskId, rsp.upstreamNodeId,
|
||||
rsp.status);
|
||||
tqDebug("tq recv task check(taskId:0x%x not built yet) req(reqId:0x%" PRIx64 ") from task:0x%x (vgId:%d), rsp status %d",
|
||||
taskId, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
}
|
||||
|
||||
SEncoder encoder;
|
||||
int32_t code;
|
||||
int32_t len;
|
||||
|
||||
tEncodeSize(tEncodeSStreamTaskCheckRsp, &rsp, len, code);
|
||||
tEncodeSize(tEncodeStreamTaskCheckRsp, &rsp, len, code);
|
||||
if (code < 0) {
|
||||
tqError("vgId:%d failed to encode task check rsp, task:0x%x", pTq->pStreamMeta->vgId, taskId);
|
||||
return -1;
|
||||
|
@ -905,7 +963,7 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
|
||||
void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
||||
tEncoderInit(&encoder, (uint8_t*)abuf, len);
|
||||
tEncodeSStreamTaskCheckRsp(&encoder, &rsp);
|
||||
tEncodeStreamTaskCheckRsp(&encoder, &rsp);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
SRpcMsg rspMsg = {.code = 0, .pCont = buf, .contLen = sizeof(SMsgHead) + len, .info = pMsg->info};
|
||||
|
@ -914,13 +972,16 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t sversion, SRpcMsg* pMsg) {
|
||||
char* pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
||||
int32_t code;
|
||||
SStreamTaskCheckRsp rsp;
|
||||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
|
||||
code = tDecodeSStreamTaskCheckRsp(&decoder, &rsp);
|
||||
tDecoderInit(&decoder, (uint8_t*)pReq, len);
|
||||
code = tDecodeStreamTaskCheckRsp(&decoder, &rsp);
|
||||
|
||||
if (code < 0) {
|
||||
tDecoderClear(&decoder);
|
||||
|
@ -928,17 +989,18 @@ int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t sversion, char* msg, int32
|
|||
}
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
tqDebug("tq recv task check rsp(reqId:0x%" PRIx64 ") %d at node %d check req from task:0x%x at node %d, status %d",
|
||||
rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
tqDebug("tq task:0x%x (vgId:%d) recv check rsp(reqId:0x%" PRIx64 ") from 0x%x (vgId:%d) status %d",
|
||||
rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.status);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, rsp.upstreamTaskId);
|
||||
if (pTask == NULL) {
|
||||
tqError("tq failed to locate the stream task:0x%x vgId:%d, it may have been destroyed", rsp.upstreamTaskId,
|
||||
tqError("tq failed to locate the stream task:0x%x (vgId:%d), it may have been destroyed", rsp.upstreamTaskId,
|
||||
pTq->pStreamMeta->vgId);
|
||||
terrno = TSDB_CODE_STREAM_TASK_NOT_EXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
code = streamProcessTaskCheckRsp(pTask, &rsp, sversion);
|
||||
code = streamProcessCheckRsp(pTask, &rsp);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return code;
|
||||
}
|
||||
|
@ -971,105 +1033,232 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t sversion, char* msg, int32_t ms
|
|||
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SStreamMeta* pStreamMeta = pTq->pStreamMeta;
|
||||
|
||||
// 2.save task, use the newest commit version as the initial start version of stream task.
|
||||
taosWLockLatch(&pTq->pStreamMeta->lock);
|
||||
code = streamMetaAddDeployedTask(pTq->pStreamMeta, sversion, pTask);
|
||||
int32_t numOfTasks = streamMetaGetNumOfTasks(pTq->pStreamMeta);
|
||||
taosWLockLatch(&pStreamMeta->lock);
|
||||
code = streamMetaAddDeployedTask(pStreamMeta, sversion, pTask);
|
||||
|
||||
int32_t numOfTasks = streamMetaGetNumOfTasks(pStreamMeta);
|
||||
if (code < 0) {
|
||||
tqError("vgId:%d failed to add s-task:%s, total:%d", vgId, pTask->id.idStr, numOfTasks);
|
||||
taosWUnLockLatch(&pTq->pStreamMeta->lock);
|
||||
taosWUnLockLatch(&pStreamMeta->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
taosWUnLockLatch(&pTq->pStreamMeta->lock);
|
||||
taosWUnLockLatch(&pStreamMeta->lock);
|
||||
|
||||
// 3.go through recover steps to fill history
|
||||
if (pTask->fillHistory) {
|
||||
streamTaskCheckDownstream(pTask, sversion);
|
||||
}
|
||||
// 3. It's an fill history task, do nothing. wait for the main task to start it
|
||||
streamPrepareNdoCheckDownstream(pTask);
|
||||
|
||||
tqDebug("vgId:%d s-task:%s is deployed and add into meta, status:%s, numOfTasks:%d", vgId, pTask->id.idStr,
|
||||
streamGetTaskStatusStr(pTask->status.taskStatus), numOfTasks);
|
||||
|
||||
tqDebug("vgId:%d s-task:%s is deployed and add meta from mnd, status:%d, total:%d", vgId, pTask->id.idStr,
|
||||
pTask->status.taskStatus, numOfTasks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskRecover1Req(STQ* pTq, SRpcMsg* pMsg) {
|
||||
int32_t code;
|
||||
int32_t tqProcessTaskScanHistory(STQ* pTq, SRpcMsg* pMsg) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
char* msg = pMsg->pCont;
|
||||
int32_t msgLen = pMsg->contLen;
|
||||
|
||||
SStreamRecoverStep1Req* pReq = (SStreamRecoverStep1Req*)msg;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
SStreamScanHistoryReq* pReq = (SStreamScanHistoryReq*)msg;
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, pReq->taskId);
|
||||
if (pTask == NULL) {
|
||||
tqError("vgId:%d failed to acquire stream task:0x%x during stream recover, task may have been destroyed",
|
||||
pMeta->vgId, pReq->taskId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check param
|
||||
int64_t fillVer1 = pTask->chkInfo.version;
|
||||
if (fillVer1 <= 0) {
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// do recovery step 1
|
||||
tqDebug("s-task:%s start non-blocking recover stage(step 1) scan", pTask->id.idStr);
|
||||
const char* pId = pTask->id.idStr;
|
||||
tqDebug("s-task:%s start history data scan stage(step 1), status:%s", pId,
|
||||
streamGetTaskStatusStr(pTask->status.taskStatus));
|
||||
|
||||
int64_t st = taosGetTimestampMs();
|
||||
int8_t schedStatus = atomic_val_compare_exchange_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE,
|
||||
TASK_SCHED_STATUS__WAITING);
|
||||
if (schedStatus != TASK_SCHED_STATUS__INACTIVE) {
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
streamSourceRecoverScanStep1(pTask);
|
||||
if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING) {
|
||||
tqDebug("s-task:%s is dropped, abort recover in step1", pTask->id.idStr);
|
||||
if (!pReq->igUntreated && !streamTaskRecoverScanStep1Finished(pTask)) {
|
||||
streamSourceScanHistoryData(pTask);
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING || streamTaskShouldPause(&pTask->status)) {
|
||||
tqDebug("s-task:%s is dropped or paused, abort recover in step1", pId);
|
||||
atomic_store_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
double el = (taosGetTimestampMs() - st) / 1000.0;
|
||||
tqDebug("s-task:%s non-blocking recover stage(step 1) ended, elapsed time:%.2fs", pTask->id.idStr, el);
|
||||
tqDebug("s-task:%s history data scan stage(step 1) ended, elapsed time:%.2fs", pId, el);
|
||||
|
||||
// build msg to launch next step
|
||||
SStreamRecoverStep2Req req;
|
||||
code = streamBuildSourceRecover2Req(pTask, &req);
|
||||
if (code < 0) {
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return -1;
|
||||
if (pTask->info.fillHistory) {
|
||||
SVersionRange* pRange = NULL;
|
||||
SStreamTask* pStreamTask = NULL;
|
||||
|
||||
if (!pReq->igUntreated && !streamTaskRecoverScanStep1Finished(pTask)) {
|
||||
// 1. stop the related stream task, get the current scan wal version of stream task, ver.
|
||||
pStreamTask = streamMetaAcquireTask(pMeta, pTask->streamTaskId.taskId);
|
||||
if (pStreamTask == NULL) {
|
||||
// todo handle error
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING) {
|
||||
ASSERT(pStreamTask->info.taskLevel == TASK_LEVEL__SOURCE);
|
||||
|
||||
// wait for the stream task get ready for scan history data
|
||||
while (((pStreamTask->status.downstreamReady == 0) && (pStreamTask->status.taskStatus != TASK_STATUS__STOP)) ||
|
||||
pStreamTask->status.taskStatus == TASK_STATUS__SCAN_HISTORY) {
|
||||
tqDebug(
|
||||
"s-task:%s level:%d related stream task:%s not ready for halt, wait for it continue and recheck in 100ms",
|
||||
pTask->id.idStr, pTask->info.taskLevel, pStreamTask->id.idStr);
|
||||
taosMsleep(100);
|
||||
}
|
||||
|
||||
// now we can stop the stream task execution
|
||||
pStreamTask->status.taskStatus = TASK_STATUS__HALT;
|
||||
tqDebug("s-task:%s level:%d status is set to halt by history scan task:%s", pStreamTask->id.idStr,
|
||||
pStreamTask->info.taskLevel, pId);
|
||||
|
||||
// if it's an source task, extract the last version in wal.
|
||||
pRange = &pTask->dataRange.range;
|
||||
int64_t latestVer = walReaderGetCurrentVer(pStreamTask->exec.pWalReader);
|
||||
ASSERT(latestVer >= pRange->maxVer);
|
||||
|
||||
int64_t nextStartVer = pRange->maxVer + 1;
|
||||
if (nextStartVer > latestVer - 1) {
|
||||
// no input data yet. no need to execute the secondardy scan while stream task halt
|
||||
streamTaskRecoverSetAllStepFinished(pTask);
|
||||
tqDebug("s-task:%s no need to perform secondary scan-history-data(step 2), since no data ingest during secondary scan", pId);
|
||||
} else {
|
||||
// 2. do secondary scan of the history data, the time window remain, and the version range is updated to
|
||||
// [pTask->dataRange.range.maxVer, ver1]
|
||||
pRange->minVer = nextStartVer;
|
||||
pRange->maxVer = latestVer - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!streamTaskRecoverScanStep1Finished(pTask)) {
|
||||
tqDebug("s-task:%s level:%d verRange:%" PRId64 " - %" PRId64
|
||||
" do secondary scan-history-data after halt the related stream task:%s",
|
||||
pId, pTask->info.taskLevel, pRange->minVer, pRange->maxVer, pStreamTask->id.idStr);
|
||||
ASSERT(pTask->status.schedStatus == TASK_SCHED_STATUS__WAITING);
|
||||
|
||||
st = taosGetTimestampMs();
|
||||
streamSetParamForStreamScannerStep2(pTask, pRange, &pTask->dataRange.window);
|
||||
}
|
||||
|
||||
if (!streamTaskRecoverScanStep2Finished(pTask)) {
|
||||
streamSourceScanHistoryData(pTask);
|
||||
if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING || streamTaskShouldPause(&pTask->status)) {
|
||||
tqDebug("s-task:%s is dropped or paused, abort recover in step1", pId);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// serialize msg
|
||||
int32_t len = sizeof(SStreamRecoverStep1Req);
|
||||
|
||||
void* serializedReq = rpcMallocCont(len);
|
||||
if (serializedReq == NULL) {
|
||||
tqError("s-task:%s failed to prepare the step2 stage, out of memory", pTask->id.idStr);
|
||||
return -1;
|
||||
streamTaskRecoverSetAllStepFinished(pTask);
|
||||
}
|
||||
|
||||
memcpy(serializedReq, &req, len);
|
||||
el = (taosGetTimestampMs() - st) / 1000.0;
|
||||
tqDebug("s-task:%s history data scan stage(step 2) ended, elapsed time:%.2fs", pId, el);
|
||||
|
||||
// dispatch msg
|
||||
tqDebug("s-task:%s start recover block stage", pTask->id.idStr);
|
||||
// 3. notify the downstream tasks to transfer executor state after handle all history blocks.
|
||||
if (!pTask->status.transferState) {
|
||||
code = streamDispatchTransferStateMsg(pTask);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
// todo handle error
|
||||
}
|
||||
|
||||
pTask->status.transferState = true;
|
||||
}
|
||||
|
||||
// 4. 1) transfer the ownership of executor state, 2) update the scan data range for source task.
|
||||
// 5. resume the related stream task.
|
||||
streamTryExec(pTask);
|
||||
|
||||
pTask->status.taskStatus = TASK_STATUS__DROPPING;
|
||||
tqDebug("s-task:%s scan-history-task set status to be dropping", pId);
|
||||
|
||||
streamMetaSaveTask(pMeta, pTask);
|
||||
streamMetaSaveTask(pMeta, pStreamTask);
|
||||
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
streamMetaReleaseTask(pMeta, pStreamTask);
|
||||
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
if (streamMetaCommit(pTask->pMeta) < 0) {
|
||||
// persist to disk
|
||||
}
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
} else {
|
||||
// todo update the chkInfo version for current task.
|
||||
// this task has an associated history stream task, so we need to scan wal from the end version of
|
||||
// history scan. The current version of chkInfo.current is not updated during the history scan
|
||||
STimeWindow* pWindow = &pTask->dataRange.window;
|
||||
|
||||
if (pTask->historyTaskId.taskId == 0) {
|
||||
*pWindow = (STimeWindow){INT64_MIN, INT64_MAX};
|
||||
tqDebug("s-task:%s no associated task, reset the time window:%" PRId64 " - %" PRId64, pId, pWindow->skey,
|
||||
pWindow->ekey);
|
||||
} else {
|
||||
tqDebug("s-task:%s history data scan completed, now start to scan data from wal, start ver:%" PRId64
|
||||
", window:%" PRId64 " - %" PRId64,
|
||||
pId, pTask->chkInfo.currentVer, pWindow->skey, pWindow->ekey);
|
||||
}
|
||||
|
||||
code = streamTaskScanHistoryDataComplete(pTask);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
|
||||
// let's start the stream task by extracting data from wal
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
tqStartStreamTasks(pTq);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
SRpcMsg rpcMsg = {
|
||||
.code = 0, .contLen = len, .msgType = TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE, .pCont = serializedReq};
|
||||
tmsgPutToQueue(&pTq->pVnode->msgCb, WRITE_QUEUE, &rpcMsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
int32_t code = 0;
|
||||
// notify the downstream tasks to transfer executor state after handle all history blocks.
|
||||
int32_t tqProcessTaskTransferStateReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
SStreamTransferReq req;
|
||||
|
||||
SStreamRecoverStep2Req* pReq = (SStreamRecoverStep2Req*)msg;
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
|
||||
int32_t code = tDecodeStreamRecoverFinishReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId);
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, req.taskId);
|
||||
if (pTask == NULL) {
|
||||
tqError("failed to find task:0x%x, it may have been dropped already", req.taskId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// do recovery step 2
|
||||
// transfer the ownership of executor state
|
||||
streamTaskReleaseState(pTask);
|
||||
tqDebug("s-task:%s receive state transfer req", pTask->id.idStr);
|
||||
|
||||
SStreamTask* pStreamTask = streamMetaAcquireTask(pTq->pStreamMeta, pTask->streamTaskId.taskId);
|
||||
streamTaskReloadState(pStreamTask);
|
||||
|
||||
ASSERT(pTask->streamTaskId.taskId != 0);
|
||||
pTask->status.transferState = true; // persistent data?
|
||||
|
||||
#if 0
|
||||
// do check if current task handle all data in the input queue
|
||||
int64_t st = taosGetTimestampMs();
|
||||
tqDebug("s-task:%s start step2 recover, ts:%" PRId64, pTask->id.idStr, st);
|
||||
|
||||
|
@ -1108,16 +1297,19 @@ int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t sversion, char* msg, int32_t
|
|||
tqDebug("s-task:%s step2 recover finished, el:%.2fs", pTask->id.idStr, el);
|
||||
|
||||
// dispatch recover finish req to all related downstream task
|
||||
code = streamDispatchRecoverFinishReq(pTask);
|
||||
code = streamDispatchScanHistoryFinishMsg(pTask);
|
||||
if (code < 0) {
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
atomic_store_8(&pTask->fillHistory, 0);
|
||||
atomic_store_8(&pTask->info.fillHistory, 0);
|
||||
streamMetaSaveTask(pTq->pStreamMeta, pTask);
|
||||
#endif
|
||||
|
||||
streamSchedExec(pTask);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1130,7 +1322,7 @@ int32_t tqProcessTaskRecoverFinishReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
|
||||
tDecodeSStreamRecoverFinishReq(&decoder, &req);
|
||||
tDecodeStreamRecoverFinishReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
// find task
|
||||
|
@ -1139,7 +1331,7 @@ int32_t tqProcessTaskRecoverFinishReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
return -1;
|
||||
}
|
||||
// do process request
|
||||
if (streamProcessRecoverFinishReq(pTask, req.childId) < 0) {
|
||||
if (streamProcessRecoverFinishReq(pTask, req.taskId, req.childId) < 0) {
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1212,22 +1404,31 @@ int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
int32_t taskId = pReq->taskId;
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
|
||||
if (taskId == WAL_READ_TASKS_ID) { // all tasks are extracted submit data from the wal
|
||||
if (taskId == STREAM_TASK_STATUS_CHECK_ID) {
|
||||
tqStreamTasksStatusCheck(pTq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (taskId == EXTRACT_DATA_FROM_WAL_ID) { // all tasks are extracted submit data from the wal
|
||||
tqStreamTasksScanWal(pTq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId);
|
||||
if (pTask != NULL) {
|
||||
if (pTask->status.taskStatus == TASK_STATUS__NORMAL) {
|
||||
tqDebug("vgId:%d s-task:%s start to process block from wal, last chk point:%" PRId64, vgId, pTask->id.idStr,
|
||||
// even in halt status, the data in inputQ must be processed
|
||||
int8_t status = pTask->status.taskStatus;
|
||||
if (status == TASK_STATUS__NORMAL || status == TASK_STATUS__HALT) {
|
||||
tqDebug("vgId:%d s-task:%s start to process block from inputQ, last chk point:%" PRId64, vgId, pTask->id.idStr,
|
||||
pTask->chkInfo.version);
|
||||
streamProcessRunReq(pTask);
|
||||
} else {
|
||||
if (streamTaskShouldPause(&pTask->status)) {
|
||||
// if (streamTaskShouldPause(&pTask->status)) {
|
||||
atomic_store_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE);
|
||||
}
|
||||
tqDebug("vgId:%d s-task:%s ignore run req since not in ready state", vgId, pTask->id.idStr);
|
||||
// }
|
||||
|
||||
tqDebug("vgId:%d s-task:%s ignore run req since not in ready state, status:%s, sched-status:%d", vgId,
|
||||
pTask->id.idStr, streamGetTaskStatusStr(pTask->status.taskStatus), pTask->status.schedStatus);
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
|
@ -1286,28 +1487,42 @@ int32_t tqProcessTaskDropReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgL
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskPauseReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
SVPauseStreamTaskReq* pReq = (SVPauseStreamTaskReq*)msg;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId);
|
||||
int32_t tqProcessTaskPauseImpl(SStreamMeta* pStreamMeta, SStreamTask* pTask) {
|
||||
if (pTask) {
|
||||
tqDebug("vgId:%d s-task:%s set pause flag", pTq->pStreamMeta->vgId, pTask->id.idStr);
|
||||
if (!streamTaskShouldPause(&pTask->status)) {
|
||||
tqDebug("vgId:%d s-task:%s set pause flag", pStreamMeta->vgId, pTask->id.idStr);
|
||||
atomic_store_8(&pTask->status.keepTaskStatus, pTask->status.taskStatus);
|
||||
atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__PAUSE);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
}
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskResumeReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
SVResumeStreamTaskReq* pReq = (SVResumeStreamTaskReq*)msg;
|
||||
|
||||
int32_t vgId = pTq->pStreamMeta->vgId;
|
||||
int32_t tqProcessTaskPauseReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
SVPauseStreamTaskReq* pReq = (SVPauseStreamTaskReq*)msg;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId);
|
||||
int32_t code = tqProcessTaskPauseImpl(pTq->pStreamMeta, pTask);
|
||||
if (code != 0) {
|
||||
return code;
|
||||
}
|
||||
SStreamTask* pHistoryTask = streamMetaAcquireTask(pTq->pStreamMeta, pTask->historyTaskId.taskId);
|
||||
if (pHistoryTask) {
|
||||
code = tqProcessTaskPauseImpl(pTq->pStreamMeta, pHistoryTask);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskResumeImpl(STQ* pTq, SStreamTask* pTask, int64_t sversion, int8_t igUntreated) {
|
||||
int32_t vgId = pTq->pStreamMeta->vgId;
|
||||
if (pTask) {
|
||||
if (streamTaskShouldPause(&pTask->status)) {
|
||||
atomic_store_8(&pTask->status.taskStatus, pTask->status.keepTaskStatus);
|
||||
|
||||
// no lock needs to secure the access of the version
|
||||
if (pReq->igUntreated && pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (igUntreated && pTask->info.taskLevel == TASK_LEVEL__SOURCE && !pTask->info.fillHistory) {
|
||||
// discard all the data when the stream task is suspended.
|
||||
walReaderSetSkipToVersion(pTask->exec.pWalReader, sversion);
|
||||
tqDebug("vgId:%d s-task:%s resume to exec, prev paused version:%" PRId64 ", start from vnode ver:%" PRId64
|
||||
|
@ -1318,33 +1533,54 @@ int32_t tqProcessTaskResumeReq(STQ* pTq, int64_t sversion, char* msg, int32_t ms
|
|||
vgId, pTask->id.idStr, pTask->chkInfo.currentVer, sversion, pTask->status.schedStatus);
|
||||
}
|
||||
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE && taosQueueItemSize(pTask->inputQueue->queue) == 0) {
|
||||
if (pTask->info.fillHistory && pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
streamStartRecoverTask(pTask, igUntreated);
|
||||
} else if (pTask->info.taskLevel == TASK_LEVEL__SOURCE && taosQueueItemSize(pTask->inputQueue->queue) == 0) {
|
||||
tqStartStreamTasks(pTq);
|
||||
} else {
|
||||
streamSchedExec(pTask);
|
||||
}
|
||||
}
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
} else {
|
||||
tqError("vgId:%d failed to find the s-task:0x%x for resume stream task", vgId, pReq->taskId);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqProcessTaskResumeReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
|
||||
SVResumeStreamTaskReq* pReq = (SVResumeStreamTaskReq*)msg;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId);
|
||||
int32_t code = tqProcessTaskResumeImpl(pTq, pTask, sversion, pReq->igUntreated);
|
||||
if (code != 0) {
|
||||
return code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
SStreamTask* pHistoryTask = streamMetaAcquireTask(pTq->pStreamMeta, pTask->historyTaskId.taskId);
|
||||
if (pHistoryTask) {
|
||||
code = tqProcessTaskResumeImpl(pTq, pHistoryTask, sversion, pReq->igUntreated);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
SStreamRetrieveReq req;
|
||||
tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen);
|
||||
tDecodeStreamRetrieveReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
int32_t taskId = req.dstTaskId;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId);
|
||||
|
||||
if (pTask) {
|
||||
SRpcMsg rsp = {.info = pMsg->info, .code = 0};
|
||||
streamProcessRetrieveReq(pTask, &req, &rsp);
|
||||
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
tDeleteStreamRetrieveReq(&req);
|
||||
return 0;
|
||||
|
@ -1425,46 +1661,6 @@ FAIL:
|
|||
|
||||
int32_t tqCheckLogInWal(STQ* pTq, int64_t sversion) { return sversion <= pTq->walLogLastVer; }
|
||||
|
||||
int32_t tqStartStreamTasks(STQ* pTq) {
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
if (numOfTasks == 0) {
|
||||
tqInfo("vgId:%d no stream tasks exist", vgId);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMeta->walScanCounter += 1;
|
||||
|
||||
if (pMeta->walScanCounter > 1) {
|
||||
tqDebug("vgId:%d wal read task has been launched, remain scan times:%d", vgId, pMeta->walScanCounter);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
|
||||
if (pRunReq == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
tqError("vgId:%d failed to create msg to start wal scanning to launch stream tasks, code:%s", vgId, terrstr());
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tqDebug("vgId:%d create msg to start wal scan to launch stream tasks, numOfTasks:%d", vgId, numOfTasks);
|
||||
pRunReq->head.vgId = vgId;
|
||||
pRunReq->streamId = 0;
|
||||
pRunReq->taskId = WAL_READ_TASKS_ID;
|
||||
|
||||
SRpcMsg msg = {.msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq)};
|
||||
tmsgPutToQueue(&pTq->pVnode->msgCb, STREAM_QUEUE, &msg);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int32_t tqProcessStreamCheckPointReq(STQ* pTq, int64_t sversion, char* pMsg, int32_t msgLen) {
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
|
|
|
@ -114,7 +114,7 @@ bool isValValidForTable(STqHandle* pHandle, SWalCont* pHead) {
|
|||
}
|
||||
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pHandle->execHandle.pTqReader->pVnodeMeta, 0);
|
||||
metaReaderDoInit(&mr, pHandle->execHandle.pTqReader->pVnodeMeta, 0);
|
||||
|
||||
if (metaGetTableEntryByName(&mr, req.tbName) < 0) {
|
||||
metaReaderClear(&mr);
|
||||
|
@ -216,9 +216,9 @@ int32_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHea
|
|||
code = 0;
|
||||
goto END;
|
||||
} else {
|
||||
if (pHandle->fetchMeta) {
|
||||
if (pHandle->fetchMeta != WITH_DATA) {
|
||||
SWalCont* pHead = &((*ppCkHead)->head);
|
||||
if (IS_META_MSG(pHead->msgType)) {
|
||||
if (IS_META_MSG(pHead->msgType) && !(pHead->msgType == TDMT_VND_DELETE && pHandle->fetchMeta == ONLY_META)) {
|
||||
code = walFetchBody(pHandle->pWalReader, ppCkHead);
|
||||
if (code < 0) {
|
||||
*fetchOffset = offset;
|
||||
|
@ -388,7 +388,7 @@ bool tqNextBlockInWal(STqReader* pReader, const char* id) {
|
|||
|
||||
int32_t numOfBlocks = taosArrayGetSize(pReader->submit.aSubmitTbData);
|
||||
while (pReader->nextBlk < numOfBlocks) {
|
||||
tqDebug("tq reader next data block %d/%d, len:%d %" PRId64 " %d", pReader->nextBlk,
|
||||
tqTrace("tq reader next data block %d/%d, len:%d %" PRId64 " %d", pReader->nextBlk,
|
||||
numOfBlocks, pReader->msg.msgLen, pReader->msg.ver, pReader->nextBlk);
|
||||
|
||||
SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk);
|
||||
|
@ -403,7 +403,7 @@ bool tqNextBlockInWal(STqReader* pReader, const char* id) {
|
|||
|
||||
void* ret = taosHashGet(pReader->tbIdHash, &pSubmitTbData->uid, sizeof(int64_t));
|
||||
if (ret != NULL) {
|
||||
tqDebug("tq reader return submit block, uid:%" PRId64 ", ver:%" PRId64, pSubmitTbData->uid, pReader->msg.ver);
|
||||
tqTrace("tq reader return submit block, uid:%" PRId64 ", ver:%" PRId64, pSubmitTbData->uid, pReader->msg.ver);
|
||||
|
||||
SSDataBlock* pRes = NULL;
|
||||
int32_t code = tqRetrieveDataBlock(pReader, &pRes, NULL);
|
||||
|
@ -412,11 +412,11 @@ bool tqNextBlockInWal(STqReader* pReader, const char* id) {
|
|||
}
|
||||
} else {
|
||||
pReader->nextBlk += 1;
|
||||
tqDebug("tq reader discard submit block, uid:%" PRId64 ", continue", pSubmitTbData->uid);
|
||||
tqTrace("tq reader discard submit block, uid:%" PRId64 ", continue", pSubmitTbData->uid);
|
||||
}
|
||||
}
|
||||
|
||||
qDebug("stream scan return empty, all %d submit blocks consumed, %s", numOfBlocks, id);
|
||||
qTrace("stream scan return empty, all %d submit blocks consumed, %s", numOfBlocks, id);
|
||||
tDestroySubmitReq(&pReader->submit, TSDB_MSG_FLG_DECODE);
|
||||
|
||||
pReader->msg.msgStr = NULL;
|
||||
|
@ -604,7 +604,7 @@ static int32_t doSetVal(SColumnInfoData* pColumnInfoData, int32_t rowIndex, SCol
|
|||
}
|
||||
|
||||
int32_t tqRetrieveDataBlock(STqReader* pReader, SSDataBlock** pRes, const char* id) {
|
||||
tqDebug("tq reader retrieve data block %p, index:%d", pReader->msg.msgStr, pReader->nextBlk);
|
||||
tqTrace("tq reader retrieve data block %p, index:%d", pReader->msg.msgStr, pReader->nextBlk);
|
||||
SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk++);
|
||||
|
||||
SSDataBlock* pBlock = pReader->pResBlock;
|
||||
|
@ -1109,7 +1109,7 @@ int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) {
|
|||
}
|
||||
|
||||
SStreamTask* pTask = *(SStreamTask**)pIter;
|
||||
if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (pTask->info.taskLevel == TASK_LEVEL__SOURCE) {
|
||||
int32_t code = qUpdateTableListForStreamScanner(pTask->exec.pExecutor, tbUidList, isAdd);
|
||||
if (code != 0) {
|
||||
tqError("vgId:%d, s-task:%s update qualified table error for stream task", vgId, pTask->id.idStr);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "tq.h"
|
||||
|
||||
static int32_t createStreamTaskRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle);
|
||||
static int32_t doSetOffsetForWalReader(SStreamTask *pTask, int32_t vgId);
|
||||
|
||||
// this function should be executed by stream threads.
|
||||
// extract submit block from WAL, and add them into the input queue for the sources tasks.
|
||||
|
@ -57,7 +58,111 @@ int32_t tqStreamTasksScanWal(STQ* pTq) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t doSetOffsetForWalReader(SStreamTask *pTask, int32_t vgId) {
|
||||
int32_t tqStreamTasksStatusCheck(STQ* pTq) {
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
tqDebug("vgId:%d start to check all (%d) stream tasks downstream status", vgId, numOfTasks);
|
||||
if (numOfTasks == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SArray* pTaskList = NULL;
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
pTaskList = taosArrayDup(pMeta->pTaskList, NULL);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
|
||||
for (int32_t i = 0; i < numOfTasks; ++i) {
|
||||
int32_t* pTaskId = taosArrayGet(pTaskList, i);
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, *pTaskId);
|
||||
if (pTask == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
streamTaskCheckDownstreamTasks(pTask);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
}
|
||||
taosArrayDestroy(pTaskList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqCheckStreamStatus(STQ* pTq) {
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
if (numOfTasks == 0) {
|
||||
tqInfo("vgId:%d no stream tasks exist", vgId);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
|
||||
if (pRunReq == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
tqError("vgId:%d failed to create msg to start wal scanning to launch stream tasks, code:%s", vgId, terrstr());
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tqDebug("vgId:%d check for stream tasks status, numOfTasks:%d", vgId, numOfTasks);
|
||||
pRunReq->head.vgId = vgId;
|
||||
pRunReq->streamId = 0;
|
||||
pRunReq->taskId = STREAM_TASK_STATUS_CHECK_ID;
|
||||
|
||||
SRpcMsg msg = {.msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq)};
|
||||
tmsgPutToQueue(&pTq->pVnode->msgCb, STREAM_QUEUE, &msg);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqStartStreamTasks(STQ* pTq) {
|
||||
int32_t vgId = TD_VID(pTq->pVnode);
|
||||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
|
||||
taosWLockLatch(&pMeta->lock);
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
if (numOfTasks == 0) {
|
||||
tqInfo("vgId:%d no stream tasks exist", vgId);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMeta->walScanCounter += 1;
|
||||
|
||||
if (pMeta->walScanCounter > 1) {
|
||||
tqDebug("vgId:%d wal read task has been launched, remain scan times:%d", vgId, pMeta->walScanCounter);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
|
||||
if (pRunReq == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
tqError("vgId:%d failed to create msg to start wal scanning to launch stream tasks, code:%s", vgId, terrstr());
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tqDebug("vgId:%d create msg to start wal scan to launch stream tasks, numOfTasks:%d", vgId, numOfTasks);
|
||||
pRunReq->head.vgId = vgId;
|
||||
pRunReq->streamId = 0;
|
||||
pRunReq->taskId = EXTRACT_DATA_FROM_WAL_ID;
|
||||
|
||||
SRpcMsg msg = {.msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq)};
|
||||
tmsgPutToQueue(&pTq->pVnode->msgCb, STREAM_QUEUE, &msg);
|
||||
taosWUnLockLatch(&pMeta->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t doSetOffsetForWalReader(SStreamTask *pTask, int32_t vgId) {
|
||||
// seek the stored version and extract data from WAL
|
||||
int64_t firstVer = walReaderGetValidFirstVer(pTask->exec.pWalReader);
|
||||
if (pTask->chkInfo.currentVer < firstVer) {
|
||||
|
@ -102,7 +207,7 @@ static int32_t doSetOffsetForWalReader(SStreamTask *pTask, int32_t vgId) {
|
|||
|
||||
int32_t createStreamTaskRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle) {
|
||||
*pScanIdle = true;
|
||||
bool noNewDataInWal = true;
|
||||
bool noDataInWal = true;
|
||||
int32_t vgId = pStreamMeta->vgId;
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pStreamMeta->pTaskList);
|
||||
|
@ -129,15 +234,13 @@ int32_t createStreamTaskRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle) {
|
|||
}
|
||||
|
||||
int32_t status = pTask->status.taskStatus;
|
||||
if (pTask->taskLevel != TASK_LEVEL__SOURCE) {
|
||||
// tqTrace("s-task:%s level:%d not source task, no need to start", pTask->id.idStr, pTask->taskLevel);
|
||||
if (pTask->info.taskLevel != TASK_LEVEL__SOURCE) {
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streamTaskShouldStop(&pTask->status) || status == TASK_STATUS__RECOVER_PREPARE ||
|
||||
status == TASK_STATUS__WAIT_DOWNSTREAM || streamTaskShouldPause(&pTask->status)) {
|
||||
tqDebug("s-task:%s not ready for new submit block from wal, status:%d", pTask->id.idStr, status);
|
||||
if (status != TASK_STATUS__NORMAL) {
|
||||
tqDebug("s-task:%s not ready for new submit block from wal, status:%s", pTask->id.idStr, streamGetTaskStatusStr(status));
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
@ -157,39 +260,47 @@ int32_t createStreamTaskRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle) {
|
|||
continue;
|
||||
}
|
||||
|
||||
int32_t numOfItemsInQ = taosQueueItemSize(pTask->inputQueue->queue);
|
||||
|
||||
// append the data for the stream
|
||||
SStreamQueueItem* pItem = NULL;
|
||||
code = extractMsgFromWal(pTask->exec.pWalReader, (void**) &pItem, pTask->id.idStr);
|
||||
if (code != TSDB_CODE_SUCCESS) { // failed, continue
|
||||
|
||||
if ((code != TSDB_CODE_SUCCESS || pItem == NULL) && (numOfItemsInQ == 0)) { // failed, continue
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
// delete ignore
|
||||
if (pItem == NULL) {
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
noNewDataInWal = false;
|
||||
|
||||
code = tqAddInputBlockNLaunchTask(pTask, pItem);
|
||||
if (pItem != NULL) {
|
||||
noDataInWal = false;
|
||||
code = tAppendDataToInputQueue(pTask, pItem);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
pTask->chkInfo.currentVer = walReaderGetCurrentVer(pTask->exec.pWalReader);
|
||||
tqDebug("s-task:%s set the ver:%" PRId64 " from WALReader after extract block from WAL", pTask->id.idStr,
|
||||
pTask->chkInfo.currentVer);
|
||||
} else {
|
||||
tqError("s-task:%s append input queue failed, ver:%" PRId64, pTask->id.idStr, pTask->chkInfo.currentVer);
|
||||
tqError("s-task:%s append input queue failed, too many in inputQ, ver:%" PRId64, pTask->id.idStr,
|
||||
pTask->chkInfo.currentVer);
|
||||
}
|
||||
}
|
||||
|
||||
if ((code == TSDB_CODE_SUCCESS) || (numOfItemsInQ > 0)) {
|
||||
code = streamSchedExec(pTask);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pStreamMeta, pTask);
|
||||
}
|
||||
|
||||
// all wal are checked, and no new data available in wal.
|
||||
if (noNewDataInWal) {
|
||||
if (noDataInWal) {
|
||||
*pScanIdle = true;
|
||||
}
|
||||
|
||||
taosArrayDestroy(pTaskList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, STaosxRsp* pRsp
|
|||
|
||||
static int32_t tqAddTbNameToRsp(const STQ* pTq, int64_t uid, STaosxRsp* pRsp, int32_t n) {
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pTq->pVnode->pMeta, 0);
|
||||
metaReaderDoInit(&mr, pTq->pVnode->pMeta, 0);
|
||||
|
||||
// TODO add reference to gurantee success
|
||||
if (metaReaderGetTableEntryByUidCache(&mr, uid) < 0) {
|
||||
|
@ -215,19 +215,15 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
taosArrayClear(pSchemas);
|
||||
SSubmitTbData* pSubmitTbDataRet = NULL;
|
||||
if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas, &pSubmitTbDataRet) < 0) {
|
||||
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;
|
||||
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) goto loop_table;
|
||||
}
|
||||
if (pRsp->withTbName) {
|
||||
int64_t uid = pExec->pTqReader->lastBlkUid;
|
||||
if (tqAddTbNameToRsp(pTq, uid, pRsp, taosArrayGetSize(pBlocks)) < 0) {
|
||||
taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes);
|
||||
taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper);
|
||||
pBlocks = taosArrayInit(0, sizeof(SSDataBlock));
|
||||
pSchemas = taosArrayInit(0, sizeof(void*));
|
||||
continue;
|
||||
goto loop_table;
|
||||
}
|
||||
}
|
||||
if (pHandle->fetchMeta && pSubmitTbDataRet->pCreateTbReq != NULL) {
|
||||
if (pHandle->fetchMeta != WITH_DATA && pSubmitTbDataRet->pCreateTbReq != NULL) {
|
||||
if (pRsp->createTableNum == 0) {
|
||||
pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t));
|
||||
pRsp->createTableReq = taosArrayInit(0, sizeof(void*));
|
||||
|
@ -237,7 +233,7 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
uint32_t len = 0;
|
||||
tEncodeSize(tEncodeSVCreateTbReq, pSubmitTbDataRet->pCreateTbReq, len, code);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
continue;
|
||||
goto loop_table;
|
||||
}
|
||||
void* createReq = taosMemoryCalloc(1, len);
|
||||
SEncoder encoder = {0};
|
||||
|
@ -246,7 +242,7 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
if (code < 0) {
|
||||
tEncoderClear(&encoder);
|
||||
taosMemoryFree(createReq);
|
||||
continue;
|
||||
goto loop_table;
|
||||
}
|
||||
|
||||
taosArrayPush(pRsp->createTableLen, &len);
|
||||
|
@ -255,6 +251,9 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
|
||||
tEncoderClear(&encoder);
|
||||
}
|
||||
if (pHandle->fetchMeta == ONLY_META && pSubmitTbDataRet->pCreateTbReq == NULL){
|
||||
goto loop_table;
|
||||
}
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pBlocks); i++) {
|
||||
SSDataBlock* pBlock = taosArrayGet(pBlocks, i);
|
||||
tqAddBlockDataToRsp(pBlock, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlock->pDataBlock),
|
||||
|
@ -265,6 +264,12 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
taosArrayPush(pRsp->blockSchema, &pSW);
|
||||
pRsp->blockNum++;
|
||||
}
|
||||
continue;
|
||||
loop_table:
|
||||
taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes);
|
||||
taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper);
|
||||
pBlocks = taosArrayInit(0, sizeof(SSDataBlock));
|
||||
pSchemas = taosArrayInit(0, sizeof(void*));
|
||||
}
|
||||
} else if (pExec->subType == TOPIC_SUB_TYPE__DB) {
|
||||
STqReader* pReader = pExec->pTqReader;
|
||||
|
@ -274,19 +279,15 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
taosArrayClear(pSchemas);
|
||||
SSubmitTbData* pSubmitTbDataRet = NULL;
|
||||
if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas, &pSubmitTbDataRet) < 0) {
|
||||
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;
|
||||
if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) goto loop_db;
|
||||
}
|
||||
if (pRsp->withTbName) {
|
||||
int64_t uid = pExec->pTqReader->lastBlkUid;
|
||||
if (tqAddTbNameToRsp(pTq, uid, pRsp, taosArrayGetSize(pBlocks)) < 0) {
|
||||
taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes);
|
||||
taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper);
|
||||
pBlocks = taosArrayInit(0, sizeof(SSDataBlock));
|
||||
pSchemas = taosArrayInit(0, sizeof(void*));
|
||||
continue;
|
||||
goto loop_db;
|
||||
}
|
||||
}
|
||||
if (pHandle->fetchMeta && pSubmitTbDataRet->pCreateTbReq != NULL) {
|
||||
if (pHandle->fetchMeta != WITH_DATA && pSubmitTbDataRet->pCreateTbReq != NULL) {
|
||||
if (pRsp->createTableNum == 0) {
|
||||
pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t));
|
||||
pRsp->createTableReq = taosArrayInit(0, sizeof(void*));
|
||||
|
@ -296,7 +297,7 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
uint32_t len = 0;
|
||||
tEncodeSize(tEncodeSVCreateTbReq, pSubmitTbDataRet->pCreateTbReq, len, code);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
continue;
|
||||
goto loop_db;
|
||||
}
|
||||
void* createReq = taosMemoryCalloc(1, len);
|
||||
SEncoder encoder = {0};
|
||||
|
@ -305,7 +306,7 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
if (code < 0) {
|
||||
tEncoderClear(&encoder);
|
||||
taosMemoryFree(createReq);
|
||||
continue;
|
||||
goto loop_db;
|
||||
}
|
||||
|
||||
taosArrayPush(pRsp->createTableLen, &len);
|
||||
|
@ -314,6 +315,9 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
|
||||
tEncoderClear(&encoder);
|
||||
}
|
||||
if (pHandle->fetchMeta == ONLY_META && pSubmitTbDataRet->pCreateTbReq == NULL){
|
||||
goto loop_db;
|
||||
}
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pBlocks); i++) {
|
||||
SSDataBlock* pBlock = taosArrayGet(pBlocks, i);
|
||||
tqAddBlockDataToRsp(pBlock, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlock->pDataBlock),
|
||||
|
@ -324,6 +328,12 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxR
|
|||
taosArrayPush(pRsp->blockSchema, &pSW);
|
||||
pRsp->blockNum++;
|
||||
}
|
||||
continue;
|
||||
loop_db:
|
||||
taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes);
|
||||
taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper);
|
||||
pBlocks = taosArrayInit(0, sizeof(SSDataBlock));
|
||||
pSchemas = taosArrayInit(0, sizeof(void*));
|
||||
}
|
||||
}
|
||||
taosArrayDestroy(pBlocks);
|
||||
|
|
|
@ -309,7 +309,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d
|
|||
tbData.uid = pTableSinkInfo->uid;
|
||||
} else {
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pVnode->pMeta, 0);
|
||||
metaReaderDoInit(&mr, pVnode->pMeta, 0);
|
||||
if (metaGetTableEntryByName(&mr, ctbName) < 0) {
|
||||
metaReaderClear(&mr);
|
||||
taosMemoryFree(pTableSinkInfo);
|
||||
|
@ -335,6 +335,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d
|
|||
tagArray = taosArrayInit(1, sizeof(STagVal));
|
||||
if (!tagArray) {
|
||||
tdDestroySVCreateTbReq(pCreateTbReq);
|
||||
taosMemoryFreeClear(pCreateTbReq);
|
||||
goto _end;
|
||||
}
|
||||
STagVal tagVal = {
|
||||
|
@ -350,6 +351,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d
|
|||
tagArray = taosArrayDestroy(tagArray);
|
||||
if (pTag == NULL) {
|
||||
tdDestroySVCreateTbReq(pCreateTbReq);
|
||||
taosMemoryFreeClear(pCreateTbReq);
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _end;
|
||||
}
|
||||
|
@ -410,7 +412,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d
|
|||
if (k == 0) {
|
||||
SColumnInfoData* pColData = taosArrayGet(pDataBlock->pDataBlock, dataIndex);
|
||||
void* colData = colDataGetData(pColData, j);
|
||||
tqDebug("tq sink pipe2, row %d, col %d ts %" PRId64, j, k, *(int64_t*)colData);
|
||||
tqTrace("tq sink pipe2, row %d, col %d ts %" PRId64, j, k, *(int64_t*)colData);
|
||||
}
|
||||
if (IS_SET_NULL(pCol)) {
|
||||
SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);
|
||||
|
|
|
@ -20,12 +20,6 @@
|
|||
static int32_t tqSendMetaPollRsp(STqHandle* pHandle, const SRpcMsg* pMsg, const SMqPollReq* pReq,
|
||||
const SMqMetaRsp* pRsp, int32_t vgId);
|
||||
|
||||
char* createStreamTaskIdStr(int64_t streamId, int32_t taskId) {
|
||||
char buf[128] = {0};
|
||||
sprintf(buf, "0x%" PRIx64 "-0x%x", streamId, taskId);
|
||||
return taosStrdup(buf);
|
||||
}
|
||||
|
||||
int32_t tqAddInputBlockNLaunchTask(SStreamTask* pTask, SStreamQueueItem* pQueueItem) {
|
||||
int32_t code = tAppendDataToInputQueue(pTask, pQueueItem);
|
||||
if (code < 0) {
|
||||
|
@ -123,28 +117,17 @@ static int32_t extractResetOffsetVal(STqOffsetVal* pOffsetVal, STQ* pTq, STqHand
|
|||
}
|
||||
} else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) {
|
||||
walRefLastVer(pTq->pVnode->pWal, pHandle->pRef);
|
||||
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||
SMqDataRsp dataRsp = {0};
|
||||
tqInitDataRsp(&dataRsp, pRequest);
|
||||
|
||||
tqOffsetResetToLog(&dataRsp.rspOffset, pHandle->pRef->refVer);
|
||||
tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, (latest) offset reset to %" PRId64, consumerId,
|
||||
pHandle->subKey, vgId, dataRsp.rspOffset.version);
|
||||
int32_t code = tqSendDataRsp(pHandle, pMsg, pRequest, &dataRsp, TMQ_MSG_TYPE__POLL_RSP, vgId);
|
||||
int32_t code = tqSendDataRsp(pHandle, pMsg, pRequest, &dataRsp, TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
tDeleteMqDataRsp(&dataRsp);
|
||||
|
||||
*pBlockReturned = true;
|
||||
return code;
|
||||
} else {
|
||||
STaosxRsp taosxRsp = {0};
|
||||
tqInitTaosxRsp(&taosxRsp, pRequest);
|
||||
tqOffsetResetToLog(&taosxRsp.rspOffset, pHandle->pRef->refVer);
|
||||
int32_t code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
|
||||
tDeleteSTaosxRsp(&taosxRsp);
|
||||
|
||||
*pBlockReturned = true;
|
||||
return code;
|
||||
}
|
||||
} else if (reqOffset.type == TMQ_OFFSET__RESET_NONE) {
|
||||
tqError("tmq poll: subkey:%s, no offset committed for consumer:0x%" PRIx64
|
||||
" in vg %d, subkey %s, reset none failed",
|
||||
|
@ -187,7 +170,7 @@ static int32_t extractDataAndRspForNormalSubscribe(STQ* pTq, STqHandle* pHandle,
|
|||
}
|
||||
}
|
||||
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&dataRsp, TMQ_MSG_TYPE__POLL_RSP, vgId);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&dataRsp, TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
|
||||
end : {
|
||||
char buf[TSDB_OFFSET_LEN] = {0};
|
||||
|
@ -230,7 +213,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
|
|||
pRequest->consumerId, pHandle->subKey, vgId, taosxRsp.blockNum, taosxRsp.rspOffset.type,
|
||||
taosxRsp.rspOffset.uid, taosxRsp.rspOffset.ts);
|
||||
if (taosxRsp.blockNum > 0) {
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
goto end;
|
||||
} else {
|
||||
*offset = taosxRsp.rspOffset;
|
||||
|
@ -260,7 +243,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
|
|||
|
||||
if (tqFetchLog(pTq, pHandle, &fetchVer, &pCkHead, pRequest->reqId) < 0) {
|
||||
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -272,7 +255,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
|
|||
if (pHead->msgType != TDMT_VND_SUBMIT) {
|
||||
if (totalRows > 0) {
|
||||
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer - 1);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -301,7 +284,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
|
|||
|
||||
if (totalRows >= 4096 || taosxRsp.createTableNum > 0) {
|
||||
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
|
||||
code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, taosxRsp.createTableNum > 0 ? TMQ_MSG_TYPE__POLL_DATA_META_RSP : TMQ_MSG_TYPE__POLL_DATA_RSP, vgId);
|
||||
goto end;
|
||||
} else {
|
||||
fetchVer++;
|
||||
|
@ -396,9 +379,9 @@ int32_t tqDoSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp*
|
|||
int32_t len = 0;
|
||||
int32_t code = 0;
|
||||
|
||||
if (type == TMQ_MSG_TYPE__POLL_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
|
||||
if (type == TMQ_MSG_TYPE__POLL_DATA_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
|
||||
tEncodeSize(tEncodeMqDataRsp, pRsp, len, code);
|
||||
} else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
} else if (type == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code);
|
||||
}
|
||||
|
||||
|
@ -420,9 +403,9 @@ int32_t tqDoSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp*
|
|||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, abuf, len);
|
||||
|
||||
if (type == TMQ_MSG_TYPE__POLL_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
|
||||
if (type == TMQ_MSG_TYPE__POLL_DATA_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
|
||||
tEncodeMqDataRsp(&encoder, pRsp);
|
||||
} else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
} else if (type == TMQ_MSG_TYPE__POLL_DATA_META_RSP) {
|
||||
tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp);
|
||||
}
|
||||
|
||||
|
|
|
@ -1610,7 +1610,7 @@ 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);
|
||||
metaReaderDoInit(&mr, pTsdb->pVnode->pMeta, 0);
|
||||
if (metaReaderGetTableEntryByUidCache(&mr, uid) < 0) {
|
||||
metaReaderClear(&mr); // table not esist
|
||||
return 0;
|
||||
|
|
|
@ -562,7 +562,8 @@ static int32_t tsdbCommitFileDataStart(SCommitter *pCommitter) {
|
|||
code = terrno;
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, did);
|
||||
code = tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, did);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
wSet.diskId = did;
|
||||
wSet.nSttF = 1;
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ static int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, STsdb
|
|||
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 SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, const char* id);
|
||||
static bool hasDataInLastBlock(SLastBlockReader* pLastBlockReader);
|
||||
static int32_t doBuildDataBlock(STsdbReader* pReader);
|
||||
static TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader);
|
||||
|
@ -775,7 +775,7 @@ static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, void
|
|||
pReader->order = pCond->order;
|
||||
|
||||
pReader->idStr = (idstr != NULL) ? taosStrdup(idstr) : NULL;
|
||||
pReader->verRange = getQueryVerRange(pVnode, pCond, level);
|
||||
pReader->verRange = getQueryVerRange(pVnode, pCond, idstr);
|
||||
pReader->type = pCond->type;
|
||||
pReader->window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows);
|
||||
pReader->blockInfoBuf.numPerBucket = 1000; // 1000 tables per bucket
|
||||
|
@ -3721,7 +3721,7 @@ static STsdb* getTsdbByRetentions(SVnode* pVnode, TSKEY winSKey, SRetention* ret
|
|||
return VND_TSDB(pVnode);
|
||||
}
|
||||
|
||||
SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level) {
|
||||
SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, const char* id) {
|
||||
int64_t startVer = (pCond->startVersion == -1) ? 0 : pCond->startVersion;
|
||||
|
||||
int64_t endVer = 0;
|
||||
|
@ -3732,6 +3732,9 @@ SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_
|
|||
endVer = (pCond->endVersion > pVnode->state.applied) ? pVnode->state.applied : pCond->endVersion;
|
||||
}
|
||||
|
||||
tsdbDebug("queried verRange:%"PRId64"-%"PRId64", revised query verRange:%"PRId64"-%"PRId64", %s", pCond->startVersion,
|
||||
pCond->endVersion, startVer, endVer, id);
|
||||
|
||||
return (SVersionRange){.minVer = startVer, .maxVer = endVer};
|
||||
}
|
||||
|
||||
|
@ -5452,7 +5455,7 @@ int64_t tsdbGetNumOfRowsInMemTable(STsdbReader* pReader) {
|
|||
|
||||
int32_t tsdbGetTableSchema(void* pVnode, int64_t uid, STSchema** pSchema, int64_t* suid) {
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, ((SVnode*)pVnode)->pMeta, 0);
|
||||
metaReaderDoInit(&mr, ((SVnode*)pVnode)->pMeta, 0);
|
||||
int32_t code = metaReaderGetTableEntryByUidCache(&mr, uid);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
|
||||
|
@ -5584,57 +5587,3 @@ void tsdbReaderSetId(STsdbReader* pReader, const char* idstr) {
|
|||
|
||||
void tsdbReaderSetCloseFlag(STsdbReader* pReader) { pReader->code = TSDB_CODE_TSC_QUERY_CANCELLED; }
|
||||
|
||||
/*-------------todo:refactor the implementation of those APIs in this file to seperate the API into two files------*/
|
||||
// opt perf, do NOT create so many readers
|
||||
int64_t tsdbGetLastTimestamp(SVnode* pVnode, void* pTableList, int32_t numOfTables, const char* pIdStr) {
|
||||
SQueryTableDataCond cond = {.type = TIMEWINDOW_RANGE_CONTAINED, .numOfCols = 1, .order = TSDB_ORDER_DESC,
|
||||
.startVersion = -1, .endVersion = -1};
|
||||
cond.twindows.skey = INT64_MIN;
|
||||
cond.twindows.ekey = INT64_MAX;
|
||||
|
||||
cond.colList = taosMemoryCalloc(1, sizeof(SColumnInfo));
|
||||
cond.pSlotList = taosMemoryMalloc(sizeof(int32_t) * cond.numOfCols);
|
||||
if (cond.colList == NULL || cond.pSlotList == NULL) {
|
||||
// todo
|
||||
}
|
||||
|
||||
cond.colList[0].colId = 1;
|
||||
cond.colList[0].slotId = 0;
|
||||
cond.colList[0].type = TSDB_DATA_TYPE_TIMESTAMP;
|
||||
|
||||
cond.pSlotList[0] = 0;
|
||||
|
||||
STableKeyInfo* pTableKeyInfo = pTableList;
|
||||
STsdbReader* pReader = NULL;
|
||||
SSDataBlock* pBlock = createDataBlock();
|
||||
|
||||
SColumnInfoData data = {0};
|
||||
data.info = (SColumnInfo) {.type = TSDB_DATA_TYPE_TIMESTAMP, .colId = 1, .bytes = TSDB_KEYSIZE};
|
||||
blockDataAppendColInfo(pBlock, &data);
|
||||
|
||||
int64_t key = INT64_MIN;
|
||||
|
||||
for(int32_t i = 0; i < numOfTables; ++i) {
|
||||
int32_t code = tsdbReaderOpen(pVnode, &cond, &pTableKeyInfo[i], 1, pBlock, (void**)&pReader, pIdStr, false, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
bool hasData = false;
|
||||
code = tsdbNextDataBlock(pReader, &hasData);
|
||||
if (!hasData || code != TSDB_CODE_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
|
||||
int64_t k = *(int64_t*)pCol->pData;
|
||||
|
||||
if (key < k) {
|
||||
key = k;
|
||||
}
|
||||
|
||||
tsdbReaderClose(pReader);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -891,8 +891,10 @@ static int32_t tsdbSnapWriteFileDataStart(STsdbSnapWriter* pWriter, int32_t fid)
|
|||
if (pSet) {
|
||||
diskId = pSet->diskId;
|
||||
} else {
|
||||
tfsAllocDisk(pTsdb->pVnode->pTfs, 0 /*TODO*/, &diskId);
|
||||
tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, diskId);
|
||||
code = tfsAllocDisk(pTsdb->pVnode->pTfs, 0 /*TODO*/, &diskId);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
code = tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, diskId);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
SDFileSet wSet = {.diskId = diskId,
|
||||
.fid = fid,
|
||||
|
|
|
@ -528,25 +528,25 @@ void tsdbFidKeyRange(int32_t fid, int32_t minutes, int8_t precision, TSKEY *minK
|
|||
*maxKey = *minKey + tsTickPerMin[precision] * minutes - 1;
|
||||
}
|
||||
|
||||
int32_t tsdbFidLevel(int32_t fid, STsdbKeepCfg *pKeepCfg, int64_t now) {
|
||||
int32_t tsdbFidLevel(int32_t fid, STsdbKeepCfg *pKeepCfg, int64_t nowSec) {
|
||||
int32_t aFid[3];
|
||||
TSKEY key;
|
||||
|
||||
if (pKeepCfg->precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
now = now * 1000;
|
||||
nowSec = nowSec * 1000;
|
||||
} else if (pKeepCfg->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
now = now * 1000000l;
|
||||
nowSec = nowSec * 1000000l;
|
||||
} else if (pKeepCfg->precision == TSDB_TIME_PRECISION_NANO) {
|
||||
now = now * 1000000000l;
|
||||
nowSec = nowSec * 1000000000l;
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
key = now - pKeepCfg->keep0 * tsTickPerMin[pKeepCfg->precision];
|
||||
key = nowSec - pKeepCfg->keep0 * tsTickPerMin[pKeepCfg->precision];
|
||||
aFid[0] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
|
||||
key = now - pKeepCfg->keep1 * tsTickPerMin[pKeepCfg->precision];
|
||||
key = nowSec - pKeepCfg->keep1 * tsTickPerMin[pKeepCfg->precision];
|
||||
aFid[1] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
|
||||
key = now - pKeepCfg->keep2 * tsTickPerMin[pKeepCfg->precision];
|
||||
key = nowSec - pKeepCfg->keep2 * tsTickPerMin[pKeepCfg->precision];
|
||||
aFid[2] = tsdbKeyFid(key, pKeepCfg->days, pKeepCfg->precision);
|
||||
|
||||
if (fid >= aFid[0]) {
|
||||
|
@ -640,7 +640,7 @@ SColVal *tsdbRowIterNext(STSDBRowIter *pIter) {
|
|||
int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema) {
|
||||
int32_t code = 0;
|
||||
TSDBKEY key = TSDBROW_KEY(pRow);
|
||||
SColVal * pColVal = &(SColVal){0};
|
||||
SColVal *pColVal = &(SColVal){0};
|
||||
STColumn *pTColumn;
|
||||
int32_t iCol, jCol = 1;
|
||||
|
||||
|
@ -764,7 +764,7 @@ int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema)
|
|||
}
|
||||
}
|
||||
|
||||
int32_t tsdbRowMergerInit(SRowMerger* pMerger, STSchema *pSchema) {
|
||||
int32_t tsdbRowMergerInit(SRowMerger *pMerger, STSchema *pSchema) {
|
||||
pMerger->pTSchema = pSchema;
|
||||
pMerger->pArray = taosArrayInit(pSchema->numOfCols, sizeof(SColVal));
|
||||
if (pMerger->pArray == NULL) {
|
||||
|
@ -774,7 +774,7 @@ int32_t tsdbRowMergerInit(SRowMerger* pMerger, STSchema *pSchema) {
|
|||
}
|
||||
}
|
||||
|
||||
void tsdbRowMergerClear(SRowMerger* pMerger) {
|
||||
void tsdbRowMergerClear(SRowMerger *pMerger) {
|
||||
for (int32_t iCol = 1; iCol < pMerger->pTSchema->numOfCols; iCol++) {
|
||||
SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol);
|
||||
if (IS_VAR_DATA_TYPE(pTColVal->type)) {
|
||||
|
@ -785,7 +785,7 @@ void tsdbRowMergerClear(SRowMerger* pMerger) {
|
|||
taosArrayClear(pMerger->pArray);
|
||||
}
|
||||
|
||||
void tsdbRowMergerCleanup(SRowMerger* pMerger) {
|
||||
void tsdbRowMergerCleanup(SRowMerger *pMerger) {
|
||||
int32_t numOfCols = taosArrayGetSize(pMerger->pArray);
|
||||
for (int32_t iCol = 1; iCol < numOfCols; iCol++) {
|
||||
SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol);
|
||||
|
@ -1041,8 +1041,6 @@ int32_t tsdbBuildDeleteSkyline2(SArray *aDelData, int32_t sidx, int32_t eidx, SA
|
|||
|
||||
// SBlockData ======================================================
|
||||
int32_t tBlockDataCreate(SBlockData *pBlockData) {
|
||||
int32_t code = 0;
|
||||
|
||||
pBlockData->suid = 0;
|
||||
pBlockData->uid = 0;
|
||||
pBlockData->nRow = 0;
|
||||
|
@ -1051,7 +1049,7 @@ int32_t tBlockDataCreate(SBlockData *pBlockData) {
|
|||
pBlockData->aTSKEY = NULL;
|
||||
pBlockData->nColData = 0;
|
||||
pBlockData->aColData = NULL;
|
||||
return code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tBlockDataDestroy(SBlockData *pBlockData) {
|
||||
|
@ -1107,8 +1105,8 @@ int32_t tBlockDataInit(SBlockData *pBlockData, TABLEID *pId, STSchema *pTSchema,
|
|||
int32_t iColumn = 1;
|
||||
STColumn *pTColumn = &pTSchema->columns[iColumn];
|
||||
for (int32_t iCid = 0; iCid < nCid; iCid++) {
|
||||
|
||||
// aCid array (from taos client catalog) contains columns that does not exist in the pTSchema. the pTSchema is newer
|
||||
// aCid array (from taos client catalog) contains columns that does not exist in the pTSchema. the pTSchema is
|
||||
// newer
|
||||
if (pTColumn == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1239,7 +1237,7 @@ int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTS
|
|||
_exit:
|
||||
return code;
|
||||
}
|
||||
static int32_t tBlockDataUpdateRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema) {
|
||||
int32_t tBlockDataUpdateRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema) {
|
||||
int32_t code = 0;
|
||||
|
||||
// version
|
||||
|
|
|
@ -203,6 +203,7 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamStateCommit = streamStateCommit;
|
||||
pStore->streamStateDestroy = streamStateDestroy;
|
||||
pStore->streamStateDeleteCheckPoint = streamStateDeleteCheckPoint;
|
||||
pStore->streamStateReloadInfo = streamStateReloadInfo;
|
||||
}
|
||||
|
||||
void initMetaReaderAPI(SStoreMetaReader* pMetaReader) {
|
||||
|
|
|
@ -144,6 +144,7 @@ int32_t vnodeRenameVgroupId(const char *srcPath, const char *dstPath, int32_t sr
|
|||
char tsdbFilePrefix[TSDB_FILENAME_LEN] = {0};
|
||||
snprintf(tsdbPath, TSDB_FILENAME_LEN, "%s%stsdb", srcPath, TD_DIRSEP);
|
||||
snprintf(tsdbFilePrefix, TSDB_FILENAME_LEN, "tsdb%sv", TD_DIRSEP);
|
||||
int32_t prefixLen = strlen(tsdbFilePrefix);
|
||||
|
||||
STfsDir *tsdbDir = tfsOpendir(pTfs, tsdbPath);
|
||||
if (tsdbDir == NULL) return 0;
|
||||
|
@ -157,11 +158,11 @@ int32_t vnodeRenameVgroupId(const char *srcPath, const char *dstPath, int32_t sr
|
|||
char *tsdbFilePrefixPos = strstr(oldRname, tsdbFilePrefix);
|
||||
if (tsdbFilePrefixPos == NULL) continue;
|
||||
|
||||
int32_t tsdbFileVgId = atoi(tsdbFilePrefixPos + 6);
|
||||
int32_t tsdbFileVgId = atoi(tsdbFilePrefixPos + prefixLen);
|
||||
if (tsdbFileVgId == srcVgId) {
|
||||
char *tsdbFileSurfixPos = tsdbFilePrefixPos + 6 + vnodeVgroupIdLen(srcVgId);
|
||||
char *tsdbFileSurfixPos = tsdbFilePrefixPos + prefixLen + vnodeVgroupIdLen(srcVgId);
|
||||
|
||||
tsdbFilePrefixPos[6] = 0;
|
||||
tsdbFilePrefixPos[prefixLen] = 0;
|
||||
snprintf(newRname, TSDB_FILENAME_LEN, "%s%d%s", oldRname, dstVgId, tsdbFileSurfixPos);
|
||||
vInfo("vgId:%d, rename file from %s to %s", dstVgId, tsdbFile->rname, newRname);
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
}
|
||||
|
||||
// query meta
|
||||
metaReaderInit(&mer1, pVnode->pMeta, 0);
|
||||
metaReaderDoInit(&mer1, pVnode->pMeta, 0);
|
||||
|
||||
if (metaGetTableEntryByName(&mer1, infoReq.tbName) < 0) {
|
||||
code = terrno;
|
||||
|
@ -79,7 +79,7 @@ int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
schemaTag = mer1.me.stbEntry.schemaTag;
|
||||
metaRsp.suid = mer1.me.uid;
|
||||
} else if (mer1.me.type == TSDB_CHILD_TABLE) {
|
||||
metaReaderInit(&mer2, pVnode->pMeta, META_READER_NOLOCK);
|
||||
metaReaderDoInit(&mer2, pVnode->pMeta, META_READER_NOLOCK);
|
||||
if (metaReaderGetTableEntryByUid(&mer2, mer1.me.ctbEntry.suid) < 0) goto _exit;
|
||||
|
||||
strcpy(metaRsp.stbName, mer2.me.name);
|
||||
|
@ -175,7 +175,7 @@ int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
}
|
||||
|
||||
// query meta
|
||||
metaReaderInit(&mer1, pVnode->pMeta, 0);
|
||||
metaReaderDoInit(&mer1, pVnode->pMeta, 0);
|
||||
|
||||
if (metaGetTableEntryByName(&mer1, cfgReq.tbName) < 0) {
|
||||
code = terrno;
|
||||
|
@ -188,7 +188,7 @@ int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
code = TSDB_CODE_VND_HASH_MISMATCH;
|
||||
goto _exit;
|
||||
} else if (mer1.me.type == TSDB_CHILD_TABLE) {
|
||||
metaReaderInit(&mer2, pVnode->pMeta, 0);
|
||||
metaReaderDoInit(&mer2, pVnode->pMeta, 0);
|
||||
if (metaReaderGetTableEntryByUid(&mer2, mer1.me.ctbEntry.suid) < 0) goto _exit;
|
||||
|
||||
strcpy(cfgRsp.stbName, mer2.me.name);
|
||||
|
|
|
@ -234,8 +234,10 @@ static int32_t vnodePreProcessSubmitTbData(SVnode *pVnode, SDecoder *pCoder, int
|
|||
}
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(pCoder)) {
|
||||
*(int64_t *)(pCoder->data + pCoder->pos) = ctimeMs;
|
||||
pCoder->pos += sizeof(int64_t);
|
||||
}
|
||||
|
||||
tEndDecode(pCoder);
|
||||
|
||||
|
@ -400,10 +402,6 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t ver, SRpcMsg
|
|||
|
||||
if (!syncUtilUserCommit(pMsg->msgType)) goto _exit;
|
||||
|
||||
if (pMsg->msgType == TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE || pMsg->msgType == TDMT_STREAM_TASK_CHECK_RSP) {
|
||||
if (tqCheckLogInWal(pVnode->pTq, ver)) return 0;
|
||||
}
|
||||
|
||||
// skip header
|
||||
pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
len = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
@ -499,16 +497,6 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t ver, SRpcMsg
|
|||
goto _err;
|
||||
}
|
||||
} break;
|
||||
case TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE: {
|
||||
if (tqProcessTaskRecover2Req(pVnode->pTq, ver, pMsg->pCont, pMsg->contLen) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
} break;
|
||||
case TDMT_STREAM_TASK_CHECK_RSP: {
|
||||
if (tqProcessStreamTaskCheckRsp(pVnode->pTq, ver, pReq, len) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TDMT_VND_STREAM_CHECK_POINT_SOURCE: {
|
||||
if (tqProcessStreamCheckPointReq(pVnode->pTq, ver, pReq, len) < 0) goto _err;
|
||||
|
@ -646,26 +634,49 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
|
|||
// return tqProcessPollReq(pVnode->pTq, pMsg);
|
||||
case TDMT_VND_TMQ_VG_WALINFO:
|
||||
return tqProcessVgWalInfoReq(pVnode->pTq, pMsg);
|
||||
default:
|
||||
vError("unknown msg type:%d in fetch queue", pMsg->msgType);
|
||||
return TSDB_CODE_APP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t vnodeProcessStreamMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
|
||||
vTrace("vgId:%d, msg:%p in fetch queue is processing", pVnode->config.vgId, pMsg);
|
||||
if ((pMsg->msgType == TDMT_SCH_FETCH || pMsg->msgType == TDMT_VND_TABLE_META || pMsg->msgType == TDMT_VND_TABLE_CFG ||
|
||||
pMsg->msgType == TDMT_VND_BATCH_META) &&
|
||||
!syncIsReadyForRead(pVnode->sync)) {
|
||||
vnodeRedirectRpcMsg(pVnode, pMsg, terrno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_RUN:
|
||||
return tqProcessTaskRunReq(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_TASK_DISPATCH:
|
||||
return tqProcessTaskDispatchReq(pVnode->pTq, pMsg, true);
|
||||
case TDMT_STREAM_TASK_CHECK:
|
||||
return tqProcessStreamTaskCheckReq(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_TASK_DISPATCH_RSP:
|
||||
return tqProcessTaskDispatchRsp(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_TASK_CHECK:
|
||||
return tqProcessStreamTaskCheckReq(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_TASK_CHECK_RSP:
|
||||
return tqProcessStreamTaskCheckRsp(pVnode->pTq, 0, pMsg);
|
||||
case TDMT_STREAM_RETRIEVE:
|
||||
return tqProcessTaskRetrieveReq(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_RETRIEVE_RSP:
|
||||
return tqProcessTaskRetrieveRsp(pVnode->pTq, pMsg);
|
||||
case TDMT_VND_STREAM_RECOVER_NONBLOCKING_STAGE:
|
||||
return tqProcessTaskRecover1Req(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_RECOVER_FINISH:
|
||||
case TDMT_VND_STREAM_SCAN_HISTORY:
|
||||
return tqProcessTaskScanHistory(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_TRANSFER_STATE: {
|
||||
char* pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
return tqProcessTaskTransferStateReq(pVnode->pTq, 0, pReq, len);
|
||||
}
|
||||
case TDMT_STREAM_SCAN_HISTORY_FINISH:
|
||||
return tqProcessTaskRecoverFinishReq(pVnode->pTq, pMsg);
|
||||
case TDMT_STREAM_RECOVER_FINISH_RSP:
|
||||
case TDMT_STREAM_SCAN_HISTORY_FINISH_RSP:
|
||||
return tqProcessTaskRecoverFinishRsp(pVnode->pTq, pMsg);
|
||||
default:
|
||||
vError("unknown msg type:%d in fetch queue", pMsg->msgType);
|
||||
vError("unknown msg type:%d in stream queue", pMsg->msgType);
|
||||
return TSDB_CODE_APP_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -1700,7 +1711,7 @@ static int32_t vnodeProcessBatchDeleteReq(SVnode *pVnode, int64_t ver, void *pRe
|
|||
tDecodeSBatchDeleteReq(&decoder, &deleteReq);
|
||||
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pVnode->pMeta, META_READER_NOLOCK);
|
||||
metaReaderDoInit(&mr, pVnode->pMeta, META_READER_NOLOCK);
|
||||
|
||||
int32_t sz = taosArrayGetSize(deleteReq.deleteReqs);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
|
|
|
@ -556,7 +556,7 @@ static void vnodeRestoreFinish(const SSyncFSM *pFsm, const SyncIndex commitIdx)
|
|||
vInfo("vgId:%d, not launch stream tasks, since stream tasks are disabled", pVnode->config.vgId);
|
||||
} else {
|
||||
vInfo("vgId:%d start to launch stream tasks", pVnode->config.vgId);
|
||||
tqStartStreamTasks(pVnode->pTq);
|
||||
tqCheckStreamStatus(pVnode->pTq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -392,7 +392,7 @@ static int32_t setAliveResultIntoDataBlock(int64_t* pConnId, SSDataBlock* pBlock
|
|||
int32_t status = 0;
|
||||
int32_t code = getAliveStatusFromApi(pConnId, dbName, &status);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
colDataAppend(pCol1, 0, (const char*)&status, false);
|
||||
colDataSetVal(pCol1, 0, (const char*)&status, false);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef struct SColMatchItem {
|
|||
int32_t srcSlotId;
|
||||
int32_t dstSlotId;
|
||||
bool needOutput;
|
||||
SDataType dataType;
|
||||
} SColMatchItem;
|
||||
|
||||
typedef struct SColMatchInfo {
|
||||
|
|
|
@ -285,6 +285,8 @@ typedef struct SStreamAggSupporter {
|
|||
int16_t stateKeyType;
|
||||
SDiskbasedBuf* pResultBuf;
|
||||
SStateStore stateStore;
|
||||
STimeWindow winRange;
|
||||
SStorageAPI* pSessionAPI;
|
||||
} SStreamAggSupporter;
|
||||
|
||||
typedef struct SWindowSupporter {
|
||||
|
@ -503,6 +505,8 @@ typedef struct SStreamSessionAggOperatorInfo {
|
|||
SArray* pUpdated;
|
||||
SSHashObj* pStUpdated;
|
||||
int64_t dataVersion;
|
||||
SArray* historyWins;
|
||||
bool isHistoryOp;
|
||||
} SStreamSessionAggOperatorInfo;
|
||||
|
||||
typedef struct SStreamStateAggOperatorInfo {
|
||||
|
@ -522,6 +526,8 @@ typedef struct SStreamStateAggOperatorInfo {
|
|||
SArray* pUpdated;
|
||||
SSHashObj* pSeUpdated;
|
||||
int64_t dataVersion;
|
||||
bool isHistoryOp;
|
||||
SArray* historyWins;
|
||||
} SStreamStateAggOperatorInfo;
|
||||
|
||||
typedef struct SStreamPartitionOperatorInfo {
|
||||
|
@ -678,6 +684,8 @@ void doUpdateNumOfRows(SqlFunctionCtx* pCtx, SResultRow* pRow, int32_t numOfExpr
|
|||
void doClearBufferedBlocks(SStreamScanInfo* pInfo);
|
||||
|
||||
uint64_t calcGroupId(char* pData, int32_t len);
|
||||
void streamOpReleaseState(struct SOperatorInfo* pOperator);
|
||||
void streamOpReloadState(struct SOperatorInfo* pOperator);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue