Merge branch 'enh/3.0' into enh/rocksdbSstateMerge
This commit is contained in:
commit
5708fcb5cb
|
@ -120,8 +120,14 @@ ELSE ()
|
|||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3 -Wformat=0")
|
||||
MESSAGE(STATUS "Compile with Address Sanitizer!")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
MESSAGE(STATUS "XXXXXXXXXXXXXX Clang/AppleClang" ${TD_DARWIN})
|
||||
IF (${TD_DARWIN})
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-reserved-user-defined-literal -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-y2k")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
# disable all assert
|
||||
|
|
|
@ -259,13 +259,26 @@ if(${BUILD_WITH_ROCKSDB})
|
|||
option(WITH_BENCHMARK_TOOLS "" OFF)
|
||||
option(WITH_TOOLS "" OFF)
|
||||
option(WITH_LIBURING "" OFF)
|
||||
|
||||
option(WITH_IOSTATS_CONTEXT "" OFF)
|
||||
option(WITH_PERF_CONTEXT "" OFF)
|
||||
option(FAIL_ON_WARNINGS "" OFF)
|
||||
#option(WITH_JEMALLOC "" ON)
|
||||
option(ROCKSDB_BUILD_SHARED "Build shared versions of the RocksDB libraries" OFF)
|
||||
IF (${TD_WINDOWS})
|
||||
option(WITH_MD_LIBRARY "build with MD" OFF)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} shlwapi.lib rpcrt4.lib)
|
||||
endif(${TD_WINDOWS})
|
||||
add_subdirectory(rocksdb EXCLUDE_FROM_ALL)
|
||||
target_include_directories(
|
||||
rocksdb
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/rocksdb/include>
|
||||
)
|
||||
IF (${TD_DARWIN})
|
||||
target_compile_options(
|
||||
rocksdb
|
||||
PRIVATE -Wno-unused-private-field
|
||||
)
|
||||
endif(${TD_DARWIN})
|
||||
endif(${BUILD_WITH_ROCKSDB})
|
||||
|
||||
# lucene
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
message("contrib test/rocksdb:" ${BUILD_DEPENDENCY_TESTS})
|
||||
|
||||
add_executable(rocksdbTest "")
|
||||
target_sources(rocksdbTest
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/main.c"
|
||||
)
|
||||
target_link_libraries(rocksdbTest rocksdb)
|
||||
target_link_libraries(rocksdbTest rocksdb)
|
||||
|
|
|
@ -116,9 +116,20 @@ int main(int argc, char const *argv[]) {
|
|||
rocksdb_options_set_create_if_missing(opt, 1);
|
||||
rocksdb_options_set_create_missing_column_families(opt, 1);
|
||||
|
||||
const char *cfName[] = {"default", "cf1"};
|
||||
int len = sizeof(cfName) / sizeof(cfName[0]);
|
||||
// Read
|
||||
rocksdb_readoptions_t *readoptions = rocksdb_readoptions_create();
|
||||
// rocksdb_readoptions_set_snapshot(readoptions, rocksdb_create_snapshot(db));
|
||||
int len = 1;
|
||||
char buf[256] = {0};
|
||||
size_t vallen = 0;
|
||||
char *val = rocksdb_get(db, readoptions, "key", 3, &vallen, &err);
|
||||
snprintf(buf, vallen + 5, "val:%s", val);
|
||||
printf("%ld %ld %s\n", strlen(val), vallen, buf);
|
||||
|
||||
char **cfName = calloc(len, sizeof(char *));
|
||||
for (int i = 0; i < len; i++) {
|
||||
cfName[i] = "test";
|
||||
}
|
||||
const rocksdb_options_t **cfOpt = malloc(len * sizeof(rocksdb_options_t *));
|
||||
for (int i = 0; i < len; i++) {
|
||||
cfOpt[i] = rocksdb_options_create_copy(opt);
|
||||
|
@ -129,7 +140,7 @@ int main(int argc, char const *argv[]) {
|
|||
}
|
||||
|
||||
rocksdb_column_family_handle_t **cfHandle = malloc(len * sizeof(rocksdb_column_family_handle_t *));
|
||||
db = rocksdb_open_column_families(opt, path, len, cfName, cfOpt, cfHandle, &err);
|
||||
db = rocksdb_open_column_families(opt, path, len, (const char *const *)cfName, cfOpt, cfHandle, &err);
|
||||
|
||||
{
|
||||
rocksdb_readoptions_t *rOpt = rocksdb_readoptions_create();
|
||||
|
@ -302,4 +313,4 @@ int main(int argc, char const *argv[]) {
|
|||
// rocksdb_close(db);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,6 +208,8 @@ The following `launchctl` commands can help you manage TDengine service:
|
|||
|
||||
- Check TDengine Server status: `sudo launchctl list | grep taosd`
|
||||
|
||||
- Check TDengine Server status details: `launchctl print system/com.tdengine.taosd`
|
||||
|
||||
:::info
|
||||
- Please use `sudo` to run `launchctl` to manage _com.tdengine.taosd_ with administrator privileges.
|
||||
- The administrator privilege is required for service management to enhance security.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```rust
|
||||
{{#include docs/examples/rust/nativeexample/examples/schemaless_insert_line.rs}}
|
||||
```
|
|
@ -222,7 +222,7 @@ A database including one supertable and two subtables is created as follows:
|
|||
|
||||
```sql
|
||||
DROP DATABASE IF EXISTS tmqdb;
|
||||
CREATE DATABASE tmqdb;
|
||||
CREATE DATABASE tmqdb WAL_RETENTION_PERIOD 3600;
|
||||
CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16));
|
||||
CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0");
|
||||
CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1");
|
||||
|
|
|
@ -6,10 +6,12 @@ description: This document describes how to create user-defined functions (UDF),
|
|||
|
||||
The built-in functions of TDengine may not be sufficient for the use cases of every application. In this case, you can define custom functions for use in TDengine queries. These are known as user-defined functions (UDF). A user-defined function takes one column of data or the result of a subquery as its input.
|
||||
|
||||
TDengine supports user-defined functions written in C or C++. This document describes the usage of user-defined functions.
|
||||
|
||||
User-defined functions can be scalar functions or aggregate functions. Scalar functions, such as `abs`, `sin`, and `concat`, output a value for every row of data. Aggregate functions, such as `avg` and `max` output one value for multiple rows of data.
|
||||
|
||||
TDengine supports user-defined functions written in C or Python. This document describes the usage of user-defined functions.
|
||||
|
||||
## Implement a UDF in C
|
||||
|
||||
When you create a user-defined function, you must implement standard interface functions:
|
||||
- For scalar functions, implement the `scalarfn` interface function.
|
||||
- For aggregate functions, implement the `aggfn_start`, `aggfn`, and `aggfn_finish` interface functions.
|
||||
|
@ -17,7 +19,7 @@ When you create a user-defined function, you must implement standard interface f
|
|||
|
||||
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.
|
||||
|
||||
## Implementing a Scalar Function
|
||||
### Implementing a Scalar Function in C
|
||||
The implementation of a scalar function is described as follows:
|
||||
```c
|
||||
#include "taos.h"
|
||||
|
@ -49,7 +51,7 @@ int32_t scalarfn_destroy() {
|
|||
```
|
||||
Replace `scalarfn` with the name of your function.
|
||||
|
||||
## Implementing an Aggregate Function
|
||||
### Implementing an Aggregate Function in C
|
||||
|
||||
The implementation of an aggregate function is described as follows:
|
||||
```c
|
||||
|
@ -100,7 +102,7 @@ int32_t aggfn_destroy() {
|
|||
```
|
||||
Replace `aggfn` with the name of your function.
|
||||
|
||||
## Interface Functions
|
||||
### UDF Interface Definition in C
|
||||
|
||||
There are strict naming conventions for 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.
|
||||
|
||||
|
@ -108,8 +110,7 @@ Interface functions return a value that indicates whether the operation was succ
|
|||
|
||||
For information about the parameters for interface functions, see Data Model
|
||||
|
||||
### Interfaces for Scalar Functions
|
||||
|
||||
#### Scalar Interface
|
||||
`int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)`
|
||||
|
||||
Replace `scalarfn` with the name of your function. This function performs scalar calculations on data blocks. You can configure a value through the parameters in the `resultColumn` structure.
|
||||
|
@ -118,7 +119,7 @@ The parameters in the function are defined as follows:
|
|||
- inputDataBlock: The data block to input.
|
||||
- resultColumn: The column to output. The column to output.
|
||||
|
||||
### Interfaces for Aggregate Functions
|
||||
#### Aggregate Interface
|
||||
|
||||
`int32_t aggfn_start(SUdfInterBuf *interBuf)`
|
||||
|
||||
|
@ -126,7 +127,7 @@ The parameters in the function are defined as follows:
|
|||
|
||||
`int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)`
|
||||
|
||||
Replace `aggfn` with the name of your function. In the function, aggfn_start is called to generate a result buffer. Data is then divided between multiple blocks, and aggfn is called on each block to update the result. Finally, aggfn_finish is called to generate final results from the intermediate results. The final result contains only one or zero data points.
|
||||
Replace `aggfn` with the name of your function. In the function, aggfn_start is called to generate a result buffer. Data is then divided between multiple blocks, and the `aggfn` function is called on each block to update the result. Finally, aggfn_finish is called to generate the final results from the intermediate results. The final result contains only one or zero data points.
|
||||
|
||||
The parameters in the function are defined as follows:
|
||||
- interBuf: The intermediate result buffer.
|
||||
|
@ -135,15 +136,15 @@ The parameters in the function are defined as follows:
|
|||
- result: The final result.
|
||||
|
||||
|
||||
### Initializing and Terminating User-Defined Functions
|
||||
#### Initialization and Cleanup Interface
|
||||
`int32_t udf_init()`
|
||||
|
||||
`int32_t udf_destroy()`
|
||||
|
||||
Replace `udf`with the name of your function. udf_init initializes the function. udf_destroy terminates the function. If it is not necessary to initialize your function, udf_init is not required. If it is not necessary to terminate your function, udf_destroy is not required.
|
||||
Replace `udf` with the name of your function. udf_init initializes the function. udf_destroy terminates the function. If it is not necessary to initialize your function, udf_init is not required. If it is not necessary to terminate your function, udf_destroy is not required.
|
||||
|
||||
|
||||
## Data Structure of User-Defined Functions
|
||||
### Data Structures for UDF in C
|
||||
```c
|
||||
typedef struct SUdfColumnMeta {
|
||||
int16_t type;
|
||||
|
@ -193,7 +194,7 @@ typedef struct SUdfInterBuf {
|
|||
```
|
||||
The data structure is described as follows:
|
||||
|
||||
- The SUdfDataBlock block includes the number of rows (numOfRows) and number of columns (numCols). udfCols[i] (0 <= i <= numCols-1) indicates that each column is of type SUdfColumn.
|
||||
- The SUdfDataBlock block includes the number of rows (numOfRows) and the number of columns (numCols). udfCols[i] (0 <= i <= numCols-1) indicates that each column is of type SUdfColumn.
|
||||
- SUdfColumn includes the definition of the data type of the column (colMeta) and the data in the column (colData).
|
||||
- The member definitions of SUdfColumnMeta are the same as the data type definitions in `taos.h`.
|
||||
- The data in SUdfColumnData can become longer. varLenCol indicates variable-length data, and fixLenCol indicates fixed-length data.
|
||||
|
@ -201,9 +202,9 @@ The data structure is described as follows:
|
|||
|
||||
Additional functions are defined in `taosudf.h` to make it easier to work with these structures.
|
||||
|
||||
## Compile UDF
|
||||
### Compiling C UDF
|
||||
|
||||
To use your user-defined function in TDengine, first compile it to a dynamically linked library (DLL).
|
||||
To use your user-defined function in TDengine, first, compile it to a shared library.
|
||||
|
||||
For example, the sample UDF `bit_and.c` can be compiled into a DLL as follows:
|
||||
|
||||
|
@ -213,12 +214,9 @@ gcc -g -O0 -fPIC -shared bit_and.c -o libbitand.so
|
|||
|
||||
The generated DLL file `libbitand.so` can now be used to implement your function. Note: GCC 7.5 or later is required.
|
||||
|
||||
## Manage and Use User-Defined Functions
|
||||
After compiling your function into a DLL, you add it to TDengine. For more information, see [User-Defined Functions](../12-taos-sql/26-udf.md).
|
||||
### UDF Sample Code in C
|
||||
|
||||
## Sample Code
|
||||
|
||||
### Sample scalar function: [bit_and](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/bit_and.c)
|
||||
#### Scalar function: [bit_and](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/bit_and.c)
|
||||
|
||||
The bit_and function implements bitwise addition for multiple columns. If there is only one column, the column is returned. The bit_and function ignores null values.
|
||||
|
||||
|
@ -231,7 +229,7 @@ The bit_and function implements bitwise addition for multiple columns. If there
|
|||
|
||||
</details>
|
||||
|
||||
### Sample aggregate function: [l2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/l2norm.c)
|
||||
#### Aggregate function 1: [l2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/l2norm.c)
|
||||
|
||||
The l2norm function finds the second-order norm for all data in the input column. This squares the values, takes a cumulative sum, and finds the square root.
|
||||
|
||||
|
@ -243,3 +241,151 @@ The l2norm function finds the second-order norm for all data in the input column
|
|||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Aggregate function 2: [max_vol](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/max_vol.c)
|
||||
|
||||
The max_vol function returns a string concatenating the deviceId column, the row number and column number of the maximum voltage and the maximum voltage given several voltage columns as input.
|
||||
|
||||
Create Table:
|
||||
```bash
|
||||
create table battery(ts timestamp, vol1 float, vol2 float, vol3 float, deviceId varchar(16));
|
||||
```
|
||||
Create the UDF:
|
||||
```bash
|
||||
create aggregate function max_vol as '/root/udf/libmaxvol.so' outputtype binary(64) bufsize 10240 language 'C';
|
||||
```
|
||||
Use the UDF in the query:
|
||||
```bash
|
||||
select max_vol(vol1,vol2,vol3,deviceid) from battery;
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>max_vol.c</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/max_vol.c}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Implement a UDF in Python
|
||||
|
||||
Implement the specified interface functions when implementing a UDF in Python.
|
||||
- implement `process` function for the scalar UDF。
|
||||
- implement `start`, `reduce`, `finish` for the aggregate UDF。
|
||||
- implement `init` for initialization and `destroy` for termination。
|
||||
|
||||
### Implement a Scalar UDF in Python
|
||||
|
||||
The implementation of a scalar UDF is described as follows:
|
||||
|
||||
```Python
|
||||
def init():
|
||||
# initialization
|
||||
def destroy():
|
||||
# destroy
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
# process input datablock,
|
||||
# datablock.data(row, col) is to access the python object in location(row,col)
|
||||
# return tuple object consisted of object of type outputtype
|
||||
```
|
||||
|
||||
### Implement an Aggregate UDF in Python
|
||||
|
||||
The implementation of an aggregate function is described as follows:
|
||||
|
||||
```Python
|
||||
def init():
|
||||
#initialization
|
||||
def destroy():
|
||||
#destroy
|
||||
def start() -> bytes:
|
||||
#return serialize(init_state)
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
# deserialize buf to state
|
||||
# reduce the inputs and state into new_state.
|
||||
# use inputs.data(i,j) to access python ojbect of location(i,j)
|
||||
# serialize new_state into new_state_bytes
|
||||
return new_state_bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
#return obj of type outputtype
|
||||
```
|
||||
|
||||
### Python UDF Interface Definition
|
||||
|
||||
#### Scalar interface
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
- `input` is a data block two-dimension matrix-like object, of which method `data(row, col)` returns the Python object located at location (`row`, `col`)
|
||||
- return a Python tuple object, of which each item is a Python object of type `output_type`
|
||||
|
||||
#### Aggregate Interface
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(input: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
- first `start()` is called to return the initial result in type `bytes`
|
||||
- then the input data are divided into multiple data blocks and for each block `input`, `reduce` is called with the data block `input` and the current result `buf` bytes and generates a new intermediate result buffer.
|
||||
- finally, the `finish` function is called on the intermediate result `buf` and outputs 0 or 1 data of type `output_type`
|
||||
|
||||
|
||||
#### Initialization and Cleanup Interface
|
||||
```Python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
Implement `init` for initialization and `destroy` for termination.
|
||||
|
||||
### Data Mapping between TDengine SQL and Python UDF
|
||||
|
||||
The following table describes the mapping between TDengine SQL data type and Python UDF Data Type. The `NULL` value of all TDengine SQL types is mapped to the `None` value in Python.
|
||||
|
||||
| **TDengine SQL Data Type** | **Python Data Type** |
|
||||
| :-----------------------: | ------------ |
|
||||
|TINYINT / SMALLINT / INT / BIGINT | int |
|
||||
|TINYINT UNSIGNED / SMALLINT UNSIGNED / INT UNSIGNED / BIGINT UNSIGNED | int |
|
||||
|FLOAT / DOUBLE | float |
|
||||
|BOOL | bool |
|
||||
|BINARY / VARCHAR / NCHAR | bytes|
|
||||
|TIMESTAMP | int |
|
||||
|JSON and other types | Not Supported |
|
||||
|
||||
### Installing Python UDF
|
||||
1. Install Python package `taospyudf` that executes Python UDF
|
||||
```bash
|
||||
sudo pip install taospyudf
|
||||
ldconfig
|
||||
```
|
||||
2. If PYTHONPATH is needed to find Python packages when the Python UDF executes, include the PYTHONPATH contents into the udfdLdLibPath variable of the taos.cfg configuration file
|
||||
|
||||
### Python UDF Sample Code
|
||||
#### Scalar Function [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py)
|
||||
|
||||
The `pybitand` function implements bitwise addition for multiple columns. If there is only one column, the column is returned. The `pybitand` function ignores null values.
|
||||
|
||||
<details>
|
||||
<summary>pybitand.py</summary>
|
||||
|
||||
```Python
|
||||
{{#include tests/script/sh/pybitand.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Aggregate Function [pyl2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pyl2norm.py)
|
||||
|
||||
The `pyl2norm` function finds the second-order norm for all data in the input column. This squares the values, takes a cumulative sum, and finds the square root.
|
||||
<details>
|
||||
<summary>pyl2norm.py</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/pyl2norm.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Manage and Use UDF
|
||||
You need to add UDF to TDengine before using it in SQL queries. For more information about how to manage UDF and how to invoke UDF, please see [Manage and Use UDF](../12-taos-sql/26-udf.md).
|
||||
|
|
|
@ -72,8 +72,8 @@ database_option: {
|
|||
- 0: The database can contain multiple supertables.
|
||||
- 1: The database can contain only one supertable.
|
||||
- STT_TRIGGER: specifies the number of file merges triggered by flushed files. The default is 8, ranging from 1 to 16. For high-frequency scenarios with few tables, it is recommended to use the default configuration or a smaller value for this parameter; For multi-table low-frequency scenarios, it is recommended to configure this parameter with a larger value.
|
||||
- TABLE_PREFIX:The prefix length in the table name that is ignored when distributing table to vnode based on table name.
|
||||
- TABLE_SUFFIX:The suffix length in the table name that is ignored when distributing table to vnode based on table name.
|
||||
- TABLE_PREFIX: The prefix in the table name that is ignored when distributing a table to a vgroup when it's a positive number, or only the prefix is used when distributing a table to a vgroup, the default value is 0; For example, if the table name v30001, then "0001" is used if TSDB_PREFIX is set to 2 but "v3" is used if TSDB_PREFIX is set to -2; It can help you to control the distribution of tables.
|
||||
- TABLE_SUFFIX:The suffix in the table name that is ignored when distributing a table to a vgroup when it's a positive number, or only the suffix is used when distributing a table to a vgroup, the default value is 0; For example, if the table name v30001, then "v300" is used if TSDB_SUFFIX is set to 2 but "01" is used if TSDB_SUFFIX is set to -2; It can help you to control the distribution of tables.
|
||||
- TSDB_PAGESIZE: The page size of the data storage engine in a vnode. The unit is KB. The default is 4 KB. The range is 1 to 16384, that is, 1 KB to 16 MB.
|
||||
- WAL_RETENTION_PERIOD: specifies the maximum time of which WAL files are to be kept for consumption. This parameter is used for data subscription. Enter a time in seconds. The default value 0. A value of 0 indicates that WAL files are not required to keep for consumption. Alter it with a proper value at first to create topics.
|
||||
- WAL_RETENTION_SIZE: specifies the maximum total size of which WAL files are to be kept for consumption. This parameter is used for data subscription. Enter a size in KB. The default value is 0. A value of 0 indicates that the total size of WAL files to keep for consumption has no upper limit.
|
||||
|
|
|
@ -6,7 +6,7 @@ description: Use Tag Index to Improve Query Performance
|
|||
|
||||
## Introduction
|
||||
|
||||
Prior to TDengine 3.0.3.0 (excluded),only one index is created by default on the first tag of each super talbe, but it's not allowed to dynamically create index on any other tags. From version 3.0.30, you can dynamically create index on any tag of any type. The index created automatically by TDengine is still valid. Query performance can benefit from indexes if you use properly.
|
||||
Prior to TDengine 3.0.3.0 (excluded),only one index is created by default on the first tag of each super table, but it's not allowed to dynamically create index on any other tags. From version 3.0.30, you can dynamically create index on any tag of any type. The index created automatically by TDengine is still valid. Query performance can benefit from indexes if you use properly.
|
||||
|
||||
## Syntax
|
||||
|
||||
|
@ -48,4 +48,4 @@ You can also add filter conditions to limit the results.
|
|||
|
||||
6. You can' create index on a normal table or a child table.
|
||||
|
||||
7. If the unique values of a tag column are too few, it's better not to create index on such tag columns, the benefit would be very small.
|
||||
7. If the unique values of a tag column are too few, it's better not to create index on such tag columns, the benefit would be very small.
|
||||
|
|
|
@ -5,9 +5,9 @@ description: This document describes the standard SQL functions available in TDe
|
|||
toc_max_heading_level: 4
|
||||
---
|
||||
|
||||
## Single Row Functions
|
||||
## Scalar Functions
|
||||
|
||||
Single row functions return a result for each row.
|
||||
Scalar functions return one result for each row.
|
||||
|
||||
### Mathematical Functions
|
||||
|
||||
|
|
|
@ -13,8 +13,11 @@ Because stream processing is built in to TDengine, you are no longer reliant on
|
|||
```sql
|
||||
CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name SUBTABLE(expression) AS subquery
|
||||
stream_options: {
|
||||
TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
|
||||
WATERMARK time
|
||||
TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
|
||||
WATERMARK time
|
||||
IGNORE EXPIRED [0|1]
|
||||
DELETE_MARK time
|
||||
FILL_HISTORY [0|1]
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -141,3 +144,27 @@ The data in expired windows is tagged as expired. TDengine stream processing pro
|
|||
2. Recalculate the data. In this method, all data in the window is reobtained from the database and recalculated. The latest results are then returned.
|
||||
|
||||
In both of these methods, configuring the watermark is essential for obtaining accurate results (if expired data is dropped) and avoiding repeated triggers that affect system performance (if expired data is recalculated).
|
||||
|
||||
## Supported functions
|
||||
|
||||
All [scalar functions](../function/#scalar-functions) are available in stream processing. All [Aggregate functions](../function/#aggregate-functions) and [Selection functions](../function/#selection-functions) are available in stream processing, except the followings:
|
||||
- [leastsquares](../function/#leastsquares)
|
||||
- [percentile](../function/#percentile)
|
||||
- [top](../function/#top)
|
||||
- [bottom](../function/#bottom)
|
||||
- [elapsed](../function/#elapsed)
|
||||
- [interp](../function/#interp)
|
||||
- [derivative](../function/#derivative)
|
||||
- [irate](../function/#irate)
|
||||
- [twa](../function/#twa)
|
||||
- [histogram](../function/#histogram)
|
||||
- [diff](../function/#diff)
|
||||
- [statecount](../function/#statecount)
|
||||
- [stateduration](../function/#stateduration)
|
||||
- [csum](../function/#csum)
|
||||
- [mavg](../function/#mavg)
|
||||
- [sample](../function/#sample)
|
||||
- [tail](../function/#tail)
|
||||
- [unique](../function/#unique)
|
||||
- [mode](../function/#mode)
|
||||
|
||||
|
|
|
@ -120,6 +120,9 @@ Provides information about user-defined functions.
|
|||
| 5 | create_time | TIMESTAMP | Creation time |
|
||||
| 6 | code_len | INT | Length of the source code |
|
||||
| 7 | bufsize | INT | Buffer size |
|
||||
| 8 | func_language | BINARY(31) | UDF programming language |
|
||||
| 9 | func_body | BINARY(16384) | UDF function body |
|
||||
| 10 | func_version | INT | UDF function version. starting from 0. Increasing by 1 each time it is updated|
|
||||
|
||||
## INS_INDEXES
|
||||
|
||||
|
|
|
@ -7,17 +7,18 @@ description: This document describes the SQL statements related to user-defined
|
|||
You can create user-defined functions and import them into TDengine.
|
||||
## Create UDF
|
||||
|
||||
SQL command can be executed on the host where the generated UDF DLL resides to load the UDF DLL into TDengine. This operation cannot be done through REST interface or web console. Once created, any client of the current TDengine can use these UDF functions in their SQL commands. UDF are stored in the management node of TDengine. The UDFs loaded in TDengine would be still available after TDengine is restarted.
|
||||
SQL command can be executed on the host where the generated UDF DLL resides to load the UDF DLL into TDengine. This operation cannot be done through REST interface or web console. Once created, any client of the current TDengine can use these UDF functions in their SQL commands. UDF is stored in the management node of TDengine. The UDFs loaded in TDengine would be still available after TDengine is restarted.
|
||||
|
||||
When creating UDF, the type of UDF, i.e. a scalar function or aggregate function must be specified. If the specified type is wrong, the SQL statements using the function would fail with errors. The input data type and output data type must be consistent with the UDF definition.
|
||||
|
||||
- Create Scalar Function
|
||||
```sql
|
||||
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type;
|
||||
CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_type [LANGUAGE 'C|Python'];
|
||||
```
|
||||
|
||||
- function_name: The scalar function name to be used in SQL statement which must be consistent with the UDF name and is also the name of the compiled DLL (.so file).
|
||||
- library_path: The absolute path of the DLL file including the name of the shared object file (.so). The path must be quoted with single or double quotes.
|
||||
- OR REPLACE: if the UDF exists, the UDF properties are modified
|
||||
- function_name: The scalar function name to be used in the SQL statement
|
||||
- LANGUAGE 'C|Python': the programming language of UDF. Now C or Python is supported. If this clause is omitted, C is assumed as the programming language.
|
||||
- library_path: For C programming language, The absolute path of the DLL file including the name of the shared object file (.so). For Python programming language, the absolute path of the Python UDF script. The path must be quoted with single or double quotes.
|
||||
- output_type: The data type of the results of the UDF.
|
||||
|
||||
For example, the following SQL statement can be used to create a UDF from `libbitand.so`.
|
||||
|
@ -25,14 +26,20 @@ CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type;
|
|||
```sql
|
||||
CREATE FUNCTION bit_and AS "/home/taos/udf_example/libbitand.so" OUTPUTTYPE INT;
|
||||
```
|
||||
For Example, the following SQL statement can be used to modify the existing function `bit_and`. The OUTPUT type is changed to BIGINT and the programming language is changed to Python.
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION bit_and AS "/home/taos/udf_example/bit_and.py" OUTPUTTYPE BIGINT LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
- Create Aggregate Function
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ];
|
||||
```
|
||||
|
||||
- function_name: The aggregate function name to be used in SQL statement which must be consistent with the udfNormalFunc name and is also the name of the compiled DLL (.so file).
|
||||
- library_path: The absolute path of the DLL file including the name of the shared object file (.so). The path must be quoted with single or double quotes.
|
||||
- OR REPLACE: if the UDF exists, the UDF properties are modified
|
||||
- function_name: The aggregate function name to be used in the SQL statement
|
||||
- LANGUAGE 'C|Python': the programming language of the UDF. Now C or Python is supported. If this clause is omitted, C is assumed as the programming language.
|
||||
- library_path: For C programming language, The absolute path of the DLL file including the name of the shared object file (.so). For Python programming language, the absolute path of the Python UDF script. The path must be quoted with single or double quotes.
|
||||
- output_type: The output data type, the value is the literal string of the supported TDengine data type.
|
||||
- buffer_size: The size of the intermediate buffer in bytes. This parameter is optional.
|
||||
|
||||
|
@ -41,6 +48,11 @@ CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [
|
|||
```sql
|
||||
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8;
|
||||
```
|
||||
For example, the following SQL statement modifies the buffer size of existing UDF `l2norm` to 64
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 64;
|
||||
```
|
||||
|
||||
For more information about user-defined functions, see [User-Defined Functions](/develop/udf).
|
||||
|
||||
## Manage UDF
|
||||
|
@ -61,9 +73,9 @@ SHOW FUNCTIONS;
|
|||
|
||||
## Call UDF
|
||||
|
||||
The function name specified when creating UDF can be used directly in SQL statements, just like builtin functions. For example:
|
||||
The function name specified when creating UDF can be used directly in SQL statements, just like built-in functions. For example:
|
||||
```sql
|
||||
SELECT bit_and(c1,c2) FROM table;
|
||||
```
|
||||
|
||||
The above SQL statement invokes function X for column c1 and c2 on table. You can use query keywords like WHERE with user-defined functions.
|
||||
The above SQL statement invokes function X for columns c1 and c2 on the table. You can use query keywords like WHERE with user-defined functions.
|
||||
|
|
|
@ -27,7 +27,7 @@ The following data types can be used in the schema for standard tables.
|
|||
| - | :------- | :-------- | :------- |
|
||||
| 1 | ALTER ACCOUNT | Deprecated| This Enterprise Edition-only statement has been removed. It returns the error "This statement is no longer supported."
|
||||
| 2 | ALTER ALL DNODES | Added | Modifies the configuration of all dnodes.
|
||||
| 3 | ALTER DATABASE | Modified | Deprecated<ul><li>QUORUM: Specified the required number of confirmations. TDengine 3.0 provides strict consistency by default and doesn't allow to change to weak consitency. </li><li>BLOCKS: Specified the memory blocks used by each vnode. BUFFER is now used to specify the size of the write cache pool for each vnode. </li><li>UPDATE: Specified whether update operations were supported. All databases now support updating data in certain columns. </li><li>CACHELAST: Specified how to cache the newest row of data. CACHEMODEL now replaces CACHELAST. </li><li>COMP: Cannot be modified. <br/>Added</li><li>CACHEMODEL: Specifies whether to cache the latest subtable data. </li><li>CACHESIZE: Specifies the size of the cache for the newest subtable data. </li><li>WAL_FSYNC_PERIOD: Replaces the FSYNC parameter. </li><li>WAL_LEVEL: Replaces the WAL parameter. </li><li>WAL_RETENTION_PERIOD: specifies the time after which WAL files are deleted. This parameter is used for data subscription. </li><li>WAL_RETENTION_SIZE: specifies the size at which WAL files are deleted. This parameter is used for data subscription. <br/>Modified</li><li>REPLICA: Cannot be modified. </li><li>KEEP: Now supports units. </li></ul>
|
||||
| 3 | ALTER DATABASE | Modified | Deprecated<ul><li>QUORUM: Specified the required number of confirmations. TDengine 3.0 provides strict consistency by default and doesn't allow to change to weak consistency. </li><li>BLOCKS: Specified the memory blocks used by each vnode. BUFFER is now used to specify the size of the write cache pool for each vnode. </li><li>UPDATE: Specified whether update operations were supported. All databases now support updating data in certain columns. </li><li>CACHELAST: Specified how to cache the newest row of data. CACHEMODEL now replaces CACHELAST. </li><li>COMP: Cannot be modified. <br/>Added</li><li>CACHEMODEL: Specifies whether to cache the latest subtable data. </li><li>CACHESIZE: Specifies the size of the cache for the newest subtable data. </li><li>WAL_FSYNC_PERIOD: Replaces the FSYNC parameter. </li><li>WAL_LEVEL: Replaces the WAL parameter. </li><li>WAL_RETENTION_PERIOD: specifies the time after which WAL files are deleted. This parameter is used for data subscription. </li><li>WAL_RETENTION_SIZE: specifies the size at which WAL files are deleted. This parameter is used for data subscription. <br/>Modified</li><li>REPLICA: Cannot be modified. </li><li>KEEP: Now supports units. </li></ul>
|
||||
| 4 | ALTER STABLE | Modified | Deprecated<ul><li>CHANGE TAG: Modified the name of a tag. Replaced by RENAME TAG. <br/>Added</li><li>RENAME TAG: Replaces CHANGE TAG. </li><li>COMMENT: Specifies comments for a supertable. </li></ul>
|
||||
| 5 | ALTER TABLE | Modified | Deprecated<ul><li>CHANGE TAG: Modified the name of a tag. Replaced by RENAME TAG. <br/>Added</li><li>RENAME TAG: Replaces CHANGE TAG. </li><li>COMMENT: Specifies comments for a standard table. </li><li>TTL: Specifies the time-to-live for a standard table. </li></ul>
|
||||
| 6 | ALTER USER | Modified | Deprecated<ul><li>PRIVILEGE: Specified user permissions. Replaced by GRANT and REVOKE. <br/>Added</li><li>ENABLE: Enables or disables a user. </li><li>SYSINFO: Specifies whether a user can query system information. </li></ul>
|
||||
|
|
|
@ -42,3 +42,304 @@ An existing Grafana Notification Channel can be specified with parameter `-E`, t
|
|||
Launch `TDinsight.sh` with the command above and restart Grafana, then open Dashboard `http://localhost:3000/d/tdinsight`.
|
||||
|
||||
For more use cases and restrictions please refer to [TDinsight](/reference/tdinsight/).
|
||||
|
||||
## log database
|
||||
|
||||
The data of tdinsight dashboard is stored in `log` database (default. You can change it in taoskeeper's config file. For more infrmation, please reference to [taoskeeper document](/reference/taosKeeper)). The taoskeeper will create log database on taoskeeper startup.
|
||||
|
||||
### cluster\_info table
|
||||
|
||||
`cluster_info` table contains cluster information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|first\_ep|VARCHAR||first ep of cluster|
|
||||
|first\_ep\_dnode\_id|INT||dnode id or first\_ep|
|
||||
|version|VARCHAR||tdengine version. such as: 3.0.4.0|
|
||||
|master\_uptime|FLOAT||days of master's uptime|
|
||||
|monitor\_interval|INT||monitor interval in second|
|
||||
|dbs\_total|INT||total number of databases in cluster|
|
||||
|tbs\_total|BIGINT||total number of tables in cluster|
|
||||
|stbs\_total|INT||total number of stables in cluster|
|
||||
|dnodes\_total|INT||total number of dnodes in cluster|
|
||||
|dnodes\_alive|INT||total number of dnodes in ready state|
|
||||
|mnodes\_total|INT||total number of mnodes in cluster|
|
||||
|mnodes\_alive|INT||total number of mnodes in ready state|
|
||||
|vgroups\_total|INT||total number of vgroups in cluster|
|
||||
|vgroups\_alive|INT||total number of vgroups in ready state|
|
||||
|vnodes\_total|INT||total number of vnode in cluster|
|
||||
|vnodes\_alive|INT||total number of vnode in ready state|
|
||||
|connections\_total|INT||total number of connections to cluster|
|
||||
|topics\_total|INT||total number of topics in cluster|
|
||||
|streams\_total|INT||total number of streams in cluster|
|
||||
|protocol|INT||protocol version|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### d\_info table
|
||||
|
||||
`d_info` table contains dnodes information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|status|VARCHAR||dnode status|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### m\_info table
|
||||
|
||||
`m_info` table contains mnode information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|role|VARCHAR||the role of mnode. leader or follower|
|
||||
|mnode\_id|INT|TAG|master node id|
|
||||
|mnode\_ep|NCHAR|TAG|master node endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### dnodes\_info table
|
||||
|
||||
`dnodes_info` table contains dnodes information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|uptime|FLOAT||dnode uptime|
|
||||
|cpu\_engine|FLOAT||cpu usage of tdengine. read from `/proc/<taosd_pid>/stat`|
|
||||
|cpu\_system|FLOAT||cpu usage of server. read from `/proc/stat`|
|
||||
|cpu\_cores|FLOAT||cpu cores of server|
|
||||
|mem\_engine|INT||memory usage of tdengine. read from `/proc/<taosd_pid>/status`|
|
||||
|mem\_system|INT||available memory on the server|
|
||||
|mem\_total|INT||total memory of server in `KB`|
|
||||
|disk\_engine|INT|||
|
||||
|disk\_used|BIGINT||usage of data dir in `bytes`|
|
||||
|disk\_total|BIGINT||the capacity of data dir in `bytes`|
|
||||
|net\_in|FLOAT||network throughput rate in kb/s. read from `/proc/net/dev`|
|
||||
|net\_out|FLOAT||network throughput rate in kb/s. read from `/proc/net/dev`|
|
||||
|io\_read|FLOAT||io throughput rate in kb/s. read from `/proc/<taosd_pid>/io`|
|
||||
|io\_write|FLOAT||io throughput rate in kb/s. read from `/proc/<taosd_pid>/io`|
|
||||
|io\_read\_disk|FLOAT||io throughput rate of disk in kb/s. read from `/proc/<taosd_pid>/io`|
|
||||
|io\_write\_disk|FLOAT||io throughput rate of disk in kb/s. read from `/proc/<taosd_pid>/io`|
|
||||
|req\_select|INT||number of select queries received per dnode|
|
||||
|req\_select\_rate|FLOAT||number of select queries received per dnode divided by monitor interval.|
|
||||
|req\_insert|INT||number of insert queries received per dnode|
|
||||
|req\_insert\_success|INT||number of successfully insert queries received per dnode|
|
||||
|req\_insert\_rate|FLOAT||number of insert queries received per dnode divided by monitor interval|
|
||||
|req\_insert\_batch|INT||number of batch insertions|
|
||||
|req\_insert\_batch\_success|INT||number of successful batch insertions|
|
||||
|req\_insert\_batch\_rate|FLOAT||number of batch insertions divided by monitor interval|
|
||||
|errors|INT||dnode errors|
|
||||
|vnodes\_num|INT||number of vnodes per dnode|
|
||||
|masters|INT||number of master vnodes|
|
||||
|has\_mnode|INT||if the dnode has mnode|
|
||||
|has\_qnode|INT||if the dnode has qnode|
|
||||
|has\_snode|INT||if the dnode has snode|
|
||||
|has\_bnode|INT||if the dnode has bnode|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### data\_dir table
|
||||
|
||||
`data_dir` table contains data directory information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|name|NCHAR||data directory. default is `/var/lib/taos`|
|
||||
|level|INT||level for multi-level storage|
|
||||
|avail|BIGINT||available space for data directory|
|
||||
|used|BIGINT||used space for data directory|
|
||||
|total|BIGINT||total space for data directory|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### log\_dir table
|
||||
|
||||
`log_dir` table contains log directory information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|name|NCHAR||log directory. default is `/var/log/taos/`|
|
||||
|avail|BIGINT||available space for log directory|
|
||||
|used|BIGINT||used space for data directory|
|
||||
|total|BIGINT||total space for data directory|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### temp\_dir table
|
||||
|
||||
`temp_dir` table contains temp dir information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|name|NCHAR||temp directory. default is `/tmp/`|
|
||||
|avail|BIGINT||available space for temp directory|
|
||||
|used|BIGINT||used space for temp directory|
|
||||
|total|BIGINT||total space for temp directory|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### vgroups\_info table
|
||||
|
||||
`vgroups_info` table contains vgroups information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|vgroup\_id|INT||vgroup id|
|
||||
|database\_name|VARCHAR||database for the vgroup|
|
||||
|tables\_num|BIGINT||number of tables per vgroup|
|
||||
|status|VARCHAR||status|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### vnodes\_role table
|
||||
|
||||
`vnodes_role` table contains vnode role information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|vnode\_role|VARCHAR||role. leader or follower|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### logs table
|
||||
|
||||
`logs` table contains login information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|level|VARCHAR||log level|
|
||||
|content|NCHAR||log content|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### log\_summary table
|
||||
|
||||
`log_summary` table contains log summary information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|error|INT||error count|
|
||||
|info|INT||info count|
|
||||
|debug|INT||debug count|
|
||||
|trace|INT||trace count|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### grants\_info table
|
||||
|
||||
`grants_info` table contains grants information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|expire\_time|BIGINT||time until grants expire in seconds|
|
||||
|timeseries\_used|BIGINT||timeseries used|
|
||||
|timeseries\_total|BIGINT||total timeseries|
|
||||
|dnode\_id|INT|TAG|dnode id|
|
||||
|dnode\_ep|NCHAR|TAG|dnode endpoint|
|
||||
|cluster\_id|NCHAR|TAG|cluster id|
|
||||
|
||||
### keeper\_monitor table
|
||||
|
||||
`keeper_monitor` table contains keeper monitor information records.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|ts|TIMESTAMP||timestamp|
|
||||
|cpu|FLOAT||cpu usage|
|
||||
|mem|FLOAT||memory usage|
|
||||
|identify|NCHAR|TAG||
|
||||
|
||||
### taosadapter\_restful\_http\_request\_total table
|
||||
|
||||
`taosadapter_restful_http_request_total` table contains taosadapter rest request information record. The timestamp column of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|request\_uri|NCHAR|TAG|request uri|
|
||||
|status\_code|NCHAR|TAG|status code|
|
||||
|
||||
### taosadapter\_restful\_http\_request\_fail table
|
||||
|
||||
`taosadapter_restful_http_request_fail` table contains taosadapter failed rest request information record. The timestamp column of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|request\_uri|NCHAR|TAG|request uri|
|
||||
|status\_code|NCHAR|TAG|status code|
|
||||
|
||||
### taosadapter\_restful\_http\_request\_in\_flight table
|
||||
|
||||
`taosadapter_restful_http_request_in_flight` table contains taosadapter rest request information record in real time. The timestamp column of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_restful\_http\_request\_summary\_milliseconds table
|
||||
|
||||
`taosadapter_restful_http_request_summary_milliseconds` table contains the summary or rest information record. The timestamp column of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|count|DOUBLE|||
|
||||
|sum|DOUBLE|||
|
||||
|0.5|DOUBLE|||
|
||||
|0.9|DOUBLE|||
|
||||
|0.99|DOUBLE|||
|
||||
|0.1|DOUBLE|||
|
||||
|0.2|DOUBLE|||
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|request\_uri|NCHAR|TAG|request uri|
|
||||
|
||||
### taosadapter\_system\_mem\_percent table
|
||||
|
||||
`taosadapter_system_mem_percent` table contains taosadapter memory usage information. The timestamp of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_system\_cpu\_percent table
|
||||
|
||||
`taosadapter_system_cpu_percent` table contains taosadapter cup usage information. The timestamp of this table is `_ts`.
|
||||
|
||||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||mertic value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
|
|
|
@ -423,6 +423,6 @@ In addition to writing data using the SQL method or the parameter binding API, w
|
|||
|
||||
**Description**
|
||||
- The above seven interfaces are extension interfaces, which are mainly used to pass ttl and reqid parameters, and can be used as needed.
|
||||
- Withing _raw interfaces represent data through the passed parameters lines and len. In order to solve the problem that the original interface data contains '\0' and is truncated. The totalRows pointer returns the number of parsed data rows.
|
||||
- Withing _ttl interfaces can pass the ttl parameter to control the ttl expiration time of the table.
|
||||
- Withing _reqid interfaces can track the entire call chain by passing the reqid parameter.
|
||||
- Within _raw interfaces represent data through the passed parameters lines and len. In order to solve the problem that the original interface data contains '\0' and is truncated. The totalRows pointer returns the number of parsed data rows.
|
||||
- Within _ttl interfaces can pass the ttl parameter to control the ttl expiration time of the table.
|
||||
- Within _reqid interfaces can track the entire call chain by passing the reqid parameter.
|
||||
|
|
|
@ -40,19 +40,19 @@ Please refer to [version support list](/reference/connector#version-support)
|
|||
|
||||
TDengine currently supports timestamp, number, character, Boolean type, and the corresponding type conversion with Java is as follows:
|
||||
|
||||
| TDengine DataType | JDBCType |
|
||||
| ----------------- | ---------------------------------- |
|
||||
| TIMESTAMP | java.sql.Timestamp |
|
||||
| INT | java.lang.Integer |
|
||||
| BIGINT | java.lang.Long |
|
||||
| FLOAT | java.lang.Float |
|
||||
| DOUBLE | java.lang.Double |
|
||||
| SMALLINT | java.lang.Short |
|
||||
| TINYINT | java.lang.Byte |
|
||||
| BOOL | java.lang.Boolean |
|
||||
| BINARY | byte array |
|
||||
| NCHAR | java.lang.String |
|
||||
| JSON | java.lang.String |
|
||||
| TDengine DataType | JDBCType |
|
||||
| ----------------- | ------------------ |
|
||||
| TIMESTAMP | java.sql.Timestamp |
|
||||
| INT | java.lang.Integer |
|
||||
| BIGINT | java.lang.Long |
|
||||
| FLOAT | java.lang.Float |
|
||||
| DOUBLE | java.lang.Double |
|
||||
| SMALLINT | java.lang.Short |
|
||||
| TINYINT | java.lang.Byte |
|
||||
| BOOL | java.lang.Boolean |
|
||||
| BINARY | byte array |
|
||||
| NCHAR | java.lang.String |
|
||||
| JSON | java.lang.String |
|
||||
|
||||
**Note**: Only TAG supports JSON types
|
||||
|
||||
|
@ -82,7 +82,7 @@ Add following dependency in the `pom.xml` file of your Maven project:
|
|||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -227,7 +227,7 @@ In addition to getting the connection from the specified URL, you can use Proper
|
|||
Note:
|
||||
|
||||
- The client parameter set in the application is process-level. If you want to update the parameters of the client, you need to restart the application. This is because the client parameter is a global parameter that takes effect only the first time the application is set.
|
||||
- The following sample code is based on taos-jdbcdriver-3.0.0.
|
||||
- The following sample code is based on taos-jdbcdriver-3.1.0.
|
||||
|
||||
```java
|
||||
public Connection getConn() throws Exception{
|
||||
|
@ -350,7 +350,12 @@ try (Statement statement = connection.createStatement()) {
|
|||
}
|
||||
```
|
||||
|
||||
There are three types of error codes that the JDBC connector can report: - Error code of the JDBC driver itself (error code between 0x2301 and 0x2350), - Error code of the native connection method (error code between 0x2351 and 0x2400), and - Error code of other TDengine function modules.
|
||||
There are four types of error codes that the JDBC connector can report:
|
||||
|
||||
- Error code of the JDBC driver itself (error code between 0x2301 and 0x2350),
|
||||
- Error code of the native connection method (error code between 0x2351 and 0x2360)
|
||||
- Error code of the consumer method (error code between 0x2371 and 0x2380)
|
||||
- Error code of other TDengine function modules.
|
||||
|
||||
For specific error codes, please refer to.
|
||||
|
||||
|
@ -364,7 +369,7 @@ TDengine has significantly improved the bind APIs to support data writing (INSER
|
|||
**Note:**
|
||||
|
||||
- JDBC REST connections do not currently support bind interface
|
||||
- The following sample code is based on taos-jdbcdriver-3.0.0
|
||||
- The following sample code is based on taos-jdbcdriver-3.1.0
|
||||
- The setString method should be called for binary type data, and the setNString method should be called for nchar type data
|
||||
- both setString and setNString require the user to declare the width of the corresponding column in the size parameter of the table definition
|
||||
|
||||
|
@ -632,7 +637,7 @@ TDengine supports schemaless writing. It is compatible with InfluxDB's Line Prot
|
|||
Note:
|
||||
|
||||
- JDBC REST connections do not currently support schemaless writes
|
||||
- The following sample code is based on taos-jdbcdriver-3.0.0
|
||||
- The following sample code is based on taos-jdbcdriver-3.1.0
|
||||
|
||||
```java
|
||||
public class SchemalessInsertTest {
|
||||
|
@ -965,17 +970,17 @@ The source code of the sample application is under `TDengine/examples/JDBC`:
|
|||
|
||||
## Recent update logs
|
||||
|
||||
| taos-jdbcdriver version | major changes |
|
||||
| :---------------------: | :--------------------------------------------: |
|
||||
| 3.1.0 | JDBC REST connection supports subscription over WebSocket |
|
||||
| 3.0.1 - 3.0.4 | fix the resultSet data is parsed incorrectly sometimes. 3.0.1 is compiled on JDK 11, you are advised to use other version in the JDK 8 environment |
|
||||
| 3.0.0 | Support for TDengine 3.0 |
|
||||
| 2.0.42 | fix wasNull interface return value in WebSocket connection |
|
||||
| 2.0.41 | fix decode method of username and password in REST connection |
|
||||
| 2.0.39 - 2.0.40 | Add REST connection/request timeout parameters |
|
||||
| 2.0.38 | JDBC REST connections add bulk pull function |
|
||||
| 2.0.37 | Support json tags |
|
||||
| 2.0.36 | Support schemaless writing |
|
||||
| taos-jdbcdriver version | major changes |
|
||||
| :---------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| 3.1.0 | JDBC REST connection supports subscription over WebSocket |
|
||||
| 3.0.1 - 3.0.4 | fix the resultSet data is parsed incorrectly sometimes. 3.0.1 is compiled on JDK 11, you are advised to use other version in the JDK 8 environment |
|
||||
| 3.0.0 | Support for TDengine 3.0 |
|
||||
| 2.0.42 | fix wasNull interface return value in WebSocket connection |
|
||||
| 2.0.41 | fix decode method of username and password in REST connection |
|
||||
| 2.0.39 - 2.0.40 | Add REST connection/request timeout parameters |
|
||||
| 2.0.38 | JDBC REST connections add bulk pull function |
|
||||
| 2.0.37 | Support json tags |
|
||||
| 2.0.36 | Support schemaless writing |
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
|
@ -999,9 +1004,9 @@ The source code of the sample application is under `TDengine/examples/JDBC`:
|
|||
|
||||
4. java.lang.NoSuchMethodError: setByteArray
|
||||
|
||||
**Cause**: taos-jbdcdriver 3.* only supports TDengine 3.0 and later.
|
||||
**Cause**: taos-jbdcdriver 3.\* only supports TDengine 3.0 and later.
|
||||
|
||||
**Solution**: Use taos-jdbcdriver 2.* with your TDengine 2.* deployment.
|
||||
**Solution**: Use taos-jdbcdriver 2.\* with your TDengine 2.\* deployment.
|
||||
|
||||
5. java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer; ... taos-jdbcdriver-3.0.1.jar
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import TabItem from '@theme/TabItem';
|
|||
import Preparition from "./_preparation.mdx"
|
||||
import RustInsert from "../../07-develop/03-insert-data/_rust_sql.mdx"
|
||||
import RustBind from "../../07-develop/03-insert-data/_rust_stmt.mdx"
|
||||
import RustSml from "../../07-develop/03-insert-data/_rust_schemaless.mdx"
|
||||
import RustQuery from "../../07-develop/04-query-data/_rust.mdx"
|
||||
|
||||
[](https://crates.io/crates/taos)  [](https://docs.rs/taos)
|
||||
|
@ -232,6 +233,10 @@ There are two ways to query data: Using built-in types or the [serde](https://se
|
|||
|
||||
<RustBind />
|
||||
|
||||
#### Schemaless Write
|
||||
|
||||
<RustSml />
|
||||
|
||||
### Query data
|
||||
|
||||
<RustQuery />
|
||||
|
|
|
@ -62,7 +62,7 @@ The different database framework specifications for various programming language
|
|||
| **Regular Query** | Support | Support | Support | Support | Support | Support |
|
||||
| **Parameter Binding** | Not Supported | Not Supported | Support | Support | Not Supported | Support |
|
||||
| **Subscription (TMQ) ** | Supported | Support | Support | Not Supported | Not Supported | Support |
|
||||
| **Schemaless** | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
| **Schemaless** | Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
| **Bulk Pulling (based on WebSocket) ** | Support | Support | Support | Support | Support | Support |
|
||||
| **DataFrame** | Not Supported | Support | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
-A, --all-databases Dump all databases.
|
||||
-D, --databases=DATABASES Dump listed databases. Use comma to separate
|
||||
database names.
|
||||
-e, --escape-character Use escaped character for database name
|
||||
-N, --without-property Dump database without its properties.
|
||||
-s, --schemaonly Only dump table schemas.
|
||||
-y, --answer-yes Input yes for prompt. It will skip data file
|
||||
|
|
|
@ -358,6 +358,17 @@ The charset that takes effect is UTF-8.
|
|||
| Value Range | 0-4096 |
|
||||
| Default Value | 2x the CPU cores |
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
### numOfCommitThreads
|
||||
|
||||
| Attribute | Description |
|
||||
| ------------- | ----------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Maximum number of threads to commit |
|
||||
| Value Range | 0-1024 |
|
||||
| Default Value | |
|
||||
|
||||
## Log Parameters
|
||||
|
||||
### logDir
|
||||
|
|
|
@ -108,7 +108,7 @@ The following `launchctl` commands can help you manage taoskeeper service:
|
|||
|
||||
#### Launch With Configuration File
|
||||
|
||||
You can quickly launch taosKeeper with the following commands. If you do not specify a configuration file, `/etc/taos/keeper.toml` is used by default. If this file does not specify configurations, the default values are used.
|
||||
You can quickly launch taosKeeper with the following commands. If you do not specify a configuration file, `/etc/taos/taoskeeper.toml` is used by default. If this file does not specify configurations, the default values are used.
|
||||
|
||||
```shell
|
||||
$ taoskeeper -c <keeper config file>
|
||||
|
@ -153,6 +153,10 @@ database = "log"
|
|||
|
||||
# standard tables to monitor
|
||||
tables = ["normal_table"]
|
||||
|
||||
# database options for db storing metrics data
|
||||
[metrics.databaseoptions]
|
||||
cachemodel = "none"
|
||||
```
|
||||
|
||||
### Obtain Monitoring Metrics
|
||||
|
@ -203,7 +207,7 @@ taos_cluster_info_dnodes_total{cluster_id="5981392874047724755"} 1
|
|||
taos_cluster_info_first_ep{cluster_id="5981392874047724755",value="hlb:6030"} 1
|
||||
```
|
||||
|
||||
### check_health
|
||||
### check\_health
|
||||
|
||||
```
|
||||
$ curl -i http://127.0.0.1:6043/check_health
|
||||
|
@ -219,3 +223,29 @@ Content-Length: 19
|
|||
|
||||
{"version":"1.0.0"}
|
||||
```
|
||||
|
||||
### taoskeeper with Prometheus
|
||||
|
||||
There is `/metrics` api in taoskeeper provide TDengine metric data for Prometheus.
|
||||
|
||||
#### scrape config
|
||||
|
||||
Scrape config in Prometheus specifies a set of targets and parameters describing how to scrape metric data from endpoint. For more information, please reference to [Prometheus documents](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config).
|
||||
|
||||
```
|
||||
# A scrape configuration containing exactly one endpoint to scrape:
|
||||
# Here it's Prometheus itself.
|
||||
scrape_configs:
|
||||
- job_name: "taoskeeper"
|
||||
# metrics_path defaults to '/metrics'
|
||||
# scheme defaults to 'http'.
|
||||
static_configs:
|
||||
- targets: ["localhost:6043"]
|
||||
```
|
||||
|
||||
#### Dashboard
|
||||
|
||||
There is a dashboard named `TaosKeeper Prometheus Dashboard for 3.x`, which provides a monitoring dashboard similar to TInsight.
|
||||
|
||||
In Grafana, click the Dashboard menu and click `import`, enter the dashboard ID `18587` and click the `Load` button. Then finished importing `TaosKeeper Prometheus Dashboard for 3.x` dashboard.
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ For TDengine 2.x installation packages by version, please visit [here](https://w
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.4.1
|
||||
|
||||
<Release type="tdengine" version="3.0.4.1" />
|
||||
|
||||
## 3.0.4.0
|
||||
|
||||
<Release type="tdengine" version="3.0.4.0" />
|
||||
|
|
|
@ -10,6 +10,10 @@ For other historical version installers, please visit [here](https://www.taosdat
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 2.5.0
|
||||
|
||||
<Release type="tools" version="2.5.0" />
|
||||
|
||||
## 2.4.12
|
||||
|
||||
<Release type="tools" version="2.4.12" />
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <taos.h>
|
||||
|
||||
typedef int16_t VarDataLenT;
|
||||
typedef uint16_t VarDataLenT;
|
||||
|
||||
#define TSDB_NCHAR_SIZE sizeof(int32_t)
|
||||
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <taos.h>
|
||||
|
||||
typedef int16_t VarDataLenT;
|
||||
typedef uint16_t VarDataLenT;
|
||||
|
||||
#define TSDB_NCHAR_SIZE sizeof(int32_t)
|
||||
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
use taos_query::common::SchemalessPrecision;
|
||||
use taos_query::common::SchemalessProtocol;
|
||||
use taos_query::common::SmlDataBuilder;
|
||||
|
||||
use crate::AsyncQueryable;
|
||||
use crate::AsyncTBuilder;
|
||||
use crate::TaosBuilder;
|
||||
|
||||
async fn put_json() -> anyhow::Result<()> {
|
||||
// std::env::set_var("RUST_LOG", "taos=trace");
|
||||
std::env::set_var("RUST_LOG", "taos=debug");
|
||||
pretty_env_logger::init();
|
||||
let dsn =
|
||||
std::env::var("TDENGINE_ClOUD_DSN").unwrap_or("http://localhost:6041".to_string());
|
||||
log::debug!("dsn: {:?}", &dsn);
|
||||
|
||||
let client = TaosBuilder::from_dsn(dsn)?.build().await?;
|
||||
|
||||
let db = "demo_schemaless_ws";
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
client
|
||||
.exec(format!("create database if not exists {db}"))
|
||||
.await?;
|
||||
|
||||
// should specify database before insert
|
||||
client.exec(format!("use {db}")).await?;
|
||||
|
||||
// SchemalessProtocol::Json
|
||||
let data = [
|
||||
r#"[{"metric": "meters.current", "timestamp": 1681345954000, "value": 10.3, "tags": {"location": "California.SanFrancisco", "groupid": 2}}, {"metric": "meters.voltage", "timestamp": 1648432611249, "value": 219, "tags": {"location": "California.LosAngeles", "groupid": 1}}, {"metric": "meters.current", "timestamp": 1648432611250, "value": 12.6, "tags": {"location": "California.SanFrancisco", "groupid": 2}}, {"metric": "meters.voltage", "timestamp": 1648432611250, "value": 221, "tags": {"location": "California.LosAngeles", "groupid": 1}}]"#
|
||||
]
|
||||
.map(String::from)
|
||||
.to_vec();
|
||||
|
||||
// demo with all fields
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Json)
|
||||
.precision(SchemalessPrecision::Millisecond)
|
||||
.data(data.clone())
|
||||
.ttl(1000)
|
||||
.req_id(300u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default precision
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Json)
|
||||
.data(data.clone())
|
||||
.ttl(1000)
|
||||
.req_id(301u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default ttl
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Json)
|
||||
.data(data.clone())
|
||||
.req_id(302u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default req_id
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Json)
|
||||
.data(data.clone())
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
use taos_query::common::SchemalessPrecision;
|
||||
use taos_query::common::SchemalessProtocol;
|
||||
use taos_query::common::SmlDataBuilder;
|
||||
|
||||
use crate::AsyncQueryable;
|
||||
use crate::AsyncTBuilder;
|
||||
use crate::TaosBuilder;
|
||||
|
||||
async fn put_line() -> anyhow::Result<()> {
|
||||
// std::env::set_var("RUST_LOG", "taos=trace");
|
||||
std::env::set_var("RUST_LOG", "taos=debug");
|
||||
pretty_env_logger::init();
|
||||
|
||||
let dsn =
|
||||
std::env::var("TDENGINE_ClOUD_DSN").unwrap_or("http://localhost:6041".to_string());
|
||||
log::debug!("dsn: {:?}", &dsn);
|
||||
|
||||
let client = TaosBuilder::from_dsn(dsn)?.build().await?;
|
||||
|
||||
let db = "demo_schemaless_ws";
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
client
|
||||
.exec(format!("create database if not exists {db}"))
|
||||
.await?;
|
||||
|
||||
// should specify database before insert
|
||||
client.exec(format!("use {db}")).await?;
|
||||
|
||||
let data = [
|
||||
"measurement,host=host1 field1=2i,field2=2.0 1577837300000",
|
||||
"measurement,host=host1 field1=2i,field2=2.0 1577837400000",
|
||||
"measurement,host=host1 field1=2i,field2=2.0 1577837500000",
|
||||
"measurement,host=host1 field1=2i,field2=2.0 1577837600000",
|
||||
]
|
||||
.map(String::from)
|
||||
.to_vec();
|
||||
|
||||
// demo with all fields
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.precision(SchemalessPrecision::Millisecond)
|
||||
.data(data.clone())
|
||||
.ttl(1000)
|
||||
.req_id(100u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default ttl
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.precision(SchemalessPrecision::Millisecond)
|
||||
.data(data.clone())
|
||||
.req_id(101u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default ttl and req_id
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.precision(SchemalessPrecision::Millisecond)
|
||||
.data(data.clone())
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default precision
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Line)
|
||||
.data(data)
|
||||
.req_id(103u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
use taos_query::common::SchemalessPrecision;
|
||||
use taos_query::common::SchemalessProtocol;
|
||||
use taos_query::common::SmlDataBuilder;
|
||||
|
||||
use crate::AsyncQueryable;
|
||||
use crate::AsyncTBuilder;
|
||||
use crate::TaosBuilder;
|
||||
|
||||
async fn put_telnet() -> anyhow::Result<()> {
|
||||
// std::env::set_var("RUST_LOG", "taos=trace");
|
||||
std::env::set_var("RUST_LOG", "taos=debug");
|
||||
pretty_env_logger::init();
|
||||
let dsn =
|
||||
std::env::var("TDENGINE_ClOUD_DSN").unwrap_or("http://localhost:6041".to_string());
|
||||
log::debug!("dsn: {:?}", &dsn);
|
||||
|
||||
let client = TaosBuilder::from_dsn(dsn)?.build().await?;
|
||||
|
||||
let db = "demo_schemaless_ws";
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
client
|
||||
.exec(format!("create database if not exists {db}"))
|
||||
.await?;
|
||||
|
||||
// should specify database before insert
|
||||
client.exec(format!("use {db}")).await?;
|
||||
|
||||
let data = [
|
||||
"meters.current 1648432611249 10.3 location=California.SanFrancisco group=2",
|
||||
"meters.current 1648432611250 12.6 location=California.SanFrancisco group=2",
|
||||
"meters.current 1648432611249 10.8 location=California.LosAngeles group=3",
|
||||
"meters.current 1648432611250 11.3 location=California.LosAngeles group=3",
|
||||
"meters.voltage 1648432611249 219 location=California.SanFrancisco group=2",
|
||||
"meters.voltage 1648432611250 218 location=California.SanFrancisco group=2",
|
||||
"meters.voltage 1648432611249 221 location=California.LosAngeles group=3",
|
||||
"meters.voltage 1648432611250 217 location=California.LosAngeles group=3",
|
||||
]
|
||||
.map(String::from)
|
||||
.to_vec();
|
||||
|
||||
// demo with all fields
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Telnet)
|
||||
.precision(SchemalessPrecision::Millisecond)
|
||||
.data(data.clone())
|
||||
.ttl(1000)
|
||||
.req_id(200u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default precision
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Telnet)
|
||||
.data(data.clone())
|
||||
.ttl(1000)
|
||||
.req_id(201u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default ttl
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Telnet)
|
||||
.data(data.clone())
|
||||
.req_id(202u64)
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
// demo with default req_id
|
||||
let sml_data = SmlDataBuilder::default()
|
||||
.protocol(SchemalessProtocol::Telnet)
|
||||
.data(data.clone())
|
||||
.build()?;
|
||||
assert_eq!(client.put(&sml_data).await?, ());
|
||||
|
||||
client.exec(format!("drop database if exists {db}")).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -100,7 +100,8 @@ sudo apt-get install tdengine
|
|||
|
||||
:::tip
|
||||
apt-get 方式只适用于 Debian 或 Ubuntu 系统。
|
||||
::::
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Windows 安装" value="windows">
|
||||
|
||||
|
@ -206,6 +207,8 @@ Active: inactive (dead)
|
|||
|
||||
- 查看服务状态:`sudo launchctl list | grep taosd`
|
||||
|
||||
- 查看服务详细信息:`launchctl print system/com.tdengine.taosd`
|
||||
|
||||
:::info
|
||||
|
||||
- `launchctl` 命令管理`com.tdengine.taosd`需要管理员权限,务必在前面加 `sudo` 来增强安全性。
|
||||
|
|
|
@ -38,7 +38,7 @@ meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0
|
|||
- field_set 中的每个数据项都需要对自身的数据类型进行描述, 比如 1.2f32 代表 FLOAT 类型的数值 1.2, 如果不带类型后缀会被当作 DOUBLE 处理;
|
||||
- timestamp 支持多种时间精度。写入数据的时候需要用参数指定时间精度,支持从小时到纳秒的 6 种时间精度。
|
||||
- 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常。(3.0.1.3 之后的版本 smlDataFormat 默认为 false,从3.0.3.0开始,该配置废弃) [TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议)
|
||||
- 默认产生的子表名是根据规则生成的唯一 ID 值。用户也可以通过在 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议)
|
||||
- 默认产生的子表名是根据规则生成的唯一 ID 值。用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议)
|
||||
:::
|
||||
|
||||
要了解更多可参考:[InfluxDB Line 协议官方文档](https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/) 和 [TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议)
|
||||
|
|
|
@ -32,7 +32,7 @@ OpenTSDB 行协议同样采用一行字符串来表示一行数据。OpenTSDB
|
|||
meters.current 1648432611250 11.3 location=California.LosAngeles groupid=3
|
||||
```
|
||||
|
||||
- 默认生产的子表名是根据规则生成的唯一 ID 值。用户也可以通过在 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 meters.current 1648432611250 11.3 tname=cpu1 location=California.LosAngeles groupid=3 则创建的表名为 cpu1,注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。
|
||||
- 默认生产的子表名是根据规则生成的唯一 ID 值。用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 meters.current 1648432611250 11.3 tname=cpu1 location=California.LosAngeles groupid=3 则创建的表名为 cpu1,注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。
|
||||
参考 [OpenTSDB Telnet API 文档](http://opentsdb.net/docs/build/html/api_telnet/put.html)。
|
||||
|
||||
## 示例代码
|
||||
|
|
|
@ -47,7 +47,7 @@ OpenTSDB JSON 格式协议采用一个 JSON 字符串表示一行或多行数据
|
|||
:::note
|
||||
|
||||
- 对于 JSON 格式协议,TDengine 并不会自动把所有标签转成 NCHAR 类型, 字符串将将转为 NCHAR 类型, 数值将同样转换为 DOUBLE 类型。
|
||||
- 默认生成的子表名是根据规则生成的唯一 ID 值。用户也可以通过在 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 `"tags": { "host": "web02","dc": "lga","tname":"cpu1"}` 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。
|
||||
- 默认生成的子表名是根据规则生成的唯一 ID 值。用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 `"tags": { "host": "web02","dc": "lga","tname":"cpu1"}` 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。
|
||||
:::
|
||||
|
||||
## 示例代码
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```rust
|
||||
{{#include docs/examples/rust/nativeexample/examples/schemaless_insert_line.rs}}
|
||||
```
|
|
@ -221,7 +221,7 @@ void Close()
|
|||
|
||||
```sql
|
||||
DROP DATABASE IF EXISTS tmqdb;
|
||||
CREATE DATABASE tmqdb;
|
||||
CREATE DATABASE tmqdb WAL_RETENTION_PERIOD 3600;
|
||||
CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16));
|
||||
CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0");
|
||||
CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1");
|
||||
|
|
|
@ -6,18 +6,20 @@ description: "支持用户编码的聚合函数和标量函数,在查询中嵌
|
|||
|
||||
在有些应用场景中,应用逻辑需要的查询无法直接使用系统内置的函数来表示。利用 UDF(User Defined Function) 功能,TDengine 可以插入用户编写的处理代码并在查询中使用它们,就能够很方便地解决特殊应用场景中的使用需求。 UDF 通常以数据表中的一列数据做为输入,同时支持以嵌套子查询的结果作为输入。
|
||||
|
||||
TDengine 支持通过 C/C++ 语言进行 UDF 定义。接下来结合示例讲解 UDF 的使用方法。
|
||||
|
||||
用户可以通过 UDF 实现两类函数:标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值 abs,正弦函数 sin,字符串拼接函数 concat 等。聚合函数对多行数据进行输出一个值,如求平均数 avg,最大值 max 等。
|
||||
|
||||
实现 UDF 时,需要实现规定的接口函数
|
||||
TDengine 支持通过 C/Python 语言进行 UDF 定义。接下来结合示例讲解 UDF 的使用方法。
|
||||
|
||||
## 用 C 语言实现 UDF
|
||||
|
||||
使用 C 语言实现 UDF 时,需要实现规定的接口函数
|
||||
- 标量函数需要实现标量接口函数 scalarfn 。
|
||||
- 聚合函数需要实现聚合接口函数 aggfn_start , aggfn , aggfn_finish。
|
||||
- 如果需要初始化,实现 udf_init;如果需要清理工作,实现udf_destroy。
|
||||
|
||||
接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(_start, _finish, _init, _destroy)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。
|
||||
|
||||
## 实现标量函数
|
||||
### 用 C 语言实现标量函数
|
||||
标量函数实现模板如下
|
||||
```c
|
||||
#include "taos.h"
|
||||
|
@ -49,7 +51,7 @@ int32_t scalarfn_destroy() {
|
|||
```
|
||||
scalarfn 为函数名的占位符,需要替换成函数名,如bit_and。
|
||||
|
||||
## 实现聚合函数
|
||||
### 用 C 语言实现聚合函数
|
||||
|
||||
聚合函数的实现模板如下
|
||||
```c
|
||||
|
@ -100,7 +102,7 @@ int32_t aggfn_destroy() {
|
|||
```
|
||||
aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。
|
||||
|
||||
## 接口函数定义
|
||||
### C 语言 UDF 接口函数定义
|
||||
|
||||
接口函数的名称是 udf 名称,或者是 udf 名称和特定后缀(_start, _finish, _init, _destroy)的连接。以下描述中函数名称中的 scalarfn,aggfn, udf 需要替换成udf函数名。
|
||||
|
||||
|
@ -108,7 +110,7 @@ aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。
|
|||
|
||||
接口函数参数类型见数据结构定义。
|
||||
|
||||
### 标量接口函数
|
||||
#### 标量函数接口
|
||||
|
||||
`int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)`
|
||||
|
||||
|
@ -118,7 +120,7 @@ aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。
|
|||
- inputDataBlock: 输入的数据块
|
||||
- resultColumn: 输出列
|
||||
|
||||
### 聚合接口函数
|
||||
#### 聚合函数接口
|
||||
|
||||
`int32_t aggfn_start(SUdfInterBuf *interBuf)`
|
||||
|
||||
|
@ -135,7 +137,7 @@ aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。
|
|||
- result:最终结果。
|
||||
|
||||
|
||||
### UDF 初始化和销毁
|
||||
#### 初始化和销毁接口
|
||||
`int32_t udf_init()`
|
||||
|
||||
`int32_t udf_destroy()`
|
||||
|
@ -143,7 +145,7 @@ aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。
|
|||
其中 udf 是函数名的占位符。udf_init 完成初始化工作。 udf_destroy 完成清理工作。如果没有初始化工作,无需定义udf_init函数。如果没有清理工作,无需定义udf_destroy函数。
|
||||
|
||||
|
||||
## UDF 数据结构
|
||||
### C 语言 UDF 数据结构
|
||||
```c
|
||||
typedef struct SUdfColumnMeta {
|
||||
int16_t type;
|
||||
|
@ -201,7 +203,7 @@ typedef struct SUdfInterBuf {
|
|||
|
||||
为了更好的操作以上数据结构,提供了一些便利函数,定义在 taosudf.h。
|
||||
|
||||
## 编译 UDF
|
||||
### 编译 C UDF
|
||||
|
||||
用户定义函数的 C 语言源代码无法直接被 TDengine 系统使用,而是需要先编译为 动态链接库,之后才能载入 TDengine 系统。
|
||||
|
||||
|
@ -213,12 +215,9 @@ gcc -g -O0 -fPIC -shared bit_and.c -o libbitand.so
|
|||
|
||||
这样就准备好了动态链接库 libbitand.so 文件,可以供后文创建 UDF 时使用了。为了保证可靠的系统运行,编译器 GCC 推荐使用 7.5 及以上版本。
|
||||
|
||||
## 管理和使用UDF
|
||||
编译好的UDF,还需要将其加入到系统才能被正常的SQL调用。关于如何管理和使用UDF,参见[UDF使用说明](../12-taos-sql/26-udf.md)
|
||||
### C UDF 示例代码
|
||||
|
||||
## 示例代码
|
||||
|
||||
### 标量函数示例 [bit_and](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/bit_and.c)
|
||||
#### 标量函数示例 [bit_and](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/bit_and.c)
|
||||
|
||||
bit_add 实现多列的按位与功能。如果只有一列,返回这一列。bit_add 忽略空值。
|
||||
|
||||
|
@ -231,7 +230,7 @@ bit_add 实现多列的按位与功能。如果只有一列,返回这一列。
|
|||
|
||||
</details>
|
||||
|
||||
### 聚合函数示例1 返回值为数值类型 [l2norm](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/l2norm.c)
|
||||
#### 聚合函数示例1 返回值为数值类型 [l2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/l2norm.c)
|
||||
|
||||
l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。
|
||||
|
||||
|
@ -244,7 +243,7 @@ l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先
|
|||
|
||||
</details>
|
||||
|
||||
### 聚合函数示例2 返回值为字符串类型 [max_vol](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/max_vol.c)
|
||||
#### 聚合函数示例2 返回值为字符串类型 [max_vol](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/max_vol.c)
|
||||
|
||||
max_vol 实现了从多个输入的电压列中找到最大电压,返回由设备ID + 最大电压所在(行,列)+ 最大电压值 组成的组合字符串值
|
||||
|
||||
|
@ -268,4 +267,125 @@ select max_vol(vol1,vol2,vol3,deviceid) from battery;
|
|||
{{#include tests/script/sh/max_vol.c}}
|
||||
```
|
||||
|
||||
</details>
|
||||
</details>
|
||||
|
||||
## 用 Python 语言实现 UDF
|
||||
|
||||
使用 Python 语言实现 UDF 时,需要实现规定的接口函数
|
||||
- 标量函数需要实现标量接口函数 process 。
|
||||
- 聚合函数需要实现聚合接口函数 start ,reduce ,finish。
|
||||
- 如果需要初始化,实现 init;如果需要清理工作,实现 destroy。
|
||||
|
||||
### 用 Python 实现标量函数
|
||||
|
||||
标量函数实现模版如下
|
||||
```Python
|
||||
def init():
|
||||
# initialization
|
||||
def destroy():
|
||||
# destroy
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
# process input datablock,
|
||||
# datablock.data(row, col) is to access the python object in location(row,col)
|
||||
# return tuple object consisted of object of type outputtype
|
||||
```
|
||||
|
||||
### 用 Python 实现聚合函数
|
||||
|
||||
聚合函数实现模版如下
|
||||
```Python
|
||||
def init():
|
||||
#initialization
|
||||
def destroy():
|
||||
#destroy
|
||||
def start() -> bytes:
|
||||
#return serialize(init_state)
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
# deserialize buf to state
|
||||
# reduce the inputs and state into new_state.
|
||||
# use inputs.data(i,j) to access python ojbect of location(i,j)
|
||||
# serialize new_state into new_state_bytes
|
||||
return new_state_bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
#return obj of type outputtype
|
||||
```
|
||||
|
||||
### Python UDF 接口函数定义
|
||||
|
||||
#### 标量函数接口
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象
|
||||
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
|
||||
|
||||
#### 聚合函数接口
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
首先调用 start 生成最初结果 buffer,然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果,最后再调用 finish 从中间结果 buf 产生最终输出,最终输出只能含 0 或 1 条数据。
|
||||
|
||||
|
||||
#### 初始化和销毁接口
|
||||
```Python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
|
||||
其中 init 完成初始化工作。 destroy 完成清理工作。如果没有初始化工作,无需定义 init 函数。如果没有清理工作,无需定义 destroy 函数。
|
||||
|
||||
### Python 和 TDengine之间的数据类型映射
|
||||
|
||||
下表描述了TDengine SQL数据类型和Python数据类型的映射。任何类型的NULL值都映射成Python的None值。
|
||||
|
||||
| **TDengine SQL数据类型** | **Python数据类型** |
|
||||
| :-----------------------: | ------------ |
|
||||
|TINYINT / SMALLINT / INT / BIGINT | int |
|
||||
|TINYINT UNSIGNED / SMALLINT UNSIGNED / INT UNSIGNED / BIGINT UNSIGNED | int |
|
||||
|FLOAT / DOUBLE | float |
|
||||
|BOOL | bool |
|
||||
|BINARY / VARCHAR / NCHAR | bytes|
|
||||
|TIMESTAMP | int |
|
||||
|JSON and other types | 不支持 |
|
||||
|
||||
### Python UDF 环境的安装
|
||||
1. 安装 taospyudf 包。此包执行Python UDF程序。
|
||||
```bash
|
||||
sudo pip install taospyudf
|
||||
ldconfig
|
||||
```
|
||||
2. 如果 Python UDF 程序执行时,通过 PYTHONPATH 引用其它的包,可以设置 taos.cfg 的 UdfdLdLibPath 变量为PYTHONPATH的内容
|
||||
|
||||
### Python UDF 示例代码
|
||||
#### 标量函数示例 [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py)
|
||||
|
||||
pybitand 实现多列的按位与功能。如果只有一列,返回这一列。pybitand 忽略空值。
|
||||
|
||||
<details>
|
||||
<summary>pybitand.py</summary>
|
||||
|
||||
```Python
|
||||
{{#include tests/script/sh/pybitand.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### 聚合函数示例 [pyl2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pyl2norm.py)
|
||||
|
||||
pyl2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。
|
||||
|
||||
<details>
|
||||
<summary>pyl2norm.py</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/pyl2norm.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 管理和使用 UDF
|
||||
在使用 UDF 之前需要先将其加入到 TDengine 系统中。关于如何管理和使用 UDF,请参考[管理和使用 UDF](../12-taos-sql/26-udf.md)
|
||||
|
||||
|
|
|
@ -40,19 +40,19 @@ REST 连接支持所有能运行 Java 的平台。
|
|||
|
||||
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
|
||||
|
||||
| TDengine DataType | JDBCType |
|
||||
| ----------------- | ---------------------------------- |
|
||||
| TIMESTAMP | java.sql.Timestamp |
|
||||
| INT | java.lang.Integer |
|
||||
| BIGINT | java.lang.Long |
|
||||
| FLOAT | java.lang.Float |
|
||||
| DOUBLE | java.lang.Double |
|
||||
| SMALLINT | java.lang.Short |
|
||||
| TINYINT | java.lang.Byte |
|
||||
| BOOL | java.lang.Boolean |
|
||||
| BINARY | byte array |
|
||||
| NCHAR | java.lang.String |
|
||||
| JSON | java.lang.String |
|
||||
| TDengine DataType | JDBCType |
|
||||
| ----------------- | ------------------ |
|
||||
| TIMESTAMP | java.sql.Timestamp |
|
||||
| INT | java.lang.Integer |
|
||||
| BIGINT | java.lang.Long |
|
||||
| FLOAT | java.lang.Float |
|
||||
| DOUBLE | java.lang.Double |
|
||||
| SMALLINT | java.lang.Short |
|
||||
| TINYINT | java.lang.Byte |
|
||||
| BOOL | java.lang.Boolean |
|
||||
| BINARY | byte array |
|
||||
| NCHAR | java.lang.String |
|
||||
| JSON | java.lang.String |
|
||||
|
||||
**注意**:JSON 类型仅在 tag 中支持。
|
||||
|
||||
|
@ -82,7 +82,7 @@ Maven 项目中,在 pom.xml 中添加以下依赖:
|
|||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -97,7 +97,7 @@ cd taos-connector-jdbc
|
|||
mvn clean install -Dmaven.test.skip=true
|
||||
```
|
||||
|
||||
编译后,在 target 目录下会产生 taos-jdbcdriver-3.0.*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。
|
||||
编译后,在 target 目录下会产生 taos-jdbcdriver-3.0.\*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
@ -230,7 +230,7 @@ INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('California.SanFra
|
|||
**注意**:
|
||||
|
||||
- 应用中设置的 client parameter 为进程级别的,即如果要更新 client 的参数,需要重启应用。这是因为 client parameter 是全局参数,仅在应用程序的第一次设置生效。
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.0.0。
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.1.0。
|
||||
|
||||
```java
|
||||
public Connection getConn() throws Exception{
|
||||
|
@ -272,7 +272,7 @@ properties 中的配置参数如下:
|
|||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket 超时时间,单位 ms,默认值为 5000。仅在 REST 连接且 batchfetch 设置为 false 时生效。
|
||||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: 消息超时时间, 单位 ms, 默认值为 3000。 仅在 REST 连接且 batchfetch 设置为 true 时生效。
|
||||
- TSDBDriver.PROPERTY_KEY_USE_SSL: 连接中是否使用 SSL。仅在 REST 连接时生效。
|
||||
此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数,比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](/reference/config/#仅客户端适用)。
|
||||
此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数,比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](/reference/config/#仅客户端适用)。
|
||||
|
||||
### 配置参数的优先级
|
||||
|
||||
|
@ -353,7 +353,12 @@ try (Statement statement = connection.createStatement()) {
|
|||
}
|
||||
```
|
||||
|
||||
JDBC 连接器可能报错的错误码包括 3 种:JDBC driver 本身的报错(错误码在 0x2301 到 0x2350 之间),原生连接方法的报错(错误码在 0x2351 到 0x2400 之间),TDengine 其他功能模块的报错。
|
||||
JDBC 连接器可能报错的错误码包括 4 种:
|
||||
|
||||
- JDBC driver 本身的报错(错误码在 0x2301 到 0x2350 之间)
|
||||
- 原生连接方法的报错(错误码在 0x2351 到 0x2360 之间)
|
||||
- 数据订阅的报错(错误码在 0x2371 到 0x2380 之间)
|
||||
- TDengine 其他功能模块的报错。
|
||||
|
||||
具体的错误码请参考:
|
||||
|
||||
|
@ -367,7 +372,7 @@ TDengine 的 JDBC 原生连接实现大幅改进了参数绑定方式对数据
|
|||
**注意**:
|
||||
|
||||
- JDBC REST 连接目前不支持参数绑定
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.0.0
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.1.0
|
||||
- binary 类型数据需要调用 setString 方法,nchar 类型数据需要调用 setNString 方法
|
||||
- setString 和 setNString 都要求用户在 size 参数里声明表定义中对应列的列宽
|
||||
|
||||
|
@ -635,7 +640,7 @@ TDengine 支持无模式写入功能。无模式写入兼容 InfluxDB 的 行协
|
|||
**注意**:
|
||||
|
||||
- JDBC REST 连接目前不支持无模式写入
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.0.0
|
||||
- 以下示例代码基于 taos-jdbcdriver-3.1.0
|
||||
|
||||
```java
|
||||
public class SchemalessInsertTest {
|
||||
|
@ -702,7 +707,7 @@ TaosConsumer consumer = new TaosConsumer<>(config);
|
|||
- td.connect.type: 连接方式。jni:表示使用动态库连接的方式,ws/WebSocket:表示使用 WebSocket 进行数据通信。默认为 jni 方式。
|
||||
- httpConnectTimeout:创建连接超时参数,单位 ms,默认为 5000 ms。仅在 WebSocket 连接下有效。
|
||||
- messageWaitTimeout:数据传输超时参数,单位 ms,默认为 10000 ms。仅在 WebSocket 连接下有效。
|
||||
其他参数请参考:[Consumer 参数列表](../../../develop/tmq#创建-consumer-以及consumer-group)
|
||||
其他参数请参考:[Consumer 参数列表](../../../develop/tmq#创建-consumer-以及consumer-group)
|
||||
|
||||
#### 订阅消费数据
|
||||
|
||||
|
@ -968,17 +973,17 @@ public static void main(String[] args) throws Exception {
|
|||
|
||||
## 最近更新记录
|
||||
|
||||
| taos-jdbcdriver 版本 | 主要变化 |
|
||||
| :------------------: | :----------------------------: |
|
||||
| 3.1.0 | WebSocket 连接支持订阅功能 |
|
||||
| 3.0.1 - 3.0.4 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用其他版本 |
|
||||
| 3.0.0 | 支持 TDengine 3.0 |
|
||||
| 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 支持 |
|
||||
| 2.0.36 | 增加对 schemaless 写入支持 |
|
||||
| taos-jdbcdriver 版本 | 主要变化 |
|
||||
| :------------------: | :--------------------------------------------------------------------------------------------: |
|
||||
| 3.1.0 | WebSocket 连接支持订阅功能 |
|
||||
| 3.0.1 - 3.0.4 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用其他版本 |
|
||||
| 3.0.0 | 支持 TDengine 3.0 |
|
||||
| 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 支持 |
|
||||
| 2.0.36 | 增加对 schemaless 写入支持 |
|
||||
|
||||
## 常见问题
|
||||
|
||||
|
@ -1002,9 +1007,9 @@ public static void main(String[] args) throws Exception {
|
|||
|
||||
4. java.lang.NoSuchMethodError: setByteArray
|
||||
|
||||
**原因**:taos-jdbcdriver 3.* 版本仅支持 TDengine 3.0 及以上版本。
|
||||
**原因**:taos-jdbcdriver 3.\* 版本仅支持 TDengine 3.0 及以上版本。
|
||||
|
||||
**解决方法**: 使用 taos-jdbcdriver 2.* 版本连接 TDengine 2.* 版本。
|
||||
**解决方法**: 使用 taos-jdbcdriver 2.\* 版本连接 TDengine 2.\* 版本。
|
||||
|
||||
5. java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer; ... taos-jdbcdriver-3.0.1.jar
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import TabItem from '@theme/TabItem';
|
|||
import Preparation from "./_preparation.mdx"
|
||||
import RustInsert from "../07-develop/03-insert-data/_rust_sql.mdx"
|
||||
import RustBind from "../07-develop/03-insert-data/_rust_stmt.mdx"
|
||||
import RustSml from "../07-develop/03-insert-data/_rust_schemaless.mdx"
|
||||
import RustQuery from "../07-develop/04-query-data/_rust.mdx"
|
||||
|
||||
[](https://crates.io/crates/taos)  [](https://docs.rs/taos)
|
||||
|
@ -230,6 +231,10 @@ async fn demo(taos: &Taos, db: &str) -> Result<(), Error> {
|
|||
|
||||
<RustBind />
|
||||
|
||||
#### Schemaless 写入
|
||||
|
||||
<RustSml />
|
||||
|
||||
### 查询数据
|
||||
|
||||
<RustQuery />
|
||||
|
|
|
@ -61,7 +61,7 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
|
|||
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **参数绑定** | 暂不支持 | 暂不支持 | 支持 | 支持 | 暂不支持 | 支持 |
|
||||
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 暂不支持 | 暂不支持 | 支持 |
|
||||
| **Schemaless** | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 |
|
||||
| **Schemaless** | 支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 |
|
||||
| **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **DataFrame** | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
|
||||
|
||||
|
|
|
@ -71,8 +71,8 @@ database_option: {
|
|||
- 0:表示可以创建多张超级表。
|
||||
- 1:表示只可以创建一张超级表。
|
||||
- STT_TRIGGER:表示落盘文件触发文件合并的个数。默认为 1,范围 1 到 16。对于少表高频场景,此参数建议使用默认配置,或较小的值;而对于多表低频场景,此参数建议配置较大的值。
|
||||
- TABLE_PREFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的前缀的长度。
|
||||
- TABLE_SUFFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的后缀的长度。
|
||||
- TABLE_PREFIX:当其为正值时,在决定把一个表分配到哪个 vgroup 时要忽略表名中指定长度的前缀;当其为负值时,在决定把一个表分配到哪个 vgroup 时只使用表名中指定长度的前缀;例如,假定表名为 "v30001",当 TSDB_PREFIX = 2 时 使用 "0001" 来决定分配到哪个 vgroup ,当 TSDB_PREFIX = -2 时使用 "v3" 来决定分配到哪个 vgroup
|
||||
- TABLE_SUFFIX:当其为正值时,在决定把一个表分配到哪个 vgroup 时要忽略表名中指定长度的后缀;当其为负值时,在决定把一个表分配到哪个 vgroup 时只使用表名中指定长度的后缀;例如,假定表名为 "v30001",当 TSDB_SUFFIX = 2 时 使用 "v300" 来决定分配到哪个 vgroup ,当 TSDB_SUFFIX = -2 时使用 "01" 来决定分配到哪个 vgroup。
|
||||
- TSDB_PAGESIZE:一个 VNODE 中时序数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB到 16 MB。
|
||||
- WAL_RETENTION_PERIOD: 为了数据订阅消费,需要WAL日志文件额外保留的最大时长策略。WAL日志清理,不受订阅客户端消费状态影响。单位为 s。默认为 0,表示无需为订阅保留。新建订阅,应先设置恰当的时长策略。
|
||||
- WAL_RETENTION_SIZE:为了数据订阅消费,需要WAL日志文件额外保留的最大累计大小策略。单位为 KB。默认为 0,表示累计大小无上限。
|
||||
|
|
|
@ -15,6 +15,7 @@ stream_options: {
|
|||
IGNORE EXPIRED [0|1]
|
||||
DELETE_MARK time
|
||||
FILL_HISTORY [0|1]
|
||||
IGNORE UPDATE [0|1]
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -169,7 +170,7 @@ T3 时刻,最新事件到达,T 向后推移超过了第二个窗口关闭的
|
|||
在 window_close 或 max_delay 模式下,窗口关闭直接影响推送结果。在 at_once 模式下,窗口关闭只与内存占用有关。
|
||||
|
||||
|
||||
## 流式计算的过期数据处理策略
|
||||
## 流式计算对于过期数据的处理策略
|
||||
|
||||
对于已关闭的窗口,再次落入该窗口中的数据被标记为过期数据.
|
||||
|
||||
|
@ -177,11 +178,20 @@ TDengine 对于过期数据提供两种处理方式,由 IGNORE EXPIRED 选项
|
|||
|
||||
1. 重新计算,即 IGNORE EXPIRED 0:从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果
|
||||
|
||||
2. 直接丢弃, 即 IGNORE EXPIRED 1:默认配置,忽略过期数据
|
||||
2. 直接丢弃,即 IGNORE EXPIRED 1:默认配置,忽略过期数据
|
||||
|
||||
|
||||
无论在哪种模式下,watermark 都应该被妥善设置,来得到正确结果(直接丢弃模式)或避免频繁触发重算带来的性能开销(重新计算模式)。
|
||||
|
||||
## 流式计算对于修改数据的处理策略
|
||||
|
||||
TDengine 对于修改数据提供两种处理方式,由 IGNORE UPDATE 选项指定:
|
||||
|
||||
1. 检查数据是否被修改,即 IGNORE UPDATE 0:默认配置,如果被修改,则重新计算对应窗口。
|
||||
|
||||
2. 不检查数据是否被修改,全部按增量数据计算,即 IGNORE UPDATE 1。
|
||||
|
||||
|
||||
## 写入已存在的超级表
|
||||
```sql
|
||||
[field1_name,...]
|
||||
|
@ -213,3 +223,29 @@ DELETE_MARK time
|
|||
```
|
||||
DELETE_MARK用于删除缓存的窗口状态,也就是删除流计算的中间结果。如果不设置,默认值是10年
|
||||
T = 最新事件时间 - DELETE_MARK
|
||||
|
||||
## 流式计算支持的函数
|
||||
|
||||
1. 所有的 [单行函数](../function/#单行函数) 均可用于流计算。
|
||||
2. 以下 19 个聚合/选择函数 <b>不能</b> 应用在创建流计算的 SQL 语句。此外的其他类型的函数均可用于流计算。
|
||||
|
||||
- [leastsquares](../function/#leastsquares)
|
||||
- [percentile](../function/#percentile)
|
||||
- [top](../function/#top)
|
||||
- [bottom](../function/#bottom)
|
||||
- [elapsed](../function/#elapsed)
|
||||
- [interp](../function/#interp)
|
||||
- [derivative](../function/#derivative)
|
||||
- [irate](../function/#irate)
|
||||
- [twa](../function/#twa)
|
||||
- [histogram](../function/#histogram)
|
||||
- [diff](../function/#diff)
|
||||
- [statecount](../function/#statecount)
|
||||
- [stateduration](../function/#stateduration)
|
||||
- [csum](../function/#csum)
|
||||
- [mavg](../function/#mavg)
|
||||
- [sample](../function/#sample)
|
||||
- [tail](../function/#tail)
|
||||
- [unique](../function/#unique)
|
||||
- [mode](../function/#mode)
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
|
|||
| 5 | create_time | TIMESTAMP | 创建时间 |
|
||||
| 6 | code_len | INT | 代码长度 |
|
||||
| 7 | bufsize | INT | buffer 大小 |
|
||||
| 8 | func_language | BINARY(31) | 自定义函数编程语言 |
|
||||
| 9 | func_body | BINARY(16384) | 函数体定义 |
|
||||
| 10 | func_version | INT | 函数版本号。初始版本为0,每次替换更新,版本号加1。|
|
||||
|
||||
|
||||
## INS_INDEXES
|
||||
|
||||
|
|
|
@ -13,27 +13,34 @@ description: 使用 UDF 的详细指南
|
|||
|
||||
- 创建标量函数
|
||||
```sql
|
||||
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type;
|
||||
CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_type [LANGUAGE 'C|Python'];
|
||||
```
|
||||
|
||||
- function_name:标量函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udf 的实际名称一致;
|
||||
- library_path:包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- OR REPLACE: 如果函数已经存在,会修改已有的函数属性。
|
||||
- function_name:标量函数未来在 SQL 中被调用时的函数名;
|
||||
- LANGUAGE 'C|Python':函数编程语言,目前支持C语言和Python语言。 如果这个从句忽略,编程语言是C语言
|
||||
- library_path:如果编程语言是C,路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件)。如果编程语言是Python,路径是包含 UDF 函数实现的Python文件路径。这个路径需要用英文单引号或英文双引号括起来;
|
||||
- output_type:此函数计算结果的数据类型名称;
|
||||
|
||||
例如,如下语句可以把 libbitand.so 创建为系统中可用的 UDF:
|
||||
例如,如下语句可以把 libbitand.so 创建为系统中可用的 UDF:
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION bit_and AS "/home/taos/udf_example/libbitand.so" OUTPUTTYPE INT;
|
||||
```
|
||||
|
||||
例如,使用以下语句可以修改已经定义的 bit_and 函数,输出类型是 BIGINT,使用Python语言实现。
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION bit_and AS "/home/taos/udf_example/bit_and.py" OUTPUTTYPE BIGINT LANGUAGE 'Python';
|
||||
```
|
||||
- 创建聚合函数:
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ];
|
||||
CREATE [OR REPLACE] AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ] [LANGUAGE 'C|Python'];
|
||||
```
|
||||
|
||||
- OR REPLACE: 如果函数已经存在,会修改已有的函数属性。
|
||||
- function_name:聚合函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
|
||||
- library_path:包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- output_type:此函数计算结果的数据类型,与上文中 udfNormalFunc 的 itype 参数不同,这里不是使用数字表示法,而是直接写类型名称即可;
|
||||
- LANGUAGE 'C|Python':函数编程语言,目前支持C语言和Python语言。
|
||||
- library_path:如果编程语言是C,路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件)。如果编程语言是Python,路径是包含 UDF 函数实现的Python文件路径。这个路径需要用英文单引号或英文双引号括起来;;
|
||||
- output_type:此函数计算结果的数据类型名称;
|
||||
- buffer_size:中间计算结果的缓冲区大小,单位是字节。如果不使用可以不设置。
|
||||
|
||||
例如,如下语句可以把 libl2norm.so 创建为系统中可用的 UDF:
|
||||
|
@ -41,6 +48,11 @@ CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [
|
|||
```sql
|
||||
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8;
|
||||
```
|
||||
例如,使用以下语句可以修改已经定义的 l2norm 函数的缓冲区大小为64。
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 64;
|
||||
```
|
||||
|
||||
关于如何开发自定义函数,请参考 [UDF使用说明](/develop/udf)。
|
||||
|
||||
## 管理 UDF
|
||||
|
|
|
@ -27,13 +27,13 @@ description: "TDengine 3.0 版本的语法变更说明"
|
|||
| - | :------- | :-------- | :------- |
|
||||
| 1 | ALTER ACCOUNT | 废除 | 2.x中为企业版功能,3.0不再支持。语法暂时保留了,执行报“This statement is no longer supported”错误。
|
||||
| 2 | ALTER ALL DNODES | 新增 | 修改所有DNODE的参数。
|
||||
| 3 | ALTER DATABASE | 调整 | 废除<ul><li>QUORUM:写入需要的副本确认数。3.0 版本默认行为是强一致性,且不支持修改为弱一致性。</li><li>BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>COMP:3.0版本暂不支持修改。</li><br/>新增<li>CACHEMODEL:表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE:表示缓存子表最近数据的内存大小。</li><li>WAL_FSYNC_PERIOD:代替原FSYNC参数。</li><li>WAL_LEVEL:代替原WAL参数。</li><li>WAL_RETENTION_PERIOD:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZE:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。<br/>调整</li><li>REPLICA:3.0.0版本暂不支持修改。</li><li>KEEP:3.0版本新增支持带单位的设置方式。</li></ul>
|
||||
| 3 | ALTER DATABASE | 调整 | <p>废除</p><ul><li>QUORUM:写入需要的副本确认数。3.0 版本默认行为是强一致性,且不支持修改为弱一致性。</li><li>BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>COMP:3.0版本暂不支持修改。</li></ul><p>新增</p><ul><li>CACHEMODEL:表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE:表示缓存子表最近数据的内存大小。</li><li>WAL_FSYNC_PERIOD:代替原FSYNC参数。</li><li>WAL_LEVEL:代替原WAL参数。</li><li>WAL_RETENTION_PERIOD:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZE:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。</li></ul><p>调整</p><ul><li>KEEP:3.0版本新增支持带单位的设置方式。</li></ul>
|
||||
| 4 | ALTER STABLE | 调整 | 废除<ul><li>CHANGE TAG:修改标签列的名称。3.0版本使用RENAME TAG代替。<br/>新增</li><li>RENAME TAG:代替原CHANGE TAG子句。</li><li>COMMENT:修改超级表的注释。</li></ul>
|
||||
| 5 | ALTER TABLE | 调整 | 废除<ul><li>CHANGE TAG:修改标签列的名称。3.0版本使用RENAME TAG代替。<br/>新增</li><li>RENAME TAG:代替原CHANGE TAG子句。</li><li>COMMENT:修改表的注释。</li><li>TTL:修改表的生命周期。</li></ul>
|
||||
| 6 | ALTER USER | 调整 | 废除<ul><li>PRIVILEGE:修改用户权限。3.0版本使用GRANT和REVOKE来授予和回收权限。<br/>新增</li><li>ENABLE:启用或停用此用户。</li><li>SYSINFO:修改用户是否可查看系统信息。</li></ul>
|
||||
| 7 | COMPACT VNODES | 暂不支持 | 整理指定VNODE的数据。3.0.0版本暂不支持。
|
||||
| 8 | CREATE ACCOUNT | 废除 | 2.x中为企业版功能,3.0不再支持。语法暂时保留了,执行报“This statement is no longer supported”错误。
|
||||
| 9 | CREATE DATABASE | 调整 | 废除<ul><li>BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHE:VNODE使用的内存块的大小。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>DAYS:数据文件存储数据的时间跨度。3.0版本使用DURATION代替。</li><li>FSYNC:当 WAL 设置为 2 时,执行 fsync 的周期。3.0版本使用WAL_FSYNC_PERIOD代替。</li><li>QUORUM:写入需要的副本确认数。3.0版本使用STRICT来指定强一致还是弱一致。</li><li>UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>WAL:WAL 级别。3.0版本使用WAL_LEVEL代替。<br/>新增</li><li>BUFFER:一个 VNODE 写入内存池大小。</li><li>CACHEMODEL:表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE:表示缓存子表最近数据的内存大小。</li><li>DURATION:代替原DAYS参数。新增支持带单位的设置方式。</li><li>PAGES:一个 VNODE 中元数据存储引擎的缓存页个数。</li><li>PAGESIZE:一个 VNODE 中元数据存储引擎的页大小。</li><li>RETENTIONS:表示数据的聚合周期和保存时长。</li><li>STRICT:表示数据同步的一致性要求。</li><li>SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表。</li><li>VGROUPS:数据库中初始VGROUP的数目。</li><li>WAL_FSYNC_PERIOD:代替原FSYNC参数。</li><li>WAL_LEVEL:代替原WAL参数。</li><li>WAL_RETENTION_PERIOD:wal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZE:wal文件的额外保留策略,用于数据订阅。</li><li>WAL_ROLL_PERIOD:wal文件切换时长。</li><li>WAL_SEGMENT_SIZE:wal单个文件大小。<br/>调整</li><li>KEEP:3.0版本新增支持带单位的设置方式。</li></ul>
|
||||
| 9 | CREATE DATABASE | 调整 | <p>废除</p><ul><li>BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHE:VNODE使用的内存块的大小。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>DAYS:数据文件存储数据的时间跨度。3.0版本使用DURATION代替。</li><li>FSYNC:当 WAL 设置为 2 时,执行 fsync 的周期。3.0版本使用WAL_FSYNC_PERIOD代替。</li><li>QUORUM:写入需要的副本确认数。3.0版本使用STRICT来指定强一致还是弱一致。</li><li>UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>WAL:WAL 级别。3.0版本使用WAL_LEVEL代替。</li></ul><p>新增</p><ul><li>BUFFER:一个 VNODE 写入内存池大小。</li><li>CACHEMODEL:表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE:表示缓存子表最近数据的内存大小。</li><li>DURATION:代替原DAYS参数。新增支持带单位的设置方式。</li><li>PAGES:一个 VNODE 中元数据存储引擎的缓存页个数。</li><li>PAGESIZE:一个 VNODE 中元数据存储引擎的页大小。</li><li>RETENTIONS:表示数据的聚合周期和保存时长。</li><li>STRICT:表示数据同步的一致性要求。</li><li>SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表。</li><li>VGROUPS:数据库中初始VGROUP的数目。</li><li>WAL_FSYNC_PERIOD:代替原FSYNC参数。</li><li>WAL_LEVEL:代替原WAL参数。</li><li>WAL_RETENTION_PERIOD:wal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZE:wal文件的额外保留策略,用于数据订阅。</li><li>WAL_ROLL_PERIOD:wal文件切换时长。</li><li>WAL_SEGMENT_SIZE:wal单个文件大小。</li></ul><p>调整</p><ul><li>KEEP:3.0版本新增支持带单位的设置方式。</li></ul>
|
||||
| 10 | CREATE DNODE | 调整 | 新增主机名和端口号分开指定语法<ul><li>CREATE DNODE dnode_host_name PORT port_val</li></ul>
|
||||
| 11 | CREATE INDEX | 新增 | 创建SMA索引。
|
||||
| 12 | CREATE MNODE | 新增 | 创建管理节点。
|
||||
|
|
|
@ -79,6 +79,7 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
-A, --all-databases Dump all databases.
|
||||
-D, --databases=DATABASES Dump inputted databases. Use comma to separate
|
||||
databases' name.
|
||||
-e, --escape-character Use escaped character for database name
|
||||
-N, --without-property Dump database without its properties.
|
||||
-s, --schemaonly Only dump tables' schema.
|
||||
-y, --answer-yes Input yes for prompt. It will skip data file
|
||||
|
|
|
@ -356,7 +356,7 @@ charset 的有效值是 UTF-8。
|
|||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | dnode 支持的最大 vnode 数目 |
|
||||
| 取值范围 | 0-4096 |
|
||||
| 缺省值 | CPU 核数的 2 倍 |
|
||||
| 缺省值 | CPU 核数的 2 倍 |
|
||||
|
||||
## 性能调优
|
||||
|
||||
|
@ -366,6 +366,7 @@ charset 的有效值是 UTF-8。
|
|||
| -------- | ---------------------- |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | 设置写入线程的最大数量 |
|
||||
| 取值范围 | 0-1024 |
|
||||
| 缺省值 | |
|
||||
|
||||
## 日志相关
|
||||
|
|
|
@ -111,7 +111,7 @@ Active: inactive (dead)
|
|||
|
||||
#### 配置文件启动
|
||||
|
||||
执行以下命令即可快速体验 taosKeeper。当不指定 taosKeeper 配置文件时,优先使用 `/etc/taos/keeper.toml` 配置,否则将使用默认配置。
|
||||
执行以下命令即可快速体验 taosKeeper。当不指定 taosKeeper 配置文件时,优先使用 `/etc/taos/taoskeeper.toml` 配置,否则将使用默认配置。
|
||||
|
||||
```shell
|
||||
$ taoskeeper -c <keeper config file>
|
||||
|
@ -156,6 +156,10 @@ database = "log"
|
|||
|
||||
# 指定需要监控的普通表
|
||||
tables = []
|
||||
|
||||
# database options for db storing metrics data
|
||||
[metrics.databaseoptions]
|
||||
cachemodel = "none"
|
||||
```
|
||||
|
||||
### 获取监控指标
|
||||
|
@ -206,7 +210,7 @@ taos_cluster_info_dnodes_total{cluster_id="5981392874047724755"} 1
|
|||
taos_cluster_info_first_ep{cluster_id="5981392874047724755",value="hlb:6030"} 1
|
||||
```
|
||||
|
||||
### check_health
|
||||
### check\_health
|
||||
|
||||
```
|
||||
$ curl -i http://127.0.0.1:6043/check_health
|
||||
|
@ -222,3 +226,29 @@ Content-Length: 19
|
|||
|
||||
{"version":"1.0.0"}
|
||||
```
|
||||
|
||||
### 集成 Prometheus
|
||||
|
||||
taoskeeper 提供了 `/metrics` 接口,返回了 Prometheus 格式的监控数据,Prometheus 可以从 taoskeeper 抽取监控数据,实现通过 Prometheus 监控 TDengine 的目的。
|
||||
|
||||
#### 抽取配置
|
||||
|
||||
Prometheus 提供了 `scrape_configs` 配置如何从 endpoint 抽取监控数据,通常只需要修改 `static_configs` 中的 targets 配置为 taoskeeper 的 endpoint 地址,更多配置信息请参考 [Prometheus 配置文档](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)。
|
||||
|
||||
```
|
||||
# A scrape configuration containing exactly one endpoint to scrape:
|
||||
# Here it's Prometheus itself.
|
||||
scrape_configs:
|
||||
- job_name: "taoskeeper"
|
||||
# metrics_path defaults to '/metrics'
|
||||
# scheme defaults to 'http'.
|
||||
static_configs:
|
||||
- targets: ["localhost:6043"]
|
||||
```
|
||||
|
||||
#### Dashboard
|
||||
|
||||
我们提供了 `TaosKeeper Prometheus Dashboard for 3.x` dashboard,提供了和 TDinsight 类似的监控 dashboard。
|
||||
|
||||
在 Grafana Dashboard 菜单点击 `import`,dashboard ID 填写 `18587`,点击 `Load` 按钮即可导入 `TaosKeeper Prometheus Dashboard for 3.x` dashboard。
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|first\_ep\_dnode\_id|INT||集群 first ep 的 dnode id|
|
||||
|version|VARCHAR||tdengine version。例如:3.0.4.0|
|
||||
|master\_uptime|FLOAT||当前 master 节点的uptime。单位:天|
|
||||
|monitor_interval|INT||monitor interval。单位:秒|
|
||||
|monitor\_interval|INT||monitor interval。单位:秒|
|
||||
|dbs\_total|INT||database 总数|
|
||||
|tbs\_total|BIGINT||当前集群 table 总数|
|
||||
|stbs\_total|INT||当前集群 stable 总数|
|
||||
|
@ -107,17 +107,17 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|cpu\_system|FLOAT||服务器 cpu 使用率,从 `/proc/stat` 读取|
|
||||
|cpu\_cores|FLOAT||服务器 cpu 核数|
|
||||
|mem\_engine|INT||taosd 内存使用率,从 `/proc/<taosd_pid>/status` 读取|
|
||||
|mem\_system|INT||服务器内存使用率|
|
||||
|mem\_system|INT||服务器可用内存|
|
||||
|mem\_total|INT||服务器内存总量,单位 KB|
|
||||
|disk\_engine|INT|||
|
||||
|disk\_used|BIGINT||data dir 挂载的磁盘使用量,单位 bytes|
|
||||
|disk\_total|BIGINT||data dir 挂载的磁盘总容量,单位 bytes|
|
||||
|net\_in|FLOAT||网络吞吐率,从 `/proc/net/dev` 中读取的 received bytes。单位 bytes per second|
|
||||
|net\_out|FLOAT||网络吞吐率,从 `/proc/net/dev` 中读取的 transmit bytes。单位 bytes per second|
|
||||
|io\_read|FLOAT||io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 rchar 与上次数值计算之后,计算得到速度。单位 bytes per second|
|
||||
|io\_write|FLOAT||io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 wchar 与上次数值计算之后,计算得到速度。单位 bytes per second|
|
||||
|io\_read\_disk|FLOAT||磁盘 io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 read_bytes。单位 bytes per second|
|
||||
|io\_write\_disk|FLOAT||磁盘 io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 write_bytes。单位 bytes per second|
|
||||
|net\_in|FLOAT||网络吞吐率,从 `/proc/net/dev` 中读取的 received bytes。单位 kb/s|
|
||||
|net\_out|FLOAT||网络吞吐率,从 `/proc/net/dev` 中读取的 transmit bytes。单位 kb/s|
|
||||
|io\_read|FLOAT||io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 rchar 与上次数值计算之后,计算得到速度。单位 kb/s|
|
||||
|io\_write|FLOAT||io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 wchar 与上次数值计算之后,计算得到速度。单位 kb/s|
|
||||
|io\_read\_disk|FLOAT||磁盘 io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 read_bytes。单位 kb/s|
|
||||
|io\_write\_disk|FLOAT||磁盘 io 吞吐率,从 `/proc/<taosd_pid>/io` 中读取的 write_bytes。单位 kb/s|
|
||||
|req\_select|INT||两个间隔内发生的查询请求数目|
|
||||
|req\_select\_rate|FLOAT||两个间隔内的查询请求速度 = `req_select / monitorInterval`|
|
||||
|req\_insert|INT||两个间隔内发生的写入请求,包含的单条数据数目|
|
||||
|
|
|
@ -10,6 +10,10 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.4.1
|
||||
|
||||
<Release type="tdengine" version="3.0.4.1" />
|
||||
|
||||
## 3.0.4.0
|
||||
|
||||
<Release type="tdengine" version="3.0.4.0" />
|
||||
|
|
|
@ -10,6 +10,14 @@ taosTools 各版本安装包下载链接如下:
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 2.5.0
|
||||
|
||||
<Release type="tools" version="2.5.0" />
|
||||
|
||||
## 2.5.0
|
||||
|
||||
<Release type="tools" version="2.5.0" />
|
||||
|
||||
## 2.4.12
|
||||
|
||||
<Release type="tools" version="2.4.12" />
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include <time.h>
|
||||
#include "taos.h"
|
||||
|
||||
static int running = 1;
|
||||
static int running = 1;
|
||||
const char* topic_name = "topicname";
|
||||
|
||||
static int32_t msg_process(TAOS_RES* msg) {
|
||||
char buf[1024];
|
||||
|
@ -243,7 +244,7 @@ _end:
|
|||
|
||||
tmq_list_t* build_topic_list() {
|
||||
tmq_list_t* topicList = tmq_list_new();
|
||||
int32_t code = tmq_list_append(topicList, "topicname");
|
||||
int32_t code = tmq_list_append(topicList, topic_name);
|
||||
if (code) {
|
||||
tmq_list_destroy(topicList);
|
||||
return NULL;
|
||||
|
@ -269,6 +270,31 @@ void basic_consume_loop(tmq_t* tmq) {
|
|||
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||
}
|
||||
|
||||
void consume_repeatly(tmq_t* tmq) {
|
||||
int32_t numOfAssignment = 0;
|
||||
tmq_topic_assignment* pAssign = NULL;
|
||||
|
||||
int32_t code = tmq_get_topic_assignment(tmq, topic_name, &pAssign, &numOfAssignment);
|
||||
if (code != 0) {
|
||||
fprintf(stderr, "failed to get assignment, reason:%s", tmq_err2str(code));
|
||||
}
|
||||
|
||||
// seek to the earliest offset
|
||||
for(int32_t i = 0; i < numOfAssignment; ++i) {
|
||||
tmq_topic_assignment* p = &pAssign[i];
|
||||
|
||||
code = tmq_offset_seek(tmq, topic_name, p->vgId, p->begin);
|
||||
if (code != 0) {
|
||||
fprintf(stderr, "failed to seek to %ld, reason:%s", p->begin, tmq_err2str(code));
|
||||
}
|
||||
}
|
||||
|
||||
free(pAssign);
|
||||
|
||||
// let's do it again
|
||||
basic_consume_loop(tmq);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int32_t code;
|
||||
|
||||
|
@ -294,10 +320,13 @@ int main(int argc, char* argv[]) {
|
|||
if ((code = tmq_subscribe(tmq, topic_list))) {
|
||||
fprintf(stderr, "Failed to tmq_subscribe(): %s\n", tmq_err2str(code));
|
||||
}
|
||||
|
||||
tmq_list_destroy(topic_list);
|
||||
|
||||
basic_consume_loop(tmq);
|
||||
|
||||
consume_repeatly(tmq);
|
||||
|
||||
code = tmq_consumer_close(tmq);
|
||||
if (code) {
|
||||
fprintf(stderr, "Failed to close consumer: %s\n", tmq_err2str(code));
|
||||
|
|
|
@ -101,6 +101,7 @@ typedef struct TAOS_FIELD_E {
|
|||
#endif
|
||||
|
||||
typedef void (*__taos_async_fn_t)(void *param, TAOS_RES *res, int code);
|
||||
typedef void (*__taos_notify_fn_t)(void *param, void *ext, int type);
|
||||
|
||||
typedef struct TAOS_MULTI_BIND {
|
||||
int buffer_type;
|
||||
|
@ -121,6 +122,10 @@ typedef enum {
|
|||
SET_CONF_RET_ERR_TOO_LONG = -6
|
||||
} SET_CONF_RET_CODE;
|
||||
|
||||
typedef enum {
|
||||
TAOS_NOTIFY_PASSVER = 0,
|
||||
} TAOS_NOTIFY_TYPE;
|
||||
|
||||
#define RET_MSG_LENGTH 1024
|
||||
typedef struct setConfRet {
|
||||
SET_CONF_RET_CODE retCode;
|
||||
|
@ -162,7 +167,7 @@ DLL_EXPORT int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name
|
|||
DLL_EXPORT int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields);
|
||||
DLL_EXPORT int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields);
|
||||
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
|
||||
DLL_EXPORT void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields);
|
||||
DLL_EXPORT void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields);
|
||||
|
||||
DLL_EXPORT int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert);
|
||||
DLL_EXPORT int taos_stmt_num_params(TAOS_STMT *stmt, int *nums);
|
||||
|
@ -227,6 +232,7 @@ DLL_EXPORT int taos_load_table_info(TAOS *taos, const char *tableNameList);
|
|||
|
||||
// set heart beat thread quit mode , if quicByKill 1 then kill thread else quit from inner
|
||||
DLL_EXPORT void taos_set_hb_quit(int8_t quitByKill);
|
||||
DLL_EXPORT int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type);
|
||||
|
||||
/* --------------------------schemaless INTERFACE------------------------------- */
|
||||
|
||||
|
@ -265,6 +271,12 @@ DLL_EXPORT tmq_t *tmq_consumer_new(tmq_conf_t *conf, char *errstr, int32_t errst
|
|||
DLL_EXPORT const char *tmq_err2str(int32_t code);
|
||||
|
||||
/* ------------------------TMQ CONSUMER INTERFACE------------------------ */
|
||||
typedef struct tmq_topic_assignment {
|
||||
int32_t vgId;
|
||||
int64_t currentOffset;
|
||||
int64_t begin;
|
||||
int64_t end;
|
||||
} tmq_topic_assignment;
|
||||
|
||||
DLL_EXPORT int32_t tmq_subscribe(tmq_t *tmq, const tmq_list_t *topic_list);
|
||||
DLL_EXPORT int32_t tmq_unsubscribe(tmq_t *tmq);
|
||||
|
@ -273,6 +285,9 @@ DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t timeout);
|
|||
DLL_EXPORT int32_t tmq_consumer_close(tmq_t *tmq);
|
||||
DLL_EXPORT int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg);
|
||||
DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const TAOS_RES *msg, tmq_commit_cb *cb, void *param);
|
||||
DLL_EXPORT int32_t tmq_get_topic_assignment(tmq_t *tmq, const char *pTopicName, tmq_topic_assignment **assignment,
|
||||
int32_t *numOfAssignment);
|
||||
DLL_EXPORT int32_t tmq_offset_seek(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset);
|
||||
|
||||
/* ----------------------TMQ CONFIGURATION INTERFACE---------------------- */
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ enum {
|
|||
TMQ_MSG_TYPE__POLL_META_RSP,
|
||||
TMQ_MSG_TYPE__EP_RSP,
|
||||
TMQ_MSG_TYPE__TAOSX_RSP,
|
||||
TMQ_MSG_TYPE__WALINFO_RSP,
|
||||
TMQ_MSG_TYPE__END_RSP,
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SLOW_LOG_TYPE_QUERY 0x1
|
||||
#define SLOW_LOG_TYPE_INSERT 0x2
|
||||
#define SLOW_LOG_TYPE_OTHERS 0x4
|
||||
#define SLOW_LOG_TYPE_ALL 0xFFFFFFFF
|
||||
|
||||
|
||||
// cluster
|
||||
extern char tsFirst[];
|
||||
extern char tsSecond[];
|
||||
|
@ -118,6 +124,8 @@ extern int32_t tsRedirectFactor;
|
|||
extern int32_t tsRedirectMaxPeriod;
|
||||
extern int32_t tsMaxRetryWaitTime;
|
||||
extern bool tsUseAdapter;
|
||||
extern int32_t tsSlowLogThreshold;
|
||||
extern int32_t tsSlowLogScope;
|
||||
|
||||
// client
|
||||
extern int32_t tsMinSlidingTime;
|
||||
|
|
|
@ -106,6 +106,7 @@ enum {
|
|||
HEARTBEAT_KEY_DBINFO,
|
||||
HEARTBEAT_KEY_STBINFO,
|
||||
HEARTBEAT_KEY_TMQ,
|
||||
HEARTBEAT_KEY_USER_PASSINFO,
|
||||
};
|
||||
|
||||
typedef enum _mgmt_table {
|
||||
|
@ -634,6 +635,7 @@ typedef struct {
|
|||
int8_t connType;
|
||||
SEpSet epSet;
|
||||
int32_t svrTimestamp;
|
||||
int32_t passVer;
|
||||
char sVer[TSDB_VERSION_LEN];
|
||||
char sDetailVer[128];
|
||||
} SConnectRsp;
|
||||
|
@ -717,6 +719,14 @@ int32_t tSerializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pR
|
|||
int32_t tDeserializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pRsp);
|
||||
void tFreeSGetUserAuthRsp(SGetUserAuthRsp* pRsp);
|
||||
|
||||
typedef struct SUserPassVersion {
|
||||
char user[TSDB_USER_LEN];
|
||||
int32_t version;
|
||||
} SUserPassVersion;
|
||||
|
||||
typedef SGetUserAuthReq SGetUserPassReq;
|
||||
typedef SUserPassVersion SGetUserPassRsp;
|
||||
|
||||
/*
|
||||
* for client side struct, only column id, type, bytes are necessary
|
||||
* But for data in vnode side, we need all the following information.
|
||||
|
@ -1047,6 +1057,14 @@ int32_t tSerializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp
|
|||
int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp* pRsp);
|
||||
void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp);
|
||||
|
||||
typedef struct {
|
||||
SArray* pArray; // Array of SGetUserPassRsp
|
||||
} SUserPassBatchRsp;
|
||||
|
||||
int32_t tSerializeSUserPassBatchRsp(void* buf, int32_t bufLen, SUserPassBatchRsp* pRsp);
|
||||
int32_t tDeserializeSUserPassBatchRsp(void* buf, int32_t bufLen, SUserPassBatchRsp* pRsp);
|
||||
void tFreeSUserPassBatchRsp(SUserPassBatchRsp* pRsp);
|
||||
|
||||
typedef struct {
|
||||
char db[TSDB_DB_FNAME_LEN];
|
||||
STimeWindow timeRange;
|
||||
|
@ -1287,6 +1305,9 @@ typedef struct {
|
|||
int16_t hashSuffix;
|
||||
int32_t tsdbPageSize;
|
||||
int64_t reserved[8];
|
||||
int8_t learnerReplica;
|
||||
int8_t learnerSelfIndex;
|
||||
SReplica learnerReplicas[TSDB_MAX_LEARNER_REPLICA];
|
||||
} SCreateVnodeReq;
|
||||
|
||||
int32_t tSerializeSCreateVnodeReq(void* buf, int32_t bufLen, SCreateVnodeReq* pReq);
|
||||
|
@ -1358,7 +1379,10 @@ typedef struct {
|
|||
int8_t replica;
|
||||
SReplica replicas[TSDB_MAX_REPLICA];
|
||||
int64_t reserved[8];
|
||||
} SAlterVnodeReplicaReq;
|
||||
int8_t learnerSelfIndex;
|
||||
int8_t learnerReplica;
|
||||
SReplica learnerReplicas[TSDB_MAX_LEARNER_REPLICA];
|
||||
} SAlterVnodeReplicaReq, SAlterVnodeTypeReq;
|
||||
|
||||
int32_t tSerializeSAlterVnodeReplicaReq(void* buf, int32_t bufLen, SAlterVnodeReplicaReq* pReq);
|
||||
int32_t tDeserializeSAlterVnodeReplicaReq(void* buf, int32_t bufLen, SAlterVnodeReplicaReq* pReq);
|
||||
|
@ -1630,7 +1654,10 @@ int32_t tDeserializeSCreateDropMQSNodeReq(void* buf, int32_t bufLen, SMCreateQno
|
|||
typedef struct {
|
||||
int8_t replica;
|
||||
SReplica replicas[TSDB_MAX_REPLICA];
|
||||
} SDCreateMnodeReq, SDAlterMnodeReq;
|
||||
int8_t learnerReplica;
|
||||
SReplica learnerReplicas[TSDB_MAX_LEARNER_REPLICA];
|
||||
int64_t lastIndex;
|
||||
} SDCreateMnodeReq, SDAlterMnodeReq, SDAlterMnodeTypeReq;
|
||||
|
||||
int32_t tSerializeSDCreateMnodeReq(void* buf, int32_t bufLen, SDCreateMnodeReq* pReq);
|
||||
int32_t tDeserializeSDCreateMnodeReq(void* buf, int32_t bufLen, SDCreateMnodeReq* pReq);
|
||||
|
@ -2800,6 +2827,7 @@ typedef struct {
|
|||
} SMqOffset;
|
||||
|
||||
typedef struct {
|
||||
int64_t consumerId;
|
||||
int32_t num;
|
||||
SMqOffset* offsets;
|
||||
} SMqCMCommitOffsetReq;
|
||||
|
@ -2867,6 +2895,14 @@ typedef struct {
|
|||
int32_t tEncodeSTqOffset(SEncoder* pEncoder, const STqOffset* pOffset);
|
||||
int32_t tDecodeSTqOffset(SDecoder* pDecoder, STqOffset* pOffset);
|
||||
|
||||
typedef struct SMqVgOffset {
|
||||
int64_t consumerId;
|
||||
STqOffset offset;
|
||||
} SMqVgOffset;
|
||||
|
||||
int32_t tEncodeMqVgOffset(SEncoder* pEncoder, const SMqVgOffset* pOffset);
|
||||
int32_t tDecodeMqVgOffset(SDecoder* pDecoder, SMqVgOffset* pOffset);
|
||||
|
||||
typedef struct {
|
||||
SMsgHead head;
|
||||
int32_t taskId;
|
||||
|
@ -3132,18 +3168,19 @@ typedef struct {
|
|||
int32_t code;
|
||||
int32_t epoch;
|
||||
int64_t consumerId;
|
||||
int64_t walsver;
|
||||
int64_t walever;
|
||||
} SMqRspHead;
|
||||
|
||||
typedef struct {
|
||||
SMsgHead head;
|
||||
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
|
||||
int8_t withTbName;
|
||||
int8_t useSnapshot;
|
||||
int32_t epoch;
|
||||
uint64_t reqId;
|
||||
int64_t consumerId;
|
||||
int64_t timeout;
|
||||
// int64_t currentOffset;
|
||||
SMsgHead head;
|
||||
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
|
||||
int8_t withTbName;
|
||||
int8_t useSnapshot;
|
||||
int32_t epoch;
|
||||
uint64_t reqId;
|
||||
int64_t consumerId;
|
||||
int64_t timeout;
|
||||
STqOffsetVal reqOffset;
|
||||
} SMqPollReq;
|
||||
|
||||
|
@ -3178,43 +3215,9 @@ typedef struct {
|
|||
SSchemaWrapper schema;
|
||||
} SMqSubTopicEp;
|
||||
|
||||
static FORCE_INLINE int32_t tEncodeSMqSubTopicEp(void** buf, const SMqSubTopicEp* pTopicEp) {
|
||||
int32_t tlen = 0;
|
||||
tlen += taosEncodeString(buf, pTopicEp->topic);
|
||||
tlen += taosEncodeString(buf, pTopicEp->db);
|
||||
int32_t sz = taosArrayGetSize(pTopicEp->vgs);
|
||||
tlen += taosEncodeFixedI32(buf, sz);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubVgEp* pVgEp = (SMqSubVgEp*)taosArrayGet(pTopicEp->vgs, i);
|
||||
tlen += tEncodeSMqSubVgEp(buf, pVgEp);
|
||||
}
|
||||
tlen += taosEncodeSSchemaWrapper(buf, &pTopicEp->schema);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void* tDecodeSMqSubTopicEp(void* buf, SMqSubTopicEp* pTopicEp) {
|
||||
buf = taosDecodeStringTo(buf, pTopicEp->topic);
|
||||
buf = taosDecodeStringTo(buf, pTopicEp->db);
|
||||
int32_t sz;
|
||||
buf = taosDecodeFixedI32(buf, &sz);
|
||||
pTopicEp->vgs = taosArrayInit(sz, sizeof(SMqSubVgEp));
|
||||
if (pTopicEp->vgs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubVgEp vgEp;
|
||||
buf = tDecodeSMqSubVgEp(buf, &vgEp);
|
||||
taosArrayPush(pTopicEp->vgs, &vgEp);
|
||||
}
|
||||
buf = taosDecodeSSchemaWrapper(buf, &pTopicEp->schema);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tDeleteSMqSubTopicEp(SMqSubTopicEp* pSubTopicEp) {
|
||||
taosMemoryFreeClear(pSubTopicEp->schema.pSchema);
|
||||
pSubTopicEp->schema.nCols = 0;
|
||||
taosArrayDestroy(pSubTopicEp->vgs);
|
||||
}
|
||||
int32_t tEncodeMqSubTopicEp(void** buf, const SMqSubTopicEp* pTopicEp);
|
||||
void* tDecodeMqSubTopicEp(void* buf, SMqSubTopicEp* pTopicEp);
|
||||
void tDeleteMqSubTopicEp(SMqSubTopicEp* pSubTopicEp);
|
||||
|
||||
typedef struct {
|
||||
SMqRspHead head;
|
||||
|
@ -3224,8 +3227,8 @@ typedef struct {
|
|||
void* metaRsp;
|
||||
} SMqMetaRsp;
|
||||
|
||||
int32_t tEncodeSMqMetaRsp(SEncoder* pEncoder, const SMqMetaRsp* pRsp);
|
||||
int32_t tDecodeSMqMetaRsp(SDecoder* pDecoder, SMqMetaRsp* pRsp);
|
||||
int32_t tEncodeMqMetaRsp(SEncoder* pEncoder, const SMqMetaRsp* pRsp);
|
||||
int32_t tDecodeMqMetaRsp(SDecoder* pDecoder, SMqMetaRsp* pRsp);
|
||||
|
||||
typedef struct {
|
||||
SMqRspHead head;
|
||||
|
@ -3240,9 +3243,9 @@ typedef struct {
|
|||
SArray* blockSchema;
|
||||
} SMqDataRsp;
|
||||
|
||||
int32_t tEncodeSMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pRsp);
|
||||
int32_t tDecodeSMqDataRsp(SDecoder* pDecoder, SMqDataRsp* pRsp);
|
||||
void tDeleteSMqDataRsp(SMqDataRsp* pRsp);
|
||||
int32_t tEncodeMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pRsp);
|
||||
int32_t tDecodeMqDataRsp(SDecoder* pDecoder, SMqDataRsp* pRsp);
|
||||
void tDeleteMqDataRsp(SMqDataRsp* pRsp);
|
||||
|
||||
typedef struct {
|
||||
SMqRspHead head;
|
||||
|
@ -3278,7 +3281,7 @@ static FORCE_INLINE int32_t tEncodeSMqAskEpRsp(void** buf, const SMqAskEpRsp* pR
|
|||
tlen += taosEncodeFixedI32(buf, sz);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubTopicEp* pVgEp = (SMqSubTopicEp*)taosArrayGet(pRsp->topics, i);
|
||||
tlen += tEncodeSMqSubTopicEp(buf, pVgEp);
|
||||
tlen += tEncodeMqSubTopicEp(buf, pVgEp);
|
||||
}
|
||||
return tlen;
|
||||
}
|
||||
|
@ -3293,14 +3296,14 @@ static FORCE_INLINE void* tDecodeSMqAskEpRsp(void* buf, SMqAskEpRsp* pRsp) {
|
|||
}
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubTopicEp topicEp;
|
||||
buf = tDecodeSMqSubTopicEp(buf, &topicEp);
|
||||
buf = tDecodeMqSubTopicEp(buf, &topicEp);
|
||||
taosArrayPush(pRsp->topics, &topicEp);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tDeleteSMqAskEpRsp(SMqAskEpRsp* pRsp) {
|
||||
taosArrayDestroyEx(pRsp->topics, (FDelete)tDeleteSMqSubTopicEp);
|
||||
taosArrayDestroyEx(pRsp->topics, (FDelete)tDeleteMqSubTopicEp);
|
||||
}
|
||||
|
||||
#define TD_AUTO_CREATE_TABLE 0x1
|
||||
|
|
|
@ -83,6 +83,8 @@ enum {
|
|||
TD_DEF_MSG_TYPE(TDMT_DND_CONFIG_DNODE, "config-dnode", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_SYSTABLE_RETRIEVE, "dnode-retrieve", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_MAX_MSG, "dnd-max", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_ALTER_MNODE_TYPE, "dnode-alter-mnode-type", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_ALTER_VNODE_TYPE, "dnode-alter-vnode-type", NULL, NULL)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_MND_MSG)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_CONNECT, "connect", NULL, NULL)
|
||||
|
@ -225,7 +227,6 @@ enum {
|
|||
TD_DEF_MSG_TYPE(TDMT_VND_COMMIT, "vnode-commit", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_CREATE_INDEX, "vnode-create-index", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_DROP_INDEX, "vnode-drop-index", NULL, NULL)
|
||||
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_DISABLE_WRITE, "vnode-disable-write", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_MAX_MSG, "vnd-max", NULL, NULL)
|
||||
|
||||
|
@ -304,9 +305,11 @@ enum {
|
|||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_SUBSCRIBE, "vnode-tmq-subscribe", SMqRebVgReq, SMqRebVgRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_DELETE_SUB, "vnode-tmq-delete-sub", SMqVDeleteReq, SMqVDeleteRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_COMMIT_OFFSET, "vnode-tmq-commit-offset", STqOffset, STqOffset)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_SEEK_TO_OFFSET, "vnode-tmq-seekto-offset", STqOffset, STqOffset)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_ADD_CHECKINFO, "vnode-tmq-add-checkinfo", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_DEL_CHECKINFO, "vnode-del-checkinfo", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_CONSUME, "vnode-tmq-consume", SMqPollReq, SMqDataBlkRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_VG_WALINFO, "vnode-tmq-vg-walinfo", SMqPollReq, SMqDataBlkRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_MAX_MSG, "vnd-tmq-max", NULL, NULL)
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "tmsg.h"
|
||||
#include "tmsgcb.h"
|
||||
#include "trpc.h"
|
||||
#include "sync.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -33,8 +34,11 @@ typedef struct {
|
|||
bool deploy;
|
||||
int8_t selfIndex;
|
||||
int8_t numOfReplicas;
|
||||
SReplica replicas[TSDB_MAX_REPLICA];
|
||||
int8_t numOfTotalReplicas;
|
||||
SReplica replicas[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
int32_t nodeRoles[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
SMsgCb msgCb;
|
||||
int64_t lastIndex;
|
||||
} SMnodeOpt;
|
||||
|
||||
/* ------------------------ SMnode ------------------------ */
|
||||
|
@ -69,6 +73,9 @@ int32_t mndStart(SMnode *pMnode);
|
|||
*/
|
||||
void mndStop(SMnode *pMnode);
|
||||
|
||||
int32_t mndIsCatchUp(SMnode *pMnode);
|
||||
ESyncRole mndGetRole(SMnode *pMnode);
|
||||
|
||||
/**
|
||||
* @brief Get mnode monitor info.
|
||||
*
|
||||
|
|
|
@ -99,11 +99,11 @@ typedef struct SSubsidiaryResInfo {
|
|||
} SSubsidiaryResInfo;
|
||||
|
||||
typedef struct SResultDataInfo {
|
||||
int16_t precision;
|
||||
int16_t scale;
|
||||
int16_t type;
|
||||
int16_t bytes;
|
||||
int32_t interBufSize;
|
||||
int16_t precision;
|
||||
int16_t scale;
|
||||
int16_t type;
|
||||
uint16_t bytes;
|
||||
int32_t interBufSize;
|
||||
} SResultDataInfo;
|
||||
|
||||
#define GET_RES_INFO(ctx) ((ctx)->resultInfo)
|
||||
|
|
|
@ -185,6 +185,7 @@ typedef struct SMergeLogicNode {
|
|||
int32_t numOfChannels;
|
||||
int32_t srcGroupId;
|
||||
bool groupSort;
|
||||
bool ignoreGroupId;
|
||||
} SMergeLogicNode;
|
||||
|
||||
typedef enum EWindowType {
|
||||
|
@ -444,6 +445,7 @@ typedef struct SMergePhysiNode {
|
|||
int32_t numOfChannels;
|
||||
int32_t srcGroupId;
|
||||
bool groupSort;
|
||||
bool ignoreGroupId;
|
||||
} SMergePhysiNode;
|
||||
|
||||
typedef struct SWinodwPhysiNode {
|
||||
|
|
|
@ -114,7 +114,7 @@ STableDataCxt* smlInitTableDataCtx(SQuery* query, STableMeta* pTableMeta);
|
|||
|
||||
int32_t smlBindData(SQuery* handle, bool dataFormat, SArray* tags, SArray* colsSchema, SArray* cols,
|
||||
STableMeta* pTableMeta, char* tableName, const char* sTableName, int32_t sTableNameLen, int32_t ttl,
|
||||
char* msgBuf, int16_t msgBufLen);
|
||||
char* msgBuf, int32_t msgBufLen);
|
||||
int32_t smlBuildOutput(SQuery* handle, SHashObj* pVgHash);
|
||||
int rawBlockBindData(SQuery *query, STableMeta* pTableMeta, void* data, SVCreateTbReq* pCreateTb, TAOS_FIELD *fields, int numFields, bool needChangeLength);
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ extern "C" {
|
|||
#define SYNC_INDEX_INVALID -1
|
||||
#define SYNC_TERM_INVALID -1
|
||||
|
||||
#define SYNC_LEARNER_CATCHUP 10
|
||||
|
||||
typedef enum {
|
||||
SYNC_STRATEGY_NO_SNAPSHOT = 0,
|
||||
SYNC_STRATEGY_STANDARD_SNAPSHOT = 1,
|
||||
|
@ -76,19 +78,29 @@ typedef enum {
|
|||
TAOS_SYNC_STATE_CANDIDATE = 101,
|
||||
TAOS_SYNC_STATE_LEADER = 102,
|
||||
TAOS_SYNC_STATE_ERROR = 103,
|
||||
TAOS_SYNC_STATE_LEARNER = 104,
|
||||
} ESyncState;
|
||||
|
||||
typedef enum {
|
||||
TAOS_SYNC_ROLE_VOTER = 0,
|
||||
TAOS_SYNC_ROLE_LEARNER = 1,
|
||||
TAOS_SYNC_ROLE_ERROR = 2,
|
||||
} ESyncRole;
|
||||
|
||||
typedef struct SNodeInfo {
|
||||
int64_t clusterId;
|
||||
int32_t nodeId;
|
||||
uint16_t nodePort;
|
||||
char nodeFqdn[TSDB_FQDN_LEN];
|
||||
int64_t clusterId;
|
||||
int32_t nodeId;
|
||||
uint16_t nodePort;
|
||||
char nodeFqdn[TSDB_FQDN_LEN];
|
||||
ESyncRole nodeRole;
|
||||
} SNodeInfo;
|
||||
|
||||
typedef struct SSyncCfg {
|
||||
int32_t totalReplicaNum;
|
||||
int32_t replicaNum;
|
||||
int32_t myIndex;
|
||||
SNodeInfo nodeInfo[TSDB_MAX_REPLICA];
|
||||
SNodeInfo nodeInfo[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
SyncIndex lastIndex;
|
||||
} SSyncCfg;
|
||||
|
||||
typedef struct SFsmCbMeta {
|
||||
|
@ -155,6 +167,7 @@ typedef struct SSyncFSM {
|
|||
|
||||
void (*FpBecomeLeaderCb)(const struct SSyncFSM* pFsm);
|
||||
void (*FpBecomeFollowerCb)(const struct SSyncFSM* pFsm);
|
||||
void (*FpBecomeLearnerCb)(const struct SSyncFSM* pFsm);
|
||||
|
||||
int32_t (*FpGetSnapshot)(const struct SSyncFSM* pFsm, SSnapshot* pSnapshot, void* pReaderParam, void** ppReader);
|
||||
void (*FpGetSnapshotInfo)(const struct SSyncFSM* pFsm, SSnapshot* pSnapshot);
|
||||
|
@ -236,6 +249,8 @@ void syncStop(int64_t rid);
|
|||
void syncPreStop(int64_t rid);
|
||||
void syncPostStop(int64_t rid);
|
||||
int32_t syncPropose(int64_t rid, SRpcMsg* pMsg, bool isWeak, int64_t* seq);
|
||||
int32_t syncIsCatchUp(int64_t rid);
|
||||
ESyncRole syncGetRole(int64_t rid);
|
||||
int32_t syncProcessMsg(int64_t rid, SRpcMsg* pMsg);
|
||||
int32_t syncReconfig(int64_t rid, SSyncCfg* pCfg);
|
||||
int32_t syncBeginSnapshot(int64_t rid, int64_t lastApplyIndex);
|
||||
|
|
|
@ -127,12 +127,12 @@ typedef struct SWal {
|
|||
typedef struct {
|
||||
int64_t refId;
|
||||
int64_t refVer;
|
||||
// int64_t refFile;
|
||||
SWal *pWal;
|
||||
// int64_t refFile;
|
||||
SWal *pWal;
|
||||
} SWalRef;
|
||||
|
||||
typedef struct {
|
||||
// int8_t scanUncommited;
|
||||
// int8_t scanUncommited;
|
||||
int8_t scanNotApplied;
|
||||
int8_t scanMeta;
|
||||
int8_t enableRef;
|
||||
|
@ -190,15 +190,16 @@ int32_t walApplyVer(SWal *, int64_t ver);
|
|||
|
||||
// int32_t walDataCorrupted(SWal*);
|
||||
|
||||
// read
|
||||
// wal reader
|
||||
SWalReader *walOpenReader(SWal *, SWalFilterCond *pCond);
|
||||
void walCloseReader(SWalReader *pRead);
|
||||
void walReadReset(SWalReader *pReader);
|
||||
int32_t walReadVer(SWalReader *pRead, int64_t ver);
|
||||
int32_t walReaderSeekVer(SWalReader *pRead, int64_t ver);
|
||||
int32_t walNextValidMsg(SWalReader *pRead);
|
||||
int64_t walReaderGetCurrentVer(const SWalReader* pReader);
|
||||
int64_t walReaderGetValidFirstVer(const SWalReader* pReader);
|
||||
int64_t walReaderGetCurrentVer(const SWalReader *pReader);
|
||||
int64_t walReaderGetValidFirstVer(const SWalReader *pReader);
|
||||
void walReaderValidVersionRange(SWalReader *pReader, int64_t *sver, int64_t *ever);
|
||||
|
||||
// only for tq usage
|
||||
void walSetReaderCapacity(SWalReader *pRead, int32_t capacity);
|
||||
|
|
|
@ -103,7 +103,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_CHECKSUM_ERROR TAOS_DEF_ERROR_CODE(0, 0x011F) // internal
|
||||
|
||||
#define TSDB_CODE_COMPRESS_ERROR TAOS_DEF_ERROR_CODE(0, 0x0120)
|
||||
#define TSDB_CODE_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0121) //
|
||||
#define TSDB_CODE_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0121)
|
||||
#define TSDB_CODE_CFG_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0122)
|
||||
#define TSDB_CODE_REPEAT_INIT TAOS_DEF_ERROR_CODE(0, 0x0123)
|
||||
#define TSDB_CODE_DUP_KEY TAOS_DEF_ERROR_CODE(0, 0x0124)
|
||||
|
@ -118,9 +118,10 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_MSG_ENCODE_ERROR TAOS_DEF_ERROR_CODE(0, 0x012D)
|
||||
#define TSDB_CODE_NO_ENOUGH_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x012E)
|
||||
|
||||
#define TSDB_CODE_APP_IS_STARTING TAOS_DEF_ERROR_CODE(0, 0x0130) //
|
||||
#define TSDB_CODE_APP_IS_STOPPING TAOS_DEF_ERROR_CODE(0, 0x0131) //
|
||||
#define TSDB_CODE_IVLD_DATA_FMT TAOS_DEF_ERROR_CODE(0, 0x0132) //
|
||||
#define TSDB_CODE_APP_IS_STARTING TAOS_DEF_ERROR_CODE(0, 0x0130)
|
||||
#define TSDB_CODE_APP_IS_STOPPING TAOS_DEF_ERROR_CODE(0, 0x0131)
|
||||
#define TSDB_CODE_INVALID_DATA_FMT TAOS_DEF_ERROR_CODE(0, 0x0132)
|
||||
#define TSDB_CODE_INVALID_CFG_VALUE TAOS_DEF_ERROR_CODE(0, 0x0133)
|
||||
|
||||
//client
|
||||
#define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200)
|
||||
|
@ -404,6 +405,8 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_SNODE_ALREADY_DEPLOYED TAOS_DEF_ERROR_CODE(0, 0x040F)
|
||||
#define TSDB_CODE_SNODE_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0410)
|
||||
#define TSDB_CODE_SNODE_NOT_DEPLOYED TAOS_DEF_ERROR_CODE(0, 0x0411)
|
||||
#define TSDB_CODE_MNODE_NOT_CATCH_UP TAOS_DEF_ERROR_CODE(0, 0x0412) // internal
|
||||
#define TSDB_CODE_MNODE_ALREADY_IS_VOTER TAOS_DEF_ERROR_CODE(0, 0x0413) // internal
|
||||
|
||||
// vnode
|
||||
// #define TSDB_CODE_VND_ACTION_IN_PROGRESS TAOS_DEF_ERROR_CODE(0, 0x0500) // 2.x
|
||||
|
@ -438,6 +441,8 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_VND_STOPPED TAOS_DEF_ERROR_CODE(0, 0x0529)
|
||||
#define TSDB_CODE_VND_DUP_REQUEST TAOS_DEF_ERROR_CODE(0, 0x0530)
|
||||
#define TSDB_CODE_VND_QUERY_BUSY TAOS_DEF_ERROR_CODE(0, 0x0531)
|
||||
#define TSDB_CODE_VND_NOT_CATCH_UP TAOS_DEF_ERROR_CODE(0, 0x0532) // internal
|
||||
#define TSDB_CODE_VND_ALREADY_IS_VOTER TAOS_DEF_ERROR_CODE(0, 0x0533) // internal
|
||||
|
||||
// tsdb
|
||||
#define TSDB_CODE_TDB_INVALID_TABLE_ID TAOS_DEF_ERROR_CODE(0, 0x0600)
|
||||
|
@ -535,20 +540,20 @@ int32_t* taosGetErrno();
|
|||
// #define TSDB_CODE_SYN_INVALID_CHECKSUM TAOS_DEF_ERROR_CODE(0, 0x0908) // 2.x
|
||||
// #define TSDB_CODE_SYN_INVALID_MSGLEN TAOS_DEF_ERROR_CODE(0, 0x0909) // 2.x
|
||||
// #define TSDB_CODE_SYN_INVALID_MSGTYPE TAOS_DEF_ERROR_CODE(0, 0x090A) // 2.x
|
||||
#define TSDB_CODE_SYN_IS_LEADER TAOS_DEF_ERROR_CODE(0, 0x090B)
|
||||
// #define TSDB_CODE_SYN_IS_LEADER TAOS_DEF_ERROR_CODE(0, 0x090B) // unused
|
||||
#define TSDB_CODE_SYN_NOT_LEADER TAOS_DEF_ERROR_CODE(0, 0x090C)
|
||||
#define TSDB_CODE_SYN_ONE_REPLICA TAOS_DEF_ERROR_CODE(0, 0x090D)
|
||||
#define TSDB_CODE_SYN_NOT_IN_NEW_CONFIG TAOS_DEF_ERROR_CODE(0, 0x090E)
|
||||
#define TSDB_CODE_SYN_NEW_CONFIG_ERROR TAOS_DEF_ERROR_CODE(0, 0x090F) // internal
|
||||
#define TSDB_CODE_SYN_RECONFIG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0910)
|
||||
// #define TSDB_CODE_SYN_ONE_REPLICA TAOS_DEF_ERROR_CODE(0, 0x090D) // unused
|
||||
// #define TSDB_CODE_SYN_NOT_IN_NEW_CONFIG TAOS_DEF_ERROR_CODE(0, 0x090E) // unused
|
||||
#define TSDB_CODE_SYN_NEW_CONFIG_ERROR TAOS_DEF_ERROR_CODE(0, 0x090F) // internal
|
||||
// #define TSDB_CODE_SYN_RECONFIG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0910) // unused
|
||||
#define TSDB_CODE_SYN_PROPOSE_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0911)
|
||||
#define TSDB_CODE_SYN_STANDBY_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0912)
|
||||
#define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913)
|
||||
// #define TSDB_CODE_SYN_STANDBY_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0912) // unused
|
||||
// #define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913) // unused
|
||||
#define TSDB_CODE_SYN_RESTORING TAOS_DEF_ERROR_CODE(0, 0x0914)
|
||||
#define TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG TAOS_DEF_ERROR_CODE(0, 0x0915) // internal
|
||||
#define TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG TAOS_DEF_ERROR_CODE(0, 0x0915) // internal
|
||||
#define TSDB_CODE_SYN_BUFFER_FULL TAOS_DEF_ERROR_CODE(0, 0x0916)
|
||||
#define TSDB_CODE_SYN_WRITE_STALL TAOS_DEF_ERROR_CODE(0, 0x0917)
|
||||
#define TSDB_CODE_SYN_NEGO_WIN_EXCEEDED TAOS_DEF_ERROR_CODE(0, 0X0918)
|
||||
#define TSDB_CODE_SYN_NEGOTIATION_WIN_FULL TAOS_DEF_ERROR_CODE(0, 0x0918)
|
||||
#define TSDB_CODE_SYN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x09FF)
|
||||
|
||||
// tq
|
||||
|
@ -569,7 +574,7 @@ int32_t* taosGetErrno();
|
|||
// wal
|
||||
// #define TSDB_CODE_WAL_APP_ERROR TAOS_DEF_ERROR_CODE(0, 0x1000) // 2.x
|
||||
#define TSDB_CODE_WAL_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x1001)
|
||||
#define TSDB_CODE_WAL_SIZE_LIMIT TAOS_DEF_ERROR_CODE(0, 0x1002)
|
||||
// #define TSDB_CODE_WAL_SIZE_LIMIT TAOS_DEF_ERROR_CODE(0, 0x1002) // unused
|
||||
#define TSDB_CODE_WAL_INVALID_VER TAOS_DEF_ERROR_CODE(0, 0x1003)
|
||||
// #define TSDB_CODE_WAL_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x1004) // 2.x
|
||||
#define TSDB_CODE_WAL_LOG_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x1005)
|
||||
|
@ -713,15 +718,13 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_UDF_STOPPING TAOS_DEF_ERROR_CODE(0, 0x2901)
|
||||
#define TSDB_CODE_UDF_PIPE_READ_ERR TAOS_DEF_ERROR_CODE(0, 0x2902)
|
||||
#define TSDB_CODE_UDF_PIPE_CONNECT_ERR TAOS_DEF_ERROR_CODE(0, 0x2903)
|
||||
#define TSDB_CODE_UDF_PIPE_NO_PIPE TAOS_DEF_ERROR_CODE(0, 0x2904)
|
||||
#define TSDB_CODE_UDF_PIPE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2904)
|
||||
#define TSDB_CODE_UDF_LOAD_UDF_FAILURE TAOS_DEF_ERROR_CODE(0, 0x2905)
|
||||
#define TSDB_CODE_UDF_INVALID_STATE TAOS_DEF_ERROR_CODE(0, 0x2906)
|
||||
#define TSDB_CODE_UDF_INVALID_INPUT TAOS_DEF_ERROR_CODE(0, 0x2907)
|
||||
#define TSDB_CODE_UDF_NO_FUNC_HANDLE TAOS_DEF_ERROR_CODE(0, 0x2908)
|
||||
#define TSDB_CODE_UDF_INVALID_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x2909)
|
||||
#define TSDB_CODE_UDF_INVALID_OUTPUT_TYPE TAOS_DEF_ERROR_CODE(0, 0x290A)
|
||||
#define TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED TAOS_DEF_ERROR_CODE(0, 0x290B)
|
||||
#define TSDB_CODE_UDF_FUNC_EXEC_FAILURE TAOS_DEF_ERROR_CODE(0, 0x290C)
|
||||
#define TSDB_CODE_UDF_INVALID_INPUT TAOS_DEF_ERROR_CODE(0, 0x2906)
|
||||
#define TSDB_CODE_UDF_INVALID_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x2907)
|
||||
#define TSDB_CODE_UDF_INVALID_OUTPUT_TYPE TAOS_DEF_ERROR_CODE(0, 0x2908)
|
||||
#define TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED TAOS_DEF_ERROR_CODE(0, 0x2909)
|
||||
#define TSDB_CODE_UDF_FUNC_EXEC_FAILURE TAOS_DEF_ERROR_CODE(0, 0x290A)
|
||||
|
||||
// sml
|
||||
#define TSDB_CODE_SML_INVALID_PROTOCOL_TYPE TAOS_DEF_ERROR_CODE(0, 0x3000)
|
||||
|
|
|
@ -232,13 +232,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_QUERY_ID_LEN 26
|
||||
#define TSDB_TRANS_OPER_LEN 16
|
||||
|
||||
/**
|
||||
* In some scenarios uint16_t (0~65535) is used to store the row len.
|
||||
* - Firstly, we use 65531(65535 - 4), as the SDataRow/SKVRow contains 4 bits header.
|
||||
* - Secondly, if all cols are VarDataT type except primary key, we need 4 bits to store the offset, thus
|
||||
* the final value is 65531-(4096-1)*4 = 49151.
|
||||
*/
|
||||
#define TSDB_MAX_BYTES_PER_ROW 49151
|
||||
#define TSDB_MAX_BYTES_PER_ROW 65531 // 49151:65531
|
||||
#define TSDB_MAX_TAGS_LEN 16384
|
||||
#define TSDB_MAX_TAGS 128
|
||||
|
||||
|
@ -285,7 +279,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_DNODE_ROLE_VNODE 2
|
||||
|
||||
#define TSDB_MAX_REPLICA 5
|
||||
|
||||
#define TSDB_MAX_LEARNER_REPLICA 10
|
||||
#define TSDB_SYNC_LOG_BUFFER_SIZE 4096
|
||||
#define TSDB_SYNC_LOG_BUFFER_RETENTION 256
|
||||
#define TSDB_SYNC_APPLYQ_SIZE_LIMIT 512
|
||||
|
@ -410,9 +404,9 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_EXPLAIN_RESULT_ROW_SIZE (16 * 1024)
|
||||
#define TSDB_EXPLAIN_RESULT_COLUMN_NAME "QUERY_PLAN"
|
||||
|
||||
#define TSDB_MAX_FIELD_LEN 16384
|
||||
#define TSDB_MAX_BINARY_LEN (TSDB_MAX_FIELD_LEN - TSDB_KEYSIZE) // keep 16384
|
||||
#define TSDB_MAX_NCHAR_LEN (TSDB_MAX_FIELD_LEN - TSDB_KEYSIZE) // keep 16384
|
||||
#define TSDB_MAX_FIELD_LEN 65519 // 16384:65519
|
||||
#define TSDB_MAX_BINARY_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define TSDB_MAX_NCHAR_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define PRIMARYKEY_TIMESTAMP_COL_ID 1
|
||||
#define COL_REACH_END(colId, maxColId) ((colId) > (maxColId))
|
||||
|
||||
|
|
|
@ -83,6 +83,12 @@ void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, cons
|
|||
#endif
|
||||
;
|
||||
|
||||
void taosPrintSlowLog(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
bool taosAssertDebug(bool condition, const char *file, int32_t line, const char *format, ...);
|
||||
bool taosAssertRelease(bool condition);
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef struct {
|
|||
// statistics
|
||||
int32_t reportCnt;
|
||||
int32_t connKeyCnt;
|
||||
int32_t passKeyCnt; // with passVer call back
|
||||
int64_t reportBytes; // not implemented
|
||||
int64_t startTime;
|
||||
// ctl
|
||||
|
@ -126,6 +127,12 @@ typedef struct SAppInfo {
|
|||
TdThreadMutex mutex;
|
||||
} SAppInfo;
|
||||
|
||||
typedef struct {
|
||||
int32_t ver;
|
||||
void* param;
|
||||
__taos_notify_fn_t fp;
|
||||
} SPassInfo;
|
||||
|
||||
typedef struct STscObj {
|
||||
char user[TSDB_USER_LEN];
|
||||
char pass[TSDB_PASSWORD_LEN];
|
||||
|
@ -141,6 +148,7 @@ typedef struct STscObj {
|
|||
int32_t numOfReqs; // number of sqlObj bound to this connection
|
||||
SAppInstInfo* pAppInfo;
|
||||
SHashObj* pRequests;
|
||||
SPassInfo passInfo;
|
||||
} STscObj;
|
||||
|
||||
typedef struct STscDbg {
|
||||
|
@ -354,7 +362,7 @@ void stopAllRequests(SHashObj* pRequests);
|
|||
|
||||
// conn level
|
||||
int hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType);
|
||||
void hbDeregisterConn(SAppHbMgr* pAppHbMgr, SClientHbKey connKey);
|
||||
void hbDeregisterConn(STscObj* pTscObj, SClientHbKey connKey);
|
||||
|
||||
typedef struct SSqlCallbackWrapper {
|
||||
SParseContext* pParseCtx;
|
||||
|
|
|
@ -42,7 +42,7 @@ SAppInfo appInfo;
|
|||
int64_t lastClusterId = 0;
|
||||
int32_t clientReqRefPool = -1;
|
||||
int32_t clientConnRefPool = -1;
|
||||
int32_t clientStop = 0;
|
||||
int32_t clientStop = -1;
|
||||
|
||||
int32_t timestampDeltaLimit = 900; // s
|
||||
|
||||
|
@ -69,7 +69,6 @@ static int32_t registerRequest(SRequestObj *pRequest, STscObj *pTscObj) {
|
|||
}
|
||||
|
||||
static void deregisterRequest(SRequestObj *pRequest) {
|
||||
const static int64_t SLOW_QUERY_INTERVAL = 3000000L; // todo configurable
|
||||
if (pRequest == NULL) {
|
||||
tscError("pRequest == NULL");
|
||||
return;
|
||||
|
@ -80,6 +79,7 @@ static void deregisterRequest(SRequestObj *pRequest) {
|
|||
|
||||
int32_t currentInst = atomic_sub_fetch_64((int64_t *)&pActivity->currentRequests, 1);
|
||||
int32_t num = atomic_sub_fetch_32(&pTscObj->numOfReqs, 1);
|
||||
int32_t reqType = SLOW_LOG_TYPE_OTHERS;
|
||||
|
||||
int64_t duration = taosGetTimestampUs() - pRequest->metric.start;
|
||||
tscDebug("0x%" PRIx64 " free Request from connObj: 0x%" PRIx64 ", reqId:0x%" PRIx64
|
||||
|
@ -95,6 +95,7 @@ static void deregisterRequest(SRequestObj *pRequest) {
|
|||
duration, pRequest->metric.parseCostUs, pRequest->metric.ctgCostUs, pRequest->metric.analyseCostUs,
|
||||
pRequest->metric.planCostUs, pRequest->metric.execCostUs);
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration);
|
||||
reqType = SLOW_LOG_TYPE_INSERT;
|
||||
} else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) {
|
||||
tscDebug("query duration %" PRId64 "us: parseCost:%" PRId64 "us, ctgCost:%" PRId64 "us, analyseCost:%" PRId64
|
||||
"us, planCost:%" PRId64 "us, exec:%" PRId64 "us",
|
||||
|
@ -102,12 +103,16 @@ static void deregisterRequest(SRequestObj *pRequest) {
|
|||
pRequest->metric.planCostUs, pRequest->metric.execCostUs);
|
||||
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration);
|
||||
reqType = SLOW_LOG_TYPE_QUERY;
|
||||
}
|
||||
}
|
||||
|
||||
if (duration >= SLOW_QUERY_INTERVAL) {
|
||||
if (duration >= (tsSlowLogThreshold * 1000000UL)) {
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->numOfSlowQueries, 1);
|
||||
tscWarnL("slow query: %s, duration:%" PRId64, pRequest->sqlstr, duration);
|
||||
if (tsSlowLogScope & reqType) {
|
||||
taosPrintSlowLog("PID:%d, Conn:%u, QID:0x%" PRIx64 ", Start:%" PRId64 ", Duration:%" PRId64 "us, SQL:%s",
|
||||
taosGetPId(), pTscObj->connId, pRequest->requestId, pRequest->metric.start, duration, pRequest->sqlstr);
|
||||
}
|
||||
}
|
||||
|
||||
releaseTscObj(pTscObj->id);
|
||||
|
@ -239,7 +244,7 @@ void destroyTscObj(void *pObj) {
|
|||
tscTrace("begin to destroy tscObj %" PRIx64 " p:%p", tscId, pTscObj);
|
||||
|
||||
SClientHbKey connKey = {.tscRid = pTscObj->id, .connType = pTscObj->connType};
|
||||
hbDeregisterConn(pTscObj->pAppInfo->pAppHbMgr, connKey);
|
||||
hbDeregisterConn(pTscObj, connKey);
|
||||
|
||||
destroyAllRequests(pTscObj->pRequests);
|
||||
taosHashCleanup(pTscObj->pRequests);
|
||||
|
@ -427,8 +432,12 @@ static void *tscCrashReportThreadFp(void *param) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (-1 != atomic_val_compare_exchange_32(&clientStop, -1, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (clientStop) break;
|
||||
if (clientStop > 0) break;
|
||||
if (loopTimes++ < reportPeriodNum) {
|
||||
taosMsleep(sleepTime);
|
||||
continue;
|
||||
|
@ -466,7 +475,7 @@ static void *tscCrashReportThreadFp(void *param) {
|
|||
loopTimes = 0;
|
||||
}
|
||||
|
||||
clientStop = -1;
|
||||
clientStop = -2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,15 @@
|
|||
#include "scheduler.h"
|
||||
#include "trpc.h"
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
int64_t clusterId;
|
||||
int32_t passKeyCnt;
|
||||
};
|
||||
};
|
||||
} SHbParam;
|
||||
|
||||
static SClientHbMgr clientHbMgr = {0};
|
||||
|
||||
static int32_t hbCreateThread();
|
||||
|
@ -49,14 +58,60 @@ static int32_t hbProcessUserAuthInfoRsp(void *value, int32_t valueLen, struct SC
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t hbProcessUserPassInfoRsp(void *value, int32_t valueLen, SClientHbKey *connKey, SAppHbMgr *pAppHbMgr) {
|
||||
int32_t code = 0;
|
||||
int32_t numOfBatchs = 0;
|
||||
SUserPassBatchRsp batchRsp = {0};
|
||||
if (tDeserializeSUserPassBatchRsp(value, valueLen, &batchRsp) != 0) {
|
||||
code = TSDB_CODE_INVALID_MSG;
|
||||
return code;
|
||||
}
|
||||
|
||||
numOfBatchs = taosArrayGetSize(batchRsp.pArray);
|
||||
|
||||
SClientHbReq *pReq = NULL;
|
||||
while ((pReq = taosHashIterate(pAppHbMgr->activeInfo, pReq))) {
|
||||
STscObj *pTscObj = (STscObj *)acquireTscObj(pReq->connKey.tscRid);
|
||||
if (!pTscObj) {
|
||||
continue;
|
||||
}
|
||||
SPassInfo *passInfo = &pTscObj->passInfo;
|
||||
if (!passInfo->fp) {
|
||||
releaseTscObj(pReq->connKey.tscRid);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfBatchs; ++i) {
|
||||
SGetUserPassRsp *rsp = taosArrayGet(batchRsp.pArray, i);
|
||||
if (0 == strncmp(rsp->user, pTscObj->user, TSDB_USER_LEN)) {
|
||||
int32_t oldVer = atomic_load_32(&passInfo->ver);
|
||||
if (oldVer < rsp->version) {
|
||||
atomic_store_32(&passInfo->ver, rsp->version);
|
||||
if (passInfo->fp) {
|
||||
(*passInfo->fp)(passInfo->param, &passInfo->ver, TAOS_NOTIFY_PASSVER);
|
||||
}
|
||||
tscDebug("update passVer of user %s from %d to %d, tscRid:%" PRIi64, rsp->user, oldVer,
|
||||
atomic_load_32(&passInfo->ver), pTscObj->id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
releaseTscObj(pReq->connKey.tscRid);
|
||||
}
|
||||
|
||||
taosArrayDestroy(batchRsp.pArray);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t hbGenerateVgInfoFromRsp(SDBVgInfo **pInfo, SUseDbRsp *rsp) {
|
||||
int32_t code = 0;
|
||||
int32_t code = 0;
|
||||
SDBVgInfo *vgInfo = taosMemoryCalloc(1, sizeof(SDBVgInfo));
|
||||
if (NULL == vgInfo) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
vgInfo->vgVersion = rsp->vgVersion;
|
||||
vgInfo->stateTs = rsp->stateTs;
|
||||
vgInfo->hashMethod = rsp->hashMethod;
|
||||
|
@ -69,7 +124,7 @@ static int32_t hbGenerateVgInfoFromRsp(SDBVgInfo **pInfo, SUseDbRsp *rsp) {
|
|||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _return;
|
||||
}
|
||||
|
||||
|
||||
for (int32_t j = 0; j < rsp->vgNum; ++j) {
|
||||
SVgroupInfo *pInfo = taosArrayGet(rsp->pVgroupInfos, j);
|
||||
if (taosHashPut(vgInfo->vgHash, &pInfo->vgId, sizeof(int32_t), pInfo, sizeof(SVgroupInfo)) != 0) {
|
||||
|
@ -123,7 +178,8 @@ static int32_t hbProcessDBInfoRsp(void *value, int32_t valueLen, struct SCatalog
|
|||
goto _return;
|
||||
}
|
||||
|
||||
catalogUpdateDBVgInfo(pCatalog, (rsp->db[0] == 'i') ? TSDB_PERFORMANCE_SCHEMA_DB : TSDB_INFORMATION_SCHEMA_DB, rsp->uid, vgInfo);
|
||||
catalogUpdateDBVgInfo(pCatalog, (rsp->db[0] == 'i') ? TSDB_PERFORMANCE_SCHEMA_DB : TSDB_INFORMATION_SCHEMA_DB,
|
||||
rsp->uid, vgInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,6 +347,15 @@ static int32_t hbQueryHbRspHandle(SAppHbMgr *pAppHbMgr, SClientHbRsp *pRsp) {
|
|||
hbProcessStbInfoRsp(kv->value, kv->valueLen, pCatalog);
|
||||
break;
|
||||
}
|
||||
case HEARTBEAT_KEY_USER_PASSINFO: {
|
||||
if (kv->valueLen <= 0 || NULL == kv->value) {
|
||||
tscError("invalid hb user pass info, len:%d, value:%p", kv->valueLen, kv->value);
|
||||
break;
|
||||
}
|
||||
|
||||
hbProcessUserPassInfoRsp(kv->value, kv->valueLen, &pRsp->connKey, pAppHbMgr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tscError("invalid hb key type:%d", kv->key);
|
||||
break;
|
||||
|
@ -308,7 +373,7 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) {
|
|||
}
|
||||
|
||||
static int32_t emptyRspNum = 0;
|
||||
int32_t idx = *(int32_t *)param;
|
||||
int32_t idx = *(int32_t *)param;
|
||||
SClientHbBatchRsp pRsp = {0};
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
tDeserializeSClientHbBatchRsp(pMsg->pData, pMsg->len, &pRsp);
|
||||
|
@ -339,8 +404,7 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) {
|
|||
|
||||
if (code != 0) {
|
||||
pInst->onlineDnodes = pInst->totalDnodes ? 0 : -1;
|
||||
tscDebug("hb rsp error %s, update server status %d/%d", tstrerror(code), pInst->onlineDnodes,
|
||||
pInst->totalDnodes);
|
||||
tscDebug("hb rsp error %s, update server status %d/%d", tstrerror(code), pInst->onlineDnodes, pInst->totalDnodes);
|
||||
}
|
||||
|
||||
if (rspNum) {
|
||||
|
@ -472,6 +536,49 @@ int32_t hbGetQueryBasicInfo(SClientHbKey *connKey, SClientHbReq *req) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t hbGetUserBasicInfo(SClientHbKey *connKey, SClientHbReq *req) {
|
||||
STscObj *pTscObj = (STscObj *)acquireTscObj(connKey->tscRid);
|
||||
if (!pTscObj) {
|
||||
tscWarn("tscObj rid %" PRIx64 " not exist", connKey->tscRid);
|
||||
return TSDB_CODE_APP_ERROR;
|
||||
}
|
||||
|
||||
int32_t code = 0;
|
||||
SUserPassVersion *user = taosMemoryMalloc(sizeof(SUserPassVersion));
|
||||
if (!user) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _return;
|
||||
}
|
||||
strncpy(user->user, pTscObj->user, TSDB_USER_LEN);
|
||||
user->version = htonl(pTscObj->passInfo.ver);
|
||||
|
||||
SKv kv = {
|
||||
.key = HEARTBEAT_KEY_USER_PASSINFO,
|
||||
.valueLen = sizeof(SUserPassVersion),
|
||||
.value = user,
|
||||
};
|
||||
|
||||
tscDebug("hb got user basic info, valueLen:%d, user:%s, passVer:%d, tscRid:%" PRIi64, kv.valueLen, user->user,
|
||||
pTscObj->passInfo.ver, connKey->tscRid);
|
||||
|
||||
if (!req->info) {
|
||||
req->info = taosHashInit(64, hbKeyHashFunc, 1, HASH_ENTRY_LOCK);
|
||||
}
|
||||
|
||||
if (taosHashPut(req->info, &kv.key, sizeof(kv.key), &kv, sizeof(kv)) < 0) {
|
||||
code = terrno ? terrno : TSDB_CODE_APP_ERROR;
|
||||
goto _return;
|
||||
}
|
||||
|
||||
_return:
|
||||
releaseTscObj(connKey->tscRid);
|
||||
if (code) {
|
||||
tscError("hb got user basic info failed since %s", terrstr(code));
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t hbGetExpiredUserInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SClientHbReq *req) {
|
||||
SUserAuthVersion *users = NULL;
|
||||
uint32_t userNum = 0;
|
||||
|
@ -526,8 +633,8 @@ int32_t hbGetExpiredDBInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SCl
|
|||
|
||||
for (int32_t i = 0; i < dbNum; ++i) {
|
||||
SDbVgVersion *db = &dbs[i];
|
||||
tscDebug("the %dth expired dbFName:%s, dbId:%" PRId64 ", vgVersion:%d, numOfTable:%d, startTs:%" PRId64,
|
||||
i, db->dbFName, db->dbId, db->vgVersion, db->numOfTable, db->stateTs);
|
||||
tscDebug("the %dth expired dbFName:%s, dbId:%" PRId64 ", vgVersion:%d, numOfTable:%d, startTs:%" PRId64, i,
|
||||
db->dbFName, db->dbId, db->vgVersion, db->numOfTable, db->stateTs);
|
||||
|
||||
db->dbId = htobe64(db->dbId);
|
||||
db->vgVersion = htonl(db->vgVersion);
|
||||
|
@ -607,19 +714,23 @@ int32_t hbGetAppInfo(int64_t clusterId, SClientHbReq *req) {
|
|||
}
|
||||
|
||||
int32_t hbQueryHbReqHandle(SClientHbKey *connKey, void *param, SClientHbReq *req) {
|
||||
int64_t *clusterId = (int64_t *)param;
|
||||
SHbParam *hbParam = (SHbParam *)param;
|
||||
struct SCatalog *pCatalog = NULL;
|
||||
|
||||
int32_t code = catalogGetHandle(*clusterId, &pCatalog);
|
||||
int32_t code = catalogGetHandle(hbParam->clusterId, &pCatalog);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscWarn("catalogGetHandle failed, clusterId:%" PRIx64 ", error:%s", *clusterId, tstrerror(code));
|
||||
tscWarn("catalogGetHandle failed, clusterId:%" PRIx64 ", error:%s", hbParam->clusterId, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
hbGetAppInfo(*clusterId, req);
|
||||
hbGetAppInfo(hbParam->clusterId, req);
|
||||
|
||||
hbGetQueryBasicInfo(connKey, req);
|
||||
|
||||
if (hbParam->passKeyCnt > 0) {
|
||||
hbGetUserBasicInfo(connKey, req);
|
||||
}
|
||||
|
||||
code = hbGetExpiredUserInfo(connKey, pCatalog, req);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
|
@ -673,7 +784,26 @@ SClientHbBatchReq *hbGatherAllInfo(SAppHbMgr *pAppHbMgr) {
|
|||
|
||||
while (pIter != NULL) {
|
||||
pOneReq = taosArrayPush(pBatchReq->reqs, pOneReq);
|
||||
code = (*clientHbMgr.reqHandle[pOneReq->connKey.connType])(&pOneReq->connKey, &pOneReq->clusterId, pOneReq);
|
||||
SHbParam param;
|
||||
switch (pOneReq->connKey.connType) {
|
||||
case CONN_TYPE__QUERY: {
|
||||
param.clusterId = pOneReq->clusterId;
|
||||
param.passKeyCnt = atomic_load_32(&pAppHbMgr->passKeyCnt);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (clientHbMgr.reqHandle[pOneReq->connKey.connType]) {
|
||||
code = (*clientHbMgr.reqHandle[pOneReq->connKey.connType])(&pOneReq->connKey, ¶m, pOneReq);
|
||||
if (code) {
|
||||
tscWarn("hbGatherAllInfo failed since %s, tscRid:%" PRIi64 ", connType:%" PRIi8, tstrerror(code),
|
||||
pOneReq->connKey.tscRid, pOneReq->connKey.connType);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
if (code) {
|
||||
pIter = taosHashIterate(pAppHbMgr->activeInfo, pIter);
|
||||
pOneReq = pIter;
|
||||
|
@ -682,6 +812,7 @@ SClientHbBatchReq *hbGatherAllInfo(SAppHbMgr *pAppHbMgr) {
|
|||
|
||||
pIter = taosHashIterate(pAppHbMgr->activeInfo, pIter);
|
||||
pOneReq = pIter;
|
||||
#endif
|
||||
}
|
||||
releaseTscObj(rid);
|
||||
|
||||
|
@ -856,7 +987,7 @@ static void hbStopThread() {
|
|||
}
|
||||
|
||||
SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) {
|
||||
if(hbMgrInit() != 0){
|
||||
if (hbMgrInit() != 0) {
|
||||
terrno = TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -868,6 +999,7 @@ SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) {
|
|||
// init stat
|
||||
pAppHbMgr->startTime = taosGetTimestampMs();
|
||||
pAppHbMgr->connKeyCnt = 0;
|
||||
pAppHbMgr->passKeyCnt = 0;
|
||||
pAppHbMgr->reportCnt = 0;
|
||||
pAppHbMgr->reportBytes = 0;
|
||||
pAppHbMgr->key = taosStrdup(key);
|
||||
|
@ -946,27 +1078,23 @@ int hbMgrInit() {
|
|||
TdThreadMutexAttr attr = {0};
|
||||
|
||||
int ret = taosThreadMutexAttrInit(&attr);
|
||||
if(ret != 0){
|
||||
uError("hbMgrInit:taosThreadMutexAttrInit error")
|
||||
return ret;
|
||||
if (ret != 0) {
|
||||
uError("hbMgrInit:taosThreadMutexAttrInit error") return ret;
|
||||
}
|
||||
|
||||
ret = taosThreadMutexAttrSetType(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if(ret != 0){
|
||||
uError("hbMgrInit:taosThreadMutexAttrSetType error")
|
||||
return ret;
|
||||
if (ret != 0) {
|
||||
uError("hbMgrInit:taosThreadMutexAttrSetType error") return ret;
|
||||
}
|
||||
|
||||
ret = taosThreadMutexInit(&clientHbMgr.lock, &attr);
|
||||
if(ret != 0){
|
||||
uError("hbMgrInit:taosThreadMutexInit error")
|
||||
return ret;
|
||||
if (ret != 0) {
|
||||
uError("hbMgrInit:taosThreadMutexInit error") return ret;
|
||||
}
|
||||
|
||||
ret = taosThreadMutexAttrDestroy(&attr);
|
||||
if(ret != 0){
|
||||
uError("hbMgrInit:taosThreadMutexAttrDestroy error")
|
||||
return ret;
|
||||
if (ret != 0) {
|
||||
uError("hbMgrInit:taosThreadMutexAttrDestroy error") return ret;
|
||||
}
|
||||
|
||||
// init handle funcs
|
||||
|
@ -1028,7 +1156,8 @@ int hbRegisterConn(SAppHbMgr *pAppHbMgr, int64_t tscRefId, int64_t clusterId, in
|
|||
}
|
||||
}
|
||||
|
||||
void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey) {
|
||||
void hbDeregisterConn(STscObj *pTscObj, SClientHbKey connKey) {
|
||||
SAppHbMgr *pAppHbMgr = pTscObj->pAppInfo->pAppHbMgr;
|
||||
SClientHbReq *pReq = taosHashAcquire(pAppHbMgr->activeInfo, &connKey, sizeof(SClientHbKey));
|
||||
if (pReq) {
|
||||
tFreeClientHbReq(pReq);
|
||||
|
@ -1041,9 +1170,12 @@ void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey) {
|
|||
}
|
||||
|
||||
atomic_sub_fetch_32(&pAppHbMgr->connKeyCnt, 1);
|
||||
taosThreadMutexLock(&pTscObj->mutex);
|
||||
if (pTscObj->passInfo.fp) {
|
||||
atomic_sub_fetch_32(&pAppHbMgr->passKeyCnt, 1);
|
||||
}
|
||||
taosThreadMutexUnlock(&pTscObj->mutex);
|
||||
}
|
||||
|
||||
// set heart beat thread quit mode , if quicByKill 1 then kill thread else quit from inner
|
||||
void taos_set_hb_quit(int8_t quitByKill) {
|
||||
clientHbMgr.quitByKill = quitByKill;
|
||||
}
|
||||
void taos_set_hb_quit(int8_t quitByKill) { clientHbMgr.quitByKill = quitByKill; }
|
||||
|
|
|
@ -1248,6 +1248,11 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pRequest->sqlstr = taosStrdup("taos_connect");
|
||||
if (pRequest->sqlstr) {
|
||||
pRequest->sqlLen = strlen(pRequest->sqlstr);
|
||||
}
|
||||
|
||||
SMsgSendInfo* body = buildConnectMsg(pRequest);
|
||||
|
||||
int64_t transporterId = 0;
|
||||
|
@ -1257,7 +1262,7 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
|
|||
if (pRequest->code != TSDB_CODE_SUCCESS) {
|
||||
const char* errorMsg =
|
||||
(pRequest->code == TSDB_CODE_RPC_FQDN_ERROR) ? taos_errstr(pRequest) : tstrerror(pRequest->code);
|
||||
fprintf(stderr, "failed to connect to server, reason: %s\n\n", errorMsg);
|
||||
tscError("failed to connect to server, reason: %s", errorMsg);
|
||||
|
||||
terrno = pRequest->code;
|
||||
destroyRequest(pRequest);
|
||||
|
|
|
@ -119,6 +119,43 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
|
||||
if (taos == NULL) {
|
||||
terrno = TSDB_CODE_INVALID_PARA;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
STscObj *pObj = acquireTscObj(*(int64_t *)taos);
|
||||
if (NULL == pObj) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
tscError("invalid parameter for %s", __func__);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TAOS_NOTIFY_PASSVER: {
|
||||
taosThreadMutexLock(&pObj->mutex);
|
||||
if (fp && !pObj->passInfo.fp) {
|
||||
atomic_add_fetch_32(&pObj->pAppInfo->pAppHbMgr->passKeyCnt, 1);
|
||||
} else if (!fp && pObj->passInfo.fp) {
|
||||
atomic_sub_fetch_32(&pObj->pAppInfo->pAppHbMgr->passKeyCnt, 1);
|
||||
}
|
||||
pObj->passInfo.fp = fp;
|
||||
pObj->passInfo.param = param;
|
||||
taosThreadMutexUnlock(&pObj->mutex);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
terrno = TSDB_CODE_INVALID_PARA;
|
||||
releaseTscObj(*(int64_t *)taos);
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
releaseTscObj(*(int64_t *)taos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taos_close_internal(void *taos) {
|
||||
if (taos == NULL) {
|
||||
return;
|
||||
|
@ -1307,6 +1344,8 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
|
|||
goto _return;
|
||||
}
|
||||
|
||||
pRequest->syncQuery = true;
|
||||
|
||||
STscObj *pTscObj = pRequest->pTscObj;
|
||||
code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
|
||||
if (code) {
|
||||
|
@ -1333,7 +1372,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
|
|||
tsem_wait(&pParam->sem);
|
||||
|
||||
_return:
|
||||
taosArrayDestroy(catalogReq.pTableMeta);
|
||||
taosArrayDestroyEx(catalogReq.pTableMeta, destoryTablesReq);
|
||||
destroyRequest(pRequest);
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
lastClusterId = connectRsp.clusterId;
|
||||
|
||||
pTscObj->connType = connectRsp.connType;
|
||||
pTscObj->passInfo.ver = connectRsp.passVer;
|
||||
|
||||
hbRegisterConn(pTscObj->pAppInfo->pAppHbMgr, pTscObj->id, connectRsp.clusterId, connectRsp.connType);
|
||||
|
||||
|
|
|
@ -1511,7 +1511,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) {
|
|||
rspObj.resType = RES_TYPE__TMQ;
|
||||
|
||||
tDecoderInit(&decoder, data, dataLen);
|
||||
code = tDecodeSMqDataRsp(&decoder, &rspObj.rsp);
|
||||
code = tDecodeMqDataRsp(&decoder, &rspObj.rsp);
|
||||
if (code != 0) {
|
||||
uError("WriteRaw:decode smqDataRsp error");
|
||||
code = TSDB_CODE_INVALID_MSG;
|
||||
|
@ -1615,7 +1615,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) {
|
|||
code = pRequest->code;
|
||||
|
||||
end:
|
||||
tDeleteSMqDataRsp(&rspObj.rsp);
|
||||
tDeleteMqDataRsp(&rspObj.rsp);
|
||||
tDecoderClear(&decoder);
|
||||
qDestroyQuery(pQuery);
|
||||
destroyRequest(pRequest);
|
||||
|
@ -1858,7 +1858,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) {
|
|||
|
||||
int32_t len = 0;
|
||||
int32_t code = 0;
|
||||
tEncodeSize(tEncodeSMqDataRsp, &rspObj->rsp, len, code);
|
||||
tEncodeSize(tEncodeMqDataRsp, &rspObj->rsp, len, code);
|
||||
if (code < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1866,7 +1866,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) {
|
|||
void* buf = taosMemoryCalloc(1, len);
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, len);
|
||||
tEncodeSMqDataRsp(&encoder, &rspObj->rsp);
|
||||
tEncodeMqDataRsp(&encoder, &rspObj->rsp);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
raw->raw = buf;
|
||||
|
|
|
@ -195,17 +195,19 @@ int32_t smlSetCTableName(SSmlTableInfo *oneTable) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tinfo){
|
||||
char key[TSDB_TABLE_NAME_LEN * 2 + 1] = {0};
|
||||
void getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tinfo) {
|
||||
char key[TSDB_TABLE_NAME_LEN * 2 + 1] = {0};
|
||||
size_t nLen = strlen(tinfo->childTableName);
|
||||
memcpy(key, currElement->measure, currElement->measureLen);
|
||||
memcpy(key + currElement->measureLen + 1, tinfo->childTableName, nLen);
|
||||
void *uid = taosHashGet(info->tableUids, key, currElement->measureLen + 1 + nLen); // use \0 as separator for stable name and child table name
|
||||
void *uid =
|
||||
taosHashGet(info->tableUids, key,
|
||||
currElement->measureLen + 1 + nLen); // use \0 as separator for stable name and child table name
|
||||
if (uid == NULL) {
|
||||
tinfo->uid = info->uid++;
|
||||
taosHashPut(info->tableUids, key, currElement->measureLen + 1 + nLen, &tinfo->uid, sizeof(uint64_t));
|
||||
}else{
|
||||
tinfo->uid = *(uint64_t*)uid;
|
||||
} else {
|
||||
tinfo->uid = *(uint64_t *)uid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,7 +550,8 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
|
|||
uint16_t *index = colHash ? (uint16_t *)taosHashGet(colHash, kv->key, kv->keyLen) : NULL;
|
||||
if (index) {
|
||||
if (colField[*index].type != kv->type) {
|
||||
uError("SML:0x%" PRIx64 " point type and db type mismatch. db type: %d, point type: %d, key: %s", info->id, colField[*index].type, kv->type, kv->key);
|
||||
uError("SML:0x%" PRIx64 " point type and db type mismatch. db type: %d, point type: %d, key: %s", info->id,
|
||||
colField[*index].type, kv->type, kv->key);
|
||||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
@ -575,17 +578,18 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
|
|||
#define BOUNDARY 1024
|
||||
static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
||||
int32_t result = 1;
|
||||
if (length >= BOUNDARY){
|
||||
if (length >= BOUNDARY) {
|
||||
result = length;
|
||||
}else{
|
||||
} else {
|
||||
while (result <= length) {
|
||||
result *= 2;
|
||||
result <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
|
||||
result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
|
||||
result = (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
|
||||
result = (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
@ -675,7 +679,7 @@ static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashO
|
|||
SField *field = taosArrayGet(results, j);
|
||||
len += field->bytes;
|
||||
}
|
||||
if(len > maxLen){
|
||||
if (len > maxLen) {
|
||||
return isTag ? TSDB_CODE_PAR_INVALID_TAGS_LENGTH : TSDB_CODE_PAR_INVALID_ROW_LENGTH;
|
||||
}
|
||||
|
||||
|
@ -690,6 +694,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
|||
SMCreateStbReq pReq = {0};
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SCmdMsgInfo pCmdMsg = {0};
|
||||
char *pSql = NULL;
|
||||
|
||||
// put front for free
|
||||
pReq.numOfColumns = taosArrayGetSize(pColumns);
|
||||
|
@ -697,7 +702,27 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
|||
pReq.numOfTags = taosArrayGetSize(pTags);
|
||||
pReq.pTags = pTags;
|
||||
|
||||
code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest, 0);
|
||||
if (action == SCHEMA_ACTION_CREATE_STABLE) {
|
||||
pReq.colVer = 1;
|
||||
pReq.tagVer = 1;
|
||||
pReq.suid = 0;
|
||||
pReq.source = TD_REQ_FROM_APP;
|
||||
pSql = "sml_create_stable";
|
||||
} else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
|
||||
pReq.colVer = pTableMeta->sversion;
|
||||
pReq.tagVer = pTableMeta->tversion + 1;
|
||||
pReq.suid = pTableMeta->uid;
|
||||
pReq.source = TD_REQ_FROM_TAOX;
|
||||
pSql = (action == SCHEMA_ACTION_ADD_TAG) ? "sml_add_tag" : "sml_modify_tag_size";
|
||||
} else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) {
|
||||
pReq.colVer = pTableMeta->sversion + 1;
|
||||
pReq.tagVer = pTableMeta->tversion;
|
||||
pReq.suid = pTableMeta->uid;
|
||||
pReq.source = TD_REQ_FROM_TAOX;
|
||||
pSql = (action == SCHEMA_ACTION_ADD_COLUMN) ? "sml_add_column" : "sml_modify_column_size";
|
||||
}
|
||||
|
||||
code = buildRequest(info->taos->id, pSql, strlen(pSql), NULL, false, &pRequest, 0);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
|
@ -708,23 +733,6 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (action == SCHEMA_ACTION_CREATE_STABLE) {
|
||||
pReq.colVer = 1;
|
||||
pReq.tagVer = 1;
|
||||
pReq.suid = 0;
|
||||
pReq.source = TD_REQ_FROM_APP;
|
||||
} else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
|
||||
pReq.colVer = pTableMeta->sversion;
|
||||
pReq.tagVer = pTableMeta->tversion + 1;
|
||||
pReq.suid = pTableMeta->uid;
|
||||
pReq.source = TD_REQ_FROM_TAOX;
|
||||
} else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) {
|
||||
pReq.colVer = pTableMeta->sversion + 1;
|
||||
pReq.tagVer = pTableMeta->tversion;
|
||||
pReq.suid = pTableMeta->uid;
|
||||
pReq.source = TD_REQ_FROM_TAOX;
|
||||
}
|
||||
|
||||
if (pReq.numOfTags == 0) {
|
||||
pReq.numOfTags = 1;
|
||||
SField field = {0};
|
||||
|
@ -1336,7 +1344,7 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
|||
if (info->pRequest->dbList == NULL) {
|
||||
info->pRequest->dbList = taosArrayInit(1, TSDB_DB_FNAME_LEN);
|
||||
}
|
||||
char *data = (char*)taosArrayReserve(info->pRequest->dbList, 1);
|
||||
char *data = (char *)taosArrayReserve(info->pRequest->dbList, 1);
|
||||
SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}};
|
||||
tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname));
|
||||
tNameGetFullDbName(&pName, data);
|
||||
|
@ -1578,9 +1586,9 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL
|
|||
|
||||
do {
|
||||
code = smlModifyDBSchemas(info);
|
||||
if (code == 0 || code == TSDB_CODE_SML_INVALID_DATA || code == TSDB_CODE_PAR_TOO_MANY_COLUMNS
|
||||
|| code == TSDB_CODE_PAR_INVALID_TAGS_NUM || code == TSDB_CODE_PAR_INVALID_TAGS_LENGTH
|
||||
|| code == TSDB_CODE_PAR_INVALID_ROW_LENGTH || code == TSDB_CODE_MND_FIELD_VALUE_OVERFLOW) {
|
||||
if (code == 0 || code == TSDB_CODE_SML_INVALID_DATA || code == TSDB_CODE_PAR_TOO_MANY_COLUMNS ||
|
||||
code == TSDB_CODE_PAR_INVALID_TAGS_NUM || code == TSDB_CODE_PAR_INVALID_TAGS_LENGTH ||
|
||||
code == TSDB_CODE_PAR_INVALID_ROW_LENGTH || code == TSDB_CODE_MND_FIELD_VALUE_OVERFLOW) {
|
||||
break;
|
||||
}
|
||||
taosMsleep(100);
|
||||
|
@ -1602,6 +1610,44 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL
|
|||
return code;
|
||||
}
|
||||
|
||||
void smlSetReqSQL(SRequestObj *request, char *lines[], char *rawLine, char *rawLineEnd) {
|
||||
if (tsSlowLogScope & SLOW_LOG_TYPE_INSERT) {
|
||||
int32_t len = 0;
|
||||
int32_t rlen = 0;
|
||||
char *p = NULL;
|
||||
|
||||
if (lines && lines[0]) {
|
||||
len = strlen(lines[0]);
|
||||
p = lines[0];
|
||||
} else if (rawLine) {
|
||||
if (rawLineEnd) {
|
||||
len = rawLineEnd - rawLine;
|
||||
} else {
|
||||
len = strlen(rawLine);
|
||||
}
|
||||
p = rawLine;
|
||||
}
|
||||
|
||||
if (NULL == p) {
|
||||
return;
|
||||
}
|
||||
|
||||
rlen = TMIN(len, TSDB_MAX_ALLOWED_SQL_LEN);
|
||||
rlen = TMAX(rlen, 0);
|
||||
|
||||
char *sql = taosMemoryMalloc(rlen + 1);
|
||||
if (NULL == sql) {
|
||||
uError("malloc %d for sml sql failed", rlen + 1);
|
||||
return;
|
||||
}
|
||||
memcpy(sql, p, rlen);
|
||||
sql[rlen] = 0;
|
||||
|
||||
request->sqlstr = sql;
|
||||
request->sqlLen = rlen;
|
||||
}
|
||||
}
|
||||
|
||||
TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine, char *rawLineEnd, int numLines,
|
||||
int protocol, int precision, int32_t ttl, int64_t reqid) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
@ -1634,6 +1680,8 @@ TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine,
|
|||
info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE;
|
||||
info->lineNum = numLines;
|
||||
|
||||
smlSetReqSQL(request, lines, rawLine, rawLineEnd);
|
||||
|
||||
SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf};
|
||||
if (request->pDb == NULL) {
|
||||
request->code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
|
||||
|
|
|
@ -27,29 +27,28 @@
|
|||
// equal =
|
||||
#define IS_EQUAL(sql) (*(sql) == EQUAL && *((sql)-1) != SLASH)
|
||||
// quote "
|
||||
//#define IS_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) != SLASH)
|
||||
// #define IS_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) != SLASH)
|
||||
// SLASH
|
||||
|
||||
#define IS_SLASH_LETTER_IN_FIELD_VALUE(sql) \
|
||||
(*((sql)-1) == SLASH && (*(sql) == QUOTE || *(sql) == SLASH))
|
||||
#define IS_SLASH_LETTER_IN_FIELD_VALUE(sql) (*((sql)-1) == SLASH && (*(sql) == QUOTE || *(sql) == SLASH))
|
||||
|
||||
#define IS_SLASH_LETTER_IN_TAG_FIELD_KEY(sql) \
|
||||
#define IS_SLASH_LETTER_IN_TAG_FIELD_KEY(sql) \
|
||||
(*((sql)-1) == SLASH && (*(sql) == COMMA || *(sql) == SPACE || *(sql) == EQUAL))
|
||||
|
||||
#define PROCESS_SLASH_IN_FIELD_VALUE(key, keyLen) \
|
||||
for (int i = 1; i < keyLen; ++i) { \
|
||||
if (IS_SLASH_LETTER_IN_FIELD_VALUE(key + i)) { \
|
||||
MOVE_FORWARD_ONE(key + i, keyLen - i); \
|
||||
keyLen--; \
|
||||
} \
|
||||
#define PROCESS_SLASH_IN_FIELD_VALUE(key, keyLen) \
|
||||
for (int i = 1; i < keyLen; ++i) { \
|
||||
if (IS_SLASH_LETTER_IN_FIELD_VALUE(key + i)) { \
|
||||
MOVE_FORWARD_ONE(key + i, keyLen - i); \
|
||||
keyLen--; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PROCESS_SLASH_IN_TAG_FIELD_KEY(key, keyLen) \
|
||||
for (int i = 1; i < keyLen; ++i) { \
|
||||
if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(key + i)) { \
|
||||
MOVE_FORWARD_ONE(key + i, keyLen - i); \
|
||||
keyLen--; \
|
||||
} \
|
||||
#define PROCESS_SLASH_IN_TAG_FIELD_KEY(key, keyLen) \
|
||||
for (int i = 1; i < keyLen; ++i) { \
|
||||
if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(key + i)) { \
|
||||
MOVE_FORWARD_ONE(key + i, keyLen - i); \
|
||||
keyLen--; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BINARY_ADD_LEN 2 // "binary" 2 means " "
|
||||
|
@ -152,15 +151,15 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
|
||||
SSmlSTableMeta *sMeta = NULL;
|
||||
if (unlikely(tmp == NULL)) {
|
||||
char* measure = currElement->measure;
|
||||
char *measure = currElement->measure;
|
||||
int measureLen = currElement->measureLen;
|
||||
if(currElement->measureEscaped){
|
||||
measure = (char*)taosMemoryMalloc(currElement->measureLen);
|
||||
if (currElement->measureEscaped) {
|
||||
measure = (char *)taosMemoryMalloc(currElement->measureLen);
|
||||
memcpy(measure, currElement->measure, currElement->measureLen);
|
||||
PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen);
|
||||
}
|
||||
STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen);
|
||||
if(currElement->measureEscaped){
|
||||
if (currElement->measureEscaped) {
|
||||
taosMemoryFree(measure);
|
||||
}
|
||||
if (pTableMeta == NULL) {
|
||||
|
@ -171,9 +170,13 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
sMeta = smlBuildSTableMeta(info->dataFormat);
|
||||
sMeta->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, currElement->measure, currElement->measureLen, &sMeta, POINTER_BYTES);
|
||||
for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){
|
||||
for (int i = pTableMeta->tableInfo.numOfColumns;
|
||||
i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++) {
|
||||
SSchema *tag = pTableMeta->schema + i;
|
||||
SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type, .length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE };
|
||||
SSmlKv kv = {.key = tag->name,
|
||||
.keyLen = strlen(tag->name),
|
||||
.type = tag->type,
|
||||
.length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE};
|
||||
taosArrayPush(sMeta->tags, &kv);
|
||||
}
|
||||
tmp = &sMeta;
|
||||
|
@ -248,19 +251,25 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
|
||||
}
|
||||
|
||||
if (keyEscaped){
|
||||
char *tmp = (char*)taosMemoryMalloc(keyLen);
|
||||
if (keyEscaped) {
|
||||
char *tmp = (char *)taosMemoryMalloc(keyLen);
|
||||
memcpy(tmp, key, keyLen);
|
||||
PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, keyLen);
|
||||
key = tmp;
|
||||
}
|
||||
if (valueEscaped){
|
||||
char *tmp = (char*)taosMemoryMalloc(valueLen);
|
||||
if (valueEscaped) {
|
||||
char *tmp = (char *)taosMemoryMalloc(valueLen);
|
||||
memcpy(tmp, value, valueLen);
|
||||
PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, valueLen);
|
||||
value = tmp;
|
||||
}
|
||||
SSmlKv kv = {.key = key, .keyLen = keyLen, .type = TSDB_DATA_TYPE_NCHAR, .value = value, .length = valueLen, .keyEscaped = keyEscaped, .valueEscaped = valueEscaped};
|
||||
SSmlKv kv = {.key = key,
|
||||
.keyLen = keyLen,
|
||||
.type = TSDB_DATA_TYPE_NCHAR,
|
||||
.value = value,
|
||||
.length = valueLen,
|
||||
.keyEscaped = keyEscaped,
|
||||
.valueEscaped = valueEscaped};
|
||||
taosArrayPush(preLineKV, &kv);
|
||||
if (info->dataFormat) {
|
||||
if (unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)) {
|
||||
|
@ -305,10 +314,10 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
tinfo->tags = taosArrayDup(preLineKV, NULL);
|
||||
for(size_t i = 0; i < taosArrayGetSize(preLineKV); i++){
|
||||
for (size_t i = 0; i < taosArrayGetSize(preLineKV); i++) {
|
||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(preLineKV, i);
|
||||
if(kv->keyEscaped)kv->key = NULL;
|
||||
if(kv->valueEscaped)kv->value = NULL;
|
||||
if (kv->keyEscaped) kv->key = NULL;
|
||||
if (kv->valueEscaped) kv->value = NULL;
|
||||
}
|
||||
|
||||
smlSetCTableName(tinfo);
|
||||
|
@ -330,7 +339,7 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
|
||||
static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLineInfo *currElement, bool isSameMeasure,
|
||||
bool isSameCTable) {
|
||||
int cnt = 0;
|
||||
int cnt = 0;
|
||||
if (info->dataFormat) {
|
||||
if (unlikely(!isSameCTable)) {
|
||||
SSmlTableInfo **oneTable =
|
||||
|
@ -346,15 +355,15 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
SSmlSTableMeta **tmp =
|
||||
(SSmlSTableMeta **)taosHashGet(info->superTables, currElement->measure, currElement->measureLen);
|
||||
if (unlikely(tmp == NULL)) {
|
||||
char* measure = currElement->measure;
|
||||
char *measure = currElement->measure;
|
||||
int measureLen = currElement->measureLen;
|
||||
if(currElement->measureEscaped){
|
||||
measure = (char*)taosMemoryMalloc(currElement->measureLen);
|
||||
if (currElement->measureEscaped) {
|
||||
measure = (char *)taosMemoryMalloc(currElement->measureLen);
|
||||
memcpy(measure, currElement->measure, currElement->measureLen);
|
||||
PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen);
|
||||
}
|
||||
STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen);
|
||||
if(currElement->measureEscaped){
|
||||
if (currElement->measureEscaped) {
|
||||
taosMemoryFree(measure);
|
||||
}
|
||||
if (pTableMeta == NULL) {
|
||||
|
@ -366,12 +375,12 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
(*tmp)->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, currElement->measure, currElement->measureLen, tmp, POINTER_BYTES);
|
||||
|
||||
for(int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++){
|
||||
for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) {
|
||||
SSchema *tag = pTableMeta->schema + i;
|
||||
SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type };
|
||||
if(tag->type == TSDB_DATA_TYPE_NCHAR){
|
||||
SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type};
|
||||
if (tag->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
kv.length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}else if(tag->type == TSDB_DATA_TYPE_BINARY){
|
||||
} else if (tag->type == TSDB_DATA_TYPE_BINARY) {
|
||||
kv.length = tag->bytes - VARSTR_HEADER_SIZE;
|
||||
}
|
||||
taosArrayPush((*tmp)->cols, &kv);
|
||||
|
@ -459,16 +468,16 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (keyEscaped){
|
||||
char *tmp = (char*)taosMemoryMalloc(kv.keyLen);
|
||||
if (keyEscaped) {
|
||||
char *tmp = (char *)taosMemoryMalloc(kv.keyLen);
|
||||
memcpy(tmp, key, kv.keyLen);
|
||||
PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, kv.keyLen);
|
||||
kv.key = tmp;
|
||||
kv.keyEscaped = keyEscaped;
|
||||
}
|
||||
|
||||
if (valueEscaped){
|
||||
char *tmp = (char*)taosMemoryMalloc(kv.length);
|
||||
if (valueEscaped) {
|
||||
char *tmp = (char *)taosMemoryMalloc(kv.length);
|
||||
memcpy(tmp, kv.value, kv.length);
|
||||
PROCESS_SLASH_IN_FIELD_VALUE(tmp, kv.length);
|
||||
kv.value = tmp;
|
||||
|
@ -643,9 +652,13 @@ int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLine
|
|||
if (info->dataFormat) {
|
||||
uDebug("SML:0x%" PRIx64 " smlParseInfluxString format true, ts:%" PRId64, info->id, ts);
|
||||
ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 0);
|
||||
if(ret != TSDB_CODE_SUCCESS){return ret;}
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = smlBuildRow(info->currTableDataCtx);
|
||||
if(ret != TSDB_CODE_SUCCESS){return ret;}
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
clearColValArray(info->currTableDataCtx->pValues);
|
||||
} else {
|
||||
uDebug("SML:0x%" PRIx64 " smlParseInfluxString format false, ts:%" PRId64, info->id, ts);
|
||||
|
|
|
@ -158,7 +158,7 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS
|
|||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (unlikely(valueLen > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)) {
|
||||
if (unlikely(valueLen > (TSDB_MAX_TAGS_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)) {
|
||||
return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,16 +133,23 @@ enum {
|
|||
TMQ_DELAYED_TASK__COMMIT,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int64_t pollCnt;
|
||||
int64_t numOfRows;
|
||||
typedef struct SVgOffsetInfo {
|
||||
STqOffsetVal committedOffset;
|
||||
STqOffsetVal currentOffset;
|
||||
int32_t vgId;
|
||||
int32_t vgStatus;
|
||||
int32_t vgSkipCnt;
|
||||
int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
|
||||
SEpSet epSet;
|
||||
int64_t walVerBegin;
|
||||
int64_t walVerEnd;
|
||||
} SVgOffsetInfo;
|
||||
|
||||
typedef struct {
|
||||
int64_t pollCnt;
|
||||
int64_t numOfRows;
|
||||
SVgOffsetInfo offsetInfo;
|
||||
int32_t vgId;
|
||||
int32_t vgStatus;
|
||||
int32_t vgSkipCnt; // here used to mark the slow vgroups
|
||||
bool receiveInfo;
|
||||
int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
|
||||
SEpSet epSet;
|
||||
} SMqClientVg;
|
||||
|
||||
typedef struct {
|
||||
|
@ -190,6 +197,23 @@ typedef struct {
|
|||
uint64_t requestId; // request id for debug purpose
|
||||
} SMqPollCbParam;
|
||||
|
||||
typedef struct SMqVgCommon {
|
||||
tsem_t rsp;
|
||||
int32_t numOfRsp;
|
||||
SArray* pList;
|
||||
TdThreadMutex mutex;
|
||||
int64_t consumerId;
|
||||
char* pTopicName;
|
||||
int32_t code;
|
||||
} SMqVgCommon;
|
||||
|
||||
typedef struct SMqVgWalInfoParam {
|
||||
int32_t vgId;
|
||||
int32_t epoch;
|
||||
int32_t totalReq;
|
||||
SMqVgCommon* pCommon;
|
||||
} SMqVgWalInfoParam;
|
||||
|
||||
typedef struct {
|
||||
int64_t refId;
|
||||
int32_t epoch;
|
||||
|
@ -204,7 +228,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
SMqCommitCbParamSet* params;
|
||||
STqOffset* pOffset;
|
||||
SMqVgOffset* pOffset;
|
||||
char topicName[TSDB_TOPIC_FNAME_LEN];
|
||||
int32_t vgId;
|
||||
tmq_t* pTmq;
|
||||
|
@ -219,7 +243,7 @@ static int32_t doAskEp(tmq_t* tmq);
|
|||
static int32_t makeTopicVgroupKey(char* dst, const char* topicName, int32_t vg);
|
||||
static int32_t tmqCommitDone(SMqCommitCbParamSet* pParamSet);
|
||||
static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet,
|
||||
int32_t index, int32_t totalVgroups);
|
||||
int32_t index, int32_t totalVgroups, int32_t type);
|
||||
static void commitRspCountDown(SMqCommitCbParamSet* pParamSet, int64_t consumerId, const char* pTopic, int32_t vgId);
|
||||
static void asyncAskEp(tmq_t* pTmq, __tmq_askep_fn_t askEpFn, void* param);
|
||||
static void addToQueueCallbackFn(tmq_t* pTmq, int32_t code, SDataBuf* pDataBuf, void* param);
|
||||
|
@ -438,7 +462,7 @@ static int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) {
|
|||
// if (code1 != TSDB_CODE_SUCCESS) { // retry failed.
|
||||
// tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64
|
||||
// " retry failed, ignore this commit. code:%s ordinal:%d/%d",
|
||||
// pParam->pTmq->consumerId, pParam->topicName, pVg->vgId, pVg->committedOffset.version,
|
||||
// pParam->pTmq->consumerId, pParam->topicName, pVg->vgId, pVg->offsetInfo.committedOffset.version,
|
||||
// tstrerror(terrno), index + 1, numOfVgroups);
|
||||
// }
|
||||
// }
|
||||
|
@ -464,22 +488,23 @@ static int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) {
|
|||
}
|
||||
|
||||
static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet,
|
||||
int32_t index, int32_t totalVgroups) {
|
||||
STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset));
|
||||
int32_t index, int32_t totalVgroups, int32_t type) {
|
||||
SMqVgOffset* pOffset = taosMemoryCalloc(1, sizeof(SMqVgOffset));
|
||||
if (pOffset == NULL) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pOffset->val = pVg->currentOffset;
|
||||
pOffset->consumerId = tmq->consumerId;
|
||||
pOffset->offset.val = pVg->offsetInfo.currentOffset;
|
||||
|
||||
int32_t groupLen = strlen(tmq->groupId);
|
||||
memcpy(pOffset->subKey, tmq->groupId, groupLen);
|
||||
pOffset->subKey[groupLen] = TMQ_SEPARATOR;
|
||||
strcpy(pOffset->subKey + groupLen + 1, pTopicName);
|
||||
memcpy(pOffset->offset.subKey, tmq->groupId, groupLen);
|
||||
pOffset->offset.subKey[groupLen] = TMQ_SEPARATOR;
|
||||
strcpy(pOffset->offset.subKey + groupLen + 1, pTopicName);
|
||||
|
||||
int32_t len = 0;
|
||||
int32_t code = 0;
|
||||
tEncodeSize(tEncodeSTqOffset, pOffset, len, code);
|
||||
tEncodeSize(tEncodeMqVgOffset, pOffset, len, code);
|
||||
if (code < 0) {
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
@ -496,7 +521,7 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
|
|||
|
||||
SEncoder encoder;
|
||||
tEncoderInit(&encoder, abuf, len);
|
||||
tEncodeSTqOffset(&encoder, pOffset);
|
||||
tEncodeMqVgOffset(&encoder, pOffset);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
// build param
|
||||
|
@ -530,19 +555,19 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
|
|||
pMsgSendInfo->param = pParam;
|
||||
pMsgSendInfo->paramFreeFp = taosMemoryFree;
|
||||
pMsgSendInfo->fp = tmqCommitCb;
|
||||
pMsgSendInfo->msgType = TDMT_VND_TMQ_COMMIT_OFFSET;
|
||||
pMsgSendInfo->msgType = type;
|
||||
|
||||
atomic_add_fetch_32(&pParamSet->waitingRspNum, 1);
|
||||
atomic_add_fetch_32(&pParamSet->totalRspNum, 1);
|
||||
|
||||
SEp* pEp = GET_ACTIVE_EP(&pVg->epSet);
|
||||
char offsetBuf[80] = {0};
|
||||
tFormatOffset(offsetBuf, tListLen(offsetBuf), &pOffset->val);
|
||||
tFormatOffset(offsetBuf, tListLen(offsetBuf), &pOffset->offset.val);
|
||||
|
||||
char commitBuf[80] = {0};
|
||||
tFormatOffset(commitBuf, tListLen(commitBuf), &pVg->committedOffset);
|
||||
tFormatOffset(commitBuf, tListLen(commitBuf), &pVg->offsetInfo.committedOffset);
|
||||
tscDebug("consumer:0x%" PRIx64 " topic:%s on vgId:%d send offset:%s prev:%s, ep:%s:%d, ordinal:%d/%d, req:0x%" PRIx64,
|
||||
tmq->consumerId, pOffset->subKey, pVg->vgId, offsetBuf, commitBuf, pEp->fqdn, pEp->port, index + 1,
|
||||
tmq->consumerId, pOffset->offset.subKey, pVg->vgId, offsetBuf, commitBuf, pEp->fqdn, pEp->port, index + 1,
|
||||
totalVgroups, pMsgSendInfo->requestId);
|
||||
|
||||
int64_t transporterId = 0;
|
||||
|
@ -551,7 +576,22 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* pCommitFp, void* userParam) {
|
||||
static SMqClientTopic* getTopicByName(tmq_t* tmq, const char* pTopicName) {
|
||||
int32_t numOfTopics = taosArrayGetSize(tmq->clientTopics);
|
||||
for (int32_t i = 0; i < numOfTopics; ++i) {
|
||||
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
|
||||
if (strcmp(pTopic->topicName, pTopicName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return pTopic;
|
||||
}
|
||||
|
||||
tscError("consumer:0x%" PRIx64 ", total:%d, failed to find topic:%s", tmq->consumerId, numOfTopics, pTopicName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, int32_t type, tmq_commit_cb* pCommitFp, void* userParam) {
|
||||
char* pTopicName = NULL;
|
||||
int32_t vgId = 0;
|
||||
int32_t code = 0;
|
||||
|
@ -593,15 +633,8 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
|
|||
|
||||
tscDebug("consumer:0x%" PRIx64 " do manual commit offset for %s, vgId:%d", tmq->consumerId, pTopicName, vgId);
|
||||
|
||||
int32_t i = 0;
|
||||
for (; i < numOfTopics; i++) {
|
||||
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
|
||||
if (strcmp(pTopic->topicName, pTopicName) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == numOfTopics) {
|
||||
SMqClientTopic* pTopic = getTopicByName(tmq, pTopicName);
|
||||
if (pTopic == NULL) {
|
||||
tscWarn("consumer:0x%" PRIx64 " failed to find the specified topic:%s, total topics:%d", tmq->consumerId,
|
||||
pTopicName, numOfTopics);
|
||||
taosMemoryFree(pParamSet);
|
||||
|
@ -609,8 +642,6 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
|
|||
return;
|
||||
}
|
||||
|
||||
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
|
||||
|
||||
int32_t j = 0;
|
||||
int32_t numOfVgroups = taosArrayGetSize(pTopic->vgs);
|
||||
for (j = 0; j < numOfVgroups; j++) {
|
||||
|
@ -629,8 +660,8 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
|
|||
}
|
||||
|
||||
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
|
||||
if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) {
|
||||
code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups);
|
||||
if (pVg->offsetInfo.currentOffset.type > 0 && !tOffsetEqual(&pVg->offsetInfo.currentOffset, &pVg->offsetInfo.committedOffset)) {
|
||||
code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups, type);
|
||||
|
||||
// failed to commit, callback user function directly.
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -670,20 +701,20 @@ static void asyncCommitAllOffsets(tmq_t* tmq, tmq_commit_cb* pCommitFp, void* us
|
|||
for (int32_t j = 0; j < numOfVgroups; j++) {
|
||||
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
|
||||
|
||||
if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) {
|
||||
int32_t code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups);
|
||||
if (pVg->offsetInfo.currentOffset.type > 0 && !tOffsetEqual(&pVg->offsetInfo.currentOffset, &pVg->offsetInfo.committedOffset)) {
|
||||
int32_t code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups, TDMT_VND_TMQ_COMMIT_OFFSET);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64 " failed, code:%s ordinal:%d/%d",
|
||||
tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->committedOffset.version, tstrerror(terrno),
|
||||
tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->offsetInfo.committedOffset.version, tstrerror(terrno),
|
||||
j + 1, numOfVgroups);
|
||||
continue;
|
||||
}
|
||||
|
||||
// update the offset value.
|
||||
pVg->committedOffset = pVg->currentOffset;
|
||||
pVg->offsetInfo.committedOffset = pVg->offsetInfo.currentOffset;
|
||||
} else {
|
||||
tscDebug("consumer:0x%" PRIx64 " topic:%s vgId:%d, no commit, current:%" PRId64 ", ordinal:%d/%d",
|
||||
tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->currentOffset.version, j + 1, numOfVgroups);
|
||||
tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->offsetInfo.currentOffset.version, j + 1, numOfVgroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1085,7 +1116,7 @@ _failed:
|
|||
}
|
||||
|
||||
int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
|
||||
const int32_t MAX_RETRY_COUNT = 120 * 2; // let's wait for 2 mins at most
|
||||
const int32_t MAX_RETRY_COUNT = 120 * 4; // let's wait for 4 mins at most
|
||||
const SArray* container = &topic_list->container;
|
||||
int32_t sz = taosArrayGetSize(container);
|
||||
void* buf = NULL;
|
||||
|
@ -1138,22 +1169,13 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
|
|||
goto FAIL;
|
||||
}
|
||||
|
||||
SMqSubscribeCbParam param = {
|
||||
.rspErr = 0,
|
||||
.refId = tmq->refId,
|
||||
.epoch = tmq->epoch,
|
||||
};
|
||||
|
||||
SMqSubscribeCbParam param = { .rspErr = 0, .refId = tmq->refId, .epoch = tmq->epoch };
|
||||
if (tsem_init(¶m.rspSem, 0, 0) != 0) {
|
||||
code = TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
sendInfo->msgInfo = (SDataBuf){
|
||||
.pData = buf,
|
||||
.len = tlen,
|
||||
.handle = NULL,
|
||||
};
|
||||
sendInfo->msgInfo = (SDataBuf){.pData = buf, .len = tlen, .handle = NULL};
|
||||
|
||||
sendInfo->requestId = generateRequestId();
|
||||
sendInfo->requestObjRefId = 0;
|
||||
|
@ -1181,7 +1203,7 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
|
|||
int32_t retryCnt = 0;
|
||||
while (TSDB_CODE_MND_CONSUMER_NOT_READY == doAskEp(tmq)) {
|
||||
if (retryCnt++ > MAX_RETRY_COUNT) {
|
||||
tscError("consumer:0x%" PRIx64 ", mnd not ready for subscribe, retry:%d in 500ms", tmq->consumerId, retryCnt);
|
||||
tscError("consumer:0x%" PRIx64 ", mnd not ready for subscribe, max retry reached:%d", tmq->consumerId, retryCnt);
|
||||
code = TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -1217,7 +1239,7 @@ void tmq_conf_set_auto_commit_cb(tmq_conf_t* conf, tmq_commit_cb* cb, void* para
|
|||
conf->commitCbUserParam = param;
|
||||
}
|
||||
|
||||
int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
||||
static int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
||||
SMqPollCbParam* pParam = (SMqPollCbParam*)param;
|
||||
|
||||
int64_t refId = pParam->refId;
|
||||
|
@ -1270,12 +1292,12 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
}
|
||||
|
||||
int32_t msgEpoch = ((SMqRspHead*)pMsg->pData)->epoch;
|
||||
int32_t tmqEpoch = atomic_load_32(&tmq->epoch);
|
||||
if (msgEpoch < tmqEpoch) {
|
||||
int32_t clientEpoch = atomic_load_32(&tmq->epoch);
|
||||
if (msgEpoch < clientEpoch) {
|
||||
// do not write into queue since updating epoch reset
|
||||
tscWarn("consumer:0x%" PRIx64
|
||||
" msg discard from vgId:%d since from earlier epoch, rsp epoch %d, current epoch %d, reqId:0x%" PRIx64,
|
||||
tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId);
|
||||
tmq->consumerId, vgId, msgEpoch, clientEpoch, requestId);
|
||||
|
||||
tsem_post(&tmq->rspSem);
|
||||
taosReleaseRef(tmqMgmt.rsetId, refId);
|
||||
|
@ -1285,9 +1307,9 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (msgEpoch != tmqEpoch) {
|
||||
if (msgEpoch != clientEpoch) {
|
||||
tscWarn("consumer:0x%" PRIx64 " mismatch rsp from vgId:%d, epoch %d, current epoch %d, reqId:0x%" PRIx64,
|
||||
tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId);
|
||||
tmq->consumerId, vgId, msgEpoch, clientEpoch, requestId);
|
||||
}
|
||||
|
||||
// handle meta rsp
|
||||
|
@ -1313,7 +1335,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
if (rspType == TMQ_MSG_TYPE__POLL_RSP) {
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
|
||||
tDecodeSMqDataRsp(&decoder, &pRspWrapper->dataRsp);
|
||||
tDecodeMqDataRsp(&decoder, &pRspWrapper->dataRsp);
|
||||
tDecoderClear(&decoder);
|
||||
memcpy(&pRspWrapper->dataRsp, pMsg->pData, sizeof(SMqRspHead));
|
||||
|
||||
|
@ -1324,7 +1346,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
} else if (rspType == TMQ_MSG_TYPE__POLL_META_RSP) {
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
|
||||
tDecodeSMqMetaRsp(&decoder, &pRspWrapper->metaRsp);
|
||||
tDecodeMqMetaRsp(&decoder, &pRspWrapper->metaRsp);
|
||||
tDecoderClear(&decoder);
|
||||
memcpy(&pRspWrapper->metaRsp, pMsg->pData, sizeof(SMqRspHead));
|
||||
} else if (rspType == TMQ_MSG_TYPE__TAOSX_RSP) {
|
||||
|
@ -1395,7 +1417,6 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
|
|||
|
||||
SMqClientVg clientVg = {
|
||||
.pollCnt = 0,
|
||||
.currentOffset = offsetNew,
|
||||
.vgId = pVgEp->vgId,
|
||||
.epSet = pVgEp->epSet,
|
||||
.vgStatus = TMQ_VG_STATUS__IDLE,
|
||||
|
@ -1404,6 +1425,10 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
|
|||
.numOfRows = numOfRows,
|
||||
};
|
||||
|
||||
clientVg.offsetInfo.currentOffset = offsetNew;
|
||||
clientVg.offsetInfo.committedOffset = offsetNew;
|
||||
clientVg.offsetInfo.walVerBegin = -1;
|
||||
clientVg.offsetInfo.walVerEnd = -1;
|
||||
taosArrayPush(pTopic->vgs, &clientVg);
|
||||
}
|
||||
}
|
||||
|
@ -1453,11 +1478,16 @@ static bool doUpdateLocalEp(tmq_t* tmq, int32_t epoch, const SMqAskEpRsp* pRsp)
|
|||
makeTopicVgroupKey(vgKey, pTopicCur->topicName, pVgCur->vgId);
|
||||
|
||||
char buf[80];
|
||||
<<<<<<< HEAD
|
||||
tFormatOffset(buf, 80, &pVgCur->currentOffset);
|
||||
tscDebug("consumer:0x%" PRIx64 ", doUpdateLocalEp current vg, epoch:%d vgId:%d vgKey:%s, offset:%s", tmq->consumerId, tmq->epoch, pVgCur->vgId,
|
||||
=======
|
||||
tFormatOffset(buf, 80, &pVgCur->offsetInfo.currentOffset);
|
||||
tscDebug("consumer:0x%" PRIx64 ", epoch:%d vgId:%d vgKey:%s, offset:%s", tmq->consumerId, epoch, pVgCur->vgId,
|
||||
>>>>>>> enh/3.0
|
||||
vgKey, buf);
|
||||
|
||||
SVgroupSaveInfo info = {.offset = pVgCur->currentOffset, .numOfRows = pVgCur->numOfRows};
|
||||
SVgroupSaveInfo info = {.offset = pVgCur->offsetInfo.currentOffset, .numOfRows = pVgCur->numOfRows};
|
||||
taosHashPut(pVgOffsetHashMap, vgKey, strlen(vgKey), &info, sizeof(SVgroupSaveInfo));
|
||||
}
|
||||
}
|
||||
|
@ -1533,8 +1563,8 @@ int32_t askEpCallbackFn(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
tscDebug("consumer:0x%" PRIx64 ", recv ep, msg epoch %d, current epoch %d, update local ep", tmq->consumerId,
|
||||
head->epoch, epoch);
|
||||
}
|
||||
pParam->pUserFn(tmq, code, pMsg, pParam->pParam);
|
||||
|
||||
pParam->pUserFn(tmq, code, pMsg, pParam->pParam);
|
||||
taosReleaseRef(tmqMgmt.rsetId, pParam->refId);
|
||||
|
||||
taosMemoryFree(pMsg->pEpSet);
|
||||
|
@ -1553,8 +1583,7 @@ void tmqBuildConsumeReqImpl(SMqPollReq* pReq, tmq_t* tmq, int64_t timeout, SMqCl
|
|||
pReq->consumerId = tmq->consumerId;
|
||||
pReq->timeout = timeout;
|
||||
pReq->epoch = tmq->epoch;
|
||||
/*pReq->currentOffset = reqOffset;*/
|
||||
pReq->reqOffset = pVg->currentOffset;
|
||||
pReq->reqOffset = pVg->offsetInfo.currentOffset;
|
||||
pReq->head.vgId = pVg->vgId;
|
||||
pReq->useSnapshot = tmq->useSnapshot;
|
||||
pReq->reqId = generateRequestId();
|
||||
|
@ -1652,7 +1681,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
|
|||
|
||||
pParam->refId = pTmq->refId;
|
||||
pParam->epoch = pTmq->epoch;
|
||||
pParam->pVg = pVg; // pVg may be released,fix it
|
||||
pParam->pVg = pVg;
|
||||
pParam->pTopic = pTopic;
|
||||
pParam->vgId = pVg->vgId;
|
||||
pParam->requestId = req.reqId;
|
||||
|
@ -1664,8 +1693,12 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
|
|||
return handleErrorBeforePoll(pVg, pTmq);
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
sendInfo->msgInfo = (SDataBuf){ .pData = msg, .len = msgSize, .handle = NULL };
|
||||
|
||||
=======
|
||||
sendInfo->msgInfo = (SDataBuf){.pData = msg, .len = msgSize, .handle = NULL};
|
||||
>>>>>>> enh/3.0
|
||||
sendInfo->requestId = req.reqId;
|
||||
sendInfo->requestObjRefId = 0;
|
||||
sendInfo->param = pParam;
|
||||
|
@ -1674,7 +1707,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
|
|||
|
||||
int64_t transporterId = 0;
|
||||
char offsetFormatBuf[80];
|
||||
tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pVg->currentOffset);
|
||||
tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pVg->offsetInfo.currentOffset);
|
||||
|
||||
tscDebug("consumer:0x%" PRIx64 " send poll to %s vgId:%d, epoch %d, req:%s, reqId:0x%" PRIx64, pTmq->consumerId,
|
||||
pTopic->topicName, pVg->vgId, pTmq->epoch, offsetFormatBuf, req.reqId);
|
||||
|
@ -1709,13 +1742,6 @@ static int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) {
|
|||
tscTrace("consumer:0x%" PRIx64 " epoch %d wait poll-rsp, skip vgId:%d skip cnt %d", tmq->consumerId, tmq->epoch,
|
||||
pVg->vgId, vgSkipCnt);
|
||||
continue;
|
||||
#if 0
|
||||
if (skipCnt < 30000) {
|
||||
continue;
|
||||
} else {
|
||||
tscDebug("consumer:0x%" PRIx64 ",skip vgId:%d skip too much reset", tmq->consumerId, pVg->vgId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
atomic_store_32(&pVg->vgSkipCnt, 0);
|
||||
|
@ -1790,11 +1816,23 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
pVg->epSet = *pollRspWrapper->pEpset;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
if(pDataRsp->rspOffset.type != 0){ // if offset is validate
|
||||
pVg->currentOffset = pDataRsp->rspOffset; // update the local offset value only for the returned values.
|
||||
}
|
||||
=======
|
||||
// update the local offset value only for the returned values.
|
||||
pVg->offsetInfo.currentOffset = pDataRsp->rspOffset;
|
||||
|
||||
// update the status
|
||||
>>>>>>> enh/3.0
|
||||
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
|
||||
|
||||
// update the valid wal version range
|
||||
pVg->offsetInfo.walVerBegin = pDataRsp->head.walsver;
|
||||
pVg->offsetInfo.walVerEnd = pDataRsp->head.walever;
|
||||
pVg->receiveInfo = true;
|
||||
|
||||
char buf[80];
|
||||
tFormatOffset(buf, 80, &pDataRsp->rspOffset);
|
||||
if (pDataRsp->blockNum == 0) {
|
||||
|
@ -1823,6 +1861,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
taosFreeQitem(pollRspWrapper);
|
||||
}
|
||||
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) {
|
||||
// todo handle the wal range and epset for each vgroup
|
||||
SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper;
|
||||
int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
|
||||
|
||||
|
@ -1830,9 +1869,13 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
|
||||
if (pollRspWrapper->metaRsp.head.epoch == consumerEpoch) {
|
||||
SMqClientVg* pVg = pollRspWrapper->vgHandle;
|
||||
<<<<<<< HEAD
|
||||
if(pollRspWrapper->metaRsp.rspOffset.type != 0){ // if offset is validate
|
||||
pVg->currentOffset = pollRspWrapper->metaRsp.rspOffset;
|
||||
}
|
||||
=======
|
||||
pVg->offsetInfo.currentOffset = pollRspWrapper->metaRsp.rspOffset;
|
||||
>>>>>>> enh/3.0
|
||||
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
|
||||
// build rsp
|
||||
SMqMetaRspObj* pRsp = tmqBuildMetaRspFromWrapper(pollRspWrapper);
|
||||
|
@ -1850,9 +1893,13 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
|
||||
if (pollRspWrapper->taosxRsp.head.epoch == consumerEpoch) {
|
||||
SMqClientVg* pVg = pollRspWrapper->vgHandle;
|
||||
<<<<<<< HEAD
|
||||
if(pollRspWrapper->taosxRsp.rspOffset.type != 0){ // if offset is validate
|
||||
pVg->currentOffset = pollRspWrapper->taosxRsp.rspOffset;
|
||||
}
|
||||
=======
|
||||
pVg->offsetInfo.currentOffset = pollRspWrapper->taosxRsp.rspOffset;
|
||||
>>>>>>> enh/3.0
|
||||
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
|
||||
|
||||
if (pollRspWrapper->taosxRsp.blockNum == 0) {
|
||||
|
@ -1878,7 +1925,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
|
|||
tmq->totalRows += numOfRows;
|
||||
|
||||
char buf[80];
|
||||
tFormatOffset(buf, 80, &pVg->currentOffset);
|
||||
tFormatOffset(buf, 80, &pVg->offsetInfo.currentOffset);
|
||||
tscDebug("consumer:0x%" PRIx64 " process taosx poll rsp, vgId:%d, offset:%s, blocks:%d, rows:%" PRId64
|
||||
", vg total:%" PRId64 " total:%" PRId64 " reqId:0x%" PRIx64,
|
||||
tmq->consumerId, pVg->vgId, buf, pollRspWrapper->dataRsp.blockNum, numOfRows, pVg->numOfRows,
|
||||
|
@ -1914,15 +1961,6 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
|
|||
tscDebug("consumer:0x%" PRIx64 " start to poll at %" PRId64 ", timeout:%" PRId64, tmq->consumerId, startTime,
|
||||
timeout);
|
||||
|
||||
#if 0
|
||||
tmqHandleAllDelayedTask(tmq);
|
||||
tmqPollImpl(tmq, timeout);
|
||||
rspObj = tmqHandleAllRsp(tmq, timeout, false);
|
||||
if (rspObj) {
|
||||
return (TAOS_RES*)rspObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// in no topic status, delayed task also need to be processed
|
||||
if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__INIT) {
|
||||
tscDebug("consumer:0x%" PRIx64 " poll return since consumer is init", tmq->consumerId);
|
||||
|
@ -2118,11 +2156,11 @@ void tmq_commit_async(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* cb, void*
|
|||
if (pRes == NULL) { // here needs to commit all offsets.
|
||||
asyncCommitAllOffsets(tmq, cb, param);
|
||||
} else { // only commit one offset
|
||||
asyncCommitOffset(tmq, pRes, cb, param);
|
||||
asyncCommitOffset(tmq, pRes, TDMT_VND_TMQ_COMMIT_OFFSET, cb, param);
|
||||
}
|
||||
}
|
||||
|
||||
static void commitCallBackFn(tmq_t *pTmq, int32_t code, void* param) {
|
||||
static void commitCallBackFn(tmq_t *UNUSED_PARAM(tmq), int32_t code, void* param) {
|
||||
SSyncCommitInfo* pInfo = (SSyncCommitInfo*) param;
|
||||
pInfo->code = code;
|
||||
tsem_post(&pInfo->sem);
|
||||
|
@ -2138,7 +2176,7 @@ int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* pRes) {
|
|||
if (pRes == NULL) {
|
||||
asyncCommitAllOffsets(tmq, commitCallBackFn, pInfo);
|
||||
} else {
|
||||
asyncCommitOffset(tmq, pRes, commitCallBackFn, pInfo);
|
||||
asyncCommitOffset(tmq, pRes, TDMT_VND_TMQ_COMMIT_OFFSET, commitCallBackFn, pInfo);
|
||||
}
|
||||
|
||||
tsem_wait(&pInfo->sem);
|
||||
|
@ -2322,4 +2360,272 @@ SReqResultInfo* tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4) {
|
|||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t tmqGetWalInfoCb(void* param, SDataBuf* pMsg, int32_t code) {
|
||||
SMqVgWalInfoParam* pParam = param;
|
||||
SMqVgCommon* pCommon = pParam->pCommon;
|
||||
|
||||
int32_t total = atomic_add_fetch_32(&pCommon->numOfRsp, 1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("consumer:0x%" PRIx64 " failed to get the wal info from vgId:%d for topic:%s", pCommon->consumerId,
|
||||
pParam->vgId, pCommon->pTopicName);
|
||||
pCommon->code = code;
|
||||
} else {
|
||||
SMqDataRsp rsp;
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
|
||||
tDecodeMqDataRsp(&decoder, &rsp);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SMqRspHead* pHead = pMsg->pData;
|
||||
|
||||
tmq_topic_assignment assignment = {.begin = pHead->walsver,
|
||||
.end = pHead->walever,
|
||||
.currentOffset = rsp.rspOffset.version,
|
||||
.vgId = pParam->vgId};
|
||||
|
||||
taosThreadMutexLock(&pCommon->mutex);
|
||||
taosArrayPush(pCommon->pList, &assignment);
|
||||
taosThreadMutexUnlock(&pCommon->mutex);
|
||||
}
|
||||
|
||||
if (total == pParam->totalReq) {
|
||||
tsem_post(&pCommon->rsp);
|
||||
}
|
||||
|
||||
taosMemoryFree(pParam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroyCommonInfo(SMqVgCommon* pCommon) {
|
||||
taosArrayDestroy(pCommon->pList);
|
||||
tsem_destroy(&pCommon->rsp);
|
||||
taosThreadMutexDestroy(&pCommon->mutex);
|
||||
taosMemoryFree(pCommon->pTopicName);
|
||||
taosMemoryFree(pCommon);
|
||||
}
|
||||
|
||||
int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_assignment** assignment,
|
||||
int32_t* numOfAssignment) {
|
||||
*numOfAssignment = 0;
|
||||
*assignment = NULL;
|
||||
|
||||
int32_t accId = tmq->pTscObj->acctId;
|
||||
char tname[128] = {0};
|
||||
sprintf(tname, "%d.%s", accId, pTopicName);
|
||||
|
||||
SMqClientTopic* pTopic = getTopicByName(tmq, tname);
|
||||
if (pTopic == NULL) {
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
// in case of snapshot is opened, no valid offset will return
|
||||
*numOfAssignment = taosArrayGetSize(pTopic->vgs);
|
||||
|
||||
*assignment = taosMemoryCalloc(*numOfAssignment, sizeof(tmq_topic_assignment));
|
||||
if (*assignment == NULL) {
|
||||
tscError("consumer:0x%" PRIx64 " failed to malloc buffer, size:%" PRIzu, tmq->consumerId,
|
||||
(*numOfAssignment) * sizeof(tmq_topic_assignment));
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
bool needFetch = false;
|
||||
|
||||
for (int32_t j = 0; j < (*numOfAssignment); ++j) {
|
||||
SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, j);
|
||||
if (!pClientVg->receiveInfo) {
|
||||
needFetch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
tmq_topic_assignment* pAssignment = &(*assignment)[j];
|
||||
if (pClientVg->offsetInfo.currentOffset.type == TMQ_OFFSET__LOG) {
|
||||
pAssignment->currentOffset = pClientVg->offsetInfo.currentOffset.version;
|
||||
} else {
|
||||
pAssignment->currentOffset = 0;
|
||||
}
|
||||
|
||||
pAssignment->begin = pClientVg->offsetInfo.walVerBegin;
|
||||
pAssignment->end = pClientVg->offsetInfo.walVerEnd;
|
||||
pAssignment->vgId = pClientVg->vgId;
|
||||
}
|
||||
|
||||
if (needFetch) {
|
||||
SMqVgCommon* pCommon = taosMemoryCalloc(1, sizeof(SMqVgCommon));
|
||||
if (pCommon == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
pCommon->pList= taosArrayInit(4, sizeof(tmq_topic_assignment));
|
||||
tsem_init(&pCommon->rsp, 0, 0);
|
||||
taosThreadMutexInit(&pCommon->mutex, 0);
|
||||
pCommon->pTopicName = taosStrdup(pTopic->topicName);
|
||||
pCommon->consumerId = tmq->consumerId;
|
||||
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
for (int32_t i = 0; i < (*numOfAssignment); ++i) {
|
||||
SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, i);
|
||||
|
||||
SMqVgWalInfoParam* pParam = taosMemoryMalloc(sizeof(SMqVgWalInfoParam));
|
||||
if (pParam == NULL) {
|
||||
destroyCommonInfo(pCommon);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
pParam->epoch = tmq->epoch;
|
||||
pParam->vgId = pClientVg->vgId;
|
||||
pParam->totalReq = *numOfAssignment;
|
||||
pParam->pCommon = pCommon;
|
||||
|
||||
SMqPollReq req = {0};
|
||||
tmqBuildConsumeReqImpl(&req, tmq, 10, pTopic, pClientVg);
|
||||
|
||||
int32_t msgSize = tSerializeSMqPollReq(NULL, 0, &req);
|
||||
if (msgSize < 0) {
|
||||
taosMemoryFree(pParam);
|
||||
destroyCommonInfo(pCommon);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
char* msg = taosMemoryCalloc(1, msgSize);
|
||||
if (NULL == msg) {
|
||||
taosMemoryFree(pParam);
|
||||
destroyCommonInfo(pCommon);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
if (tSerializeSMqPollReq(msg, msgSize, &req) < 0) {
|
||||
taosMemoryFree(msg);
|
||||
taosMemoryFree(pParam);
|
||||
destroyCommonInfo(pCommon);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
|
||||
if (sendInfo == NULL) {
|
||||
taosMemoryFree(pParam);
|
||||
taosMemoryFree(msg);
|
||||
destroyCommonInfo(pCommon);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
sendInfo->msgInfo = (SDataBuf){.pData = msg, .len = msgSize, .handle = NULL};
|
||||
sendInfo->requestId = req.reqId;
|
||||
sendInfo->requestObjRefId = 0;
|
||||
sendInfo->param = pParam;
|
||||
sendInfo->fp = tmqGetWalInfoCb;
|
||||
sendInfo->msgType = TDMT_VND_TMQ_VG_WALINFO;
|
||||
|
||||
int64_t transporterId = 0;
|
||||
char offsetFormatBuf[80];
|
||||
tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pClientVg->offsetInfo.currentOffset);
|
||||
|
||||
tscDebug("consumer:0x%" PRIx64 " %s retrieve wal info vgId:%d, epoch %d, req:%s, reqId:0x%" PRIx64,
|
||||
tmq->consumerId, pTopic->topicName, pClientVg->vgId, tmq->epoch, offsetFormatBuf, req.reqId);
|
||||
asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pClientVg->epSet, &transporterId, sendInfo);
|
||||
}
|
||||
|
||||
tsem_wait(&pCommon->rsp);
|
||||
int32_t code = pCommon->code;
|
||||
|
||||
terrno = code;
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
taosMemoryFree(*assignment);
|
||||
*assignment = NULL;
|
||||
*numOfAssignment = 0;
|
||||
} else {
|
||||
int32_t num = taosArrayGetSize(pCommon->pList);
|
||||
for(int32_t i = 0; i < num; ++i) {
|
||||
(*assignment)[i] = *(tmq_topic_assignment*)taosArrayGet(pCommon->pList, i);
|
||||
}
|
||||
*numOfAssignment = num;
|
||||
}
|
||||
|
||||
destroyCommonInfo(pCommon);
|
||||
return code;
|
||||
} else {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tmq_offset_seek(tmq_t* tmq, const char* pTopicName, int32_t vgId, int64_t offset) {
|
||||
if (tmq == NULL) {
|
||||
tscError("invalid tmq handle, null");
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
int32_t accId = tmq->pTscObj->acctId;
|
||||
char tname[128] = {0};
|
||||
sprintf(tname, "%d.%s", accId, pTopicName);
|
||||
|
||||
SMqClientTopic* pTopic = getTopicByName(tmq, tname);
|
||||
if (pTopic == NULL) {
|
||||
tscError("consumer:0x%" PRIx64 " invalid topic name:%s", tmq->consumerId, pTopicName);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
SMqClientVg* pVg = NULL;
|
||||
int32_t numOfVgs = taosArrayGetSize(pTopic->vgs);
|
||||
for (int32_t i = 0; i < numOfVgs; ++i) {
|
||||
SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, i);
|
||||
if (pClientVg->vgId == vgId) {
|
||||
pVg = pClientVg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pVg == NULL) {
|
||||
tscError("consumer:0x%" PRIx64 " invalid vgroup id:%d", tmq->consumerId, vgId);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
SVgOffsetInfo* pOffsetInfo = &pVg->offsetInfo;
|
||||
|
||||
int32_t type = pOffsetInfo->currentOffset.type;
|
||||
if (type != TMQ_OFFSET__LOG) {
|
||||
tscError("consumer:0x%" PRIx64 " offset type:%d not wal version, seek not allowed", tmq->consumerId, type);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
if (offset < pOffsetInfo->walVerBegin || offset > pOffsetInfo->walVerEnd) {
|
||||
tscError("consumer:0x%" PRIx64 " invalid seek params, offset:%" PRId64, tmq->consumerId, offset);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
// update the offset, and then commit to vnode
|
||||
if (pOffsetInfo->currentOffset.type == TMQ_OFFSET__LOG) {
|
||||
pOffsetInfo->currentOffset.version = offset;
|
||||
pOffsetInfo->committedOffset.version = INT64_MIN;
|
||||
}
|
||||
|
||||
SMqRspObj rspObj = {.resType = RES_TYPE__TMQ, .vgId = pVg->vgId};
|
||||
tstrncpy(rspObj.topic, tname, tListLen(rspObj.topic));
|
||||
|
||||
tscDebug("consumer:0x%" PRIx64 " seek to %" PRId64 " on vgId:%d", tmq->consumerId, offset, pVg->vgId);
|
||||
|
||||
SSyncCommitInfo* pInfo = taosMemoryMalloc(sizeof(SSyncCommitInfo));
|
||||
if (pInfo == NULL) {
|
||||
tscError("consumer:0x%"PRIx64" failed to prepare seek operation", tmq->consumerId);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
tsem_init(&pInfo->sem, 0, 0);
|
||||
pInfo->code = 0;
|
||||
|
||||
asyncCommitOffset(tmq, &rspObj, TDMT_VND_TMQ_SEEK_TO_OFFSET, commitCallBackFn, pInfo);
|
||||
|
||||
tsem_wait(&pInfo->sem);
|
||||
int32_t code = pInfo->code;
|
||||
|
||||
tsem_destroy(&pInfo->sem);
|
||||
taosMemoryFree(pInfo);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("consumer:0x%" PRIx64 " failed to send seek to vgId:%d, code:%s", tmq->consumerId, pVg->vgId,
|
||||
tstrerror(code));
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
|
@ -30,6 +30,27 @@
|
|||
#include "taos.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void printSubResults(void* pRes, int32_t* totalRows) {
|
||||
char buf[1024];
|
||||
|
||||
while (1) {
|
||||
TAOS_ROW row = taos_fetch_row(pRes);
|
||||
if (row == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
TAOS_FIELD* fields = taos_fetch_fields(pRes);
|
||||
int32_t numOfFields = taos_field_count(pRes);
|
||||
int32_t precision = taos_result_precision(pRes);
|
||||
taos_print_row(buf, row, fields, numOfFields);
|
||||
*totalRows += 1;
|
||||
printf("precision: %d, row content: %s\n", precision, buf);
|
||||
}
|
||||
|
||||
// taos_free_result(pRes);
|
||||
}
|
||||
|
||||
void showDB(TAOS* pConn) {
|
||||
TAOS_RES* pRes = taos_query(pConn, "show databases");
|
||||
TAOS_ROW pRow = NULL;
|
||||
|
@ -112,7 +133,7 @@ void createNewTable(TAOS* pConn, int32_t index) {
|
|||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
for (int32_t i = 0; i < 100; i += 20) {
|
||||
for (int32_t i = 0; i < 10000; i += 20) {
|
||||
char sql[1024] = {0};
|
||||
sprintf(sql,
|
||||
"insert into tu%d values(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
|
||||
|
@ -803,7 +824,7 @@ TEST(clientCase, projection_query_tables) {
|
|||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
for (int32_t i = 0; i < 10000; ++i) {
|
||||
for (int32_t i = 0; i < 1; ++i) {
|
||||
printf("create table :%d\n", i);
|
||||
createNewTable(pConn, i);
|
||||
}
|
||||
|
@ -990,7 +1011,7 @@ TEST(clientCase, sub_db_test) {
|
|||
tmq_conf_set(conf, "td.connect.user", "root");
|
||||
tmq_conf_set(conf, "td.connect.pass", "taosdata");
|
||||
tmq_conf_set(conf, "auto.offset.reset", "earliest");
|
||||
tmq_conf_set(conf, "experimental.snapshot.enable", "true");
|
||||
tmq_conf_set(conf, "experimental.snapshot.enable", "false");
|
||||
tmq_conf_set(conf, "msg.with.table.name", "true");
|
||||
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
|
||||
|
||||
|
@ -1000,7 +1021,7 @@ TEST(clientCase, sub_db_test) {
|
|||
// 创建订阅 topics 列表
|
||||
tmq_list_t* topicList = tmq_list_new();
|
||||
tmq_list_append(topicList, "topic_t1");
|
||||
tmq_list_append(topicList, "topic_s2");
|
||||
// tmq_list_append(topicList, "topic_s2");
|
||||
|
||||
// 启动订阅
|
||||
tmq_subscribe(tmq, topicList);
|
||||
|
@ -1059,6 +1080,7 @@ TEST(clientCase, sub_tb_test) {
|
|||
ASSERT_NE(pConn, nullptr);
|
||||
|
||||
tmq_conf_t* conf = tmq_conf_new();
|
||||
<<<<<<< HEAD
|
||||
|
||||
int32_t ts = taosGetTimestampMs()%INT32_MAX;
|
||||
char consumerGroupid[128] = {0};
|
||||
|
@ -1067,6 +1089,11 @@ TEST(clientCase, sub_tb_test) {
|
|||
tmq_conf_set(conf, "enable.auto.commit", "true");
|
||||
tmq_conf_set(conf, "auto.commit.interval.ms", "2000");
|
||||
tmq_conf_set(conf, "group.id", consumerGroupid);
|
||||
=======
|
||||
tmq_conf_set(conf, "enable.auto.commit", "false");
|
||||
tmq_conf_set(conf, "auto.commit.interval.ms", "1000");
|
||||
tmq_conf_set(conf, "group.id", "cgrpName1024");
|
||||
>>>>>>> enh/3.0
|
||||
tmq_conf_set(conf, "td.connect.user", "root");
|
||||
tmq_conf_set(conf, "td.connect.pass", "taosdata");
|
||||
tmq_conf_set(conf, "auto.offset.reset", "earliest");
|
||||
|
@ -1083,7 +1110,6 @@ TEST(clientCase, sub_tb_test) {
|
|||
|
||||
// 启动订阅
|
||||
tmq_subscribe(tmq, topicList);
|
||||
|
||||
tmq_list_destroy(topicList);
|
||||
|
||||
TAOS_FIELD* fields = NULL;
|
||||
|
@ -1095,11 +1121,27 @@ TEST(clientCase, sub_tb_test) {
|
|||
|
||||
int32_t count = 0;
|
||||
|
||||
tmq_topic_assignment* pAssign = NULL;
|
||||
int32_t numOfAssign = 0;
|
||||
|
||||
int32_t code = tmq_get_topic_assignment(tmq, "topic_t1", &pAssign, &numOfAssign);
|
||||
if (code != 0) {
|
||||
printf("error occurs:%s\n", tmq_err2str(code));
|
||||
tmq_consumer_close(tmq);
|
||||
taos_close(pConn);
|
||||
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout);
|
||||
<<<<<<< HEAD
|
||||
if (pRes) {
|
||||
char buf[128];
|
||||
|
||||
=======
|
||||
if (pRes != NULL) {
|
||||
>>>>>>> enh/3.0
|
||||
const char* topicName = tmq_get_topic_name(pRes);
|
||||
// const char* dbName = tmq_get_db_name(pRes);
|
||||
// int32_t vgroupId = tmq_get_vgroup_id(pRes);
|
||||
|
@ -1108,6 +1150,7 @@ TEST(clientCase, sub_tb_test) {
|
|||
// printf("db: %s\n", dbName);
|
||||
// printf("vgroup id: %d\n", vgroupId);
|
||||
|
||||
<<<<<<< HEAD
|
||||
while (1) {
|
||||
TAOS_ROW row = taos_fetch_row(pRes);
|
||||
if (row == NULL) {
|
||||
|
@ -1124,9 +1167,20 @@ TEST(clientCase, sub_tb_test) {
|
|||
}
|
||||
|
||||
taos_free_result(pRes);
|
||||
=======
|
||||
printSubResults(pRes, &totalRows);
|
||||
>>>>>>> enh/3.0
|
||||
} else {
|
||||
break;
|
||||
// tmq_offset_seek(tmq, "topic_t1", pAssign[0].vgroupHandle, pAssign[0].begin);
|
||||
// break;
|
||||
}
|
||||
|
||||
tmq_commit_sync(tmq, pRes);
|
||||
if (pRes != NULL) {
|
||||
taos_free_result(pRes);
|
||||
}
|
||||
|
||||
tmq_offset_seek(tmq, "topic_t1", pAssign[0].vgId, pAssign[0].begin);
|
||||
}
|
||||
|
||||
tmq_consumer_close(tmq);
|
||||
|
|
|
@ -500,7 +500,7 @@ int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal)
|
|||
break;
|
||||
default:
|
||||
ASSERTS(0, "invalid row format");
|
||||
return TSDB_CODE_IVLD_DATA_FMT;
|
||||
return TSDB_CODE_INVALID_DATA_FMT;
|
||||
}
|
||||
|
||||
if (bv == BIT_FLG_NONE) {
|
||||
|
@ -755,7 +755,7 @@ SColVal *tRowIterNext(SRowIter *pIter) {
|
|||
}
|
||||
|
||||
if (pIter->pRow->flag == HAS_NULL) {
|
||||
pIter->cv = COL_VAL_NULL(pTColumn->type, pTColumn->colId);
|
||||
pIter->cv = COL_VAL_NULL(pTColumn->colId, pTColumn->type);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
|
@ -938,7 +938,7 @@ static int32_t tRowTupleUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *
|
|||
break;
|
||||
default:
|
||||
ASSERTS(0, "Invalid row flag");
|
||||
return TSDB_CODE_IVLD_DATA_FMT;
|
||||
return TSDB_CODE_INVALID_DATA_FMT;
|
||||
}
|
||||
|
||||
while (pColData) {
|
||||
|
@ -963,7 +963,7 @@ static int32_t tRowTupleUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *
|
|||
break;
|
||||
default:
|
||||
ASSERTS(0, "Invalid row flag");
|
||||
return TSDB_CODE_IVLD_DATA_FMT;
|
||||
return TSDB_CODE_INVALID_DATA_FMT;
|
||||
}
|
||||
|
||||
if (bv == BIT_FLG_NONE) {
|
||||
|
@ -1054,7 +1054,7 @@ static int32_t tRowKVUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aCo
|
|||
pData = pv + ((uint32_t *)pKVIdx->idx)[iCol];
|
||||
} else {
|
||||
ASSERTS(0, "Invalid KV row format");
|
||||
return TSDB_CODE_IVLD_DATA_FMT;
|
||||
return TSDB_CODE_INVALID_DATA_FMT;
|
||||
}
|
||||
|
||||
int16_t cid;
|
||||
|
@ -2441,7 +2441,7 @@ _exit:
|
|||
int32_t tColDataAddValueByDataBlock(SColData *pColData, int8_t type, int32_t bytes, int32_t nRows, char *lengthOrbitmap,
|
||||
char *data) {
|
||||
int32_t code = 0;
|
||||
if(data == NULL){
|
||||
if (data == NULL) {
|
||||
for (int32_t i = 0; i < nRows; ++i) {
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0);
|
||||
}
|
||||
|
@ -2455,8 +2455,9 @@ int32_t tColDataAddValueByDataBlock(SColData *pColData, int8_t type, int32_t byt
|
|||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0);
|
||||
if (code) goto _exit;
|
||||
} else {
|
||||
if(ASSERT(varDataTLen(data + offset) <= bytes)){
|
||||
uError("var data length invalid, varDataTLen(data + offset):%d <= bytes:%d", (int)varDataTLen(data + offset), bytes);
|
||||
if (ASSERT(varDataTLen(data + offset) <= bytes)) {
|
||||
uError("var data length invalid, varDataTLen(data + offset):%d <= bytes:%d", (int)varDataTLen(data + offset),
|
||||
bytes);
|
||||
code = TSDB_CODE_INVALID_PARA;
|
||||
goto _exit;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,10 @@ int32_t tsRedirectFactor = 2;
|
|||
int32_t tsRedirectMaxPeriod = 1000;
|
||||
int32_t tsMaxRetryWaitTime = 10000;
|
||||
bool tsUseAdapter = false;
|
||||
int32_t tsSlowLogThreshold = 3; // seconds
|
||||
int32_t tsSlowLogScope = SLOW_LOG_TYPE_ALL;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -347,6 +351,8 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
|
|||
if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1;
|
||||
if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, true) != 0) return -1;
|
||||
if (cfgAddInt64(pCfg, "queryMaxConcurrentTables", tsQueryMaxConcurrentTables, INT64_MIN, INT64_MAX, 1) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "slowLogThreshold", tsSlowLogThreshold, 0, INT32_MAX, true) != 0) return -1;
|
||||
if (cfgAddString(pCfg, "slowLogScope", "", true) != 0) return -1;
|
||||
|
||||
tsNumOfRpcThreads = tsNumOfCores / 2;
|
||||
tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 2, TSDB_MAX_RPC_THREADS);
|
||||
|
@ -696,6 +702,42 @@ static void taosSetServerLogCfg(SConfig *pCfg) {
|
|||
metaDebugFlag = cfgGetItem(pCfg, "metaDebugFlag")->i32;
|
||||
}
|
||||
|
||||
static int32_t taosSetSlowLogScope(char *pScope) {
|
||||
if (NULL == pScope || 0 == strlen(pScope)) {
|
||||
tsSlowLogScope = SLOW_LOG_TYPE_ALL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(pScope, "all")) {
|
||||
tsSlowLogScope = SLOW_LOG_TYPE_ALL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(pScope, "query")) {
|
||||
tsSlowLogScope = SLOW_LOG_TYPE_QUERY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(pScope, "insert")) {
|
||||
tsSlowLogScope = SLOW_LOG_TYPE_INSERT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(pScope, "others")) {
|
||||
tsSlowLogScope = SLOW_LOG_TYPE_OTHERS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(pScope, "none")) {
|
||||
tsSlowLogScope = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uError("Invalid slowLog scope value:%s", pScope);
|
||||
terrno = TSDB_CODE_INVALID_CFG_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t taosSetClientCfg(SConfig *pCfg) {
|
||||
tstrncpy(tsLocalFqdn, cfgGetItem(pCfg, "fqdn")->str, TSDB_FQDN_LEN);
|
||||
tsServerPort = (uint16_t)cfgGetItem(pCfg, "serverPort")->i32;
|
||||
|
@ -746,6 +788,10 @@ static int32_t taosSetClientCfg(SConfig *pCfg) {
|
|||
tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval;
|
||||
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
|
||||
tsQueryMaxConcurrentTables = cfgGetItem(pCfg, "queryMaxConcurrentTables")->i64;
|
||||
tsSlowLogThreshold = cfgGetItem(pCfg, "slowLogThreshold")->i32;
|
||||
if (taosSetSlowLogScope(cfgGetItem(pCfg, "slowLogScope")->str)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tsMaxRetryWaitTime = cfgGetItem(pCfg, "maxRetryWaitTime")->i32;
|
||||
|
||||
|
@ -1162,6 +1208,12 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
|
|||
sDebugFlag = cfgGetItem(pCfg, "sDebugFlag")->i32;
|
||||
} else if (strcasecmp("smaDebugFlag", name) == 0) {
|
||||
smaDebugFlag = cfgGetItem(pCfg, "smaDebugFlag")->i32;
|
||||
} else if (strcasecmp("slowLogThreshold", name) == 0) {
|
||||
tsSlowLogThreshold = cfgGetItem(pCfg, "slowLogThreshold")->i32;
|
||||
} else if (strcasecmp("slowLogScope", name) == 0) {
|
||||
if (taosSetSlowLogScope(cfgGetItem(pCfg, "slowLogScope")->str)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2937,6 +2937,59 @@ void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp *pRsp) {
|
|||
taosArrayDestroy(pRsp->pArray);
|
||||
}
|
||||
|
||||
int32_t tSerializeSUserPassBatchRsp(void *buf, int32_t bufLen, SUserPassBatchRsp *pRsp) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
if (tStartEncode(&encoder) < 0) return -1;
|
||||
|
||||
int32_t numOfBatch = taosArrayGetSize(pRsp->pArray);
|
||||
if (tEncodeI32(&encoder, numOfBatch) < 0) return -1;
|
||||
for (int32_t i = 0; i < numOfBatch; ++i) {
|
||||
SGetUserPassRsp *pUserPassRsp = taosArrayGet(pRsp->pArray, i);
|
||||
if (tEncodeCStr(&encoder, pUserPassRsp->user) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pUserPassRsp->version) < 0) return -1;
|
||||
}
|
||||
tEndEncode(&encoder);
|
||||
|
||||
int32_t tlen = encoder.pos;
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
int32_t tDeserializeSUserPassBatchRsp(void *buf, int32_t bufLen, SUserPassBatchRsp *pRsp) {
|
||||
SDecoder decoder = {0};
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
if (tStartDecode(&decoder) < 0) return -1;
|
||||
|
||||
int32_t numOfBatch = taosArrayGetSize(pRsp->pArray);
|
||||
if (tDecodeI32(&decoder, &numOfBatch) < 0) return -1;
|
||||
|
||||
pRsp->pArray = taosArrayInit(numOfBatch, sizeof(SGetUserPassRsp));
|
||||
if (pRsp->pArray == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfBatch; ++i) {
|
||||
SGetUserPassRsp rsp = {0};
|
||||
if (tDecodeCStrTo(&decoder, rsp.user) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &rsp.version) < 0) return -1;
|
||||
taosArrayPush(pRsp->pArray, &rsp);
|
||||
}
|
||||
tEndDecode(&decoder);
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tFreeSUserPassBatchRsp(SUserPassBatchRsp *pRsp) {
|
||||
if(pRsp) {
|
||||
taosArrayDestroy(pRsp->pArray);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tSerializeSDbCfgReq(void *buf, int32_t bufLen, SDbCfgReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
@ -3977,6 +4030,7 @@ int32_t tSerializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
|
|||
if (tEncodeI32(&encoder, pRsp->svrTimestamp) < 0) return -1;
|
||||
if (tEncodeCStr(&encoder, pRsp->sVer) < 0) return -1;
|
||||
if (tEncodeCStr(&encoder, pRsp->sDetailVer) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pRsp->passVer) < 0) return -1;
|
||||
tEndEncode(&encoder);
|
||||
|
||||
int32_t tlen = encoder.pos;
|
||||
|
@ -4000,6 +4054,13 @@ int32_t tDeserializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
|
|||
if (tDecodeI32(&decoder, &pRsp->svrTimestamp) < 0) return -1;
|
||||
if (tDecodeCStrTo(&decoder, pRsp->sVer) < 0) return -1;
|
||||
if (tDecodeCStrTo(&decoder, pRsp->sDetailVer) < 0) return -1;
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
if (tDecodeI32(&decoder, &pRsp->passVer) < 0) return -1;
|
||||
} else {
|
||||
pRsp->passVer = 0;
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
|
@ -4130,6 +4191,12 @@ int32_t tSerializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *pR
|
|||
for (int32_t i = 0; i < 8; ++i) {
|
||||
if (tEncodeI64(&encoder, pReq->reserved[i]) < 0) return -1;
|
||||
}
|
||||
if (tEncodeI8(&encoder, pReq->learnerReplica) < 0) return -1;
|
||||
if (tEncodeI8(&encoder, pReq->learnerSelfIndex) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tEncodeSReplica(&encoder, pReplica) < 0) return -1;
|
||||
}
|
||||
|
||||
tEndEncode(&encoder);
|
||||
|
||||
|
@ -4208,6 +4275,14 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *
|
|||
for (int32_t i = 0; i < 8; ++i) {
|
||||
if (tDecodeI64(&decoder, &pReq->reserved[i]) < 0) return -1;
|
||||
}
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
if (tDecodeI8(&decoder, &pReq->learnerReplica) < 0) return -1;
|
||||
if (tDecodeI8(&decoder, &pReq->learnerSelfIndex) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tDecodeSReplica(&decoder, pReplica) < 0) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
tDecoderClear(&decoder);
|
||||
|
@ -4434,6 +4509,12 @@ int32_t tSerializeSAlterVnodeReplicaReq(void *buf, int32_t bufLen, SAlterVnodeRe
|
|||
for (int32_t i = 0; i < 8; ++i) {
|
||||
if (tEncodeI64(&encoder, pReq->reserved[i]) < 0) return -1;
|
||||
}
|
||||
if (tEncodeI8(&encoder, pReq->learnerSelfIndex) < 0) return -1;
|
||||
if (tEncodeI8(&encoder, pReq->learnerReplica) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tEncodeSReplica(&encoder, pReplica) < 0) return -1;
|
||||
}
|
||||
tEndEncode(&encoder);
|
||||
|
||||
int32_t tlen = encoder.pos;
|
||||
|
@ -4457,7 +4538,15 @@ int32_t tDeserializeSAlterVnodeReplicaReq(void *buf, int32_t bufLen, SAlterVnode
|
|||
for (int32_t i = 0; i < 8; ++i) {
|
||||
if (tDecodeI64(&decoder, &pReq->reserved[i]) < 0) return -1;
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
if (tDecodeI8(&decoder, &pReq->learnerSelfIndex) < 0) return -1;
|
||||
if (tDecodeI8(&decoder, &pReq->learnerReplica) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tDecodeSReplica(&decoder, pReplica) < 0) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
tDecoderClear(&decoder);
|
||||
return 0;
|
||||
|
@ -4768,6 +4857,12 @@ int32_t tSerializeSDCreateMnodeReq(void *buf, int32_t bufLen, SDCreateMnodeReq *
|
|||
SReplica *pReplica = &pReq->replicas[i];
|
||||
if (tEncodeSReplica(&encoder, pReplica) < 0) return -1;
|
||||
}
|
||||
if (tEncodeI8(&encoder, pReq->learnerReplica) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tEncodeSReplica(&encoder, pReplica) < 0) return -1;
|
||||
}
|
||||
if (tEncodeI64(&encoder, pReq->lastIndex) < 0) return -1;
|
||||
tEndEncode(&encoder);
|
||||
|
||||
int32_t tlen = encoder.pos;
|
||||
|
@ -4785,6 +4880,14 @@ int32_t tDeserializeSDCreateMnodeReq(void *buf, int32_t bufLen, SDCreateMnodeReq
|
|||
SReplica *pReplica = &pReq->replicas[i];
|
||||
if (tDecodeSReplica(&decoder, pReplica) < 0) return -1;
|
||||
}
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
if (tDecodeI8(&decoder, &pReq->learnerReplica) < 0) return -1;
|
||||
for (int32_t i = 0; i < TSDB_MAX_LEARNER_REPLICA; ++i) {
|
||||
SReplica *pReplica = &pReq->learnerReplicas[i];
|
||||
if (tDecodeSReplica(&decoder, pReplica) < 0) return -1;
|
||||
}
|
||||
if (tDecodeI64(&decoder, &pReq->lastIndex) < 0) return -1;
|
||||
}
|
||||
tEndDecode(&decoder);
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
|
@ -6906,6 +7009,18 @@ int32_t tDecodeSTqOffset(SDecoder *pDecoder, STqOffset *pOffset) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tEncodeMqVgOffset(SEncoder* pEncoder, const SMqVgOffset* pOffset) {
|
||||
if (tEncodeSTqOffset(pEncoder, &pOffset->offset) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pOffset->consumerId) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tDecodeMqVgOffset(SDecoder* pDecoder, SMqVgOffset* pOffset) {
|
||||
if (tDecodeSTqOffset(pDecoder, &pOffset->offset) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pOffset->consumerId) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tEncodeSTqCheckInfo(SEncoder *pEncoder, const STqCheckInfo *pInfo) {
|
||||
if (tEncodeCStr(pEncoder, pInfo->topic) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pInfo->ntbUid) < 0) return -1;
|
||||
|
@ -6970,21 +7085,21 @@ int32_t tDecodeDeleteRes(SDecoder *pCoder, SDeleteRes *pRes) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tEncodeSMqMetaRsp(SEncoder *pEncoder, const SMqMetaRsp *pRsp) {
|
||||
int32_t tEncodeMqMetaRsp(SEncoder *pEncoder, const SMqMetaRsp *pRsp) {
|
||||
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->rspOffset) < 0) return -1;
|
||||
if (tEncodeI16(pEncoder, pRsp->resMsgType)) return -1;
|
||||
if (tEncodeBinary(pEncoder, pRsp->metaRsp, pRsp->metaRspLen)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tDecodeSMqMetaRsp(SDecoder *pDecoder, SMqMetaRsp *pRsp) {
|
||||
int32_t tDecodeMqMetaRsp(SDecoder *pDecoder, SMqMetaRsp *pRsp) {
|
||||
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->rspOffset) < 0) return -1;
|
||||
if (tDecodeI16(pDecoder, &pRsp->resMsgType) < 0) return -1;
|
||||
if (tDecodeBinaryAlloc(pDecoder, &pRsp->metaRsp, (uint64_t *)&pRsp->metaRspLen) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tEncodeSMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
|
||||
int32_t tEncodeMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
|
||||
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->reqOffset) < 0) return -1;
|
||||
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->rspOffset) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pRsp->blockNum) < 0) return -1;
|
||||
|
@ -7009,7 +7124,7 @@ int32_t tEncodeSMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
|
||||
int32_t tDecodeMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
|
||||
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->reqOffset) < 0) return -1;
|
||||
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->rspOffset) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pRsp->blockNum) < 0) return -1;
|
||||
|
@ -7054,7 +7169,7 @@ int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tDeleteSMqDataRsp(SMqDataRsp *pRsp) {
|
||||
void tDeleteMqDataRsp(SMqDataRsp *pRsp) {
|
||||
pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen);
|
||||
taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree);
|
||||
pRsp->blockData = NULL;
|
||||
|
@ -7155,8 +7270,7 @@ int32_t tDecodeSTaosxRsp(SDecoder *pDecoder, STaosxRsp *pRsp) {
|
|||
}
|
||||
|
||||
void tDeleteSTaosxRsp(STaosxRsp *pRsp) {
|
||||
taosArrayDestroy(pRsp->blockDataLen);
|
||||
pRsp->blockDataLen = NULL;
|
||||
pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen);
|
||||
taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree);
|
||||
pRsp->blockData = NULL;
|
||||
taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSchemaWrapper);
|
||||
|
@ -7164,8 +7278,7 @@ void tDeleteSTaosxRsp(STaosxRsp *pRsp) {
|
|||
taosArrayDestroyP(pRsp->blockTbName, (FDelete)taosMemoryFree);
|
||||
pRsp->blockTbName = NULL;
|
||||
|
||||
taosArrayDestroy(pRsp->createTableLen);
|
||||
pRsp->createTableLen = NULL;
|
||||
pRsp->createTableLen = taosArrayDestroy(pRsp->createTableLen);
|
||||
taosArrayDestroyP(pRsp->createTableReq, (FDelete)taosMemoryFree);
|
||||
pRsp->createTableReq = NULL;
|
||||
}
|
||||
|
@ -7539,6 +7652,7 @@ void tDestroySSubmitRsp2(SSubmitRsp2 *pRsp, int32_t flag) {
|
|||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
int32_t tSerializeSMPauseStreamReq(void *buf, int32_t bufLen, const SMPauseStreamReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
@ -7591,3 +7705,42 @@ int32_t tDeserializeSMResumeStreamReq(void *buf, int32_t bufLen, SMResumeStreamR
|
|||
return 0;
|
||||
}
|
||||
|
||||
=======
|
||||
int32_t tEncodeMqSubTopicEp(void **buf, const SMqSubTopicEp *pTopicEp) {
|
||||
int32_t tlen = 0;
|
||||
tlen += taosEncodeString(buf, pTopicEp->topic);
|
||||
tlen += taosEncodeString(buf, pTopicEp->db);
|
||||
int32_t sz = taosArrayGetSize(pTopicEp->vgs);
|
||||
tlen += taosEncodeFixedI32(buf, sz);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubVgEp *pVgEp = (SMqSubVgEp *)taosArrayGet(pTopicEp->vgs, i);
|
||||
tlen += tEncodeSMqSubVgEp(buf, pVgEp);
|
||||
}
|
||||
tlen += taosEncodeSSchemaWrapper(buf, &pTopicEp->schema);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
void *tDecodeMqSubTopicEp(void *buf, SMqSubTopicEp *pTopicEp) {
|
||||
buf = taosDecodeStringTo(buf, pTopicEp->topic);
|
||||
buf = taosDecodeStringTo(buf, pTopicEp->db);
|
||||
int32_t sz;
|
||||
buf = taosDecodeFixedI32(buf, &sz);
|
||||
pTopicEp->vgs = taosArrayInit(sz, sizeof(SMqSubVgEp));
|
||||
if (pTopicEp->vgs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
SMqSubVgEp vgEp;
|
||||
buf = tDecodeSMqSubVgEp(buf, &vgEp);
|
||||
taosArrayPush(pTopicEp->vgs, &vgEp);
|
||||
}
|
||||
buf = taosDecodeSSchemaWrapper(buf, &pTopicEp->schema);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void tDeleteMqSubTopicEp(SMqSubTopicEp *pSubTopicEp) {
|
||||
taosMemoryFreeClear(pSubTopicEp->schema.pSchema);
|
||||
pSubTopicEp->schema.nCols = 0;
|
||||
taosArrayDestroy(pSubTopicEp->vgs);
|
||||
}
|
||||
>>>>>>> enh/3.0
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct SDnodeMgmt {
|
|||
TdThread crashReportThread;
|
||||
SSingleWorker mgmtWorker;
|
||||
ProcessCreateNodeFp processCreateNodeFp;
|
||||
ProcessAlterNodeTypeFp processAlterNodeTypeFp;
|
||||
ProcessDropNodeFp processDropNodeFp;
|
||||
SendMonitorReportFp sendMonitorReportFp;
|
||||
GetVnodeLoadsFp getVnodeLoadsFp;
|
||||
|
|
|
@ -352,6 +352,7 @@ SArray *dmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_DND_CONFIG_DNODE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_SERVER_STATUS, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_SYSTABLE_RETRIEVE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_ALTER_MNODE_TYPE, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
|
||||
// Requests handled by MNODE
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_GRANT, dmPutNodeMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
|
|
|
@ -48,6 +48,7 @@ static int32_t dmOpenMgmt(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
|||
pMgmt->path = pInput->path;
|
||||
pMgmt->name = pInput->name;
|
||||
pMgmt->processCreateNodeFp = pInput->processCreateNodeFp;
|
||||
pMgmt->processAlterNodeTypeFp = pInput->processAlterNodeTypeFp;
|
||||
pMgmt->processDropNodeFp = pInput->processDropNodeFp;
|
||||
pMgmt->sendMonitorReportFp = pInput->sendMonitorReportFp;
|
||||
pMgmt->getVnodeLoadsFp = pInput->getVnodeLoadsFp;
|
||||
|
|
|
@ -227,6 +227,9 @@ static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
|||
case TDMT_DND_DROP_SNODE:
|
||||
code = (*pMgmt->processDropNodeFp)(SNODE, pMsg);
|
||||
break;
|
||||
case TDMT_DND_ALTER_MNODE_TYPE:
|
||||
code = (*pMgmt->processAlterNodeTypeFp)(MNODE, pMsg);
|
||||
break;
|
||||
case TDMT_DND_SERVER_STATUS:
|
||||
code = dmProcessServerRunStatus(pMgmt, pMsg);
|
||||
break;
|
||||
|
|
|
@ -24,12 +24,16 @@ static int32_t mmDecodeOption(SJson *pJson, SMnodeOpt *pOption) {
|
|||
if (code < 0) return -1;
|
||||
tjsonGetInt32ValueFromDouble(pJson, "selfIndex", pOption->selfIndex, code);
|
||||
if (code < 0) return 0;
|
||||
tjsonGetInt32ValueFromDouble(pJson, "lastIndex", pOption->lastIndex, code);
|
||||
if (code < 0) return 0;
|
||||
|
||||
SJson *replicas = tjsonGetObjectItem(pJson, "replicas");
|
||||
if (replicas == NULL) return 0;
|
||||
pOption->numOfReplicas = tjsonGetArraySize(replicas);
|
||||
pOption->numOfTotalReplicas = tjsonGetArraySize(replicas);
|
||||
|
||||
for (int32_t i = 0; i < pOption->numOfReplicas; ++i) {
|
||||
pOption->numOfReplicas = 0;
|
||||
|
||||
for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
|
||||
SJson *replica = tjsonGetArrayItem(replicas, i);
|
||||
if (replica == NULL) return -1;
|
||||
|
||||
|
@ -40,6 +44,14 @@ static int32_t mmDecodeOption(SJson *pJson, SMnodeOpt *pOption) {
|
|||
if (code < 0) return -1;
|
||||
tjsonGetUInt16ValueFromDouble(replica, "port", pReplica->port, code);
|
||||
if (code < 0) return -1;
|
||||
tjsonGetInt32ValueFromDouble(replica, "role", pOption->nodeRoles[i], code);
|
||||
if (code < 0) return -1;
|
||||
if(pOption->nodeRoles[i] == TAOS_SYNC_ROLE_VOTER){
|
||||
pOption->numOfReplicas++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -112,14 +124,14 @@ _OVER:
|
|||
}
|
||||
|
||||
static int32_t mmEncodeOption(SJson *pJson, const SMnodeOpt *pOption) {
|
||||
if (pOption->deploy && pOption->numOfReplicas > 0) {
|
||||
if (pOption->deploy && pOption->numOfTotalReplicas > 0) {
|
||||
if (tjsonAddDoubleToObject(pJson, "selfIndex", pOption->selfIndex) < 0) return -1;
|
||||
|
||||
SJson *replicas = tjsonCreateArray();
|
||||
if (replicas == NULL) return -1;
|
||||
if (tjsonAddItemToObject(pJson, "replicas", replicas) < 0) return -1;
|
||||
|
||||
for (int32_t i = 0; i < pOption->numOfReplicas; ++i) {
|
||||
for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
|
||||
SJson *replica = tjsonCreateObject();
|
||||
if (replica == NULL) return -1;
|
||||
|
||||
|
@ -127,10 +139,13 @@ static int32_t mmEncodeOption(SJson *pJson, const SMnodeOpt *pOption) {
|
|||
if (tjsonAddDoubleToObject(replica, "id", pReplica->id) < 0) return -1;
|
||||
if (tjsonAddStringToObject(replica, "fqdn", pReplica->fqdn) < 0) return -1;
|
||||
if (tjsonAddDoubleToObject(replica, "port", pReplica->port) < 0) return -1;
|
||||
if (tjsonAddDoubleToObject(replica, "role", pOption->nodeRoles[i]) < 0) return -1;
|
||||
if (tjsonAddItemToArray(replicas, replica) < 0) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tjsonAddDoubleToObject(pJson, "lastIndex", pOption->lastIndex) < 0) return -1;
|
||||
|
||||
if (tjsonAddDoubleToObject(pJson, "deployed", pOption->deploy) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -33,12 +33,24 @@ int32_t mmProcessCreateReq(const SMgmtInputOpt *pInput, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
SMnodeOpt option = {.deploy = true, .numOfReplicas = createReq.replica, .selfIndex = -1};
|
||||
SMnodeOpt option = {.deploy = true, .numOfReplicas = createReq.replica,
|
||||
.numOfTotalReplicas = createReq.replica + createReq.learnerReplica,
|
||||
.selfIndex = -1, .lastIndex = createReq.lastIndex};
|
||||
|
||||
memcpy(option.replicas, createReq.replicas, sizeof(createReq.replicas));
|
||||
for (int32_t i = 0; i < option.numOfReplicas; ++i) {
|
||||
for (int32_t i = 0; i < createReq.replica; ++i) {
|
||||
if (createReq.replicas[i].id == pInput->pData->dnodeId) {
|
||||
option.selfIndex = i;
|
||||
}
|
||||
option.nodeRoles[i] = TAOS_SYNC_ROLE_VOTER;
|
||||
}
|
||||
|
||||
memcpy(&(option.replicas[createReq.replica]), createReq.learnerReplicas, sizeof(createReq.learnerReplicas));
|
||||
for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
|
||||
if (createReq.learnerReplicas[i].id == pInput->pData->dnodeId) {
|
||||
option.selfIndex = createReq.replica + i;
|
||||
}
|
||||
option.nodeRoles[createReq.replica + i] = TAOS_SYNC_ROLE_LEARNER;
|
||||
}
|
||||
|
||||
if (option.selfIndex == -1) {
|
||||
|
@ -92,6 +104,8 @@ SArray *mmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_DND_CREATE_VNODE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_DROP_VNODE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_CONFIG_DNODE_RSP, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_ALTER_MNODE_TYPE_RSP, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_ALTER_VNODE_TYPE_RSP, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_CONNECT, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_ACCT, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
|
|
|
@ -45,9 +45,11 @@ static void mmBuildOptionForDeploy(SMnodeMgmt *pMgmt, const SMgmtInputOpt *pInpu
|
|||
pOption->dnodeId = pMgmt->pData->dnodeId;
|
||||
pOption->selfIndex = 0;
|
||||
pOption->numOfReplicas = 1;
|
||||
pOption->numOfTotalReplicas = 1;
|
||||
pOption->replicas[0].id = 1;
|
||||
pOption->replicas[0].port = tsServerPort;
|
||||
tstrncpy(pOption->replicas[0].fqdn, tsLocalFqdn, TSDB_FQDN_LEN);
|
||||
pOption->lastIndex = SYNC_INDEX_INVALID;
|
||||
}
|
||||
|
||||
static void mmBuildOptionForOpen(SMnodeMgmt *pMgmt, SMnodeOpt *pOption) {
|
||||
|
@ -123,9 +125,10 @@ static int32_t mmOpen(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
|||
}
|
||||
tmsgReportStartup("mnode-worker", "initialized");
|
||||
|
||||
if (option.numOfReplicas > 0) {
|
||||
if (option.numOfTotalReplicas > 0) {
|
||||
option.deploy = true;
|
||||
option.numOfReplicas = 0;
|
||||
option.numOfTotalReplicas = 0;
|
||||
if (mmWriteFile(pMgmt->path, &option) != 0) {
|
||||
dError("failed to write mnode file since %s", terrstr());
|
||||
return -1;
|
||||
|
@ -152,6 +155,14 @@ static void mmStop(SMnodeMgmt *pMgmt) {
|
|||
mndStop(pMgmt->pMnode);
|
||||
}
|
||||
|
||||
static int32_t mmSyncIsCatchUp(SMnodeMgmt *pMgmt) {
|
||||
return mndIsCatchUp(pMgmt->pMnode);
|
||||
}
|
||||
|
||||
static ESyncRole mmSyncGetRole(SMnodeMgmt *pMgmt) {
|
||||
return mndGetRole(pMgmt->pMnode);
|
||||
}
|
||||
|
||||
SMgmtFunc mmGetMgmtFunc() {
|
||||
SMgmtFunc mgmtFunc = {0};
|
||||
mgmtFunc.openFp = mmOpen;
|
||||
|
@ -162,6 +173,8 @@ SMgmtFunc mmGetMgmtFunc() {
|
|||
mgmtFunc.dropFp = (NodeDropFp)mmProcessDropReq;
|
||||
mgmtFunc.requiredFp = mmRequire;
|
||||
mgmtFunc.getHandlesFp = mmGetMsgHandles;
|
||||
mgmtFunc.isCatchUpFp = (NodeIsCatchUpFp)mmSyncIsCatchUp;
|
||||
mgmtFunc.nodeRoleFp = (NodeRole)mmSyncGetRole;
|
||||
|
||||
return mgmtFunc;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ int32_t vmProcessDropVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
|
|||
int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
|
||||
int32_t vmProcessDisableVnodeWriteReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
|
||||
int32_t vmProcessAlterHashRangeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
|
||||
int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg);
|
||||
|
||||
// vmFile.c
|
||||
int32_t vmGetVnodeListFromFile(SVnodeMgmt *pMgmt, SWrapperCfg **ppCfgs, int32_t *numOfVnodes);
|
||||
|
|
|
@ -131,15 +131,34 @@ static void vmGenerateVnodeCfg(SCreateVnodeReq *pCreate, SVnodeCfg *pCfg) {
|
|||
pCfg->tsdbPageSize = pCreate->tsdbPageSize * 1024;
|
||||
|
||||
pCfg->standby = 0;
|
||||
pCfg->syncCfg.myIndex = pCreate->selfIndex;
|
||||
pCfg->syncCfg.replicaNum = pCreate->replica;
|
||||
pCfg->syncCfg.replicaNum = 0;
|
||||
pCfg->syncCfg.totalReplicaNum = 0;
|
||||
|
||||
memset(&pCfg->syncCfg.nodeInfo, 0, sizeof(pCfg->syncCfg.nodeInfo));
|
||||
for (int32_t i = 0; i < pCreate->replica; ++i) {
|
||||
SNodeInfo *pNode = &pCfg->syncCfg.nodeInfo[i];
|
||||
pNode->nodeId = pCreate->replicas[i].id;
|
||||
pNode->nodePort = pCreate->replicas[i].port;
|
||||
tstrncpy(pNode->nodeFqdn, pCreate->replicas[i].fqdn, TSDB_FQDN_LEN);
|
||||
pNode->nodeId = pCreate->replicas[pCfg->syncCfg.replicaNum].id;
|
||||
pNode->nodePort = pCreate->replicas[pCfg->syncCfg.replicaNum].port;
|
||||
pNode->nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
tstrncpy(pNode->nodeFqdn, pCreate->replicas[pCfg->syncCfg.replicaNum].fqdn, TSDB_FQDN_LEN);
|
||||
tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort);
|
||||
pCfg->syncCfg.replicaNum++;
|
||||
}
|
||||
if(pCreate->selfIndex != -1){
|
||||
pCfg->syncCfg.myIndex = pCreate->selfIndex;
|
||||
}
|
||||
for (int32_t i = pCfg->syncCfg.replicaNum; i < pCreate->replica + pCreate->learnerReplica; ++i) {
|
||||
SNodeInfo *pNode = &pCfg->syncCfg.nodeInfo[i];
|
||||
pNode->nodeId = pCreate->learnerReplicas[pCfg->syncCfg.totalReplicaNum].id;
|
||||
pNode->nodePort = pCreate->learnerReplicas[pCfg->syncCfg.totalReplicaNum].port;
|
||||
pNode->nodeRole = TAOS_SYNC_ROLE_LEARNER;
|
||||
tstrncpy(pNode->nodeFqdn, pCreate->learnerReplicas[pCfg->syncCfg.totalReplicaNum].fqdn, TSDB_FQDN_LEN);
|
||||
tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort);
|
||||
pCfg->syncCfg.totalReplicaNum++;
|
||||
}
|
||||
pCfg->syncCfg.totalReplicaNum += pCfg->syncCfg.replicaNum;
|
||||
if(pCreate->learnerSelfIndex != -1){
|
||||
pCfg->syncCfg.myIndex = pCreate->replica + pCreate->learnerSelfIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,23 +201,40 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, start to create vnode, page:%d pageSize:%d buffer:%d szPage:%d szBuf:%" PRIu64
|
||||
if(req.learnerReplica == 0)
|
||||
{
|
||||
req.learnerSelfIndex = -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, vnode management handle msgType:%s, start to create vnode, page:%d pageSize:%d buffer:%d szPage:%d szBuf:%" PRIu64
|
||||
", cacheLast:%d cacheLastSize:%d sstTrigger:%d tsdbPageSize:%d %d dbname:%s dbId:%" PRId64
|
||||
", days:%d keep0:%d keep1:%d keep2:%d tsma:%d precision:%d compression:%d minRows:%d maxRows:%d"
|
||||
", wal fsync:%d level:%d retentionPeriod:%d retentionSize:%" PRId64 " rollPeriod:%d segSize:%" PRId64
|
||||
", hash method:%d begin:%u end:%u prefix:%d surfix:%d replica:%d selfIndex:%d strict:%d",
|
||||
req.vgId, req.pages, req.pageSize, req.buffer, req.pageSize * 1024, (uint64_t)req.buffer * 1024 * 1024,
|
||||
", hash method:%d begin:%u end:%u prefix:%d surfix:%d replica:%d selfIndex:%d "
|
||||
"learnerReplica:%d learnerSelfIndex:%d strict:%d",
|
||||
req.vgId, TMSG_INFO(pMsg->msgType), req.pages, req.pageSize, req.buffer, req.pageSize * 1024,
|
||||
(uint64_t)req.buffer * 1024 * 1024,
|
||||
req.cacheLast, req.cacheLastSize, req.sstTrigger, req.tsdbPageSize, req.tsdbPageSize * 1024, req.db, req.dbUid,
|
||||
req.daysPerFile, req.daysToKeep0, req.daysToKeep1, req.daysToKeep2, req.isTsma, req.precision, req.compression,
|
||||
req.minRows, req.maxRows, req.walFsyncPeriod, req.walLevel, req.walRetentionPeriod, req.walRetentionSize,
|
||||
req.walRollPeriod, req.walSegmentSize, req.hashMethod, req.hashBegin, req.hashEnd, req.hashPrefix,
|
||||
req.hashSuffix, req.replica, req.selfIndex, req.strict);
|
||||
req.hashSuffix, req.replica, req.selfIndex, req.learnerReplica, req.learnerSelfIndex, req.strict);
|
||||
for (int32_t i = 0; i < req.replica; ++i) {
|
||||
dInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", req.vgId, i, req.replicas[i].fqdn, req.replicas[i].port,
|
||||
req.replicas[i].id);
|
||||
}
|
||||
for (int32_t i = 0; i < req.learnerReplica; ++i) {
|
||||
dInfo("vgId:%d, learnerReplica:%d ep:%s:%u dnode:%d", req.vgId, i, req.learnerReplicas[i].fqdn,
|
||||
req.learnerReplicas[i].port, req.replicas[i].id);
|
||||
}
|
||||
|
||||
SReplica *pReplica = &req.replicas[req.selfIndex];
|
||||
SReplica *pReplica = NULL;
|
||||
if(req.selfIndex != -1){
|
||||
pReplica = &req.replicas[req.selfIndex];
|
||||
}
|
||||
else{
|
||||
pReplica = &req.learnerReplicas[req.learnerSelfIndex];
|
||||
}
|
||||
if (pReplica->id != pMgmt->pData->dnodeId || pReplica->port != tsServerPort ||
|
||||
strcmp(pReplica->fqdn, tsLocalFqdn) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
|
@ -275,7 +311,8 @@ _OVER:
|
|||
vnodeClose(pImpl);
|
||||
vnodeDestroy(path, pMgmt->pTfs);
|
||||
} else {
|
||||
dInfo("vgId:%d, vnode is created", req.vgId);
|
||||
dInfo("vgId:%d, vnode management handle msgType:%s, end to create vnode, vnode is created",
|
||||
req.vgId, TMSG_INFO(pMsg->msgType));
|
||||
}
|
||||
|
||||
tFreeSCreateVnodeReq(&req);
|
||||
|
@ -283,6 +320,122 @@ _OVER:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||
SAlterVnodeTypeReq req = {0};
|
||||
if (tDeserializeSAlterVnodeReplicaReq(pMsg->pCont, pMsg->contLen, &req) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(req.learnerReplicas == 0){
|
||||
req.learnerSelfIndex = -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, vnode management handle msgType:%s, start to process alter-node-type-request",
|
||||
req.vgId, TMSG_INFO(pMsg->msgType));
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to alter vnode type since %s", req.vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESyncRole role = vnodeGetRole(pVnode->pImpl);
|
||||
dInfo("vgId:%d, checking node role:%d", req.vgId, role);
|
||||
if(role == TAOS_SYNC_ROLE_VOTER){
|
||||
terrno = TSDB_CODE_VND_ALREADY_IS_VOTER;
|
||||
vmReleaseVnode(pMgmt, pVnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, checking node catch up", req.vgId);
|
||||
if(vnodeIsCatchUp(pVnode->pImpl) != 1){
|
||||
terrno = TSDB_CODE_VND_NOT_CATCH_UP;
|
||||
vmReleaseVnode(pMgmt, pVnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dInfo("node:%s, catched up leader, continue to process alter-node-type-request", pMgmt->name);
|
||||
|
||||
int32_t vgId = req.vgId;
|
||||
dInfo("vgId:%d, start to alter vnode type replica:%d selfIndex:%d strict:%d", vgId, req.replica, req.selfIndex,
|
||||
req.strict);
|
||||
for (int32_t i = 0; i < req.replica; ++i) {
|
||||
SReplica *pReplica = &req.replicas[i];
|
||||
dInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", vgId, i, pReplica->fqdn, pReplica->port, pReplica->id);
|
||||
}
|
||||
for (int32_t i = 0; i < req.learnerReplica; ++i) {
|
||||
SReplica *pReplica = &req.learnerReplicas[i];
|
||||
dInfo("vgId:%d, learnerReplicas:%d ep:%s:%u dnode:%d", vgId, i, pReplica->fqdn, pReplica->port, pReplica->id);
|
||||
}
|
||||
|
||||
if (req.replica <= 0 ||
|
||||
(req.selfIndex < 0 && req.learnerSelfIndex <0)||
|
||||
req.selfIndex >= req.replica || req.learnerSelfIndex >= req.learnerReplica) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
dError("vgId:%d, failed to alter replica since invalid msg", vgId);
|
||||
vmReleaseVnode(pMgmt, pVnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SReplica *pReplica = NULL;
|
||||
if(req.selfIndex > 0){
|
||||
pReplica = &req.replicas[req.selfIndex];
|
||||
}
|
||||
else{
|
||||
pReplica = &req.learnerReplicas[req.learnerSelfIndex];
|
||||
}
|
||||
|
||||
if (pReplica->id != pMgmt->pData->dnodeId || pReplica->port != tsServerPort ||
|
||||
strcmp(pReplica->fqdn, tsLocalFqdn) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
dError("vgId:%d, dnodeId:%d ep:%s:%u not matched with local dnode", vgId, pReplica->id, pReplica->fqdn,
|
||||
pReplica->port);
|
||||
vmReleaseVnode(pMgmt, pVnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, start to close vnode", vgId);
|
||||
SWrapperCfg wrapperCfg = {
|
||||
.dropped = pVnode->dropped,
|
||||
.vgId = pVnode->vgId,
|
||||
.vgVersion = pVnode->vgVersion,
|
||||
};
|
||||
tstrncpy(wrapperCfg.path, pVnode->path, sizeof(wrapperCfg.path));
|
||||
vmCloseVnode(pMgmt, pVnode, false);
|
||||
|
||||
char path[TSDB_FILENAME_LEN] = {0};
|
||||
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, vgId);
|
||||
|
||||
dInfo("vgId:%d, start to alter vnode replica at %s", vgId, path);
|
||||
if (vnodeAlterReplica(path, &req, pMgmt->pTfs) < 0) {
|
||||
dError("vgId:%d, failed to alter vnode at %s since %s", vgId, path, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, begin to open vnode", vgId);
|
||||
SVnode *pImpl = vnodeOpen(path, pMgmt->pTfs, pMgmt->msgCb);
|
||||
if (pImpl == NULL) {
|
||||
dError("vgId:%d, failed to open vnode at %s since %s", vgId, path, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vmOpenVnode(pMgmt, &wrapperCfg, pImpl) != 0) {
|
||||
dError("vgId:%d, failed to open vnode mgmt since %s", vgId, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vnodeStart(pImpl) != 0) {
|
||||
dError("vgId:%d, failed to start sync since %s", vgId, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, vnode management handle msgType:%s, end to process alter-node-type-request, vnode config is altered",
|
||||
req.vgId, TMSG_INFO(pMsg->msgType));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t vmProcessDisableVnodeWriteReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||
SDisableVnodeWriteReq req = {0};
|
||||
if (tDeserializeSDisableVnodeWriteReq(pMsg->pCont, pMsg->contLen, &req) != 0) {
|
||||
|
@ -377,21 +530,40 @@ int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if(alterReq.learnerReplica == 0){
|
||||
alterReq.learnerSelfIndex = -1;
|
||||
}
|
||||
|
||||
int32_t vgId = alterReq.vgId;
|
||||
dInfo("vgId:%d, start to alter vnode replica:%d selfIndex:%d strict:%d", vgId, alterReq.replica, alterReq.selfIndex,
|
||||
alterReq.strict);
|
||||
dInfo("vgId:%d,vnode management handle msgType:%s, start to alter vnode replica:%d selfIndex:%d leanerReplica:%d "
|
||||
"learnerSelfIndex:%d strict:%d",
|
||||
vgId, TMSG_INFO(pMsg->msgType), alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica,
|
||||
alterReq.learnerSelfIndex, alterReq.strict);
|
||||
for (int32_t i = 0; i < alterReq.replica; ++i) {
|
||||
SReplica *pReplica = &alterReq.replicas[i];
|
||||
dInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", vgId, i, pReplica->fqdn, pReplica->port, pReplica->port);
|
||||
}
|
||||
|
||||
if (alterReq.replica <= 0 || alterReq.selfIndex < 0 || alterReq.selfIndex >= alterReq.replica) {
|
||||
for (int32_t i = 0; i < alterReq.learnerReplica; ++i) {
|
||||
SReplica *pReplica = &alterReq.learnerReplicas[i];
|
||||
dInfo("vgId:%d, learnerReplicas:%d ep:%s:%u dnode:%d", vgId, i, pReplica->fqdn, pReplica->port, pReplica->port);
|
||||
}
|
||||
|
||||
if (alterReq.replica <= 0 ||
|
||||
(alterReq.selfIndex < 0 && alterReq.learnerSelfIndex <0)||
|
||||
alterReq.selfIndex >= alterReq.replica || alterReq.learnerSelfIndex >= alterReq.learnerReplica) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
dError("vgId:%d, failed to alter replica since invalid msg", vgId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SReplica *pReplica = &alterReq.replicas[alterReq.selfIndex];
|
||||
SReplica *pReplica = NULL;
|
||||
if(alterReq.selfIndex != -1){
|
||||
pReplica = &alterReq.replicas[alterReq.selfIndex];
|
||||
}
|
||||
else{
|
||||
pReplica = &alterReq.learnerReplicas[alterReq.learnerSelfIndex];
|
||||
}
|
||||
|
||||
if (pReplica->id != pMgmt->pData->dnodeId || pReplica->port != tsServerPort ||
|
||||
strcmp(pReplica->fqdn, tsLocalFqdn) != 0) {
|
||||
terrno = TSDB_CODE_INVALID_MSG;
|
||||
|
@ -425,7 +597,7 @@ int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, close vnode", vgId);
|
||||
dInfo("vgId:%d, begin to open vnode", vgId);
|
||||
SVnode *pImpl = vnodeOpen(path, pMgmt->pTfs, pMgmt->msgCb);
|
||||
if (pImpl == NULL) {
|
||||
dError("vgId:%d, failed to open vnode at %s since %s", vgId, path, terrstr());
|
||||
|
@ -442,7 +614,10 @@ int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
dInfo("vgId:%d, vnode config is altered", vgId);
|
||||
dInfo("vgId:%d, vnode management handle msgType:%s, end to alter vnode replica:%d selfIndex:%d leanerReplica:%d "
|
||||
"learnerSelfIndex:%d strict:%d",
|
||||
vgId, TMSG_INFO(pMsg->msgType), alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica,
|
||||
alterReq.learnerSelfIndex, alterReq.strict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -517,9 +692,15 @@ SArray *vmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_SUBSCRIBE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_DELETE_SUB, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_COMMIT_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_SEEK_TO_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_ADD_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_DEL_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
<<<<<<< HEAD
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_CONSUME, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER;
|
||||
=======
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_CONSUME, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_VG_WALINFO, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
|
||||
>>>>>>> enh/3.0
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_DELETE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_BATCH_DEL, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_COMMIT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
|
@ -550,6 +731,7 @@ SArray *vmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_VND_TRIM, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_CREATE_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_DROP_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_DND_ALTER_VNODE_TYPE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER;
|
||||
|
||||
if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT_ELECTION, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER;
|
||||
|
|
|
@ -49,6 +49,9 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
|||
case TDMT_VND_ALTER_HASHRANGE:
|
||||
code = vmProcessAlterHashRangeReq(pMgmt, pMsg);
|
||||
break;
|
||||
case TDMT_DND_ALTER_VNODE_TYPE:
|
||||
code = vmProcessAlterVnodeTypeReq(pMgmt, pMsg);
|
||||
break;
|
||||
default:
|
||||
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
|
||||
dGError("msg:%p, not processed in vnode-mgmt queue", pMsg);
|
||||
|
@ -57,7 +60,7 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
|||
if (IsReq(pMsg)) {
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dGError("msg:%p, failed to process since %s, type:%s", pMsg, terrstr(code), TMSG_INFO(pMsg->msgType));
|
||||
dGError("msg:%p, failed to process since %s, type:%s", pMsg, tstrerror(code), TMSG_INFO(pMsg->msgType));
|
||||
}
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
|
|
@ -169,6 +169,8 @@ static int32_t dmProcessCreateNodeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
dInfo("start to process create-node-request");
|
||||
|
||||
pWrapper = &pDnode->wrappers[ntype];
|
||||
if (taosMkDir(pWrapper->path) != 0) {
|
||||
dmReleaseWrapper(pWrapper);
|
||||
|
@ -198,6 +200,74 @@ static int32_t dmProcessCreateNodeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t dmProcessAlterNodeTypeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
|
||||
SDnode *pDnode = dmInstance();
|
||||
|
||||
SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
|
||||
if (pWrapper == NULL) {
|
||||
dError("fail to process alter node type since node not exist");
|
||||
return -1;
|
||||
}
|
||||
dmReleaseWrapper(pWrapper);
|
||||
|
||||
dInfo("node:%s, start to process alter-node-type-request", pWrapper->name);
|
||||
|
||||
pWrapper = &pDnode->wrappers[ntype];
|
||||
|
||||
if(pWrapper->func.nodeRoleFp != NULL){
|
||||
ESyncRole role = (*pWrapper->func.nodeRoleFp)(pWrapper->pMgmt);
|
||||
dInfo("node:%s, checking node role:%d", pWrapper->name, role);
|
||||
if(role == TAOS_SYNC_ROLE_VOTER){
|
||||
terrno = TSDB_CODE_MNODE_ALREADY_IS_VOTER;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(pWrapper->func.isCatchUpFp != NULL){
|
||||
dInfo("node:%s, checking node catch up", pWrapper->name);
|
||||
if((*pWrapper->func.isCatchUpFp)(pWrapper->pMgmt) != 1){
|
||||
terrno = TSDB_CODE_MNODE_NOT_CATCH_UP;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dInfo("node:%s, catched up leader, continue to process alter-node-type-request", pWrapper->name);
|
||||
|
||||
taosThreadMutexLock(&pDnode->mutex);
|
||||
|
||||
dInfo("node:%s, stopping node", pWrapper->name);
|
||||
dmStopNode(pWrapper);
|
||||
dInfo("node:%s, closing node", pWrapper->name);
|
||||
dmCloseNode(pWrapper);
|
||||
|
||||
pWrapper = &pDnode->wrappers[ntype];
|
||||
if (taosMkDir(pWrapper->path) != 0) {
|
||||
dmReleaseWrapper(pWrapper);
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
dError("failed to create dir:%s since %s", pWrapper->path, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);
|
||||
|
||||
dInfo("node:%s, start to create", pWrapper->name);
|
||||
int32_t code = (*pWrapper->func.createFp)(&input, pMsg);
|
||||
if (code != 0) {
|
||||
dError("node:%s, failed to create since %s", pWrapper->name, terrstr());
|
||||
} else {
|
||||
dInfo("node:%s, has been created", pWrapper->name);
|
||||
code = dmOpenNode(pWrapper);
|
||||
if (code == 0) {
|
||||
code = dmStartNode(pWrapper);
|
||||
}
|
||||
pWrapper->deployed = true;
|
||||
pWrapper->required = true;
|
||||
}
|
||||
|
||||
taosThreadMutexUnlock(&pDnode->mutex);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t dmProcessDropNodeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
|
||||
SDnode *pDnode = dmInstance();
|
||||
|
||||
|
@ -251,6 +321,7 @@ SMgmtInputOpt dmBuildMgmtInputOpt(SMgmtWrapper *pWrapper) {
|
|||
.name = pWrapper->name,
|
||||
.pData = &pWrapper->pDnode->data,
|
||||
.processCreateNodeFp = dmProcessCreateNodeReq,
|
||||
.processAlterNodeTypeFp = dmProcessAlterNodeTypeReq,
|
||||
.processDropNodeFp = dmProcessDropNodeReq,
|
||||
.sendMonitorReportFp = dmSendMonitorReport,
|
||||
.getVnodeLoadsFp = dmGetVnodeLoads,
|
||||
|
|
|
@ -89,6 +89,7 @@ typedef void (*SendMonitorReportFp)();
|
|||
typedef void (*GetVnodeLoadsFp)(SMonVloadInfo *pInfo);
|
||||
typedef void (*GetMnodeLoadsFp)(SMonMloadInfo *pInfo);
|
||||
typedef void (*GetQnodeLoadsFp)(SQnodeLoad *pInfo);
|
||||
typedef int32_t (*ProcessAlterNodeTypeFp)(EDndNodeType ntype, SRpcMsg *pMsg);
|
||||
|
||||
typedef struct {
|
||||
int32_t dnodeId;
|
||||
|
@ -112,6 +113,7 @@ typedef struct {
|
|||
SDnodeData *pData;
|
||||
SMsgCb msgCb;
|
||||
ProcessCreateNodeFp processCreateNodeFp;
|
||||
ProcessAlterNodeTypeFp processAlterNodeTypeFp;
|
||||
ProcessDropNodeFp processDropNodeFp;
|
||||
SendMonitorReportFp sendMonitorReportFp;
|
||||
GetVnodeLoadsFp getVnodeLoadsFp;
|
||||
|
@ -132,6 +134,8 @@ typedef int32_t (*NodeCreateFp)(const SMgmtInputOpt *pInput, SRpcMsg *pMsg);
|
|||
typedef int32_t (*NodeDropFp)(const SMgmtInputOpt *pInput, SRpcMsg *pMsg);
|
||||
typedef int32_t (*NodeRequireFp)(const SMgmtInputOpt *pInput, bool *required);
|
||||
typedef SArray *(*NodeGetHandlesFp)(); // array of SMgmtHandle
|
||||
typedef bool (*NodeIsCatchUpFp)(void *pMgmt);
|
||||
typedef bool (*NodeRole)(void *pMgmt);
|
||||
|
||||
typedef struct {
|
||||
NodeOpenFp openFp;
|
||||
|
@ -142,6 +146,8 @@ typedef struct {
|
|||
NodeDropFp dropFp;
|
||||
NodeRequireFp requiredFp;
|
||||
NodeGetHandlesFp getHandlesFp;
|
||||
NodeIsCatchUpFp isCatchUpFp;
|
||||
NodeRole nodeRoleFp;
|
||||
} SMgmtFunc;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -118,7 +118,7 @@ typedef enum {
|
|||
} ETrnPolicy;
|
||||
|
||||
typedef enum {
|
||||
TRN_EXEC_PRARLLEL = 0,
|
||||
TRN_EXEC_PARALLEL = 0,
|
||||
TRN_EXEC_SERIAL = 1,
|
||||
} ETrnExec;
|
||||
|
||||
|
@ -177,6 +177,7 @@ typedef struct {
|
|||
SArray* pRpcArray;
|
||||
SRWLatch lockRpcArray;
|
||||
int64_t mTraceId;
|
||||
TdThreadMutex mutex;
|
||||
} STrans;
|
||||
|
||||
typedef struct {
|
||||
|
@ -215,6 +216,8 @@ typedef struct {
|
|||
bool syncRestore;
|
||||
int64_t stateStartTime;
|
||||
SDnodeObj* pDnode;
|
||||
int32_t role;
|
||||
SyncIndex lastIndex;
|
||||
} SMnodeObj;
|
||||
|
||||
typedef struct {
|
||||
|
@ -278,6 +281,7 @@ typedef struct {
|
|||
int8_t reserve;
|
||||
int32_t acctId;
|
||||
int32_t authVersion;
|
||||
int32_t passVersion;
|
||||
SHashObj* readDbs;
|
||||
SHashObj* writeDbs;
|
||||
SHashObj* topics;
|
||||
|
@ -341,6 +345,7 @@ typedef struct {
|
|||
ESyncState syncState;
|
||||
bool syncRestore;
|
||||
bool syncCanRead;
|
||||
ESyncRole nodeRole;
|
||||
} SVnodeGid;
|
||||
|
||||
typedef struct {
|
||||
|
@ -361,7 +366,7 @@ typedef struct {
|
|||
int8_t compact;
|
||||
int8_t isTsma;
|
||||
int8_t replica;
|
||||
SVnodeGid vnodeGid[TSDB_MAX_REPLICA];
|
||||
SVnodeGid vnodeGid[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
void* pTsma;
|
||||
int32_t numOfCachedTables;
|
||||
} SVgObj;
|
||||
|
|
|
@ -92,8 +92,11 @@ typedef struct {
|
|||
int64_t transSeq;
|
||||
TdThreadMutex lock;
|
||||
int8_t selfIndex;
|
||||
int8_t numOfTotalReplicas;
|
||||
int8_t numOfReplicas;
|
||||
SReplica replicas[TSDB_MAX_REPLICA];
|
||||
SReplica replicas[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
ESyncRole nodeRoles[TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA];
|
||||
SyncIndex lastIndex;
|
||||
} SSyncMgmt;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -76,6 +76,7 @@ void mndTransSetRpcRsp(STrans *pTrans, void *pCont, int32_t contLen);
|
|||
void mndTransSetCb(STrans *pTrans, ETrnFunc startFunc, ETrnFunc stopFunc, void *param, int32_t paramLen);
|
||||
void mndTransSetDbName(STrans *pTrans, const char *dbname, const char *stbname);
|
||||
void mndTransSetSerial(STrans *pTrans);
|
||||
void mndTransSetParallel(STrans *pTrans);
|
||||
void mndTransSetOper(STrans *pTrans, EOperType oper);
|
||||
int32_t mndTrancCheckConflict(SMnode *pMnode, STrans *pTrans);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ SHashObj *mndDupTableHash(SHashObj *pOld);
|
|||
SHashObj *mndDupTopicHash(SHashObj *pOld);
|
||||
int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp,
|
||||
int32_t *pRspLen);
|
||||
int32_t mndValidateUserPassInfo(SMnode *pMnode, SUserPassVersion *pUsers, int32_t numOfUses, void **ppRsp,
|
||||
int32_t *pRspLen);
|
||||
int32_t mndUserRemoveDb(SMnode *pMnode, STrans *pTrans, char *db);
|
||||
int32_t mndUserRemoveTopic(SMnode *pMnode, STrans *pTrans, char *topic);
|
||||
|
||||
|
|
|
@ -564,9 +564,14 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
((SMqRspHead *)buf)->mqMsgType = TMQ_MSG_TYPE__EP_RSP;
|
||||
((SMqRspHead *)buf)->epoch = serverEpoch;
|
||||
((SMqRspHead *)buf)->consumerId = pConsumer->consumerId;
|
||||
SMqRspHead* pHead = buf;
|
||||
|
||||
pHead->mqMsgType = TMQ_MSG_TYPE__EP_RSP;
|
||||
pHead->epoch = serverEpoch;
|
||||
pHead->consumerId = pConsumer->consumerId;
|
||||
pHead->walsver = 0;
|
||||
pHead->walever = 0;
|
||||
|
||||
|
||||
void *abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
|
||||
tEncodeSMqAskEpRsp(&abuf, &rsp);
|
||||
|
|
|
@ -421,6 +421,7 @@ void dumpUser(SSdb *pSdb, SJson *json) {
|
|||
tjsonAddStringToObject(item, "updateTime", i642str(pObj->updateTime));
|
||||
tjsonAddStringToObject(item, "superUser", i642str(pObj->superUser));
|
||||
tjsonAddStringToObject(item, "authVersion", i642str(pObj->authVersion));
|
||||
tjsonAddStringToObject(item, "passVersion", i642str(pObj->passVersion));
|
||||
tjsonAddStringToObject(item, "numOfReadDbs", i642str(taosHashGetSize(pObj->readDbs)));
|
||||
tjsonAddStringToObject(item, "numOfWriteDbs", i642str(taosHashGetSize(pObj->writeDbs)));
|
||||
sdbRelease(pSdb, pObj);
|
||||
|
|
|
@ -556,7 +556,7 @@ RETRIEVE_FUNC_OVER:
|
|||
return code;
|
||||
}
|
||||
|
||||
static void *mnodeGenTypeStr(char *buf, int32_t buflen, uint8_t type, int16_t len) {
|
||||
static void *mnodeGenTypeStr(char *buf, int32_t buflen, uint8_t type, int32_t len) {
|
||||
char *msg = "unknown";
|
||||
if (type >= sizeof(tDataTypes) / sizeof(tDataTypes[0])) {
|
||||
return msg;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue