other: merge 3.0.
This commit is contained in:
commit
de47ea6c81
|
@ -401,7 +401,7 @@ pipeline {
|
|||
}
|
||||
}
|
||||
stage('linux test') {
|
||||
agent{label " slave1_50 || slave1_47 || slave1_48 || slave1_49 || slave1_52 || worker03 || slave215 || slave217 || slave219 "}
|
||||
agent{label " slave1_47 || slave1_48 || slave1_49 || slave1_52 || worker03 || slave215 || slave217 || slave219 "}
|
||||
options { skipDefaultCheckout() }
|
||||
when {
|
||||
changeRequest()
|
||||
|
|
|
@ -97,7 +97,15 @@ ENDIF()
|
|||
SET(JEMALLOC_ENABLED OFF)
|
||||
IF (TD_WINDOWS)
|
||||
MESSAGE("${Yellow} set compiler flag for Windows! ${ColourReset}")
|
||||
IF (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
MESSAGE("${Green} will build Release version! ${ColourReset}")
|
||||
SET(COMMON_FLAGS "/W3 /D_WIN32 /DWIN32 /Zi- /O2 /GL /MD")
|
||||
|
||||
ELSE ()
|
||||
MESSAGE("${Green} will build Debug version! ${ColourReset}")
|
||||
SET(COMMON_FLAGS "/w /D_WIN32 /DWIN32 /Zi /MTd")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
|
||||
# IF (MSVC AND (MSVC_VERSION GREATER_EQUAL 1900))
|
||||
# SET(COMMON_FLAGS "${COMMON_FLAGS} /Wv:18")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "3.2.1.0.alpha")
|
||||
SET(TD_VER_NUMBER "3.2.2.0.alpha")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
|
|
@ -284,7 +284,8 @@ if (${BUILD_WITH_ROCKSDB})
|
|||
SET(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
endif(${TD_LINUX})
|
||||
MESSAGE(STATUS "CXXXX STATUS CONFIG: " ${CMAKE_CXX_FLAGS})
|
||||
MESSAGE(STATUS "ROCKSDB CXXXX STATUS CONFIG: " ${CMAKE_CXX_FLAGS})
|
||||
MESSAGE(STATUS "ROCKSDB C STATUS CONFIG: " ${CMAKE_C_FLAGS})
|
||||
|
||||
if(${TD_DARWIN})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=maybe-uninitialized")
|
||||
|
@ -296,8 +297,12 @@ if (${BUILD_WITH_ROCKSDB})
|
|||
|
||||
if (${TD_WINDOWS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4819")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4244 /wd4819")
|
||||
option(WITH_JNI "" OFF)
|
||||
if(CMAKE_C_FLAGS MATCHES "/MT" OR CMAKE_C_FLAGS MATCHES "/MTd")
|
||||
message("Rocksdb build runtime lib use /MT or /MTd")
|
||||
option(WITH_MD_LIBRARY "build with MD" OFF)
|
||||
endif()
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} shlwapi.lib rpcrt4.lib)
|
||||
endif(${TD_WINDOWS})
|
||||
|
||||
|
@ -328,9 +333,11 @@ if (${BUILD_WITH_ROCKSDB})
|
|||
)
|
||||
else()
|
||||
if (NOT ${TD_LINUX})
|
||||
MESSAGE(STATUS "CXXXX STATUS CONFIG: " ${CMAKE_CXX_FLAGS})
|
||||
MESSAGE(STATUS "ROCKSDB CXX STATUS CONFIG: " ${CMAKE_CXX_FLAGS})
|
||||
MESSAGE(STATUS "ROCKSDB C STATUS CONFIG: " ${CMAKE_C_FLAGS})
|
||||
if(${TD_DARWIN})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=maybe-uninitialized")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=maybe-uninitialized")
|
||||
endif(${TD_DARWIN})
|
||||
|
||||
if (${TD_DARWIN_ARM64})
|
||||
|
@ -339,8 +346,12 @@ if (${BUILD_WITH_ROCKSDB})
|
|||
|
||||
if (${TD_WINDOWS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4819")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4244 /wd4819")
|
||||
option(WITH_JNI "" OFF)
|
||||
if(CMAKE_C_FLAGS MATCHES "/MT" OR CMAKE_C_FLAGS MATCHES "/MTd")
|
||||
message("Rocksdb build runtime lib use /MT or /MTd")
|
||||
option(WITH_MD_LIBRARY "build with MD" OFF)
|
||||
endif()
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} shlwapi.lib rpcrt4.lib)
|
||||
endif(${TD_WINDOWS})
|
||||
|
||||
|
@ -406,7 +417,9 @@ endif()
|
|||
|
||||
# pthread
|
||||
if(${BUILD_PTHREAD})
|
||||
set(CMAKE_BUILD_TYPE debug)
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
SET(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
add_definitions(-DPTW32_STATIC_LIB)
|
||||
add_subdirectory(pthread EXCLUDE_FROM_ALL)
|
||||
set_target_properties(libpthreadVC3 PROPERTIES OUTPUT_NAME pthread)
|
||||
|
@ -554,13 +567,18 @@ if(${BUILD_GEOS})
|
|||
if(${TD_LINUX})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_REL}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_REL}")
|
||||
IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
SET(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
endif(${TD_LINUX})
|
||||
option(BUILD_SHARED_LIBS "Build GEOS with shared libraries" OFF)
|
||||
add_subdirectory(geos EXCLUDE_FROM_ALL)
|
||||
if (${TD_WINDOWS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
else ()
|
||||
unset(CMAKE_CXX_STANDARD CACHE) # undo libgeos's setting of global CMAKE_CXX_STANDARD
|
||||
endif(${TD_WINDOWS})
|
||||
target_include_directories(
|
||||
geos_c
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/geos/include>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,7 +5,8 @@ description: This document describes how to insert data into TDengine.
|
|||
---
|
||||
|
||||
## Syntax
|
||||
|
||||
The writing of records supports two syntaxes, normal syntax and super table syntax. In the normal syntax, the table name immediately following `INSERT INTO` represents subtable names or regular table names. In the super table syntax, the table name immediately following `INSERT INTO` represents the super table name.
|
||||
### Normal Syntax
|
||||
```sql
|
||||
INSERT INTO
|
||||
tb_name
|
||||
|
@ -20,6 +21,15 @@ INSERT INTO
|
|||
|
||||
INSERT INTO tb_name [(field1_name, ...)] subquery
|
||||
```
|
||||
### Super Table Syntax
|
||||
```sql
|
||||
INSERT INTO
|
||||
stb1_name [(field1_name, ...)]
|
||||
VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
||||
[stb2_name [(field1_name, ...)]
|
||||
VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
||||
...];
|
||||
```
|
||||
|
||||
**Timestamps**
|
||||
|
||||
|
@ -32,26 +42,34 @@ INSERT INTO tb_name [(field1_name, ...)] subquery
|
|||
|
||||
**Syntax**
|
||||
|
||||
1. The USING clause automatically creates the specified subtable if it does not exist. If it's unknown whether the table already exists, the table can be created automatically while inserting using the SQL statement below. To use this functionality, a STable must be used as template and tag values must be provided. Any tags that you do not specify will be assigned a null value.
|
||||
1. You can insert data into specified columns. Any columns in which you do not insert data will be assigned a null value.
|
||||
|
||||
2. You can insert data into specified columns. Any columns in which you do not insert data will be assigned a null value.
|
||||
2. The VALUES clause inserts one or more rows of data into a table.
|
||||
|
||||
3. The VALUES clause inserts one or more rows of data into a table.
|
||||
3. The FILE clause inserts tags or data from a comma-separates values (CSV) file. Do not include headers in your CSV files.
|
||||
|
||||
4. The FILE clause inserts tags or data from a comma-separates values (CSV) file. Do not include headers in your CSV files.
|
||||
4. A single `INSERT ... VALUES` statement and `INSERT ... FILE` statement can write data to multiple tables.
|
||||
|
||||
5. A single `INSERT ... VALUES` statement and `INSERT ... FILE` statement can write data to multiple tables.
|
||||
|
||||
6. The INSERT statement is fully parsed before being executed, so that if any element of the statement fails, the entire statement will fail. For example, the following statement will not create a table because the latter part of the statement is invalid:
|
||||
5. The INSERT statement is fully parsed before being executed, so that if any element of the statement fails, the entire statement will fail. For example, the following statement will not create a table because the latter part of the statement is invalid:
|
||||
|
||||
```sql
|
||||
INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 2) VALUES('a');
|
||||
```
|
||||
|
||||
7. However, an INSERT statement that writes data to multiple subtables can succeed for some tables and fail for others. This situation is caused because vnodes perform write operations independently of each other. One vnode failing to write data does not affect the ability of other vnodes to write successfully.
|
||||
6. However, an INSERT statement that writes data to multiple subtables can succeed for some tables and fail for others. This situation is caused because vnodes perform write operations independently of each other. One vnode failing to write data does not affect the ability of other vnodes to write successfully.
|
||||
|
||||
8. Data from TDengine can be inserted into a specified table using the `INSERT ... subquery` statement. Arbitrary query statements are supported. This syntax can only be used for subtables and normal tables, and does not support automatic table creation.
|
||||
**Normal Syntax**
|
||||
1. The USING clause automatically creates the specified subtable if it does not exist. If it's unknown whether the table already exists, the table can be created automatically while inserting using the SQL statement below. To use this functionality, a STable must be used as template and tag values must be provided. Any tags that you do not specify will be assigned a null value.
|
||||
|
||||
2. Data from TDengine can be inserted into a specified table using the `INSERT ... subquery` statement. Arbitrary query statements are supported. This syntax can only be used for subtables and normal tables, and does not support automatic table creation.
|
||||
|
||||
**Super Table Syntax**
|
||||
|
||||
1. The tbname column must be included in the field_name list and represents the name of the child table. This column is of string type, and the use of the . character is not permitted in the tbname column.
|
||||
|
||||
2. Tag columns are eligible for inclusion in the field_name list. If the specified child table doesn't exist, a new child table will be generated with the provided tag values. In the absence of specified tag values, the newly created table will have all NULL tag values. Existing child table tag values remain unchanged.
|
||||
|
||||
3. Param binding is not supported.
|
||||
## Insert a Record
|
||||
|
||||
Single row or multiple rows specified with VALUES can be inserted into a specific table. A single row is inserted using the below statement.
|
||||
|
@ -134,3 +152,14 @@ When writing data from a file, you can automatically create the specified subtab
|
|||
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile_21001.csv'
|
||||
d21002 USING meters (groupId) TAGS (2) FILE '/tmp/csvfile_21002.csv';
|
||||
```
|
||||
## Super Table Syntax
|
||||
|
||||
Automatically creating table and the table name is specified through the `tbname` column
|
||||
|
||||
```sql
|
||||
INSERT INTO meters(tbname, location, groupId, ts, current, phase)
|
||||
values('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:34.630', 10.2, 219, 0.32)
|
||||
values('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:35.779', 10.15, 217, 0.33)
|
||||
values('d31002', NULL, 2, '2021-07-13 14:06:34.255', 10.15, 217, 0.33)
|
||||
```
|
||||
|
||||
|
|
|
@ -436,11 +436,22 @@ The `TaosConnection` class and the `TaosResult` class already implement all the
|
|||
:::note
|
||||
The TaosCursor class uses native connections for write and query operations. In a client-side multi-threaded scenario, this cursor instance must remain thread exclusive and cannot be shared across threads for use, otherwise, it will result in errors in the returned results.
|
||||
|
||||
The best practice for TaosCursor is to create a cursor at the beginning of a query and close it immediately after use. Please avoid reusing the same cursor for multiple executions.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="rest" label="REST connection">
|
||||
|
||||
##### Use of the RestClient class
|
||||
|
||||
The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-api). It contains only a `sql()` method for executing arbitrary SQL statements and returning the result.
|
||||
|
||||
```python title="Use of RestClient"
|
||||
{{#include docs/examples/python/rest_client_example.py}}
|
||||
```
|
||||
|
||||
For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html).
|
||||
|
||||
##### Use of TaosRestCursor class
|
||||
|
||||
The `TaosRestCursor` class is an implementation of the PEP249 Cursor interface.
|
||||
|
@ -452,15 +463,9 @@ The `TaosRestCursor` class is an implementation of the PEP249 Cursor interface.
|
|||
- `cursor.rowcount` : For write operations, returns the number of successful rows written. For query operations, returns the number of rows in the result set.
|
||||
- `cursor.description` : Returns the description of the field. Please refer to [TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html) for the specific format of the description information.
|
||||
|
||||
##### Use of the RestClient class
|
||||
|
||||
The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-api). It contains only a `sql()` method for executing arbitrary SQL statements and returning the result.
|
||||
|
||||
```python title="Use of RestClient"
|
||||
{{#include docs/examples/python/rest_client_example.py}}
|
||||
```
|
||||
|
||||
For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html).
|
||||
:::note
|
||||
The best practice for TaosRestCursor is to create a cursor at the beginning of a query and close it immediately after use. Please avoid reusing the same cursor for multiple executions.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="websocket" label="WebSocket connection">
|
||||
|
@ -554,6 +559,16 @@ The `TaosConnection` class and the `TaosResult` class already implement all the
|
|||
</TabItem>
|
||||
<TabItem value="rest" label="REST connection">
|
||||
|
||||
##### Use of the RestClient class
|
||||
|
||||
The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-api). It contains only a `sql()` method for executing arbitrary SQL statements and returning the result.
|
||||
|
||||
```python title="Use of RestClient"
|
||||
{{#include docs/examples/python/rest_client_with_req_id_example.py}}
|
||||
```
|
||||
|
||||
For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html).
|
||||
|
||||
##### Use of TaosRestCursor class
|
||||
|
||||
As the way to connect introduced above but add `req_id` argument.
|
||||
|
@ -565,16 +580,6 @@ As the way to connect introduced above but add `req_id` argument.
|
|||
- `cursor.rowcount` : For write operations, returns the number of successful rows written. For query operations, returns the number of rows in the result set.
|
||||
- `cursor.description` : Returns the description of the field. Please refer to [TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html) for the specific format of the description information.
|
||||
|
||||
##### Use of the RestClient class
|
||||
|
||||
The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-api). It contains only a `sql()` method for executing arbitrary SQL statements and returning the result.
|
||||
|
||||
```python title="Use of RestClient"
|
||||
{{#include docs/examples/python/rest_client_with_req_id_example.py}}
|
||||
```
|
||||
|
||||
For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html).
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="websocket" label="WebSocket connection">
|
||||
|
|
|
@ -10,6 +10,10 @@ For TDengine 2.x installation packages by version, please visit [here](https://t
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.2.1.0
|
||||
|
||||
<Release type="tdengine" version="3.2.1.0" />
|
||||
|
||||
## 3.2.0.0
|
||||
|
||||
<Release type="tdengine" version="3.2.0.0" />
|
||||
|
|
|
@ -33,6 +33,8 @@ data = cursor.fetchall()
|
|||
print(column_names)
|
||||
for row in data:
|
||||
print(row)
|
||||
# close cursor
|
||||
cursor.close()
|
||||
|
||||
# output:
|
||||
# inserted row count: 8
|
||||
|
|
|
@ -33,6 +33,8 @@ data = cursor.fetchall()
|
|||
print(column_names)
|
||||
for row in data:
|
||||
print(row)
|
||||
# close cursor
|
||||
cursor.close()
|
||||
|
||||
# output:
|
||||
# inserted row count: 8
|
||||
|
|
|
@ -436,11 +436,23 @@ now 为系统内部函数,默认为客户端所在计算机当前时间。 now
|
|||
|
||||
:::note
|
||||
TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线程的场景下,这个游标实例必须保持线程独享,不能跨线程共享使用,否则会导致返回结果出现错误。
|
||||
|
||||
TaosCursor 的最佳实践是,查询开始时创建 cursor,用完之后就关闭,请避免复用同一个 cursor 多次执行。
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="rest" label="REST 连接">
|
||||
|
||||
##### RestClient 类的使用
|
||||
|
||||
`RestClient` 类是对于 [REST API](../rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。
|
||||
|
||||
```python title="RestClient 的使用"
|
||||
{{#include docs/examples/python/rest_client_example.py}}
|
||||
```
|
||||
|
||||
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
|
||||
|
||||
##### TaosRestCursor 类的使用
|
||||
|
||||
`TaosRestCursor` 类是对 PEP249 Cursor 接口的实现。
|
||||
|
@ -452,15 +464,10 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
- `cursor.rowcount`: 对于写入操作返回写入成功记录数。对于查询操作,返回结果集行数。
|
||||
- `cursor.description` : 返回字段的描述信息。关于描述信息的具体格式请参考[TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html)。
|
||||
|
||||
##### RestClient 类的使用
|
||||
:::note
|
||||
TaosRestCursor 的最佳实践是,查询开始时创建 cursor,用完之后就关闭,请避免复用同一个 cursor 多次执行。
|
||||
:::
|
||||
|
||||
`RestClient` 类是对于 [REST API](../rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。
|
||||
|
||||
```python title="RestClient 的使用"
|
||||
{{#include docs/examples/python/rest_client_example.py}}
|
||||
```
|
||||
|
||||
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
|
||||
</TabItem>
|
||||
<TabItem value="websocket" label="WebSocket 连接">
|
||||
|
||||
|
@ -557,6 +564,16 @@ RestClient 类是对于 REST API 的直接封装。它只包含一个 sql() 方
|
|||
|
||||
类似上文介绍的使用方法,增加 `req_id` 参数。
|
||||
|
||||
##### RestClient 类的使用
|
||||
|
||||
`RestClient` 类是对于 [REST API](../rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。
|
||||
|
||||
```python title="RestClient 的使用"
|
||||
{{#include docs/examples/python/rest_client_with_req_id_example.py}}
|
||||
```
|
||||
|
||||
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
|
||||
|
||||
##### TaosRestCursor 类的使用
|
||||
|
||||
`TaosRestCursor` 类是对 PEP249 Cursor 接口的实现。
|
||||
|
@ -568,15 +585,6 @@ RestClient 类是对于 REST API 的直接封装。它只包含一个 sql() 方
|
|||
- `cursor.rowcount`: 对于写入操作返回写入成功记录数。对于查询操作,返回结果集行数。
|
||||
- `cursor.description` : 返回字段的描述信息。关于描述信息的具体格式请参考[TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html)。
|
||||
|
||||
##### RestClient 类的使用
|
||||
|
||||
`RestClient` 类是对于 [REST API](../rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。
|
||||
|
||||
```python title="RestClient 的使用"
|
||||
{{#include docs/examples/python/rest_client_with_req_id_example.py}}
|
||||
```
|
||||
|
||||
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="websocket" label="WebSocket 连接">
|
||||
|
|
|
@ -5,7 +5,9 @@ description: 写入数据的详细语法
|
|||
---
|
||||
|
||||
## 写入语法
|
||||
写入记录支持两种语法, 正常语法和超级表语法. 正常语法下, 紧跟INSERT INTO后名的表名是子表名或者普通表名. 超级表语法下, 紧跟INSERT INTO后名的表名是超级表名
|
||||
|
||||
### 正常语法
|
||||
```sql
|
||||
INSERT INTO
|
||||
tb_name
|
||||
|
@ -20,6 +22,15 @@ INSERT INTO
|
|||
|
||||
INSERT INTO tb_name [(field1_name, ...)] subquery
|
||||
```
|
||||
### 超级表语法
|
||||
```sql
|
||||
INSERT INTO
|
||||
stb1_name [(field1_name, ...)]
|
||||
VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
||||
[stb2_name [(field1_name, ...)]
|
||||
VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
||||
...];
|
||||
```
|
||||
|
||||
**关于时间戳**
|
||||
|
||||
|
@ -32,26 +43,34 @@ INSERT INTO tb_name [(field1_name, ...)] subquery
|
|||
|
||||
**语法说明**
|
||||
|
||||
1. USING 子句是自动建表语法。如果用户在写数据时并不确定某个表是否存在,此时可以在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。自动建表时,要求必须以超级表为模板,并写明数据表的 TAGS 取值。可以只是指定部分 TAGS 列的取值,未被指定的 TAGS 列将置为 NULL。
|
||||
1. 可以指定要插入值的列,对于未指定的列数据库将自动填充为 NULL。
|
||||
|
||||
2. 可以指定要插入值的列,对于为指定的列数据库将自动填充为 NULL。
|
||||
2. VALUES 语法表示了要插入的一行或多行数据。
|
||||
|
||||
3. VALUES 语法表示了要插入的一行或多行数据。
|
||||
3. FILE 语法表示数据来自于 CSV 文件(英文逗号分隔、英文单引号括住每个值),CSV 文件无需表头。
|
||||
|
||||
4. FILE 语法表示数据来自于 CSV 文件(英文逗号分隔、英文单引号括住每个值),CSV 文件无需表头。
|
||||
4. `INSERT ... VALUES` 语句和 `INSERT ... FILE` 语句均可以在一条 INSERT 语句中同时向多个表插入数据。
|
||||
|
||||
5. `INSERT ... VALUES` 语句和 `INSERT ... FILE` 语句均可以在一条 INSERT 语句中同时向多个表插入数据。
|
||||
|
||||
6. INSERT 语句是完整解析后再执行的,对如下语句,不会再出现数据错误但建表成功的情况:
|
||||
5. INSERT 语句是完整解析后再执行的,对如下语句,不会再出现数据错误但建表成功的情况:
|
||||
|
||||
```sql
|
||||
INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 2) VALUES('a');
|
||||
```
|
||||
6. 对于向多个子表插入数据的情况,依然会有部分数据写入失败,部分数据写入成功的情况。这是因为多个子表可能分布在不同的 VNODE 上,客户端将 INSERT 语句完整解析后,将数据发往各个涉及的 VNODE 上,每个 VNODE 独立进行写入操作。如果某个 VNODE 因为某些原因(比如网络问题或磁盘故障)导致写入失败,并不会影响其他 VNODE 节点的写入。
|
||||
|
||||
7. 对于向多个子表插入数据的情况,依然会有部分数据写入失败,部分数据写入成功的情况。这是因为多个子表可能分布在不同的 VNODE 上,客户端将 INSERT 语句完整解析后,将数据发往各个涉及的 VNODE 上,每个 VNODE 独立进行写入操作。如果某个 VNODE 因为某些原因(比如网络问题或磁盘故障)导致写入失败,并不会影响其他 VNODE 节点的写入。
|
||||
**正常语法说明**
|
||||
|
||||
8. 可以使用 `INSERT ... subquery` 语句将 TDengine 中的数据插入到指定表中。subquery 可以是任意的查询语句。此语法只能用于子表和普通表,且不支持自动建表。
|
||||
1. USING 子句是自动建表语法。如果用户在写数据时并不确定某个表是否存在,此时可以在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。自动建表时,要求必须以超级表为模板,并写明数据表的 TAGS 取值。可以只是指定部分 TAGS 列的取值,未被指定的 TAGS 列将置为 NULL。
|
||||
|
||||
2. 可以使用 `INSERT ... subquery` 语句将 TDengine 中的数据插入到指定表中。subquery 可以是任意的查询语句。此语法只能用于子表和普通表,且不支持自动建表。
|
||||
|
||||
**超级表语法说明**
|
||||
|
||||
1. 在 field_name 列表中必须指定 tbname 列,否则报错. tbname列是子表名, 类型是字符串. 其中字符不用转义, 不能包含点‘.‘
|
||||
|
||||
2. 在 field_name 列表中支持标签列,当子表已经存在时,指定标签值并不会触发标签值的修改;当子表不存在时会使用所指定的标签值建立子表. 如果没有指定任何标签列,则把所有标签列的值设置为NULL
|
||||
|
||||
3. 不支持参数绑定写入
|
||||
## 插入一条记录
|
||||
|
||||
指定已经创建好的数据子表的表名,并通过 VALUES 关键字提供一行或多行数据,即可向数据库写入这些数据。例如,执行如下语句可以写入一行记录:
|
||||
|
@ -134,3 +153,12 @@ INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/c
|
|||
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile_21001.csv'
|
||||
d21002 USING meters (groupId) TAGS (2) FILE '/tmp/csvfile_21002.csv';
|
||||
```
|
||||
## 超级表语法
|
||||
|
||||
自动建表, 表名通过tbname列指定
|
||||
```sql
|
||||
INSERT INTO meters(tbname, location, groupId, ts, current, phase)
|
||||
values('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:34.630', 10.2, 219, 0.32)
|
||||
values('d31001', 'California.SanFrancisco', 2, '2021-07-13 14:06:35.779', 10.15, 217, 0.33)
|
||||
values('d31002', NULL, 2, '2021-07-13 14:06:34.255', 10.15, 217, 0.33)
|
||||
```
|
||||
|
|
|
@ -10,6 +10,10 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.2.1.0
|
||||
|
||||
<Release type="tdengine" version="3.2.1.0" />
|
||||
|
||||
## 3.2.0.0
|
||||
|
||||
<Release type="tdengine" version="3.2.0.0" />
|
||||
|
|
|
@ -31,6 +31,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define GRANT_HEART_BEAT_MIN 2
|
||||
#define GRANT_ACTIVE_CODE "activeCode"
|
||||
#define GRANT_C_ACTIVE_CODE "cActiveCode"
|
||||
|
||||
typedef enum {
|
||||
TSDB_GRANT_ALL,
|
||||
|
@ -50,6 +52,11 @@ typedef enum {
|
|||
TSDB_GRANT_TABLE,
|
||||
} EGrantType;
|
||||
|
||||
typedef struct {
|
||||
int64_t grantedTime;
|
||||
int64_t connGrantedTime;
|
||||
} SGrantedInfo;
|
||||
|
||||
int32_t grantCheck(EGrantType grant);
|
||||
int32_t grantAlterActiveCode(int32_t did, const char* old, const char* newer, char* out, int8_t type);
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct {
|
|||
*/
|
||||
SSnode *sndOpen(const char *path, const SSnodeOpt *pOption);
|
||||
|
||||
int32_t sndInit(SSnode * pSnode);
|
||||
/**
|
||||
* @brief Stop Snode in Dnode.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Created by mingming wanng on 2023/11/15.
|
||||
//
|
||||
|
||||
#ifndef TDENGINE_STREAM_H
|
||||
#define TDENGINE_STREAM_H
|
||||
|
||||
#define STREAM_EXEC_EXTRACT_DATA_IN_WAL_ID (-1)
|
||||
#define STREAM_EXEC_START_ALL_TASKS_ID (-2)
|
||||
#define STREAM_EXEC_RESTART_ALL_TASKS_ID (-3)
|
||||
|
||||
typedef struct STaskUpdateEntry {
|
||||
int64_t streamId;
|
||||
int32_t taskId;
|
||||
int32_t transId;
|
||||
} STaskUpdateEntry;
|
||||
|
||||
#endif // TDENGINE_STREAM_H
|
|
@ -34,7 +34,6 @@ extern "C" {
|
|||
#define SIZE_IN_MiB(_v) ((_v) / ONE_MiB_F)
|
||||
#define SIZE_IN_KiB(_v) ((_v) / ONE_KiB_F)
|
||||
|
||||
|
||||
#define TASK_DOWNSTREAM_READY 0x0
|
||||
#define TASK_DOWNSTREAM_NOT_READY 0x1
|
||||
#define TASK_DOWNSTREAM_NOT_LEADER 0x2
|
||||
|
@ -591,7 +590,7 @@ typedef struct {
|
|||
int32_t downstreamNodeId;
|
||||
int32_t downstreamTaskId;
|
||||
int32_t childId;
|
||||
int32_t oldStage;
|
||||
int64_t oldStage;
|
||||
int8_t status;
|
||||
} SStreamTaskCheckRsp;
|
||||
|
||||
|
@ -656,7 +655,7 @@ int32_t tDecodeStreamCheckpointReadyMsg(SDecoder* pDecoder, SStreamCheckpointRea
|
|||
typedef struct STaskStatusEntry {
|
||||
STaskId id;
|
||||
int32_t status;
|
||||
int32_t stage;
|
||||
int64_t stage;
|
||||
int32_t nodeId;
|
||||
int64_t verStart; // start version in WAL, only valid for source task
|
||||
int64_t verEnd; // end version in WAL, only valid for source task
|
||||
|
@ -759,7 +758,8 @@ void initRpcMsg(SRpcMsg* pMsg, int32_t msgType, void* pCont, int32_t contLen)
|
|||
// recover and fill history
|
||||
void streamTaskCheckDownstream(SStreamTask* pTask);
|
||||
|
||||
int32_t streamTaskCheckStatus(SStreamTask* pTask, int32_t upstreamTaskId, int32_t vgId, int64_t stage);
|
||||
int32_t streamTaskCheckStatus(SStreamTask* pTask, int32_t upstreamTaskId, int32_t vgId, int64_t stage,
|
||||
int64_t* oldStage);
|
||||
int32_t streamTaskUpdateEpsetInfo(SStreamTask* pTask, SArray* pNodeList);
|
||||
void streamTaskResetUpstreamStageInfo(SStreamTask* pTask);
|
||||
bool streamTaskAllUpstreamClosed(SStreamTask* pTask);
|
||||
|
@ -829,7 +829,6 @@ int32_t streamMetaLoadAllTasks(SStreamMeta* pMeta);
|
|||
int64_t streamMetaGetLatestCheckpointId(SStreamMeta* pMeta);
|
||||
void streamMetaNotifyClose(SStreamMeta* pMeta);
|
||||
void streamMetaStartHb(SStreamMeta* pMeta);
|
||||
void streamMetaInitForSnode(SStreamMeta* pMeta);
|
||||
bool streamMetaTaskInTimer(SStreamMeta* pMeta);
|
||||
int32_t streamMetaUpdateTaskDownstreamStatus(SStreamTask* pTask, int64_t startTs, int64_t endTs, bool succ);
|
||||
void streamMetaRLock(SStreamMeta* pMeta);
|
||||
|
@ -842,7 +841,7 @@ void streamMetaResetStartInfo(STaskStartInfo* pMeta);
|
|||
int32_t streamProcessCheckpointSourceReq(SStreamTask* pTask, SStreamCheckpointSourceReq* pReq);
|
||||
int32_t streamProcessCheckpointReadyMsg(SStreamTask* pTask);
|
||||
int32_t streamTaskBuildCheckpoint(SStreamTask* pTask);
|
||||
void streamTaskClearCheckInfo(SStreamTask* pTask);
|
||||
void streamTaskClearCheckInfo(SStreamTask* pTask, bool clearChkpReadyMsg);
|
||||
int32_t streamAlignTransferState(SStreamTask* pTask);
|
||||
int32_t streamBuildAndSendDropTaskMsg(SMsgCb* pMsgCb, int32_t vgId, SStreamTaskId* pTaskId);
|
||||
int32_t streamAddCheckpointSourceRspMsg(SStreamCheckpointSourceReq* pReq, SRpcHandleInfo* pRpcInfo, SStreamTask* pTask,
|
||||
|
|
|
@ -45,8 +45,8 @@ extern "C" {
|
|||
|
||||
#define SYNC_HEARTBEAT_SLOW_MS 1500
|
||||
#define SYNC_HEARTBEAT_REPLY_SLOW_MS 1500
|
||||
#define SYNC_SNAP_RESEND_MS 1000 * 60
|
||||
#define SYNC_SNAP_TIMEOUT_MS 1000 * 600
|
||||
#define SYNC_SNAP_RESEND_MS 1000 * 300
|
||||
#define SYNC_SNAP_TIMEOUT_MS 1000 * 1800
|
||||
|
||||
#define SYNC_VND_COMMIT_MIN_MS 3000
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef struct TdFile *TdFilePtr;
|
|||
#define TD_FILE_AUTO_DEL 0x0040
|
||||
#define TD_FILE_EXCL 0x0080
|
||||
#define TD_FILE_STREAM 0x0100 // Only support taosFprintfFile, taosGetLineFile, taosEOFFile
|
||||
#define TD_FILE_WRITE_THROUGH 0x0200
|
||||
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions);
|
||||
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions);
|
||||
|
||||
|
|
|
@ -557,6 +557,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_GRANT_GEN_IVLD_KEY TAOS_DEF_ERROR_CODE(0, 0x0812)
|
||||
#define TSDB_CODE_GRANT_GEN_APP_LIMIT TAOS_DEF_ERROR_CODE(0, 0x0813)
|
||||
#define TSDB_CODE_GRANT_GEN_ENC_IVLD_KLEN TAOS_DEF_ERROR_CODE(0, 0x0814)
|
||||
#define TSDB_CODE_GRANT_PAR_IVLD_DIST TAOS_DEF_ERROR_CODE(0, 0x0815)
|
||||
|
||||
// sync
|
||||
// #define TSDB_CODE_SYN_INVALID_CONFIG TAOS_DEF_ERROR_CODE(0, 0x0900) // 2.x
|
||||
|
|
|
@ -66,6 +66,7 @@ extern int32_t udfDebugFlag;
|
|||
extern int32_t smaDebugFlag;
|
||||
extern int32_t idxDebugFlag;
|
||||
extern int32_t tdbDebugFlag;
|
||||
extern int32_t sndDebugFlag;
|
||||
|
||||
int32_t taosInitLog(const char *logName, int32_t maxFiles);
|
||||
void taosCloseLog();
|
||||
|
|
|
@ -60,8 +60,8 @@ if(${BUILD_S3})
|
|||
find_library(S3_LIBRARY s3)
|
||||
find_library(CURL_LIBRARY curl $ENV{HOME}/.cos-local.2/lib NO_DEFAULT_PATH)
|
||||
find_library(XML2_LIBRARY xml2)
|
||||
find_library(SSL_LIBRARY ssl $ENV{HOME}/.cos-local.2/lib64 NO_DEFAULT_PATH)
|
||||
find_library(CRYPTO_LIBRARY crypto $ENV{HOME}/.cos-local.2/lib64 NO_DEFAULT_PATH)
|
||||
find_library(SSL_LIBRARY ssl $ENV{HOME}/.cos-local.2/lib64 $ENV{HOME}/.cos-local.2/lib NO_DEFAULT_PATH)
|
||||
find_library(CRYPTO_LIBRARY crypto $ENV{HOME}/.cos-local.2/lib64 $ENV{HOME}/.cos-local.2/lib NO_DEFAULT_PATH)
|
||||
target_link_libraries(
|
||||
common
|
||||
|
||||
|
|
|
@ -66,11 +66,12 @@ static int should_retry() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void s3PrintError(const char *func, S3Status status, char error_details[]) {
|
||||
static void s3PrintError(const char *filename, int lineno, const char *funcname, S3Status status,
|
||||
char error_details[]) {
|
||||
if (status < S3StatusErrorAccessDenied) {
|
||||
uError("%s: %s", __func__, S3_get_status_name(status));
|
||||
uError("%s/%s:%d-%s: %s", __func__, filename, lineno, funcname, S3_get_status_name(status));
|
||||
} else {
|
||||
uError("%s: %s, %s", __func__, S3_get_status_name(status), error_details);
|
||||
uError("%s/%s:%d-%s: %s, %s", __func__, filename, lineno, funcname, S3_get_status_name(status), error_details);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,9 +231,9 @@ typedef struct put_object_callback_data {
|
|||
int noStatus;
|
||||
} put_object_callback_data;
|
||||
|
||||
#define MULTIPART_CHUNK_SIZE (768 << 20) // multipart is 768M
|
||||
#define MULTIPART_CHUNK_SIZE (64 << 20) // multipart is 768M
|
||||
|
||||
typedef struct UploadManager {
|
||||
typedef struct {
|
||||
char err_msg[512];
|
||||
S3Status status;
|
||||
uint64_t content_length;
|
||||
|
@ -307,6 +308,7 @@ static int putObjectDataCallback(int bufferSize, char *buffer, void *callbackDat
|
|||
S3Status initial_multipart_callback(const char *upload_id, void *callbackData) {
|
||||
UploadManager *manager = (UploadManager *)callbackData;
|
||||
manager->upload_id = strdup(upload_id);
|
||||
manager->status = S3StatusOK;
|
||||
return S3StatusOK;
|
||||
}
|
||||
|
||||
|
@ -437,7 +439,7 @@ static int try_get_parts_info(const char *bucketName, const char *key, UploadMan
|
|||
// printListMultipartHeader(data.allDetails);
|
||||
}
|
||||
} else {
|
||||
s3PrintError(__func__, data.status, data.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, data.status, data.err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -498,7 +500,7 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
} while (S3_status_is_retryable(data.status) && should_retry());
|
||||
|
||||
if (data.status != S3StatusOK) {
|
||||
s3PrintError(__func__, data.status, data.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, data.status, data.err_msg);
|
||||
code = TAOS_SYSTEM_ERROR(EIO);
|
||||
} else if (data.contentLength) {
|
||||
uError("ERROR: %s Failed to read remaining %llu bytes from input", __func__,
|
||||
|
@ -508,15 +510,15 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
} else {
|
||||
uint64_t totalContentLength = contentLength;
|
||||
uint64_t todoContentLength = contentLength;
|
||||
UploadManager manager;
|
||||
manager.upload_id = 0;
|
||||
manager.gb = 0;
|
||||
UploadManager manager = {0};
|
||||
// manager.upload_id = 0;
|
||||
// manager.gb = 0;
|
||||
|
||||
// div round up
|
||||
int seq;
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 7;
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 1000;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
|
@ -535,7 +537,7 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
S3MultipartCommitHandler commit_handler = {
|
||||
{&responsePropertiesCallbackNull, &responseCompleteCallback}, &multipartPutXmlCallback, 0};
|
||||
|
||||
manager.etags = (char **)taosMemoryMalloc(sizeof(char *) * totalSeq);
|
||||
manager.etags = (char **)taosMemoryCalloc(totalSeq, sizeof(char *));
|
||||
manager.next_etags_pos = 0;
|
||||
/*
|
||||
if (uploadId) {
|
||||
|
@ -556,7 +558,7 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
} while (S3_status_is_retryable(manager.status) && should_retry());
|
||||
|
||||
if (manager.upload_id == 0 || manager.status != S3StatusOK) {
|
||||
s3PrintError(__func__, manager.status, manager.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, manager.status, manager.err_msg);
|
||||
code = TAOS_SYSTEM_ERROR(EIO);
|
||||
goto clean;
|
||||
}
|
||||
|
@ -581,7 +583,7 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
partContentLength, 0, timeoutMsG, &partData);
|
||||
} while (S3_status_is_retryable(partData.put_object_data.status) && should_retry());
|
||||
if (partData.put_object_data.status != S3StatusOK) {
|
||||
s3PrintError(__func__, partData.put_object_data.status, partData.put_object_data.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, partData.put_object_data.status, partData.put_object_data.err_msg);
|
||||
code = TAOS_SYSTEM_ERROR(EIO);
|
||||
goto clean;
|
||||
}
|
||||
|
@ -595,6 +597,10 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
char buf[256];
|
||||
int n;
|
||||
for (i = 0; i < totalSeq; i++) {
|
||||
if (!manager.etags[i]) {
|
||||
code = TAOS_SYSTEM_ERROR(EIO);
|
||||
goto clean;
|
||||
}
|
||||
n = snprintf(buf, sizeof(buf),
|
||||
"<Part><PartNumber>%d</PartNumber>"
|
||||
"<ETag>%s</ETag></Part>",
|
||||
|
@ -609,7 +615,7 @@ int32_t s3PutObjectFromFile2(const char *file, const char *object) {
|
|||
timeoutMsG, &manager);
|
||||
} while (S3_status_is_retryable(manager.status) && should_retry());
|
||||
if (manager.status != S3StatusOK) {
|
||||
s3PrintError(__func__, manager.status, manager.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, manager.status, manager.err_msg);
|
||||
code = TAOS_SYSTEM_ERROR(EIO);
|
||||
goto clean;
|
||||
}
|
||||
|
@ -722,7 +728,7 @@ static SArray *getListByPrefix(const char *prefix) {
|
|||
return data.objectArray;
|
||||
}
|
||||
} else {
|
||||
s3PrintError(__func__, data.status, data.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, data.status, data.err_msg);
|
||||
}
|
||||
|
||||
taosArrayDestroyEx(data.objectArray, s3FreeObjectKey);
|
||||
|
@ -741,7 +747,7 @@ void s3DeleteObjects(const char *object_name[], int nobject) {
|
|||
} while (S3_status_is_retryable(cbd.status) && should_retry());
|
||||
|
||||
if ((cbd.status != S3StatusOK) && (cbd.status != S3StatusErrorPreconditionFailed)) {
|
||||
s3PrintError(__func__, cbd.status, cbd.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, cbd.status, cbd.err_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -884,7 +890,7 @@ long s3Size(const char *object_name) {
|
|||
} while (S3_status_is_retryable(cbd.status) && should_retry());
|
||||
|
||||
if ((cbd.status != S3StatusOK) && (cbd.status != S3StatusErrorPreconditionFailed)) {
|
||||
uError("%s: %d(%s)", __func__, cbd.status, cbd.err_msg);
|
||||
s3PrintError(__FILE__, __LINE__, __func__, cbd.status, cbd.err_msg);
|
||||
}
|
||||
|
||||
size = cbd.content_length;
|
||||
|
|
|
@ -167,7 +167,7 @@ static const SSysDbTableSchema streamTaskSchema[] = {
|
|||
{.name = "node_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "level", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "status", .bytes = 15 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "stage", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "stage", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT, .sysInfo = false},
|
||||
{.name = "in_queue", .bytes = 20, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
// {.name = "out_queue", .bytes = 20, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "info", .bytes = 25, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
|
|
|
@ -3590,9 +3590,9 @@ void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_
|
|||
tColDataCalcSMAUInt, // TSDB_DATA_TYPE_UINT
|
||||
tColDataCalcSMAUBigInt, // TSDB_DATA_TYPE_UBIGINT
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_JSON
|
||||
NULL, // TSDB_DATA_TYPE_VARBINARY
|
||||
NULL, // TSDB_DATA_TYPE_DECIMAL
|
||||
NULL, // TSDB_DATA_TYPE_BLOB
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_VARBINARY
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_DECIMAL
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_BLOB
|
||||
NULL, // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
tColDataCalcSMAVarType // TSDB_DATA_TYPE_GEOMETRY
|
||||
};
|
||||
|
|
|
@ -354,11 +354,16 @@ static int32_t taosLoadCfg(SConfig *pCfg, const char **envCmd, const char *input
|
|||
char cfgFile[PATH_MAX + 100] = {0};
|
||||
|
||||
taosExpandDir(inputCfgDir, cfgDir, PATH_MAX);
|
||||
char lastC = cfgDir[strlen(cfgDir) - 1];
|
||||
char *tdDirsep = TD_DIRSEP;
|
||||
if (lastC == '\\' || lastC == '/') {
|
||||
tdDirsep = "";
|
||||
}
|
||||
if (taosIsDir(cfgDir)) {
|
||||
#ifdef CUS_PROMPT
|
||||
snprintf(cfgFile, sizeof(cfgFile), "%s" TD_DIRSEP "%s.cfg", cfgDir, CUS_PROMPT);
|
||||
snprintf(cfgFile, sizeof(cfgFile), "%s" "%s" "%s.cfg", cfgDir, tdDirsep, CUS_PROMPT);
|
||||
#else
|
||||
snprintf(cfgFile, sizeof(cfgFile), "%s" TD_DIRSEP "taos.cfg", cfgDir);
|
||||
snprintf(cfgFile, sizeof(cfgFile), "%s" "%s" "taos.cfg", cfgDir, tdDirsep);
|
||||
#endif
|
||||
} else {
|
||||
tstrncpy(cfgFile, cfgDir, sizeof(cfgDir));
|
||||
|
@ -431,6 +436,7 @@ static int32_t taosAddServerLogCfg(SConfig *pCfg) {
|
|||
if (cfgAddInt32(pCfg, "tdbDebugFlag", tdbDebugFlag, 0, 255, CFG_SCOPE_SERVER, CFG_DYN_SERVER) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "metaDebugFlag", metaDebugFlag, 0, 255, CFG_SCOPE_SERVER, CFG_DYN_SERVER) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "stDebugFlag", stDebugFlag, 0, 255, CFG_SCOPE_SERVER, CFG_DYN_SERVER) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "sndDebugFlag", sndDebugFlag, 0, 255, CFG_SCOPE_SERVER, CFG_DYN_SERVER) != 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -507,6 +513,7 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
|
|||
|
||||
tsNumOfTaskQueueThreads = tsNumOfCores / 2;
|
||||
tsNumOfTaskQueueThreads = TMAX(tsNumOfTaskQueueThreads, 4);
|
||||
|
||||
if (tsNumOfTaskQueueThreads >= 50) {
|
||||
tsNumOfTaskQueueThreads = 50;
|
||||
}
|
||||
|
@ -951,6 +958,7 @@ static void taosSetServerLogCfg(SConfig *pCfg) {
|
|||
tdbDebugFlag = cfgGetItem(pCfg, "tdbDebugFlag")->i32;
|
||||
metaDebugFlag = cfgGetItem(pCfg, "metaDebugFlag")->i32;
|
||||
stDebugFlag = cfgGetItem(pCfg, "stDebugFlag")->i32;
|
||||
sndDebugFlag = cfgGetItem(pCfg, "sndDebugFlag")->i32;
|
||||
}
|
||||
|
||||
static int32_t taosSetSlowLogScope(char *pScope) {
|
||||
|
@ -1424,7 +1432,7 @@ static int32_t taosCfgDynamicOptionsForServer(SConfig *pCfg, char *name) {
|
|||
{"smaDebugFlag", &smaDebugFlag}, {"idxDebugFlag", &idxDebugFlag}, {"tdbDebugFlag", &tdbDebugFlag},
|
||||
{"tmrDebugFlag", &tmrDebugFlag}, {"uDebugFlag", &uDebugFlag}, {"smaDebugFlag", &smaDebugFlag},
|
||||
{"rpcDebugFlag", &rpcDebugFlag}, {"qDebugFlag", &qDebugFlag}, {"metaDebugFlag", &metaDebugFlag},
|
||||
{"jniDebugFlag", &jniDebugFlag}, {"stDebugFlag", &stDebugFlag},
|
||||
{"jniDebugFlag", &jniDebugFlag}, {"stDebugFlag", &stDebugFlag}, {"sndDebugFlag", &sndDebugFlag},
|
||||
};
|
||||
|
||||
static OptionNameAndVar options[] = {
|
||||
|
@ -1732,6 +1740,7 @@ void taosSetAllDebugFlag(int32_t flag, bool rewrite) {
|
|||
taosSetDebugFlag(&tdbDebugFlag, "tdbDebugFlag", flag, rewrite);
|
||||
taosSetDebugFlag(&metaDebugFlag, "metaDebugFlag", flag, rewrite);
|
||||
taosSetDebugFlag(&stDebugFlag, "stDebugFlag", flag, rewrite);
|
||||
taosSetDebugFlag(&sndDebugFlag, "sndDebugFlag", flag, rewrite);
|
||||
uInfo("all debug flag are set to %d", flag);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ int32_t mmWriteFile(const char *path, const SMnodeOpt *pOption) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -73,6 +73,7 @@ SArray *smGetMsgHandles() {
|
|||
SArray *pArray = taosArrayInit(4, sizeof(SMgmtHandle));
|
||||
if (pArray == NULL) goto _OVER;
|
||||
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TASK_UPDATE, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DEPLOY, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DROP, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_RUN, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
|
@ -87,7 +88,8 @@ SArray *smGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_TASK_CHECK_RSP, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_SCAN_HISTORY_FINISH, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_SCAN_HISTORY_FINISH_RSP, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_STREAM_CHECK_POINT_SOURCE, smPutNodeMsgToMgmtQueue, 1) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_CHECKPOINT_READY, smPutNodeMsgToStreamQueue, 1) == NULL) goto _OVER;
|
||||
|
||||
|
||||
code = 0;
|
||||
_OVER:
|
||||
|
|
|
@ -76,9 +76,14 @@ int32_t smOpen(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t smStartSnodes(SSnodeMgmt *pMgmt) {
|
||||
return sndInit(pMgmt->pSnode);
|
||||
}
|
||||
|
||||
SMgmtFunc smGetMgmtFunc() {
|
||||
SMgmtFunc mgmtFunc = {0};
|
||||
mgmtFunc.openFp = smOpen;
|
||||
mgmtFunc.startFp = (NodeStartFp)smStartSnodes;
|
||||
mgmtFunc.closeFp = (NodeCloseFp)smClose;
|
||||
mgmtFunc.createFp = (NodeCreateFp)smProcessCreateReq;
|
||||
mgmtFunc.dropFp = (NodeDropFp)smProcessDropReq;
|
||||
|
|
|
@ -84,8 +84,10 @@ typedef struct {
|
|||
} SVnodeThread;
|
||||
|
||||
// vmInt.c
|
||||
int32_t vmGetPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId);
|
||||
int32_t vmAllocPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId);
|
||||
SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId);
|
||||
SVnodeObj *vmAcquireVnodeImpl(SVnodeMgmt *pMgmt, int32_t vgId, bool strict);
|
||||
void vmReleaseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode);
|
||||
int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl);
|
||||
void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode, bool commitAndRemoveWal);
|
||||
|
|
|
@ -200,7 +200,7 @@ int32_t vmWriteVnodeListToFile(SVnodeMgmt *pMgmt) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -282,7 +282,7 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
vmGenerateWrapperCfg(pMgmt, &req, &wrapperCfg);
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
|
||||
if (pVnode != NULL && !pVnode->failed) {
|
||||
if (pVnode != NULL) {
|
||||
dError("vgId:%d, already exist", req.vgId);
|
||||
tFreeSCreateVnodeReq(&req);
|
||||
vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -291,10 +291,11 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
ASSERT(pVnode == NULL || pVnode->failed);
|
||||
|
||||
wrapperCfg.diskPrimary = pVnode ? pVnode->diskPrimary : vmAllocPrimaryDisk(pMgmt, vnodeCfg.vgId);
|
||||
int32_t diskPrimary = wrapperCfg.diskPrimary;
|
||||
int32_t diskPrimary = vmGetPrimaryDisk(pMgmt, vnodeCfg.vgId);
|
||||
if (diskPrimary < 0) {
|
||||
diskPrimary = vmAllocPrimaryDisk(pMgmt, vnodeCfg.vgId);
|
||||
}
|
||||
wrapperCfg.diskPrimary = diskPrimary;
|
||||
|
||||
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, vnodeCfg.vgId);
|
||||
|
||||
|
@ -371,7 +372,7 @@ int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
TMSG_INFO(pMsg->msgType));
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to alter vnode type since %s", req.vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
if (pVnode) vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -489,7 +490,7 @@ int32_t vmProcessCheckLearnCatchupReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
req.vgId, TMSG_INFO(pMsg->msgType));
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to alter vnode type since %s", req.vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
if (pVnode) vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -532,7 +533,7 @@ int32_t vmProcessDisableVnodeWriteReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
dInfo("vgId:%d, vnode write disable:%d", req.vgId, req.disable);
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to disable write since %s", req.vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
if (pVnode) vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -565,7 +566,7 @@ int32_t vmProcessAlterHashRangeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
dInfo("vgId:%d, start to alter vnode hashrange:[%u, %u], dstVgId:%d", req.srcVgId, req.hashBegin, req.hashEnd,
|
||||
req.dstVgId);
|
||||
pVnode = vmAcquireVnode(pMgmt, srcVgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to alter hashrange since %s", srcVgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
if (pVnode) vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -680,7 +681,7 @@ int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
}
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, vgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, failed to alter replica since %s", vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
if (pVnode) vmReleaseVnode(pMgmt, pVnode);
|
||||
|
@ -748,7 +749,7 @@ int32_t vmProcessDropVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, vgId);
|
||||
SVnodeObj *pVnode = vmAcquireVnodeImpl(pMgmt, vgId, false);
|
||||
if (pVnode == NULL) {
|
||||
dInfo("vgId:%d, failed to drop since %s", vgId, terrstr());
|
||||
terrno = TSDB_CODE_VND_NOT_EXIST;
|
||||
|
|
|
@ -19,6 +19,19 @@
|
|||
#include "vnd.h"
|
||||
#include "libs/function/tudf.h"
|
||||
|
||||
int32_t vmGetPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId) {
|
||||
int32_t diskId = -1;
|
||||
SVnodeObj *pVnode = NULL;
|
||||
|
||||
taosThreadRwlockRdlock(&pMgmt->lock);
|
||||
taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
||||
if (pVnode != NULL) {
|
||||
diskId = pVnode->diskPrimary;
|
||||
}
|
||||
taosThreadRwlockUnlock(&pMgmt->lock);
|
||||
return diskId;
|
||||
}
|
||||
|
||||
int32_t vmAllocPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId) {
|
||||
STfs *pTfs = pMgmt->pTfs;
|
||||
int32_t diskId = 0;
|
||||
|
@ -74,12 +87,12 @@ int32_t vmAllocPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId) {
|
|||
return diskId;
|
||||
}
|
||||
|
||||
SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId) {
|
||||
SVnodeObj *vmAcquireVnodeImpl(SVnodeMgmt *pMgmt, int32_t vgId, bool strict) {
|
||||
SVnodeObj *pVnode = NULL;
|
||||
|
||||
taosThreadRwlockRdlock(&pMgmt->lock);
|
||||
taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
||||
if (pVnode == NULL || pVnode->dropped) {
|
||||
if (pVnode == NULL || strict && (pVnode->dropped || pVnode->failed)) {
|
||||
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
|
||||
pVnode = NULL;
|
||||
} else {
|
||||
|
@ -91,6 +104,8 @@ SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId) {
|
|||
return pVnode;
|
||||
}
|
||||
|
||||
SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId) { return vmAcquireVnodeImpl(pMgmt, vgId, true); }
|
||||
|
||||
void vmReleaseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
|
||||
if (pVnode == NULL) return;
|
||||
|
||||
|
@ -100,6 +115,15 @@ void vmReleaseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
|
|||
taosThreadRwlockUnlock(&pMgmt->lock);
|
||||
}
|
||||
|
||||
static void vmFreeVnodeObj(SVnodeObj **ppVnode) {
|
||||
if (!ppVnode || !(*ppVnode)) return;
|
||||
|
||||
SVnodeObj *pVnode = *ppVnode;
|
||||
taosMemoryFree(pVnode->path);
|
||||
taosMemoryFree(pVnode);
|
||||
ppVnode[0] = NULL;
|
||||
}
|
||||
|
||||
int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) {
|
||||
SVnodeObj *pVnode = taosMemoryCalloc(1, sizeof(SVnodeObj));
|
||||
if (pVnode == NULL) {
|
||||
|
@ -134,6 +158,12 @@ int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) {
|
|||
}
|
||||
|
||||
taosThreadRwlockWrlock(&pMgmt->lock);
|
||||
SVnodeObj *pOld = NULL;
|
||||
taosHashGetDup(pMgmt->hash, &pVnode->vgId, sizeof(int32_t), (void *)&pOld);
|
||||
if (pOld) {
|
||||
ASSERT(pOld->failed);
|
||||
vmFreeVnodeObj(&pOld);
|
||||
}
|
||||
int32_t code = taosHashPut(pMgmt->hash, &pVnode->vgId, sizeof(int32_t), &pVnode, sizeof(SVnodeObj *));
|
||||
taosThreadRwlockUnlock(&pMgmt->lock);
|
||||
|
||||
|
@ -223,8 +253,7 @@ _closed:
|
|||
vnodeDestroy(pVnode->vgId, path, pMgmt->pTfs);
|
||||
}
|
||||
|
||||
taosMemoryFree(pVnode->path);
|
||||
taosMemoryFree(pVnode);
|
||||
vmFreeVnodeObj(&pVnode);
|
||||
}
|
||||
|
||||
static int32_t vmRestoreVgroupId(SWrapperCfg *pCfg, STfs *pTfs) {
|
||||
|
@ -621,7 +650,7 @@ static void *vmRestoreVnodeInThread(void *param) {
|
|||
for (int32_t v = 0; v < pThread->vnodeNum; ++v) {
|
||||
SVnodeObj *pVnode = pThread->ppVnodes[v];
|
||||
if (pVnode->failed) {
|
||||
dError("vgId:%d, skip restoring vnode in failure mode.", pVnode->vgId);
|
||||
dError("vgId:%d, cannot restore a vnode in failed mode.", pVnode->vgId);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp
|
|||
pHead->vgId = ntohl(pHead->vgId);
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, pHead->vgId);
|
||||
if (pVnode == NULL || pVnode->failed) {
|
||||
if (pVnode == NULL) {
|
||||
dGDebug("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s qtype:%d contLen:%d", pHead->vgId, pMsg,
|
||||
terrstr(), TMSG_INFO(pMsg->msgType), qtype, pHead->contLen);
|
||||
terrno = (terrno != 0) ? terrno : -1;
|
||||
|
@ -316,7 +316,7 @@ int32_t vmPutRpcMsgToQueue(SVnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc) {
|
|||
int32_t vmGetQueueSize(SVnodeMgmt *pMgmt, int32_t vgId, EQueueType qtype) {
|
||||
int32_t size = -1;
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, vgId);
|
||||
if (pVnode != NULL && !pVnode->failed) {
|
||||
if (pVnode != NULL) {
|
||||
switch (qtype) {
|
||||
case WRITE_QUEUE:
|
||||
size = taosQueueItemSize(pVnode->pWriteW.queue);
|
||||
|
|
|
@ -232,7 +232,7 @@ int32_t dmWriteEps(SDnodeData *pData) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -120,7 +120,7 @@ int32_t dmWriteFile(const char *path, const char *name, bool deployed) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -27,6 +27,8 @@ void mndCleanupCluster(SMnode *pMnode);
|
|||
int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len);
|
||||
int64_t mndGetClusterId(SMnode *pMnode);
|
||||
int64_t mndGetClusterCreateTime(SMnode *pMnode);
|
||||
int32_t mndGetClusterGrantedInfo(SMnode *pMnode, SGrantedInfo *pInfo);
|
||||
int32_t mndSetClusterGrantedInfo(SMnode *pMnode, SGrantedInfo *pInfo);
|
||||
int64_t mndGetClusterUpTime(SMnode *pMnode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -192,6 +192,8 @@ typedef struct {
|
|||
int64_t createdTime;
|
||||
int64_t updateTime;
|
||||
int32_t upTime;
|
||||
int64_t grantedTime;
|
||||
int64_t connGrantedTime;
|
||||
} SClusterObj;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "mndTrans.h"
|
||||
|
||||
#define CLUSTER_VER_NUMBE 1
|
||||
#define CLUSTER_RESERVE_SIZE 60
|
||||
#define CLUSTER_RESERVE_SIZE 44
|
||||
int64_t tsExpireTime = 0;
|
||||
|
||||
static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster);
|
||||
|
@ -112,6 +112,19 @@ int64_t mndGetClusterCreateTime(SMnode *pMnode) {
|
|||
return createTime;
|
||||
}
|
||||
|
||||
int32_t mndGetClusterGrantedInfo(SMnode *pMnode, SGrantedInfo *pInfo) {
|
||||
void *pIter = NULL;
|
||||
SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter);
|
||||
if (pCluster != NULL) {
|
||||
pInfo->grantedTime = pCluster->grantedTime;
|
||||
pInfo->connGrantedTime = pCluster->connGrantedTime;
|
||||
mndReleaseCluster(pMnode, pCluster, pIter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t mndGetClusterUpTimeImp(SClusterObj *pCluster) {
|
||||
#if 0
|
||||
int32_t upTime = taosGetTimestampSec() - pCluster->updateTime / 1000;
|
||||
|
@ -146,6 +159,8 @@ static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) {
|
|||
SDB_SET_INT64(pRaw, dataPos, pCluster->updateTime, _OVER)
|
||||
SDB_SET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, pCluster->upTime, _OVER)
|
||||
SDB_SET_INT64(pRaw, dataPos, pCluster->grantedTime, _OVER)
|
||||
SDB_SET_INT64(pRaw, dataPos, pCluster->connGrantedTime, _OVER)
|
||||
SDB_SET_RESERVE(pRaw, dataPos, CLUSTER_RESERVE_SIZE, _OVER)
|
||||
|
||||
terrno = 0;
|
||||
|
@ -186,6 +201,8 @@ static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw) {
|
|||
SDB_GET_INT64(pRaw, dataPos, &pCluster->updateTime, _OVER)
|
||||
SDB_GET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, _OVER)
|
||||
SDB_GET_INT32(pRaw, dataPos, &pCluster->upTime, _OVER)
|
||||
SDB_GET_INT64(pRaw, dataPos, &pCluster->grantedTime, _OVER);
|
||||
SDB_GET_INT64(pRaw, dataPos, &pCluster->connGrantedTime, _OVER);
|
||||
SDB_GET_RESERVE(pRaw, dataPos, CLUSTER_RESERVE_SIZE, _OVER)
|
||||
|
||||
terrno = 0;
|
||||
|
@ -218,6 +235,8 @@ static int32_t mndClusterActionUpdate(SSdb *pSdb, SClusterObj *pOld, SClusterObj
|
|||
mTrace("cluster:%" PRId64 ", perform update action, old row:%p new row:%p, uptime from %d to %d", pOld->id, pOld,
|
||||
pNew, pOld->upTime, pNew->upTime);
|
||||
pOld->upTime = pNew->upTime;
|
||||
pOld->grantedTime = pNew->grantedTime;
|
||||
pOld->connGrantedTime = pNew->connGrantedTime;
|
||||
pOld->updateTime = taosGetTimestampMs();
|
||||
return 0;
|
||||
}
|
||||
|
@ -359,3 +378,44 @@ static int32_t mndProcessUptimeTimer(SRpcMsg *pReq) {
|
|||
mndTransDrop(pTrans);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndSetClusterGrantedInfo(SMnode *pMnode, SGrantedInfo *pInfo) {
|
||||
SClusterObj clusterObj = {0};
|
||||
void *pIter = NULL;
|
||||
SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter);
|
||||
if (pCluster != NULL) {
|
||||
if (pCluster->grantedTime >= pInfo->grantedTime && pCluster->connGrantedTime >= pInfo->connGrantedTime) {
|
||||
mndReleaseCluster(pMnode, pCluster, pIter);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&clusterObj, pCluster, sizeof(SClusterObj));
|
||||
if (pCluster->grantedTime < pInfo->grantedTime) clusterObj.grantedTime = pInfo->grantedTime;
|
||||
if (pCluster->connGrantedTime < pInfo->connGrantedTime) clusterObj.connGrantedTime = pInfo->connGrantedTime;
|
||||
mndReleaseCluster(pMnode, pCluster, pIter);
|
||||
}
|
||||
|
||||
if (clusterObj.id <= 0) {
|
||||
mError("can't get cluster info while update granted info");
|
||||
return -1;
|
||||
}
|
||||
|
||||
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, NULL, "granted-info");
|
||||
if (pTrans == NULL) return -1;
|
||||
|
||||
SSdbRaw *pCommitRaw = mndClusterActionEncode(&clusterObj);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
(void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
return 0;
|
||||
}
|
|
@ -919,7 +919,7 @@ static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *
|
|||
if (pIter == NULL) break;
|
||||
|
||||
if (mndVgroupInDb(pVgroup, pNewDb->uid)) {
|
||||
if (mndBuildRaftAlterVgroupAction(pMnode, pTrans, pOldDb, pNewDb, pVgroup, pArray) != 0) {
|
||||
if (mndBuildAlterVgroupAction(pMnode, pTrans, pOldDb, pNewDb, pVgroup, pArray) != 0) {
|
||||
sdbCancelFetch(pSdb, pIter);
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
taosArrayDestroy(pArray);
|
||||
|
|
|
@ -790,7 +790,9 @@ static int32_t mndConfigDnode(SMnode *pMnode, SRpcMsg *pReq, SMCfgDnodeReq *pCfg
|
|||
if (cfgAll) { // alter all dnodes:
|
||||
if (!failRecord) failRecord = taosArrayInit(1, sizeof(int32_t));
|
||||
if (failRecord) taosArrayPush(failRecord, &pDnode->id);
|
||||
if (0 == cfgAllErr) cfgAllErr = terrno; // output 1st terrno.
|
||||
if (0 == cfgAllErr || cfgAllErr == TSDB_CODE_GRANT_PAR_IVLD_ACTIVE) {
|
||||
cfgAllErr = terrno; // output 1st or more specific error
|
||||
}
|
||||
}
|
||||
} else {
|
||||
terrno = 0; // no action for dup active code
|
||||
|
@ -806,7 +808,9 @@ static int32_t mndConfigDnode(SMnode *pMnode, SRpcMsg *pReq, SMCfgDnodeReq *pCfg
|
|||
if (cfgAll) {
|
||||
if (!failRecord) failRecord = taosArrayInit(1, sizeof(int32_t));
|
||||
if (failRecord) taosArrayPush(failRecord, &pDnode->id);
|
||||
if (0 == cfgAllErr) cfgAllErr = terrno;
|
||||
if (0 == cfgAllErr || cfgAllErr == TSDB_CODE_GRANT_PAR_IVLD_ACTIVE) {
|
||||
cfgAllErr = terrno; // output 1st or more specific error
|
||||
}
|
||||
}
|
||||
} else {
|
||||
terrno = 0;
|
||||
|
@ -1283,7 +1287,12 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
|
|||
|
||||
strcpy(dcfgReq.config, "supportvnodes");
|
||||
snprintf(dcfgReq.value, TSDB_DNODE_VALUE_LEN, "%d", flag);
|
||||
} else if (strncasecmp(cfgReq.config, "activeCode", 10) == 0 || strncasecmp(cfgReq.config, "cActiveCode", 11) == 0) {
|
||||
} else if (strncasecmp(cfgReq.config, GRANT_ACTIVE_CODE, 10) == 0 ||
|
||||
strncasecmp(cfgReq.config, GRANT_C_ACTIVE_CODE, 11) == 0) {
|
||||
if (cfgReq.dnodeId != -1) {
|
||||
terrno = TSDB_CODE_INVALID_CFG;
|
||||
goto _err_out;
|
||||
}
|
||||
int8_t opt = strncasecmp(cfgReq.config, "a", 1) == 0 ? DND_ACTIVE_CODE : DND_CONN_ACTIVE_CODE;
|
||||
int8_t index = opt == DND_ACTIVE_CODE ? 10 : 11;
|
||||
if (' ' != cfgReq.config[index] && 0 != cfgReq.config[index]) {
|
||||
|
@ -1301,12 +1310,11 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
|
|||
goto _err_out;
|
||||
}
|
||||
|
||||
strcpy(dcfgReq.config, opt == DND_ACTIVE_CODE ? "activeCode" : "cActiveCode");
|
||||
strcpy(dcfgReq.config, opt == DND_ACTIVE_CODE ? GRANT_ACTIVE_CODE : GRANT_C_ACTIVE_CODE);
|
||||
snprintf(dcfgReq.value, TSDB_DNODE_VALUE_LEN, "%s", cfgReq.value);
|
||||
|
||||
if (mndConfigDnode(pMnode, pReq, &cfgReq, opt) != 0) {
|
||||
if ((terrno = mndConfigDnode(pMnode, pReq, &cfgReq, opt)) != 0) {
|
||||
mError("dnode:%d, failed to config activeCode since %s", cfgReq.dnodeId, terrstr());
|
||||
terrno = TSDB_CODE_INVALID_CFG;
|
||||
goto _err_out;
|
||||
}
|
||||
tFreeSMCfgDnodeReq(&cfgReq);
|
||||
|
|
|
@ -605,7 +605,7 @@ void mndDumpSdb() {
|
|||
char *pCont = tjsonToString(json);
|
||||
int32_t contLen = strlen(pCont);
|
||||
char file[] = "sdb.json";
|
||||
TdFilePtr pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
TdFilePtr pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC| TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) {
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
mError("failed to write %s since %s", file, terrstr());
|
||||
|
|
|
@ -1403,7 +1403,7 @@ static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) {
|
|||
SName name = {0};
|
||||
tNameFromString(&name, dropReq.name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
|
||||
|
||||
auditRecord(pReq, pMnode->clusterId, "dropStream", name.dbname, name.tname, dropReq.sql, dropReq.sqlLen);
|
||||
auditRecord(pReq, pMnode->clusterId, "dropStream", "", name.dbname, dropReq.sql, dropReq.sqlLen);
|
||||
|
||||
sdbRelease(pMnode->pSdb, pStream);
|
||||
mndTransDrop(pTrans);
|
||||
|
@ -2173,6 +2173,9 @@ static SVgroupChangeInfo mndFindChangedNodeInfo(SMnode *pMnode, const SArray *pP
|
|||
epsetAssign(&updateInfo.newEp, &pCurrent->epset);
|
||||
taosArrayPush(info.pUpdateNodeList, &updateInfo);
|
||||
|
||||
|
||||
}
|
||||
if(pCurrent->nodeId != SNODE_HANDLE){
|
||||
SVgObj *pVgroup = mndAcquireVgroup(pMnode, pCurrent->nodeId);
|
||||
taosHashPut(info.pDBMap, pVgroup->dbName, strlen(pVgroup->dbName), NULL, 0);
|
||||
mndReleaseVgroup(pMnode, pVgroup);
|
||||
|
@ -2228,6 +2231,24 @@ static SArray *mndTakeVgroupSnapshot(SMnode *pMnode, bool *allReady) {
|
|||
sdbRelease(pSdb, pVgroup);
|
||||
}
|
||||
|
||||
SSnodeObj *pObj = NULL;
|
||||
while (1) {
|
||||
pIter = sdbFetch(pSdb, SDB_SNODE, pIter, (void **)&pObj);
|
||||
if (pIter == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
SNodeEntry entry = {0};
|
||||
addEpIntoEpSet(&entry.epset, pObj->pDnode->fqdn, pObj->pDnode->port);
|
||||
entry.nodeId = SNODE_HANDLE;
|
||||
|
||||
char buf[256] = {0};
|
||||
EPSET_TO_STR(&entry.epset, buf);
|
||||
mDebug("take snode snapshot, nodeId:%d %s", entry.nodeId, buf);
|
||||
taosArrayPush(pVgroupListSnapshot, &entry);
|
||||
sdbRelease(pSdb, pObj);
|
||||
}
|
||||
|
||||
return pVgroupListSnapshot;
|
||||
}
|
||||
|
||||
|
@ -2405,6 +2426,8 @@ int32_t removeExpirednodeEntryAndTask(SArray *pNodeSnapshot) {
|
|||
STaskId * pId = taosArrayGet(execInfo.pTaskList, i);
|
||||
STaskStatusEntry *pEntry = taosHashGet(execInfo.pTaskMap, pId, sizeof(*pId));
|
||||
|
||||
if(pEntry->nodeId == SNODE_HANDLE) continue;
|
||||
|
||||
bool existed = taskNodeExists(pNodeSnapshot, pEntry->nodeId);
|
||||
if (!existed) {
|
||||
taosArrayPush(pRemovedTasks, pId);
|
||||
|
@ -2765,12 +2788,12 @@ int32_t setNodeEpsetExpiredFlag(const SArray *pNodeList) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void updateStageInfo(STaskStatusEntry* pTaskEntry, int32_t stage) {
|
||||
static void updateStageInfo(STaskStatusEntry* pTaskEntry, int64_t stage) {
|
||||
int32_t numOfNodes = taosArrayGetSize(execInfo.pNodeList);
|
||||
for(int32_t j = 0; j < numOfNodes; ++j) {
|
||||
SNodeEntry* pNodeEntry = taosArrayGet(execInfo.pNodeList, j);
|
||||
if (pNodeEntry->nodeId == pTaskEntry->nodeId) {
|
||||
mInfo("vgId:%d stage updated from %d to %d, nodeUpdate trigger by s-task:0x%" PRIx64, pTaskEntry->nodeId,
|
||||
mInfo("vgId:%d stage updated from %"PRId64 " to %"PRId64 ", nodeUpdate trigger by s-task:0x%" PRIx64, pTaskEntry->nodeId,
|
||||
pTaskEntry->stage, stage, pTaskEntry->id.taskId);
|
||||
|
||||
pNodeEntry->stageUpdated = true;
|
||||
|
@ -2815,6 +2838,7 @@ int32_t mndProcessStreamHb(SRpcMsg *pReq) {
|
|||
setNodeEpsetExpiredFlag(req.pUpdateNodes);
|
||||
}
|
||||
|
||||
bool snodeChanged = false;
|
||||
for (int32_t i = 0; i < req.numOfTasks; ++i) {
|
||||
STaskStatusEntry *p = taosArrayGet(req.pTaskStatus, i);
|
||||
STaskStatusEntry *pTaskEntry = taosHashGet(execInfo.pTaskMap, &p->id, sizeof(p->id));
|
||||
|
@ -2825,6 +2849,7 @@ int32_t mndProcessStreamHb(SRpcMsg *pReq) {
|
|||
|
||||
if (pTaskEntry->stage != p->stage && pTaskEntry->stage != -1) {
|
||||
updateStageInfo(pTaskEntry, p->stage);
|
||||
if(pTaskEntry->nodeId == SNODE_HANDLE) snodeChanged = true;
|
||||
} else {
|
||||
streamTaskStatusCopy(pTaskEntry, p);
|
||||
if (p->activeCheckpointId != 0) {
|
||||
|
@ -2853,7 +2878,7 @@ int32_t mndProcessStreamHb(SRpcMsg *pReq) {
|
|||
SArray *p = mndTakeVgroupSnapshot(pMnode, &allReady);
|
||||
taosArrayDestroy(p);
|
||||
|
||||
if (allReady) {
|
||||
if (allReady || snodeChanged) {
|
||||
// if the execInfo.activeCheckpoint == 0, the checkpoint is restoring from wal
|
||||
mInfo("checkpointId:%" PRId64 " failed, issue task-reset trans to reset all tasks status",
|
||||
execInfo.activeCheckpoint);
|
||||
|
|
|
@ -38,7 +38,7 @@ class MndTestTrans1 : public ::testing::Test {
|
|||
|
||||
test.ServerStop();
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
int32_t writeLen = taosWriteFile(pFile, buffer, readLen);
|
||||
if (writeLen < 0 || writeLen == readLen) {
|
||||
ASSERT(1);
|
||||
|
|
|
@ -3,6 +3,7 @@ add_library(snode STATIC ${SNODE_SRC})
|
|||
target_include_directories(
|
||||
snode
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/dnode/snode"
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/dnode/vnode"
|
||||
private "${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
||||
)
|
||||
target_link_libraries(
|
||||
|
|
|
@ -18,6 +18,28 @@
|
|||
#include "sndInt.h"
|
||||
#include "tstream.h"
|
||||
#include "tuuid.h"
|
||||
#include "stream.h"
|
||||
|
||||
#define sndError(...) \
|
||||
do { \
|
||||
if (sndDebugFlag & DEBUG_ERROR) { \
|
||||
taosPrintLog("SND ERROR ", DEBUG_ERROR, sndDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define sndInfo(...) \
|
||||
do { \
|
||||
if (sndDebugFlag & DEBUG_INFO) { \
|
||||
taosPrintLog("SND INFO ", DEBUG_INFO, sndDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define sndDebug(...) \
|
||||
do { \
|
||||
if (sndDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLog("SND ", DEBUG_DEBUG, sndDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void sndEnqueueStreamDispatch(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
char *msgStr = pMsg->pCont;
|
||||
|
@ -40,10 +62,14 @@ void sndEnqueueStreamDispatch(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
if (pTask) {
|
||||
SRpcMsg rsp = { .info = pMsg->info, .code = 0 };
|
||||
streamProcessDispatchMsg(pTask, &req, &rsp);
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
return;
|
||||
} else {
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
FAIL:
|
||||
|
@ -63,20 +89,37 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t nextProcessVer
|
|||
|
||||
streamTaskOpenAllUpstreamInput(pTask);
|
||||
|
||||
pTask->pState = streamStateOpen(pSnode->path, pTask, false, -1, -1);
|
||||
if (pTask->pState == NULL) {
|
||||
qError("s-task:%s failed to open state for task", pTask->id.idStr);
|
||||
return -1;
|
||||
} else {
|
||||
qDebug("s-task:%s state:%p", pTask->id.idStr, pTask->pState);
|
||||
SStreamTask* pSateTask = pTask;
|
||||
SStreamTask task = {0};
|
||||
if (pTask->info.fillHistory) {
|
||||
task.id.streamId = pTask->streamTaskId.streamId;
|
||||
task.id.taskId = pTask->streamTaskId.taskId;
|
||||
task.pMeta = pTask->pMeta;
|
||||
pSateTask = &task;
|
||||
}
|
||||
|
||||
int32_t numOfChildEp = taosArrayGetSize(pTask->upstreamInfo.pList);
|
||||
SReadHandle handle = { .vnode = NULL, .numOfVgroups = numOfChildEp, .pStateBackend = pTask->pState, .fillHistory = pTask->info.fillHistory };
|
||||
pTask->pState = streamStateOpen(pSnode->path, pSateTask, false, -1, -1);
|
||||
if (pTask->pState == NULL) {
|
||||
sndError("s-task:%s failed to open state for task", pTask->id.idStr);
|
||||
return -1;
|
||||
} else {
|
||||
sndDebug("s-task:%s state:%p", pTask->id.idStr, pTask->pState);
|
||||
}
|
||||
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTask->upstreamInfo.pList);
|
||||
SReadHandle handle = {
|
||||
.checkpointId = pTask->chkInfo.checkpointId,
|
||||
.vnode = NULL,
|
||||
.numOfVgroups = numOfVgroups,
|
||||
.pStateBackend = pTask->pState,
|
||||
.fillHistory = pTask->info.fillHistory,
|
||||
.winRange = pTask->dataRange.window,
|
||||
};
|
||||
initStreamStateAPI(&handle.api);
|
||||
|
||||
pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, 0, pTask->id.taskId);
|
||||
pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, SNODE_HANDLE, pTask->id.taskId);
|
||||
ASSERT(pTask->exec.pExecutor);
|
||||
qSetTaskId(pTask->exec.pExecutor, pTask->id.taskId, pTask->id.streamId);
|
||||
|
||||
streamTaskResetUpstreamStageInfo(pTask);
|
||||
streamSetupScheduleTrigger(pTask);
|
||||
|
@ -85,7 +128,7 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t nextProcessVer
|
|||
// checkpoint ver is the kept version, handled data should be the next version.
|
||||
if (pTask->chkInfo.checkpointId != 0) {
|
||||
pTask->chkInfo.nextProcessVer = pTask->chkInfo.checkpointVer + 1;
|
||||
qInfo("s-task:%s restore from the checkpointId:%" PRId64 " ver:%" PRId64 " nextProcessVer:%" PRId64, pTask->id.idStr,
|
||||
sndInfo("s-task:%s restore from the checkpointId:%" PRId64 " ver:%" PRId64 " nextProcessVer:%" PRId64, pTask->id.idStr,
|
||||
pChkInfo->checkpointId, pChkInfo->checkpointVer, pChkInfo->nextProcessVer);
|
||||
} else {
|
||||
if (pTask->chkInfo.nextProcessVer == -1) {
|
||||
|
@ -96,7 +139,7 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t nextProcessVer
|
|||
char* p = NULL;
|
||||
streamTaskGetStatus(pTask, &p);
|
||||
|
||||
qInfo("snode:%d expand stream task, s-task:%s, checkpointId:%" PRId64 " checkpointVer:%" PRId64
|
||||
sndInfo("snode:%d expand stream task, s-task:%s, checkpointId:%" PRId64 " checkpointVer:%" PRId64
|
||||
" nextProcessVer:%" PRId64 " child id:%d, level:%d, status:%s fill-history:%d, trigger:%" PRId64 " ms",
|
||||
SNODE_HANDLE, pTask->id.idStr, pChkInfo->checkpointId, pChkInfo->checkpointVer, pChkInfo->nextProcessVer,
|
||||
pTask->info.selfChildId, pTask->info.taskLevel, p, pTask->info.fillHistory, pTask->info.triggerParam);
|
||||
|
@ -104,6 +147,142 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t nextProcessVer
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndStartStreamTasks(SSnode* pSnode) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t vgId = SNODE_HANDLE;
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
sndDebug("vgId:%d start to check all %d stream task(s) downstream status", vgId, numOfTasks);
|
||||
if (numOfTasks == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SArray* pTaskList = NULL;
|
||||
streamMetaWLock(pMeta);
|
||||
pTaskList = taosArrayDup(pMeta->pTaskList, NULL);
|
||||
taosHashClear(pMeta->startInfo.pReadyTaskSet);
|
||||
taosHashClear(pMeta->startInfo.pFailedTaskSet);
|
||||
pMeta->startInfo.startTs = taosGetTimestampMs();
|
||||
streamMetaWUnLock(pMeta);
|
||||
|
||||
// broadcast the check downstream tasks msg
|
||||
for (int32_t i = 0; i < numOfTasks; ++i) {
|
||||
SStreamTaskId* pTaskId = taosArrayGet(pTaskList, i);
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, pTaskId->streamId, pTaskId->taskId);
|
||||
if (pTask == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// fill-history task can only be launched by related stream tasks.
|
||||
if (pTask->info.fillHistory == 1) {
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pTask->status.downstreamReady == 1) {
|
||||
if (HAS_RELATED_FILLHISTORY_TASK(pTask)) {
|
||||
sndDebug("s-task:%s downstream ready, no need to check downstream, check only related fill-history task",
|
||||
pTask->id.idStr);
|
||||
streamLaunchFillHistoryTask(pTask);
|
||||
}
|
||||
|
||||
streamMetaUpdateTaskDownstreamStatus(pTask, pTask->execInfo.init, pTask->execInfo.start, true);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
EStreamTaskEvent event = (HAS_RELATED_FILLHISTORY_TASK(pTask)) ? TASK_EVENT_INIT_STREAM_SCANHIST : TASK_EVENT_INIT;
|
||||
int32_t ret = streamTaskHandleEvent(pTask->status.pSM, event);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
code = ret;
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pTaskList);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t sndResetStreamTaskStatus(SSnode* pSnode) {
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
int32_t vgId = pMeta->vgId;
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
|
||||
sndDebug("vgId:%d reset all %d stream task(s) status to be uninit", vgId, numOfTasks);
|
||||
if (numOfTasks == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfTasks; ++i) {
|
||||
SStreamTaskId* pTaskId = taosArrayGet(pMeta->pTaskList, i);
|
||||
|
||||
STaskId id = {.streamId = pTaskId->streamId, .taskId = pTaskId->taskId};
|
||||
SStreamTask** pTask = taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
|
||||
streamTaskResetStatus(*pTask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndRestartStreamTasks(SSnode* pSnode) {
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
int32_t vgId = pMeta->vgId;
|
||||
int32_t code = 0;
|
||||
int64_t st = taosGetTimestampMs();
|
||||
|
||||
while(1) {
|
||||
int32_t startVal = atomic_val_compare_exchange_32(&pMeta->startInfo.taskStarting, 0, 1);
|
||||
if (startVal == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sndDebug("vgId:%d in start stream tasks procedure, wait for 500ms and recheck", vgId);
|
||||
taosMsleep(500);
|
||||
}
|
||||
|
||||
terrno = 0;
|
||||
sndInfo("vgId:%d tasks are all updated and stopped, restart all tasks, triggered by transId:%d", vgId,
|
||||
pMeta->updateInfo.transId);
|
||||
|
||||
while (streamMetaTaskInTimer(pMeta)) {
|
||||
sndDebug("vgId:%d some tasks in timer, wait for 100ms and recheck", pMeta->vgId);
|
||||
taosMsleep(100);
|
||||
}
|
||||
|
||||
streamMetaWLock(pMeta);
|
||||
|
||||
code = streamMetaReopen(pMeta);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sndError("vgId:%d failed to reopen stream meta", vgId);
|
||||
streamMetaWUnLock(pMeta);
|
||||
code = terrno;
|
||||
return code;
|
||||
}
|
||||
|
||||
streamMetaInitBackend(pMeta);
|
||||
int64_t el = taosGetTimestampMs() - st;
|
||||
|
||||
sndInfo("vgId:%d close&reload state elapsed time:%.3fs", vgId, el/1000.);
|
||||
|
||||
code = streamMetaLoadAllTasks(pMeta);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sndError("vgId:%d failed to load stream tasks, code:%s", vgId, tstrerror(terrno));
|
||||
streamMetaWUnLock(pMeta);
|
||||
code = terrno;
|
||||
return code;
|
||||
}
|
||||
sndInfo("vgId:%d restart all stream tasks after all tasks being updated", vgId);
|
||||
sndResetStreamTaskStatus(pSnode);
|
||||
|
||||
streamMetaWUnLock(pMeta);
|
||||
sndStartStreamTasks(pSnode);
|
||||
|
||||
code = terrno;
|
||||
return code;
|
||||
}
|
||||
|
||||
SSnode *sndOpen(const char *path, const SSnodeOpt *pOption) {
|
||||
SSnode *pSnode = taosMemoryCalloc(1, sizeof(SSnode));
|
||||
if (pSnode == NULL) {
|
||||
|
@ -117,17 +296,19 @@ SSnode *sndOpen(const char *path, const SSnodeOpt *pOption) {
|
|||
}
|
||||
|
||||
pSnode->msgCb = pOption->msgCb;
|
||||
pSnode->pMeta = streamMetaOpen(path, pSnode, (FTaskExpand *)sndExpandTask, SNODE_HANDLE, -1);
|
||||
pSnode->pMeta = streamMetaOpen(path, pSnode, (FTaskExpand *)sndExpandTask, SNODE_HANDLE, taosGetTimestampMs());
|
||||
if (pSnode->pMeta == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
if (streamMetaLoadAllTasks(pSnode->pMeta) < 0) {
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
stopRsync();
|
||||
startRsync();
|
||||
|
||||
// todo fix it: send msg to mnode to rollback to an existed checkpoint
|
||||
streamMetaInitForSnode(pSnode->pMeta);
|
||||
return pSnode;
|
||||
|
||||
FAIL:
|
||||
|
@ -136,7 +317,14 @@ FAIL:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int32_t sndInit(SSnode * pSnode) {
|
||||
sndResetStreamTaskStatus(pSnode);
|
||||
sndStartStreamTasks(pSnode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sndClose(SSnode *pSnode) {
|
||||
stopRsync();
|
||||
streamMetaNotifyClose(pSnode->pMeta);
|
||||
streamMetaCommit(pSnode->pMeta);
|
||||
streamMetaClose(pSnode->pMeta);
|
||||
|
@ -146,6 +334,33 @@ void sndClose(SSnode *pSnode) {
|
|||
|
||||
int32_t sndGetLoad(SSnode *pSnode, SSnodeLoad *pLoad) { return 0; }
|
||||
|
||||
int32_t sndStartStreamTaskAsync(SSnode* pSnode, bool restart) {
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
int32_t vgId = pMeta->vgId;
|
||||
|
||||
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
|
||||
if (numOfTasks == 0) {
|
||||
sndDebug("vgId:%d no stream tasks existed to run", vgId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
|
||||
if (pRunReq == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
sndError("vgId:%d failed to create msg to start wal scanning to launch stream tasks, code:%s", vgId, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
sndDebug("vgId:%d start all %d stream task(s) async", vgId, numOfTasks);
|
||||
pRunReq->head.vgId = vgId;
|
||||
pRunReq->streamId = 0;
|
||||
pRunReq->taskId = restart? STREAM_EXEC_RESTART_ALL_TASKS_ID:STREAM_EXEC_START_ALL_TASKS_ID;
|
||||
|
||||
SRpcMsg msg = {.msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq)};
|
||||
tmsgPutToQueue(&pSnode->msgCb, STREAM_QUEUE, &msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
||||
int32_t code;
|
||||
|
||||
|
@ -184,24 +399,23 @@ int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
|||
char* p = NULL;
|
||||
streamTaskGetStatus(pTask, &p);
|
||||
|
||||
qDebug("snode:%d s-task:%s is deployed on snode and add into meta, status:%s, numOfTasks:%d", SNODE_HANDLE,
|
||||
sndDebug("snode:%d s-task:%s is deployed on snode and add into meta, status:%s, numOfTasks:%d", SNODE_HANDLE,
|
||||
pTask->id.idStr, p, numOfTasks);
|
||||
|
||||
EStreamTaskEvent event = (HAS_RELATED_FILLHISTORY_TASK(pTask)) ? TASK_EVENT_INIT_STREAM_SCANHIST : TASK_EVENT_INIT;
|
||||
streamTaskHandleEvent(pTask->status.pSM, event);
|
||||
streamTaskCheckDownstream(pTask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessTaskDropReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
||||
SVDropStreamTaskReq *pReq = (SVDropStreamTaskReq *)msg;
|
||||
qDebug("snode:%d receive msg to drop stream task:0x%x", pSnode->pMeta->vgId, pReq->taskId);
|
||||
sndDebug("snode:%d receive msg to drop stream task:0x%x", pSnode->pMeta->vgId, pReq->taskId);
|
||||
streamMetaUnregisterTask(pSnode->pMeta, pReq->streamId, pReq->taskId);
|
||||
|
||||
// commit the update
|
||||
streamMetaWLock(pSnode->pMeta);
|
||||
int32_t numOfTasks = streamMetaGetNumOfTasks(pSnode->pMeta);
|
||||
qDebug("vgId:%d task:0x%x dropped, remain tasks:%d", pSnode->pMeta->vgId, pReq->taskId, numOfTasks);
|
||||
sndDebug("vgId:%d task:0x%x dropped, remain tasks:%d", pSnode->pMeta->vgId, pReq->taskId, numOfTasks);
|
||||
|
||||
if (streamMetaCommit(pSnode->pMeta) < 0) {
|
||||
// persist to disk
|
||||
|
@ -213,6 +427,16 @@ int32_t sndProcessTaskDropReq(SSnode *pSnode, char *msg, int32_t msgLen) {
|
|||
int32_t sndProcessTaskRunReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
SStreamTaskRunReq *pReq = pMsg->pCont;
|
||||
|
||||
int32_t taskId = pReq->taskId;
|
||||
|
||||
if (taskId == STREAM_EXEC_START_ALL_TASKS_ID) {
|
||||
sndStartStreamTasks(pSnode);
|
||||
return 0;
|
||||
} else if (taskId == STREAM_EXEC_RESTART_ALL_TASKS_ID) {
|
||||
sndRestartStreamTasks(pSnode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamTask *pTask = streamMetaAcquireTask(pSnode->pMeta, pReq->streamId, pReq->taskId);
|
||||
if (pTask) {
|
||||
streamExecTask(pTask);
|
||||
|
@ -231,14 +455,17 @@ int32_t sndProcessTaskDispatchReq(SSnode *pSnode, SRpcMsg *pMsg, bool exec) {
|
|||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t *)msgBody, msgLen);
|
||||
tDecodeStreamDispatchReq(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SStreamTask *pTask = streamMetaAcquireTask(pSnode->pMeta, req.streamId, req.taskId);
|
||||
if (pTask) {
|
||||
SRpcMsg rsp = {.info = pMsg->info, .code = 0};
|
||||
streamProcessDispatchMsg(pTask, &req, &rsp);
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
return 0;
|
||||
} else {
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -270,6 +497,9 @@ int32_t sndProcessTaskDispatchRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
|
||||
pRsp->upstreamTaskId = htonl(pRsp->upstreamTaskId);
|
||||
pRsp->streamId = htobe64(pRsp->streamId);
|
||||
pRsp->downstreamTaskId = htonl(pRsp->downstreamTaskId);
|
||||
pRsp->downstreamNodeId = htonl(pRsp->downstreamNodeId);
|
||||
pRsp->stage = htobe64(pRsp->stage);
|
||||
pRsp->msgId = htonl(pRsp->msgId);
|
||||
|
||||
SStreamTask *pTask = streamMetaAcquireTask(pSnode->pMeta, pRsp->streamId, pRsp->upstreamTaskId);
|
||||
|
@ -287,23 +517,7 @@ int32_t sndProcessTaskRetrieveRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessWriteMsg(SSnode *pSnode, SRpcMsg *pMsg, SRpcMsg *pRsp) {
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_DEPLOY: {
|
||||
void *pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
return sndProcessTaskDeployReq(pSnode, pReq, len);
|
||||
}
|
||||
|
||||
case TDMT_STREAM_TASK_DROP:
|
||||
return sndProcessTaskDropReq(pSnode, pMsg->pCont, pMsg->contLen);
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamTaskScanHistoryFinishReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
int32_t sndProcessTaskScanHistoryFinishReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
char *msg = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
||||
|
@ -330,11 +544,73 @@ int32_t sndProcessStreamTaskScanHistoryFinishReq(SSnode *pSnode, SRpcMsg *pMsg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessTaskRecoverFinishRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
//
|
||||
int32_t sndProcessTaskScanHistoryFinishRsp(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
char* msg = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t msgLen = pMsg->contLen - sizeof(SMsgHead);
|
||||
|
||||
// deserialize
|
||||
SStreamCompleteHistoryMsg req = {0};
|
||||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
|
||||
tDecodeCompleteHistoryDataMsg(&decoder, &req);
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pSnode->pMeta, req.streamId, req.upstreamTaskId);
|
||||
if (pTask == NULL) {
|
||||
sndError("vgId:%d process scan history finish rsp, failed to find task:0x%x, it may be destroyed",
|
||||
pSnode->pMeta->vgId, req.upstreamTaskId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t remain = atomic_sub_fetch_32(&pTask->notReadyTasks, 1);
|
||||
if (remain > 0) {
|
||||
sndDebug("s-task:%s scan-history finish rsp received from downstream task:0x%x, unfinished remain:%d",
|
||||
pTask->id.idStr, req.downstreamId, remain);
|
||||
} else {
|
||||
sndDebug(
|
||||
"s-task:%s scan-history finish rsp received from downstream task:0x%x, all downstream tasks rsp scan-history "
|
||||
"completed msg",
|
||||
pTask->id.idStr, req.downstreamId);
|
||||
streamProcessScanHistoryFinishRsp(pTask);
|
||||
}
|
||||
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// downstream task has complete the stream task checkpoint procedure, let's start the handle the rsp by execute task
|
||||
int32_t sndProcessTaskCheckpointReadyMsg(SSnode *pSnode, SRpcMsg* pMsg) {
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
char* msg = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
int32_t code = 0;
|
||||
|
||||
SStreamCheckpointReadyMsg req = {0};
|
||||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, len);
|
||||
if (tDecodeStreamCheckpointReadyMsg(&decoder, &req) < 0) {
|
||||
code = TSDB_CODE_MSG_DECODE_ERROR;
|
||||
tDecoderClear(&decoder);
|
||||
return code;
|
||||
}
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, req.streamId, req.upstreamTaskId);
|
||||
if (pTask == NULL) {
|
||||
sndError("vgId:%d failed to find s-task:0x%x, it may have been destroyed already", pMeta->vgId, req.downstreamTaskId);
|
||||
return code;
|
||||
}
|
||||
|
||||
sndDebug("snode vgId:%d s-task:%s received the checkpoint ready msg from task:0x%x (vgId:%d), handle it", pMeta->vgId,
|
||||
pTask->id.idStr, req.downstreamTaskId, req.downstreamNodeId);
|
||||
|
||||
streamProcessCheckpointReadyMsg(pTask);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamTaskCheckReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
char *msgStr = pMsg->pCont;
|
||||
char *msgBody = POINTER_SHIFT(msgStr, sizeof(SMsgHead));
|
||||
|
@ -362,15 +638,15 @@ int32_t sndProcessStreamTaskCheckReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
SStreamTask *pTask = streamMetaAcquireTask(pSnode->pMeta, req.streamId, taskId);
|
||||
|
||||
if (pTask != NULL) {
|
||||
rsp.status = streamTaskCheckStatus(pTask, req.upstreamTaskId, req.upstreamNodeId, req.stage);
|
||||
rsp.status = streamTaskCheckStatus(pTask, req.upstreamTaskId, req.upstreamNodeId, req.stage, &rsp.oldStage);
|
||||
streamMetaReleaseTask(pSnode->pMeta, pTask);
|
||||
char* p = NULL;
|
||||
streamTaskGetStatus(pTask, &p);
|
||||
qDebug("s-task:%s status:%s, recv task check req(reqId:0x%" PRIx64 ") task:0x%x (vgId:%d), ready:%d",
|
||||
sndDebug("s-task:%s status:%s, recv task check req(reqId:0x%" PRIx64 ") task:0x%x (vgId:%d), ready:%d",
|
||||
pTask->id.idStr, p, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
} else {
|
||||
rsp.status = TASK_DOWNSTREAM_NOT_READY;
|
||||
qDebug("recv task check(taskId:0x%x not built yet) req(reqId:0x%" PRIx64 ") from task:0x%x (vgId:%d), rsp status %d",
|
||||
sndDebug("recv task check(taskId:0x%x not built yet) req(reqId:0x%" PRIx64 ") from task:0x%x (vgId:%d), rsp status %d",
|
||||
taskId, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
}
|
||||
|
||||
|
@ -380,7 +656,7 @@ int32_t sndProcessStreamTaskCheckReq(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
|
||||
tEncodeSize(tEncodeStreamTaskCheckRsp, &rsp, len, code);
|
||||
if (code < 0) {
|
||||
qError("vgId:%d failed to encode task check rsp, task:0x%x", pSnode->pMeta->vgId, taskId);
|
||||
sndError("vgId:%d failed to encode task check rsp, task:0x%x", pSnode->pMeta->vgId, taskId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -415,12 +691,12 @@ int32_t sndProcessStreamTaskCheckRsp(SSnode* pSnode, SRpcMsg* pMsg) {
|
|||
}
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
qDebug("tq task:0x%x (vgId:%d) recv check rsp(reqId:0x%" PRIx64 ") from 0x%x (vgId:%d) status %d",
|
||||
sndDebug("tq task:0x%x (vgId:%d) recv check rsp(reqId:0x%" PRIx64 ") from 0x%x (vgId:%d) status %d",
|
||||
rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.status);
|
||||
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pSnode->pMeta, rsp.streamId, rsp.upstreamTaskId);
|
||||
if (pTask == NULL) {
|
||||
qError("tq failed to locate the stream task:0x%x (vgId:%d), it may have been destroyed", rsp.upstreamTaskId,
|
||||
sndError("tq failed to locate the stream task:0x%x (vgId:%d), it may have been destroyed", rsp.upstreamTaskId,
|
||||
pSnode->pMeta->vgId);
|
||||
return -1;
|
||||
}
|
||||
|
@ -430,6 +706,181 @@ int32_t sndProcessStreamTaskCheckRsp(SSnode* pSnode, SRpcMsg* pMsg) {
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t sndProcessTaskUpdateReq(SSnode* pSnode, SRpcMsg* pMsg) {
|
||||
SStreamMeta* pMeta = pSnode->pMeta;
|
||||
int32_t vgId = SNODE_HANDLE;
|
||||
char* msg = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
SRpcMsg rsp = {.info = pMsg->info, .code = TSDB_CODE_SUCCESS};
|
||||
|
||||
SStreamTaskNodeUpdateMsg req = {0};
|
||||
|
||||
SDecoder decoder;
|
||||
tDecoderInit(&decoder, (uint8_t*)msg, len);
|
||||
if (tDecodeStreamTaskUpdateMsg(&decoder, &req) < 0) {
|
||||
rsp.code = TSDB_CODE_MSG_DECODE_ERROR;
|
||||
sndError("vgId:%d failed to decode task update msg, code:%s", vgId, tstrerror(rsp.code));
|
||||
tDecoderClear(&decoder);
|
||||
return rsp.code;
|
||||
}
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
|
||||
// update the nodeEpset when it exists
|
||||
streamMetaWLock(pMeta);
|
||||
|
||||
// the task epset may be updated again and again, when replaying the WAL, the task may be in stop status.
|
||||
STaskId id = {.streamId = req.streamId, .taskId = req.taskId};
|
||||
SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
|
||||
if (ppTask == NULL || *ppTask == NULL) {
|
||||
sndError("vgId:%d failed to acquire task:0x%x when handling update, it may have been dropped already", pMeta->vgId,
|
||||
req.taskId);
|
||||
rsp.code = TSDB_CODE_SUCCESS;
|
||||
streamMetaWUnLock(pMeta);
|
||||
|
||||
taosArrayDestroy(req.pNodeList);
|
||||
return rsp.code;
|
||||
}
|
||||
|
||||
SStreamTask* pTask = *ppTask;
|
||||
|
||||
if (pMeta->updateInfo.transId != req.transId) {
|
||||
pMeta->updateInfo.transId = req.transId;
|
||||
sndInfo("s-task:%s receive new trans to update nodeEp msg from mnode, transId:%d", pTask->id.idStr, req.transId);
|
||||
// info needs to be kept till the new trans to update the nodeEp arrived.
|
||||
taosHashClear(pMeta->updateInfo.pTasks);
|
||||
} else {
|
||||
sndDebug("s-task:%s recv trans to update nodeEp from mnode, transId:%d", pTask->id.idStr, req.transId);
|
||||
}
|
||||
|
||||
STaskUpdateEntry entry = {.streamId = req.streamId, .taskId = req.taskId, .transId = req.transId};
|
||||
void* exist = taosHashGet(pMeta->updateInfo.pTasks, &entry, sizeof(STaskUpdateEntry));
|
||||
if (exist != NULL) {
|
||||
sndDebug("s-task:%s (vgId:%d) already update in trans:%d, discard the nodeEp update msg", pTask->id.idStr, vgId,
|
||||
req.transId);
|
||||
rsp.code = TSDB_CODE_SUCCESS;
|
||||
streamMetaWUnLock(pMeta);
|
||||
taosArrayDestroy(req.pNodeList);
|
||||
return rsp.code;
|
||||
}
|
||||
|
||||
streamMetaWUnLock(pMeta);
|
||||
|
||||
// the following two functions should not be executed within the scope of meta lock to avoid deadlock
|
||||
streamTaskUpdateEpsetInfo(pTask, req.pNodeList);
|
||||
streamTaskResetStatus(pTask);
|
||||
|
||||
// continue after lock the meta again
|
||||
streamMetaWLock(pMeta);
|
||||
|
||||
SStreamTask** ppHTask = NULL;
|
||||
if (HAS_RELATED_FILLHISTORY_TASK(pTask)) {
|
||||
ppHTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &pTask->hTaskInfo.id, sizeof(pTask->hTaskInfo.id));
|
||||
if (ppHTask == NULL || *ppHTask == NULL) {
|
||||
sndError("vgId:%d failed to acquire fill-history task:0x%x when handling update, it may have been dropped already",
|
||||
pMeta->vgId, req.taskId);
|
||||
CLEAR_RELATED_FILLHISTORY_TASK(pTask);
|
||||
} else {
|
||||
sndDebug("s-task:%s fill-history task update nodeEp along with stream task", (*ppHTask)->id.idStr);
|
||||
streamTaskUpdateEpsetInfo(*ppHTask, req.pNodeList);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
streamMetaSaveTask(pMeta, pTask);
|
||||
if (ppHTask != NULL) {
|
||||
streamMetaSaveTask(pMeta, *ppHTask);
|
||||
}
|
||||
|
||||
if (streamMetaCommit(pMeta) < 0) {
|
||||
// persist to disk
|
||||
}
|
||||
}
|
||||
|
||||
streamTaskStop(pTask);
|
||||
|
||||
// keep the already handled info
|
||||
taosHashPut(pMeta->updateInfo.pTasks, &entry, sizeof(entry), NULL, 0);
|
||||
|
||||
if (ppHTask != NULL) {
|
||||
streamTaskStop(*ppHTask);
|
||||
sndDebug("s-task:%s task nodeEp update completed, streamTask and related fill-history task closed", pTask->id.idStr);
|
||||
taosHashPut(pMeta->updateInfo.pTasks, &(*ppHTask)->id, sizeof(pTask->id), NULL, 0);
|
||||
} else {
|
||||
sndDebug("s-task:%s task nodeEp update completed, streamTask closed", pTask->id.idStr);
|
||||
}
|
||||
|
||||
rsp.code = 0;
|
||||
|
||||
// possibly only handle the stream task.
|
||||
int32_t numOfTasks = streamMetaGetNumOfTasks(pMeta);
|
||||
int32_t updateTasks = taosHashGetSize(pMeta->updateInfo.pTasks);
|
||||
|
||||
pMeta->startInfo.tasksWillRestart = 1;
|
||||
|
||||
if (updateTasks < numOfTasks) {
|
||||
sndDebug("vgId:%d closed tasks:%d, unclosed:%d, all tasks will be started when nodeEp update completed", vgId,
|
||||
updateTasks, (numOfTasks - updateTasks));
|
||||
streamMetaWUnLock(pMeta);
|
||||
} else {
|
||||
sndDebug("vgId:%d all %d task(s) nodeEp updated and closed", vgId, numOfTasks);
|
||||
#if 1
|
||||
sndStartStreamTaskAsync(pSnode, true);
|
||||
streamMetaWUnLock(pMeta);
|
||||
#else
|
||||
streamMetaWUnLock(pMeta);
|
||||
|
||||
// For debug purpose.
|
||||
// the following procedure consume many CPU resource, result in the re-election of leader
|
||||
// with high probability. So we employ it as a test case for the stream processing framework, with
|
||||
// checkpoint/restart/nodeUpdate etc.
|
||||
while(1) {
|
||||
int32_t startVal = atomic_val_compare_exchange_32(&pMeta->startInfo.taskStarting, 0, 1);
|
||||
if (startVal == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tqDebug("vgId:%d in start stream tasks procedure, wait for 500ms and recheck", vgId);
|
||||
taosMsleep(500);
|
||||
}
|
||||
|
||||
while (streamMetaTaskInTimer(pMeta)) {
|
||||
tqDebug("vgId:%d some tasks in timer, wait for 100ms and recheck", pMeta->vgId);
|
||||
taosMsleep(100);
|
||||
}
|
||||
|
||||
streamMetaWLock(pMeta);
|
||||
|
||||
int32_t code = streamMetaReopen(pMeta);
|
||||
if (code != 0) {
|
||||
tqError("vgId:%d failed to reopen stream meta", vgId);
|
||||
streamMetaWUnLock(pMeta);
|
||||
taosArrayDestroy(req.pNodeList);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (streamMetaLoadAllTasks(pTq->pStreamMeta) < 0) {
|
||||
tqError("vgId:%d failed to load stream tasks", vgId);
|
||||
streamMetaWUnLock(pMeta);
|
||||
taosArrayDestroy(req.pNodeList);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vnodeIsRoleLeader(pTq->pVnode) && !tsDisableStream) {
|
||||
tqInfo("vgId:%d start all stream tasks after all being updated", vgId);
|
||||
tqResetStreamTaskStatus(pTq);
|
||||
tqStartStreamTaskAsync(pTq, false);
|
||||
} else {
|
||||
tqInfo("vgId:%d, follower node not start stream tasks", vgId);
|
||||
}
|
||||
streamMetaWUnLock(pMeta);
|
||||
#endif
|
||||
}
|
||||
|
||||
taosArrayDestroy(req.pNodeList);
|
||||
return rsp.code;
|
||||
}
|
||||
|
||||
int32_t sndProcessStreamMsg(SSnode *pSnode, SRpcMsg *pMsg) {
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_RUN:
|
||||
|
@ -443,13 +894,34 @@ int32_t sndProcessStreamMsg(SSnode *pSnode, SRpcMsg *pMsg) {
|
|||
case TDMT_STREAM_RETRIEVE_RSP:
|
||||
return sndProcessTaskRetrieveRsp(pSnode, pMsg);
|
||||
case TDMT_VND_STREAM_SCAN_HISTORY_FINISH:
|
||||
return sndProcessStreamTaskScanHistoryFinishReq(pSnode, pMsg);
|
||||
return sndProcessTaskScanHistoryFinishReq(pSnode, pMsg);
|
||||
case TDMT_VND_STREAM_SCAN_HISTORY_FINISH_RSP:
|
||||
return sndProcessTaskRecoverFinishRsp(pSnode, pMsg);
|
||||
return sndProcessTaskScanHistoryFinishRsp(pSnode, pMsg);
|
||||
case TDMT_VND_STREAM_TASK_CHECK:
|
||||
return sndProcessStreamTaskCheckReq(pSnode, pMsg);
|
||||
case TDMT_VND_STREAM_TASK_CHECK_RSP:
|
||||
return sndProcessStreamTaskCheckRsp(pSnode, pMsg);
|
||||
case TDMT_STREAM_TASK_CHECKPOINT_READY:
|
||||
return sndProcessTaskCheckpointReadyMsg(pSnode, pMsg);
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sndProcessWriteMsg(SSnode *pSnode, SRpcMsg *pMsg, SRpcMsg *pRsp) {
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_STREAM_TASK_DEPLOY: {
|
||||
void *pReq = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
|
||||
int32_t len = pMsg->contLen - sizeof(SMsgHead);
|
||||
return sndProcessTaskDeployReq(pSnode, pReq, len);
|
||||
}
|
||||
|
||||
case TDMT_STREAM_TASK_DROP:
|
||||
return sndProcessTaskDropReq(pSnode, pMsg->pCont, pMsg->contLen);
|
||||
case TDMT_VND_STREAM_TASK_UPDATE:
|
||||
sndProcessTaskUpdateReq(pSnode, pMsg);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
|
|
@ -138,6 +138,11 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
vnode
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/dnode/vnode"
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
vnode
|
||||
PUBLIC os
|
||||
|
|
|
@ -43,9 +43,6 @@ extern "C" {
|
|||
|
||||
typedef struct STqOffsetStore STqOffsetStore;
|
||||
|
||||
#define STREAM_EXEC_EXTRACT_DATA_IN_WAL_ID (-1)
|
||||
#define STREAM_EXEC_START_ALL_TASKS_ID (-2)
|
||||
#define STREAM_EXEC_RESTART_ALL_TASKS_ID (-3)
|
||||
#define IS_OFFSET_RESET_TYPE(_t) ((_t) < 0)
|
||||
|
||||
// tqExec
|
||||
|
|
|
@ -14,18 +14,13 @@
|
|||
*/
|
||||
|
||||
#include "tq.h"
|
||||
#include "stream.h"
|
||||
#include "vnd.h"
|
||||
|
||||
typedef struct {
|
||||
int8_t inited;
|
||||
} STqMgmt;
|
||||
|
||||
typedef struct STaskUpdateEntry {
|
||||
int64_t streamId;
|
||||
int32_t taskId;
|
||||
int32_t transId;
|
||||
} STaskUpdateEntry;
|
||||
|
||||
static STqMgmt tqMgmt = {0};
|
||||
|
||||
// 0: not init
|
||||
|
@ -714,8 +709,8 @@ int32_t tqProcessSubscribeReq(STQ* pTq, int64_t sversion, char* msg, int32_t msg
|
|||
taosWLockLatch(&pTq->lock);
|
||||
bool exec = tqIsHandleExec(pHandle);
|
||||
if (exec) {
|
||||
tqInfo("vgId:%d, topic:%s, subscription is executing, sub wait for 10ms and retry, pHandle:%p", pTq->pVnode->config.vgId,
|
||||
pHandle->subKey, pHandle);
|
||||
tqInfo("vgId:%d, topic:%s, subscription is executing, sub wait for 10ms and retry, pHandle:%p",
|
||||
pTq->pVnode->config.vgId, pHandle->subKey, pHandle);
|
||||
taosWUnLockLatch(&pTq->lock);
|
||||
taosMsleep(10);
|
||||
continue;
|
||||
|
@ -922,18 +917,20 @@ int32_t tqProcessTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
|
||||
// only the leader node handle the check request
|
||||
if (pMeta->role == NODE_ROLE_FOLLOWER) {
|
||||
tqError("s-task:0x%x invalid check msg from upstream:0x%x(vgId:%d), vgId:%d is follower, not handle check status msg",
|
||||
tqError(
|
||||
"s-task:0x%x invalid check msg from upstream:0x%x(vgId:%d), vgId:%d is follower, not handle check status msg",
|
||||
taskId, req.upstreamTaskId, req.upstreamNodeId, pMeta->vgId);
|
||||
rsp.status = TASK_DOWNSTREAM_NOT_LEADER;
|
||||
} else {
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, req.streamId, taskId);
|
||||
if (pTask != NULL) {
|
||||
rsp.status = streamTaskCheckStatus(pTask, req.upstreamTaskId, req.upstreamNodeId, req.stage);
|
||||
rsp.status = streamTaskCheckStatus(pTask, req.upstreamTaskId, req.upstreamNodeId, req.stage, &rsp.oldStage);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
|
||||
char* p = NULL;
|
||||
streamTaskGetStatus(pTask, &p);
|
||||
tqDebug("s-task:%s status:%s, stage:%d recv task check req(reqId:0x%" PRIx64 ") task:0x%x (vgId:%d), check_status:%d",
|
||||
tqDebug("s-task:%s status:%s, stage:%" PRId64 " recv task check req(reqId:0x%" PRIx64
|
||||
") task:0x%x (vgId:%d), check_status:%d",
|
||||
pTask->id.idStr, p, rsp.oldStage, rsp.reqId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status);
|
||||
} else {
|
||||
rsp.status = TASK_DOWNSTREAM_NOT_READY;
|
||||
|
@ -1029,7 +1026,8 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t sversion, char* msg, int32_t ms
|
|||
streamMetaWUnLock(pStreamMeta);
|
||||
|
||||
if (code < 0) {
|
||||
tqError("failed to add s-task:0x%x into vgId:%d meta, total:%d, code:%s", vgId, taskId, numOfTasks, tstrerror(code));
|
||||
tqError("failed to add s-task:0x%x into vgId:%d meta, total:%d, code:%s", vgId, taskId, numOfTasks,
|
||||
tstrerror(code));
|
||||
tFreeStreamTask(pTask);
|
||||
return code;
|
||||
}
|
||||
|
@ -1361,6 +1359,7 @@ int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg, bool exec) {
|
|||
if (pTask) {
|
||||
SRpcMsg rsp = {.info = pMsg->info, .code = 0};
|
||||
streamProcessDispatchMsg(pTask, &req, &rsp);
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -1478,7 +1477,6 @@ int32_t tqProcessTaskResumeImpl(STQ* pTq, SStreamTask* pTask, int64_t sversion,
|
|||
int32_t level = pTask->info.taskLevel;
|
||||
if (level == TASK_LEVEL__SINK) {
|
||||
if (status == TASK_STATUS__UNINIT) {
|
||||
|
||||
}
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
return 0;
|
||||
|
@ -1599,6 +1597,7 @@ int32_t vnodeEnqueueStreamMsg(SVnode* pVnode, SRpcMsg* pMsg) {
|
|||
if (pTask != NULL) {
|
||||
SRpcMsg rsp = {.info = pMsg->info, .code = 0};
|
||||
streamProcessDispatchMsg(pTask, &req, &rsp);
|
||||
tDeleteStreamDispatchReq(&req);
|
||||
streamMetaReleaseTask(pTq->pStreamMeta, pTask);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
|
@ -1704,7 +1703,8 @@ int32_t tqProcessTaskCheckPointSourceReq(STQ* pTq, SRpcMsg* pMsg, SRpcMsg* pRsp)
|
|||
pTask->checkpointingId = req.checkpointId;
|
||||
|
||||
qError("s-task:%s not ready for checkpoint, since downstream not ready, ignore this checkpoint:%" PRId64
|
||||
", set it failure", pTask->id.idStr, req.checkpointId);
|
||||
", set it failure",
|
||||
pTask->id.idStr, req.checkpointId);
|
||||
streamMetaReleaseTask(pMeta, pTask);
|
||||
|
||||
SRpcMsg rsp = {0};
|
||||
|
@ -1925,7 +1925,8 @@ int32_t tqProcessTaskUpdateReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
streamMetaWUnLock(pMeta);
|
||||
} else {
|
||||
if (!pTq->pVnode->restored) {
|
||||
tqDebug("vgId:%d vnode restore not completed, not restart the tasks, clear the start after nodeUpdate flag", vgId);
|
||||
tqDebug("vgId:%d vnode restore not completed, not restart the tasks, clear the start after nodeUpdate flag",
|
||||
vgId);
|
||||
pMeta->startInfo.tasksWillRestart = 0;
|
||||
streamMetaWUnLock(pMeta);
|
||||
} else {
|
||||
|
@ -1997,8 +1998,8 @@ int32_t tqProcessTaskResetReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
SStreamMeta* pMeta = pTq->pStreamMeta;
|
||||
SStreamTask* pTask = streamMetaAcquireTask(pMeta, pReq->streamId, pReq->taskId);
|
||||
if (pTask == NULL) {
|
||||
tqError("vgId:%d process task-reset req, failed to acquire task:0x%x, it may have been dropped already", pMeta->vgId,
|
||||
pReq->taskId);
|
||||
tqError("vgId:%d process task-reset req, failed to acquire task:0x%x, it may have been dropped already",
|
||||
pMeta->vgId, pReq->taskId);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2006,8 +2007,7 @@ int32_t tqProcessTaskResetReq(STQ* pTq, SRpcMsg* pMsg) {
|
|||
|
||||
// clear flag set during do checkpoint, and open inputQ for all upstream tasks
|
||||
if (streamTaskGetStatus(pTask, NULL) == TASK_STATUS__CK) {
|
||||
streamTaskClearCheckInfo(pTask);
|
||||
taosArrayClear(pTask->pReadyMsgList);
|
||||
streamTaskClearCheckInfo(pTask, true);
|
||||
streamTaskSetStatusReady(pTask);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "tq.h"
|
||||
#include "vnd.h"
|
||||
#include "stream.h"
|
||||
|
||||
#define MAX_REPEAT_SCAN_THRESHOLD 3
|
||||
#define SCAN_WAL_IDLE_DURATION 100
|
||||
|
|
|
@ -104,7 +104,7 @@ static int32_t tsdbSaveFSToFile(STsdbFS *pFS, const char *fname) {
|
|||
taosCalcChecksumAppend(0, pData, size);
|
||||
|
||||
// save to file
|
||||
TdFilePtr pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
|
||||
TdFilePtr pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFD == NULL) {
|
||||
code = TAOS_SYSTEM_ERROR(errno);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
|
|
@ -85,7 +85,7 @@ static int32_t save_json(const cJSON *json, const char *fname) {
|
|||
char *data = cJSON_PrintUnformatted(json);
|
||||
if (data == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
TdFilePtr fp = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
|
||||
TdFilePtr fp = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (fp == NULL) {
|
||||
code = TAOS_SYSTEM_ERROR(code);
|
||||
goto _exit;
|
||||
|
@ -1186,11 +1186,6 @@ const char *gFSBgTaskName[] = {NULL, "MERGE", "RETENTION", "COMPACT"};
|
|||
static int32_t tsdbFSRunBgTask(void *arg) {
|
||||
STFSBgTask *task = (STFSBgTask *)arg;
|
||||
STFileSystem *fs = task->fs;
|
||||
STFileSet *fset;
|
||||
|
||||
tsdbFSGetFSet(fs, task->fid, &fset);
|
||||
|
||||
ASSERT(fset != NULL && fset->bgTaskRunning == task);
|
||||
|
||||
task->launchTime = taosGetTimestampMs();
|
||||
task->run(task->arg);
|
||||
|
@ -1203,6 +1198,10 @@ static int32_t tsdbFSRunBgTask(void *arg) {
|
|||
|
||||
taosThreadMutexLock(&fs->tsdb->mutex);
|
||||
|
||||
STFileSet *fset = NULL;
|
||||
tsdbFSGetFSet(fs, task->fid, &fset);
|
||||
ASSERT(fset != NULL && fset->bgTaskRunning == task);
|
||||
|
||||
// free last
|
||||
tsdbDoDoneBgTask(fs, task);
|
||||
fset->bgTaskRunning = NULL;
|
||||
|
|
|
@ -177,7 +177,7 @@ int32_t tsdbDFileRollback(STsdb *pTsdb, SDFileSet *pSet, EDataFileT ftype) {
|
|||
taosCalcChecksumAppend(0, hdr, TSDB_FHDR_SIZE);
|
||||
|
||||
// open
|
||||
pFD = taosOpenFile(fname, TD_FILE_WRITE);
|
||||
pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_WRITE_THROUGH);
|
||||
if (pFD == NULL) {
|
||||
code = TAOS_SYSTEM_ERROR(errno);
|
||||
goto _err;
|
||||
|
|
|
@ -576,7 +576,10 @@ static int32_t tsdbMerge(void *arg) {
|
|||
}
|
||||
}
|
||||
|
||||
if (skipMerge) return 0;
|
||||
if (skipMerge) {
|
||||
code = 0;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
// do merge
|
||||
tsdbDebug("vgId:%d merge begin, fid:%d", TD_VID(tsdb->pVnode), merger->fid);
|
||||
|
|
|
@ -177,7 +177,7 @@ int vnodeSaveInfo(const char *dir, const SVnodeInfo *pInfo) {
|
|||
}
|
||||
|
||||
// save info to a vnode_tmp.json
|
||||
pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) {
|
||||
vError("failed to open info file:%s for write:%s", fname, terrstr());
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
|
|
|
@ -293,6 +293,9 @@ typedef struct STableMergeScanInfo {
|
|||
int32_t readIdx;
|
||||
SSDataBlock* pResBlock;
|
||||
SSampleExecInfo sample; // sample execution info
|
||||
SSHashObj* mTableNumRows; // uid->num of table rows
|
||||
SHashObj* mSkipTables;
|
||||
int64_t mergeLimit;
|
||||
SSortExecInfo sortExecInfo;
|
||||
} STableMergeScanInfo;
|
||||
|
||||
|
|
|
@ -3200,6 +3200,27 @@ _error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t tableMergeScanDoSkipTable(STableMergeScanInfo* pInfo, SSDataBlock* pBlock) {
|
||||
int64_t nRows = 0;
|
||||
void* pNum = tSimpleHashGet(pInfo->mTableNumRows, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid));
|
||||
if (pNum == NULL) {
|
||||
nRows = pBlock->info.rows;
|
||||
tSimpleHashPut(pInfo->mTableNumRows, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid), &nRows, sizeof(nRows));
|
||||
} else {
|
||||
*(int64_t*)pNum = *(int64_t*)pNum + pBlock->info.rows;
|
||||
}
|
||||
|
||||
if (nRows >= pInfo->mergeLimit) {
|
||||
if (pInfo->mSkipTables == NULL) {
|
||||
pInfo->mSkipTables = taosHashInit(pInfo->tableEndIndex - pInfo->tableStartIndex + 1,
|
||||
taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK);
|
||||
}
|
||||
int bSkip = 1;
|
||||
taosHashPut(pInfo->mSkipTables, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid), &bSkip, sizeof(bSkip));
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static SSDataBlock* getBlockForTableMergeScan(void* param) {
|
||||
STableMergeScanSortSourceParam* source = param;
|
||||
SOperatorInfo* pOperator = source->pOperator;
|
||||
|
@ -3257,6 +3278,10 @@ static SSDataBlock* getBlockForTableMergeScan(void* param) {
|
|||
|
||||
pBlock->info.id.groupId = tableListGetTableGroupId(pInfo->base.pTableListInfo, pBlock->info.id.uid);
|
||||
|
||||
if (pInfo->mergeLimit != -1) {
|
||||
tableMergeScanDoSkipTable(pInfo, pBlock);
|
||||
}
|
||||
|
||||
pOperator->resultInfo.totalRows += pBlock->info.rows;
|
||||
pInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
|
||||
|
||||
|
@ -3316,22 +3341,20 @@ int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) {
|
|||
int32_t tableStartIdx = pInfo->tableStartIndex;
|
||||
int32_t tableEndIdx = pInfo->tableEndIndex;
|
||||
|
||||
bool hasLimit = pInfo->limitInfo.limit.limit != -1 || pInfo->limitInfo.limit.offset != -1;
|
||||
int64_t mergeLimit = -1;
|
||||
if (hasLimit) {
|
||||
mergeLimit = pInfo->limitInfo.limit.limit + pInfo->limitInfo.limit.offset;
|
||||
}
|
||||
tSimpleHashClear(pInfo->mTableNumRows);
|
||||
|
||||
size_t szRow = blockDataGetRowSize(pInfo->pResBlock);
|
||||
if (hasLimit) {
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1,
|
||||
NULL, pTaskInfo->id.str, mergeLimit, szRow+8, tsPQSortMemThreshold * 1024* 1024);
|
||||
} else {
|
||||
// if (pInfo->mergeLimit != -1) {
|
||||
// pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1,
|
||||
// NULL, pTaskInfo->id.str, pInfo->mergeLimit, szRow+8, tsPQSortMemThreshold * 1024* 1024);
|
||||
// } else
|
||||
{
|
||||
pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
|
||||
int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
|
||||
pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0);
|
||||
|
||||
tsortSetMergeLimit(pInfo->pSortHandle, mergeLimit);
|
||||
tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
|
||||
tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
|
||||
}
|
||||
|
||||
|
@ -3343,7 +3366,8 @@ int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) {
|
|||
STableMergeScanSortSourceParam *param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
|
||||
param->pOperator = pOperator;
|
||||
STableKeyInfo* startKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, tableStartIdx);
|
||||
pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock, (void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), false, NULL);
|
||||
pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock,
|
||||
(void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), false, &pInfo->mSkipTables);
|
||||
|
||||
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
|
||||
ps->param = param;
|
||||
|
@ -3385,6 +3409,8 @@ int32_t stopGroupTableMergeScan(SOperatorInfo* pOperator) {
|
|||
pInfo->pSortHandle = NULL;
|
||||
|
||||
resetLimitInfoForNextGroup(&pInfo->limitInfo);
|
||||
taosHashCleanup(pInfo->mSkipTables);
|
||||
pInfo->mSkipTables = NULL;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3493,7 +3519,10 @@ void destroyTableMergeScanOperatorInfo(void* param) {
|
|||
taosArrayDestroy(pTableScanInfo->sortSourceParams);
|
||||
tsortDestroySortHandle(pTableScanInfo->pSortHandle);
|
||||
pTableScanInfo->pSortHandle = NULL;
|
||||
|
||||
tSimpleHashCleanup(pTableScanInfo->mTableNumRows);
|
||||
pTableScanInfo->mTableNumRows = NULL;
|
||||
taosHashCleanup(pTableScanInfo->mSkipTables);
|
||||
pTableScanInfo->mSkipTables = NULL;
|
||||
destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
|
||||
|
||||
pTableScanInfo->pResBlock = blockDataDestroy(pTableScanInfo->pResBlock);
|
||||
|
@ -3583,7 +3612,14 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN
|
|||
pInfo->pSortInfo = generateSortByTsInfo(pInfo->base.matchInfo.pList, pInfo->base.cond.order);
|
||||
pInfo->pSortInputBlock = createOneDataBlock(pInfo->pResBlock, false);
|
||||
initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
|
||||
|
||||
pInfo->mTableNumRows = tSimpleHashInit(1024,
|
||||
taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT));
|
||||
pInfo->mergeLimit = -1;
|
||||
bool hasLimit = pInfo->limitInfo.limit.limit != -1 || pInfo->limitInfo.limit.offset != -1;
|
||||
if (hasLimit) {
|
||||
pInfo->mergeLimit = pInfo->limitInfo.limit.limit + pInfo->limitInfo.limit.offset;
|
||||
pInfo->mSkipTables = NULL;
|
||||
}
|
||||
pInfo->pReaderBlock = createOneDataBlock(pInfo->pResBlock, false);
|
||||
|
||||
int32_t rowSize = pInfo->pResBlock->info.rowSize;
|
||||
|
|
|
@ -328,6 +328,7 @@ static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
|
|||
SIF_ERR_RET(scalarGenerateSetFromList((void **)¶m->pFilter, node, nl->node.resType.type));
|
||||
if (taosHashPut(ctx->pRes, &node, POINTER_BYTES, param, sizeof(*param))) {
|
||||
taosHashCleanup(param->pFilter);
|
||||
param->pFilter = NULL;
|
||||
indexError("taosHashPut nodeList failed, size:%d", (int32_t)sizeof(*param));
|
||||
SIF_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
|
||||
}
|
||||
|
|
|
@ -1433,14 +1433,18 @@ static int32_t dataTypeComp(const SDataType* l, const SDataType* r) {
|
|||
|
||||
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
if (isMultiResFunc(pOp->pLeft)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
if (isMultiResFunc(pOp->pRight)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS != scalarGetOperatorResultType(pOp)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pOp->node.aliasName);
|
||||
int32_t res = scalarGetOperatorResultType(pOp);
|
||||
if (TSDB_CODE_SUCCESS != res) {
|
||||
pCxt->errCode = res;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
return DEAL_RES_CONTINUE;
|
||||
|
|
|
@ -208,6 +208,7 @@ void sclFreeParam(SScalarParam *param) {
|
|||
if (param->columnData != NULL) {
|
||||
colDataDestroy(param->columnData);
|
||||
taosMemoryFreeClear(param->columnData);
|
||||
param->columnData = NULL;
|
||||
}
|
||||
|
||||
if (param->pHashFilter != NULL) {
|
||||
|
@ -845,6 +846,7 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp
|
|||
SScalarParam *params = NULL;
|
||||
int32_t rowNum = 0;
|
||||
int32_t code = 0;
|
||||
int32_t paramNum = 0;
|
||||
|
||||
// json not support in in operator
|
||||
if (nodeType(node->pLeft) == QUERY_NODE_VALUE) {
|
||||
|
@ -865,7 +867,7 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp
|
|||
|
||||
_bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(node->opType);
|
||||
|
||||
int32_t paramNum = scalarGetOperatorParamNum(node->opType);
|
||||
paramNum = scalarGetOperatorParamNum(node->opType);
|
||||
SScalarParam *pLeft = ¶ms[0];
|
||||
SScalarParam *pRight = paramNum > 1 ? ¶ms[1] : NULL;
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
#include "executor.h"
|
||||
#include "query.h"
|
||||
#include "tstream.h"
|
||||
#include "streamBackendRocksdb.h"
|
||||
#include "trpc.h"
|
||||
#include "tstream.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -120,7 +120,9 @@ void streamTaskSetRetryInfoForLaunch(SHistoryTaskInfo* pInfo);
|
|||
int32_t streamTaskBuildScanhistoryRspMsg(SStreamTask* pTask, SStreamScanHistoryFinishReq* pReq, void** pBuffer, int32_t* pLen);
|
||||
int32_t streamTaskFillHistoryFinished(SStreamTask* pTask);
|
||||
|
||||
int32_t streamTaskGetDataFromInputQ(SStreamTask* pTask, SStreamQueueItem** pInput, int32_t* numOfBlocks, int32_t* blockSize);
|
||||
void streamClearChkptReadyMsg(SStreamTask* pTask);
|
||||
int32_t streamTaskGetDataFromInputQ(SStreamTask* pTask, SStreamQueueItem** pInput, int32_t* numOfBlocks,
|
||||
int32_t* blockSize);
|
||||
int32_t streamQueueItemGetSize(const SStreamQueueItem* pItem);
|
||||
void streamQueueItemIncSize(const SStreamQueueItem* pItem, int32_t size);
|
||||
const char* streamQueueItemGetTypeStr(int32_t type);
|
||||
|
|
|
@ -283,7 +283,6 @@ int32_t streamProcessDispatchMsg(SStreamTask* pTask, SStreamDispatchReq* pReq, S
|
|||
tmsgSendRsp(pRsp);
|
||||
}
|
||||
|
||||
tDeleteStreamDispatchReq(pReq);
|
||||
streamSchedExec(pTask);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -519,6 +519,7 @@ void* streamBackendInit(const char* streamPath, int64_t chkpId, int32_t vgId) {
|
|||
if (err != NULL) {
|
||||
stError("failed to open rocksdb, path:%s, reason:%s", backendPath, err);
|
||||
taosMemoryFreeClear(err);
|
||||
rocksdb_list_column_families_destroy(cfs, nCf);
|
||||
goto _EXIT;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "streamInt.h"
|
||||
#include "rsync.h"
|
||||
#include "cos.h"
|
||||
#include "rsync.h"
|
||||
#include "streamInt.h"
|
||||
|
||||
int32_t tEncodeStreamCheckpointSourceReq(SEncoder* pEncoder, const SStreamCheckpointSourceReq* pReq) {
|
||||
if (tStartEncode(pEncoder) < 0) return -1;
|
||||
|
@ -199,7 +199,8 @@ int32_t streamProcessCheckpointBlock(SStreamTask* pTask, SStreamDataBlock* pBloc
|
|||
// todo fix race condition: set the status and append checkpoint block
|
||||
int32_t taskLevel = pTask->info.taskLevel;
|
||||
if (taskLevel == TASK_LEVEL__SOURCE) {
|
||||
if (pTask->outputInfo.type == TASK_OUTPUT__FIXED_DISPATCH || pTask->outputInfo.type == TASK_OUTPUT__SHUFFLE_DISPATCH) {
|
||||
if (pTask->outputInfo.type == TASK_OUTPUT__FIXED_DISPATCH ||
|
||||
pTask->outputInfo.type == TASK_OUTPUT__SHUFFLE_DISPATCH) {
|
||||
stDebug("s-task:%s set childIdx:%d, and add checkpoint-trigger block into outputQ", id, pTask->info.selfChildId);
|
||||
continueDispatchCheckpointBlock(pBlock, pTask);
|
||||
} else { // only one task exists, no need to dispatch downstream info
|
||||
|
@ -235,7 +236,8 @@ int32_t streamProcessCheckpointBlock(SStreamTask* pTask, SStreamDataBlock* pBloc
|
|||
} else {
|
||||
stDebug(
|
||||
"s-task:%s process checkpoint block, all %d upstreams sent checkpoint msgs, dispatch checkpoint msg "
|
||||
"downstream", id, num);
|
||||
"downstream",
|
||||
id, num);
|
||||
|
||||
// set the needed checked downstream tasks, only when all downstream tasks do checkpoint complete, this task
|
||||
// can start local checkpoint procedure
|
||||
|
@ -273,7 +275,7 @@ int32_t streamProcessCheckpointReadyMsg(SStreamTask* pTask) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void streamTaskClearCheckInfo(SStreamTask* pTask) {
|
||||
void streamTaskClearCheckInfo(SStreamTask* pTask, bool clearChkpReadyMsg) {
|
||||
pTask->checkpointingId = 0; // clear the checkpoint id
|
||||
pTask->chkInfo.failedId = 0;
|
||||
pTask->chkInfo.startTs = 0; // clear the recorded start time
|
||||
|
@ -281,6 +283,9 @@ void streamTaskClearCheckInfo(SStreamTask* pTask) {
|
|||
pTask->checkpointAlignCnt = 0;
|
||||
pTask->chkInfo.dispatchCheckpointTrigger = false;
|
||||
streamTaskOpenAllUpstreamInput(pTask); // open inputQ for all upstream tasks
|
||||
if (clearChkpReadyMsg) {
|
||||
streamClearChkptReadyMsg(pTask);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t streamSaveAllTaskStatus(SStreamMeta* pMeta, int64_t checkpointId) {
|
||||
|
@ -307,7 +312,7 @@ int32_t streamSaveAllTaskStatus(SStreamMeta* pMeta, int64_t checkpointId) {
|
|||
p->chkInfo.checkpointId = p->checkpointingId;
|
||||
p->chkInfo.checkpointVer = p->chkInfo.processedVer;
|
||||
|
||||
streamTaskClearCheckInfo(p);
|
||||
streamTaskClearCheckInfo(p, false);
|
||||
|
||||
char* str = NULL;
|
||||
streamTaskGetStatus(p, &str);
|
||||
|
@ -387,8 +392,7 @@ static int uploadCheckpointToS3(char* id, char* path){
|
|||
TdDirEntryPtr de = NULL;
|
||||
while ((de = taosReadDir(pDir)) != NULL) {
|
||||
char* name = taosGetDirEntryName(de);
|
||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0 ||
|
||||
taosDirEntryIsDir(de)) continue;
|
||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || taosDirEntryIsDir(de)) continue;
|
||||
|
||||
char filename[PATH_MAX] = {0};
|
||||
if (path[strlen(path) - 1] == TD_DIRSEP_CHAR) {
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
*/
|
||||
|
||||
#include "streamInt.h"
|
||||
#include "tmisce.h"
|
||||
#include "trpc.h"
|
||||
#include "ttimer.h"
|
||||
#include "tmisce.h"
|
||||
|
||||
typedef struct SBlockName {
|
||||
uint32_t hashValue;
|
||||
|
@ -343,7 +343,8 @@ static int32_t doBuildDispatchMsg(SStreamTask* pTask, const SStreamDataBlock* pD
|
|||
SSDataBlock* pDataBlock = taosArrayGet(pData->blocks, i);
|
||||
|
||||
// TODO: do not use broadcast
|
||||
if (pDataBlock->info.type == STREAM_DELETE_RESULT || pDataBlock->info.type == STREAM_CHECKPOINT || pDataBlock->info.type == STREAM_TRANS_STATE) {
|
||||
if (pDataBlock->info.type == STREAM_DELETE_RESULT || pDataBlock->info.type == STREAM_CHECKPOINT ||
|
||||
pDataBlock->info.type == STREAM_TRANS_STATE) {
|
||||
for (int32_t j = 0; j < numOfVgroups; j++) {
|
||||
code = streamAddBlockIntoDispatchMsg(pDataBlock, &pReqs[j]);
|
||||
if (code != 0) {
|
||||
|
@ -371,7 +372,8 @@ static int32_t doBuildDispatchMsg(SStreamTask* pTask, const SStreamDataBlock* pD
|
|||
pTask->msgInfo.pData = pReqs;
|
||||
}
|
||||
|
||||
stDebug("s-task:%s build dispatch msg success, msgId:%d", pTask->id.idStr, pTask->execInfo.dispatch);
|
||||
stDebug("s-task:%s build dispatch msg success, msgId:%d, stage:%" PRId64, pTask->id.idStr, pTask->execInfo.dispatch,
|
||||
pTask->pMeta->stage);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -393,8 +395,8 @@ static int32_t sendDispatchMsg(SStreamTask* pTask, SStreamDispatchReq* pDispatch
|
|||
SArray* vgInfo = pTask->outputInfo.shuffleDispatcher.dbInfo.pVgroupInfos;
|
||||
int32_t numOfVgroups = taosArrayGetSize(vgInfo);
|
||||
|
||||
stDebug("s-task:%s (child taskId:%d) start to shuffle-dispatch blocks to %d vgroup(s), msgId:%d",
|
||||
id, pTask->info.selfChildId, numOfVgroups, msgId);
|
||||
stDebug("s-task:%s (child taskId:%d) start to shuffle-dispatch blocks to %d vgroup(s), msgId:%d", id,
|
||||
pTask->info.selfChildId, numOfVgroups, msgId);
|
||||
|
||||
for (int32_t i = 0; i < numOfVgroups; i++) {
|
||||
if (pDispatchMsg[i].blockNum > 0) {
|
||||
|
@ -409,7 +411,8 @@ static int32_t sendDispatchMsg(SStreamTask* pTask, SStreamDispatchReq* pDispatch
|
|||
}
|
||||
}
|
||||
|
||||
stDebug("s-task:%s complete shuffle-dispatch blocks to all %d vnodes, msgId:%d", pTask->id.idStr, numOfVgroups, msgId);
|
||||
stDebug("s-task:%s complete shuffle-dispatch blocks to all %d vnodes, msgId:%d", pTask->id.idStr, numOfVgroups,
|
||||
msgId);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -441,8 +444,8 @@ static void doRetryDispatchData(void* param, void* tmrId) {
|
|||
int32_t numOfVgroups = taosArrayGetSize(vgInfo);
|
||||
|
||||
int32_t numOfFailed = taosArrayGetSize(pList);
|
||||
stDebug("s-task:%s (child taskId:%d) retry shuffle-dispatch blocks to %d vgroup(s), msgId:%d",
|
||||
id, pTask->info.selfChildId, numOfFailed, msgId);
|
||||
stDebug("s-task:%s (child taskId:%d) retry shuffle-dispatch blocks to %d vgroup(s), msgId:%d", id,
|
||||
pTask->info.selfChildId, numOfFailed, msgId);
|
||||
|
||||
for (int32_t i = 0; i < numOfFailed; i++) {
|
||||
int32_t vgId = *(int32_t*)taosArrayGet(pList, i);
|
||||
|
@ -461,7 +464,8 @@ static void doRetryDispatchData(void* param, void* tmrId) {
|
|||
}
|
||||
}
|
||||
|
||||
stDebug("s-task:%s complete re-try shuffle-dispatch blocks to all %d vnodes, msgId:%d", pTask->id.idStr, numOfFailed, msgId);
|
||||
stDebug("s-task:%s complete re-try shuffle-dispatch blocks to all %d vnodes, msgId:%d", pTask->id.idStr,
|
||||
numOfFailed, msgId);
|
||||
} else {
|
||||
int32_t vgId = pTask->outputInfo.fixedDispatcher.nodeId;
|
||||
SEpSet* pEpSet = &pTask->outputInfo.fixedDispatcher.epSet;
|
||||
|
@ -531,10 +535,12 @@ int32_t streamSearchAndAddBlock(SStreamTask* pTask, SStreamDispatchReq* pReqs, S
|
|||
}
|
||||
|
||||
if (pDataBlock->info.parTbName[0]) {
|
||||
snprintf(ctbName, TSDB_TABLE_NAME_LEN, "%s.%s", pTask->outputInfo.shuffleDispatcher.dbInfo.db, pDataBlock->info.parTbName);
|
||||
snprintf(ctbName, TSDB_TABLE_NAME_LEN, "%s.%s", pTask->outputInfo.shuffleDispatcher.dbInfo.db,
|
||||
pDataBlock->info.parTbName);
|
||||
} else {
|
||||
buildCtbNameByGroupIdImpl(pTask->outputInfo.shuffleDispatcher.stbFullName, groupId, pDataBlock->info.parTbName);
|
||||
snprintf(ctbName, TSDB_TABLE_NAME_LEN, "%s.%s", pTask->outputInfo.shuffleDispatcher.dbInfo.db, pDataBlock->info.parTbName);
|
||||
snprintf(ctbName, TSDB_TABLE_NAME_LEN, "%s.%s", pTask->outputInfo.shuffleDispatcher.dbInfo.db,
|
||||
pDataBlock->info.parTbName);
|
||||
}
|
||||
|
||||
/*uint32_t hashValue = MurmurHash3_32(ctbName, strlen(ctbName));*/
|
||||
|
@ -576,13 +582,15 @@ int32_t streamSearchAndAddBlock(SStreamTask* pTask, SStreamDispatchReq* pReqs, S
|
|||
}
|
||||
|
||||
int32_t streamDispatchStreamBlock(SStreamTask* pTask) {
|
||||
ASSERT((pTask->outputInfo.type == TASK_OUTPUT__FIXED_DISPATCH || pTask->outputInfo.type == TASK_OUTPUT__SHUFFLE_DISPATCH));
|
||||
ASSERT((pTask->outputInfo.type == TASK_OUTPUT__FIXED_DISPATCH ||
|
||||
pTask->outputInfo.type == TASK_OUTPUT__SHUFFLE_DISPATCH));
|
||||
|
||||
const char* id = pTask->id.idStr;
|
||||
int32_t numOfElems = streamQueueGetNumOfItems(pTask->outputq.queue);
|
||||
if (numOfElems > 0) {
|
||||
double size = SIZE_IN_MiB(taosQueueMemorySize(pTask->outputq.queue->pQueue));
|
||||
stDebug("s-task:%s start to dispatch intermediate block to downstream, elem in outputQ:%d, size:%.2fMiB", id, numOfElems, size);
|
||||
stDebug("s-task:%s start to dispatch intermediate block to downstream, elem in outputQ:%d, size:%.2fMiB", id,
|
||||
numOfElems, size);
|
||||
}
|
||||
|
||||
// to make sure only one dispatch is running
|
||||
|
@ -641,7 +649,8 @@ int32_t streamDispatchStreamBlock(SStreamTask* pTask) {
|
|||
|
||||
if (++retryCount > MAX_CONTINUE_RETRY_COUNT) { // add to timer to retry
|
||||
int32_t ref = atomic_add_fetch_32(&pTask->status.timerActive, 1);
|
||||
stDebug("s-task:%s failed to dispatch msg to downstream for %d times, code:%s, add timer to retry in %dms, ref:%d",
|
||||
stDebug(
|
||||
"s-task:%s failed to dispatch msg to downstream for %d times, code:%s, add timer to retry in %dms, ref:%d",
|
||||
pTask->id.idStr, retryCount, tstrerror(terrno), DISPATCH_RETRY_INTERVAL_MS, ref);
|
||||
|
||||
streamRetryDispatchData(pTask, DISPATCH_RETRY_INTERVAL_MS);
|
||||
|
@ -665,7 +674,8 @@ int32_t streamDispatchScanHistoryFinishMsg(SStreamTask* pTask) {
|
|||
if (pTask->outputInfo.type == TASK_OUTPUT__FIXED_DISPATCH) {
|
||||
req.downstreamTaskId = pTask->outputInfo.fixedDispatcher.taskId;
|
||||
pTask->notReadyTasks = 1;
|
||||
doDispatchScanHistoryFinishMsg(pTask, &req, pTask->outputInfo.fixedDispatcher.nodeId, &pTask->outputInfo.fixedDispatcher.epSet);
|
||||
doDispatchScanHistoryFinishMsg(pTask, &req, pTask->outputInfo.fixedDispatcher.nodeId,
|
||||
&pTask->outputInfo.fixedDispatcher.epSet);
|
||||
} else if (pTask->outputInfo.type == TASK_OUTPUT__SHUFFLE_DISPATCH) {
|
||||
SArray* vgInfo = pTask->outputInfo.shuffleDispatcher.dbInfo.pVgroupInfos;
|
||||
int32_t numOfVgs = taosArrayGetSize(vgInfo);
|
||||
|
@ -673,8 +683,8 @@ int32_t streamDispatchScanHistoryFinishMsg(SStreamTask* pTask) {
|
|||
|
||||
char* p = NULL;
|
||||
streamTaskGetStatus(pTask, &p);
|
||||
stDebug("s-task:%s send scan-history data complete msg to downstream (shuffle-dispatch) %d tasks, status:%s", pTask->id.idStr,
|
||||
numOfVgs, p);
|
||||
stDebug("s-task:%s send scan-history data complete msg to downstream (shuffle-dispatch) %d tasks, status:%s",
|
||||
pTask->id.idStr, numOfVgs, p);
|
||||
for (int32_t i = 0; i < numOfVgs; i++) {
|
||||
SVgroupInfo* pVgInfo = taosArrayGet(vgInfo, i);
|
||||
req.downstreamTaskId = pVgInfo->taskId;
|
||||
|
@ -702,7 +712,8 @@ int32_t streamTaskSendCheckpointReadyMsg(SStreamTask* pTask) {
|
|||
}
|
||||
|
||||
taosArrayClear(pTask->pReadyMsgList);
|
||||
stDebug("s-task:%s level:%d checkpoint ready msg sent to all %d upstreams", pTask->id.idStr, pTask->info.taskLevel, num);
|
||||
stDebug("s-task:%s level:%d checkpoint ready msg sent to all %d upstreams", pTask->id.idStr, pTask->info.taskLevel,
|
||||
num);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -872,8 +883,8 @@ int32_t buildCheckpointSourceRsp(SStreamCheckpointSourceReq* pReq, SRpcHandleInf
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t streamAddCheckpointSourceRspMsg(SStreamCheckpointSourceReq* pReq, SRpcHandleInfo* pRpcInfo,
|
||||
SStreamTask* pTask, int8_t isSucceed) {
|
||||
int32_t streamAddCheckpointSourceRspMsg(SStreamCheckpointSourceReq* pReq, SRpcHandleInfo* pRpcInfo, SStreamTask* pTask,
|
||||
int8_t isSucceed) {
|
||||
SStreamChkptReadyInfo info = {0};
|
||||
buildCheckpointSourceRsp(pReq, pRpcInfo, &info.msg, isSucceed);
|
||||
|
||||
|
@ -882,7 +893,8 @@ int32_t streamAddCheckpointSourceRspMsg(SStreamCheckpointSourceReq* pReq, SRpcHa
|
|||
}
|
||||
|
||||
taosArrayPush(pTask->pReadyMsgList, &info);
|
||||
stDebug("s-task:%s add checkpoint source rsp msg, total:%d", pTask->id.idStr, (int32_t)taosArrayGetSize(pTask->pReadyMsgList));
|
||||
stDebug("s-task:%s add checkpoint source rsp msg, total:%d", pTask->id.idStr,
|
||||
(int32_t)taosArrayGetSize(pTask->pReadyMsgList));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -932,8 +944,10 @@ int32_t streamAddCheckpointReadyMsg(SStreamTask* pTask, int32_t upstreamTaskId,
|
|||
initRpcMsg(&info.msg, TDMT_STREAM_TASK_CHECKPOINT_READY, buf, tlen + sizeof(SMsgHead));
|
||||
info.msg.info.noResp = 1; // refactor later.
|
||||
|
||||
stDebug("s-task:%s (level:%d) prepare checkpoint ready msg to upstream s-task:0x%" PRIx64 ":0x%x (vgId:%d) idx:%d",
|
||||
pTask->id.idStr, pTask->info.taskLevel, req.streamId, req.upstreamTaskId, req.upstreamNodeId, index);
|
||||
stDebug("s-task:%s (level:%d) prepare checkpoint ready msg to upstream s-task:0x%" PRIx64
|
||||
":0x%x (vgId:%d) idx:%d, vgId:%d",
|
||||
pTask->id.idStr, pTask->info.taskLevel, req.streamId, req.upstreamTaskId, req.upstreamNodeId, index,
|
||||
req.upstreamNodeId);
|
||||
|
||||
if (pTask->pReadyMsgList == NULL) {
|
||||
pTask->pReadyMsgList = taosArrayInit(4, sizeof(SStreamChkptReadyInfo));
|
||||
|
@ -943,6 +957,18 @@ int32_t streamAddCheckpointReadyMsg(SStreamTask* pTask, int32_t upstreamTaskId,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void streamClearChkptReadyMsg(SStreamTask* pTask) {
|
||||
if (pTask->pReadyMsgList == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < taosArrayGetSize(pTask->pReadyMsgList); i++) {
|
||||
SStreamChkptReadyInfo* pInfo = taosArrayGet(pTask->pReadyMsgList, i);
|
||||
rpcFreeCont(pInfo->msg.pCont);
|
||||
}
|
||||
taosArrayClear(pTask->pReadyMsgList);
|
||||
}
|
||||
|
||||
int32_t tEncodeCompleteHistoryDataMsg(SEncoder* pEncoder, const SStreamCompleteHistoryMsg* pReq) {
|
||||
if (tStartEncode(pEncoder) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
|
||||
|
@ -965,7 +991,8 @@ int32_t tDecodeCompleteHistoryDataMsg(SDecoder* pDecoder, SStreamCompleteHistory
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t streamTaskBuildScanhistoryRspMsg(SStreamTask* pTask, SStreamScanHistoryFinishReq* pReq, void** pBuffer, int32_t* pLen) {
|
||||
int32_t streamTaskBuildScanhistoryRspMsg(SStreamTask* pTask, SStreamScanHistoryFinishReq* pReq, void** pBuffer,
|
||||
int32_t* pLen) {
|
||||
int32_t len = 0;
|
||||
int32_t code = 0;
|
||||
SEncoder encoder;
|
||||
|
@ -1095,7 +1122,8 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, i
|
|||
|
||||
// follower not handle the dispatch rsp
|
||||
if ((pTask->pMeta->role == NODE_ROLE_FOLLOWER) || (pTask->status.downstreamReady != 1)) {
|
||||
stError("s-task:%s vgId:%d is follower or task just re-launched, not handle the dispatch rsp, discard it", id, vgId);
|
||||
stError("s-task:%s vgId:%d is follower or task just re-launched, not handle the dispatch rsp, discard it", id,
|
||||
vgId);
|
||||
return TSDB_CODE_STREAM_TASK_NOT_EXIST;
|
||||
}
|
||||
|
||||
|
@ -1113,8 +1141,8 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, i
|
|||
// flag. Here we need to retry dispatch this message to downstream task immediately. handle the case the failure
|
||||
// happened too fast.
|
||||
if (code == TSDB_CODE_STREAM_TASK_NOT_EXIST) { // destination task does not exist, not retry anymore
|
||||
stError("s-task:%s failed to dispatch msg to task:0x%x(vgId:%d), msgId:%d no retry, since task destroyed already", id,
|
||||
pRsp->downstreamTaskId, pRsp->downstreamNodeId, msgId);
|
||||
stError("s-task:%s failed to dispatch msg to task:0x%x(vgId:%d), msgId:%d no retry, since task destroyed already",
|
||||
id, pRsp->downstreamTaskId, pRsp->downstreamNodeId, msgId);
|
||||
} else {
|
||||
stError("s-task:%s failed to dispatch msgId:%d to task:0x%x(vgId:%d), code:%s, add to retry list", id, msgId,
|
||||
pRsp->downstreamTaskId, pRsp->downstreamNodeId, tstrerror(code));
|
||||
|
@ -1158,7 +1186,9 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, i
|
|||
ASSERT(leftRsp >= 0);
|
||||
|
||||
if (leftRsp > 0) {
|
||||
stDebug( "s-task:%s recv dispatch rsp, msgId:%d from 0x%x(vgId:%d), downstream task input status:%d code:%s, waiting for %d rsp",
|
||||
stDebug(
|
||||
"s-task:%s recv dispatch rsp, msgId:%d from 0x%x(vgId:%d), downstream task input status:%d code:%s, waiting "
|
||||
"for %d rsp",
|
||||
id, msgId, pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->inputStatus, tstrerror(code), leftRsp);
|
||||
} else {
|
||||
stDebug(
|
||||
|
@ -1166,8 +1196,8 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, i
|
|||
id, msgId, pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->inputStatus, tstrerror(code));
|
||||
}
|
||||
} else {
|
||||
stDebug("s-task:%s recv fix-dispatch rsp, msgId:%d from 0x%x(vgId:%d), downstream task input status:%d code:%s",
|
||||
id, msgId, pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->inputStatus, tstrerror(code));
|
||||
stDebug("s-task:%s recv fix-dispatch rsp, msgId:%d from 0x%x(vgId:%d), downstream task input status:%d code:%s", id,
|
||||
msgId, pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->inputStatus, tstrerror(code));
|
||||
}
|
||||
|
||||
ASSERT(leftRsp >= 0);
|
||||
|
|
|
@ -174,6 +174,7 @@ SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandF
|
|||
pMeta->ahandle = ahandle;
|
||||
pMeta->expandFunc = expandFunc;
|
||||
pMeta->stage = stage;
|
||||
pMeta->role = (vgId == SNODE_HANDLE) ? NODE_ROLE_LEADER : NODE_ROLE_UNINIT;
|
||||
|
||||
// send heartbeat every 5sec.
|
||||
pMeta->rid = taosAddRef(streamMetaId, pMeta);
|
||||
|
@ -204,7 +205,6 @@ SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandF
|
|||
}
|
||||
pMeta->streamBackendRid = taosAddRef(streamBackendId, pMeta->streamBackend);
|
||||
|
||||
pMeta->role = NODE_ROLE_UNINIT;
|
||||
code = streamBackendLoadCheckpointInfo(pMeta);
|
||||
|
||||
taosInitRWLatch(&pMeta->lock);
|
||||
|
@ -784,7 +784,7 @@ int32_t tEncodeStreamHbMsg(SEncoder* pEncoder, const SStreamHbMsg* pReq) {
|
|||
if (tEncodeI64(pEncoder, ps->id.streamId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, ps->id.taskId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, ps->status) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, ps->stage) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, ps->stage) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, ps->nodeId) < 0) return -1;
|
||||
if (tEncodeDouble(pEncoder, ps->inputQUsed) < 0) return -1;
|
||||
if (tEncodeDouble(pEncoder, ps->inputRate) < 0) return -1;
|
||||
|
@ -822,7 +822,7 @@ int32_t tDecodeStreamHbMsg(SDecoder* pDecoder, SStreamHbMsg* pReq) {
|
|||
if (tDecodeI64(pDecoder, &entry.id.streamId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &taskId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &entry.status) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &entry.stage) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &entry.stage) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &entry.nodeId) < 0) return -1;
|
||||
if (tDecodeDouble(pDecoder, &entry.inputQUsed) < 0) return -1;
|
||||
if (tDecodeDouble(pDecoder, &entry.inputRate) < 0) return -1;
|
||||
|
@ -938,7 +938,7 @@ void metaHbToMnode(void* param, void* tmrId) {
|
|||
SStreamHbMsg hbMsg = {0};
|
||||
SEpSet epset = {0};
|
||||
bool hasMnodeEpset = false;
|
||||
int32_t stage = 0;
|
||||
int64_t stage = 0;
|
||||
|
||||
streamMetaRLock(pMeta);
|
||||
|
||||
|
@ -1117,11 +1117,6 @@ void streamMetaStartHb(SStreamMeta* pMeta) {
|
|||
metaHbToMnode(pRid, NULL);
|
||||
}
|
||||
|
||||
void streamMetaInitForSnode(SStreamMeta* pMeta) {
|
||||
pMeta->stage = 0;
|
||||
pMeta->role = NODE_ROLE_LEADER;
|
||||
}
|
||||
|
||||
void streamMetaResetStartInfo(STaskStartInfo* pStartInfo) {
|
||||
taosHashClear(pStartInfo->pReadyTaskSet);
|
||||
taosHashClear(pStartInfo->pFailedTaskSet);
|
||||
|
|
|
@ -289,10 +289,11 @@ static void recheckDownstreamTasks(void* param, void* tmrId) {
|
|||
stDebug("s-task:%s complete send check in timer, ref:%d", pTask->id.idStr, ref);
|
||||
}
|
||||
|
||||
int32_t streamTaskCheckStatus(SStreamTask* pTask, int32_t upstreamTaskId, int32_t vgId, int64_t stage) {
|
||||
int32_t streamTaskCheckStatus(SStreamTask* pTask, int32_t upstreamTaskId, int32_t vgId, int64_t stage, int64_t* oldStage) {
|
||||
SStreamChildEpInfo* pInfo = streamTaskGetUpstreamTaskEpInfo(pTask, upstreamTaskId);
|
||||
ASSERT(pInfo != NULL);
|
||||
|
||||
*oldStage = pInfo->stage;
|
||||
const char* id = pTask->id.idStr;
|
||||
if (stage == -1) {
|
||||
stDebug("s-task:%s receive check msg from upstream task:0x%x(vgId:%d), invalid stageId:%" PRId64 ", not ready", id,
|
||||
|
@ -457,9 +458,9 @@ int32_t streamProcessCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRs
|
|||
if (pRsp->status == TASK_UPSTREAM_NEW_STAGE || pRsp->status == TASK_DOWNSTREAM_NOT_LEADER) {
|
||||
if (pRsp->status == TASK_UPSTREAM_NEW_STAGE) {
|
||||
stError(
|
||||
"s-task:%s vgId:%d self vnode-transfer/leader-change/restart detected, old stage:%d, current stage:%d, "
|
||||
"s-task:%s vgId:%d self vnode-transfer/leader-change/restart detected, old stage:%"PRId64", current stage:%"PRId64", "
|
||||
"not check wait for downstream task nodeUpdate, and all tasks restart",
|
||||
id, pRsp->upstreamNodeId, pRsp->oldStage, (int32_t)pTask->pMeta->stage);
|
||||
id, pRsp->upstreamNodeId, pRsp->oldStage, pTask->pMeta->stage);
|
||||
} else {
|
||||
stError(
|
||||
"s-task:%s downstream taskId:0x%x (vgId:%d) not leader, self dispatch epset needs to be updated, not check "
|
||||
|
@ -474,7 +475,7 @@ int32_t streamProcessCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRs
|
|||
STaskRecheckInfo* pInfo = createRecheckInfo(pTask, pRsp);
|
||||
|
||||
int32_t ref = atomic_add_fetch_32(&pTask->status.timerActive, 1);
|
||||
stDebug("s-task:%s downstream taskId:0x%x (vgId:%d) not ready, stage:%d, retry in 100ms, ref:%d ", id,
|
||||
stDebug("s-task:%s downstream taskId:0x%x (vgId:%d) not ready, stage:%"PRId64", retry in 100ms, ref:%d ", id,
|
||||
pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->oldStage, ref);
|
||||
pInfo->checkTimer = taosTmrStart(recheckDownstreamTasks, CHECK_DOWNSTREAM_INTERVAL, pInfo, streamEnv.timer);
|
||||
}
|
||||
|
@ -921,7 +922,7 @@ int32_t tEncodeStreamTaskCheckRsp(SEncoder* pEncoder, const SStreamTaskCheckRsp*
|
|||
if (tEncodeI32(pEncoder, pRsp->downstreamNodeId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pRsp->downstreamTaskId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pRsp->childId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pRsp->oldStage) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pRsp->oldStage) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pRsp->status) < 0) return -1;
|
||||
tEndEncode(pEncoder);
|
||||
return pEncoder->pos;
|
||||
|
@ -936,7 +937,7 @@ int32_t tDecodeStreamTaskCheckRsp(SDecoder* pDecoder, SStreamTaskCheckRsp* pRsp)
|
|||
if (tDecodeI32(pDecoder, &pRsp->downstreamNodeId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pRsp->downstreamTaskId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pRsp->childId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pRsp->oldStage) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pRsp->oldStage) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pRsp->status) < 0) return -1;
|
||||
tEndDecode(pDecoder);
|
||||
return 0;
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
|
||||
#include "executor.h"
|
||||
#include "streamInt.h"
|
||||
#include "streamsm.h"
|
||||
#include "tmisce.h"
|
||||
#include "tstream.h"
|
||||
#include "ttimer.h"
|
||||
#include "wal.h"
|
||||
#include "streamsm.h"
|
||||
|
||||
static void streamTaskDestroyUpstreamInfo(SUpstreamInfo* pUpstreamInfo);
|
||||
|
||||
|
@ -358,7 +358,9 @@ void tFreeStreamTask(SStreamTask* pTask) {
|
|||
walCloseReader(pTask->exec.pWalReader);
|
||||
}
|
||||
|
||||
streamClearChkptReadyMsg(pTask);
|
||||
pTask->pReadyMsgList = taosArrayDestroy(pTask->pReadyMsgList);
|
||||
|
||||
if (pTask->msgInfo.pData != NULL) {
|
||||
destroyDispatchMsg(pTask->msgInfo.pData, getNumOfDispatchBranch(pTask));
|
||||
pTask->msgInfo.pData = NULL;
|
||||
|
@ -442,7 +444,8 @@ int32_t streamTaskInit(SStreamTask* pTask, SStreamMeta* pMeta, SMsgCb* pMsgCb, i
|
|||
|
||||
pTask->outputInfo.pTokenBucket = taosMemoryCalloc(1, sizeof(STokenBucket));
|
||||
if (pTask->outputInfo.pTokenBucket == NULL) {
|
||||
stError("s-task:%s failed to prepare the tokenBucket, code:%s", pTask->id.idStr, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
|
||||
stError("s-task:%s failed to prepare the tokenBucket, code:%s", pTask->id.idStr,
|
||||
tstrerror(TSDB_CODE_OUT_OF_MEMORY));
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -529,8 +532,8 @@ void streamTaskUpdateUpstreamInfo(SStreamTask* pTask, int32_t nodeId, const SEpS
|
|||
SStreamChildEpInfo* pInfo = taosArrayGetP(pTask->upstreamInfo.pList, i);
|
||||
if (pInfo->nodeId == nodeId) {
|
||||
epsetAssign(&pInfo->epSet, pEpSet);
|
||||
stDebug("s-task:0x%x update the upstreamInfo taskId:0x%x(nodeId:%d) newEpset:%s", pTask->id.taskId,
|
||||
pInfo->taskId, nodeId, buf);
|
||||
stDebug("s-task:0x%x update the upstreamInfo taskId:0x%x(nodeId:%d) newEpset:%s", pTask->id.taskId, pInfo->taskId,
|
||||
nodeId, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ int32_t syncWriteCfgFile(SSyncNode *pNode) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -128,7 +128,7 @@ int32_t raftStoreWriteFile(SSyncNode *pNode) {
|
|||
if (buffer == NULL) goto _OVER;
|
||||
terrno = 0;
|
||||
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pFile == NULL) goto _OVER;
|
||||
|
||||
int32_t len = strlen(buffer);
|
||||
|
|
|
@ -112,7 +112,7 @@ int32_t tfsAllocDiskOnTier(STfsTier *pTier) {
|
|||
int32_t retId = -1;
|
||||
int64_t avail = 0;
|
||||
for (int32_t id = 0; id < TFS_MAX_DISKS_PER_TIER; ++id) {
|
||||
#if 0 // round-robin
|
||||
#if 1 // round-robin
|
||||
int32_t diskId = (pTier->nextid + id) % pTier->ndisk;
|
||||
STfsDisk *pDisk = pTier->disks[diskId];
|
||||
|
||||
|
|
|
@ -873,7 +873,7 @@ int walSaveMeta(SWal* pWal) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pMetaFile == NULL) {
|
||||
wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
|
|
|
@ -133,6 +133,7 @@ int32_t walRollback(SWal *pWal, int64_t ver) {
|
|||
}
|
||||
|
||||
walBuildIdxName(pWal, walGetCurFileFirstVer(pWal), fnameStr);
|
||||
taosCloseFile(&pWal->pIdxFile);
|
||||
TdFilePtr pIdxFile = taosOpenFile(fnameStr, TD_FILE_WRITE | TD_FILE_READ | TD_FILE_APPEND);
|
||||
|
||||
if (pIdxFile == NULL) {
|
||||
|
@ -153,6 +154,7 @@ int32_t walRollback(SWal *pWal, int64_t ver) {
|
|||
}
|
||||
|
||||
walBuildLogName(pWal, walGetCurFileFirstVer(pWal), fnameStr);
|
||||
taosCloseFile(&pWal->pLogFile);
|
||||
TdFilePtr pLogFile = taosOpenFile(fnameStr, TD_FILE_WRITE | TD_FILE_READ | TD_FILE_APPEND);
|
||||
wDebug("vgId:%d, wal truncate file %s", pWal->cfg.vgId, fnameStr);
|
||||
if (pLogFile == NULL) {
|
||||
|
@ -204,6 +206,7 @@ int32_t walRollback(SWal *pWal, int64_t ver) {
|
|||
pWal->vers.lastVer = ver - 1;
|
||||
((SWalFileInfo *)taosArrayGetLast(pWal->fileInfoSet))->lastVer = ver - 1;
|
||||
((SWalFileInfo *)taosArrayGetLast(pWal->fileInfoSet))->fileSize = entry.offset;
|
||||
|
||||
taosCloseFile(&pIdxFile);
|
||||
taosCloseFile(&pLogFile);
|
||||
|
||||
|
@ -605,7 +608,7 @@ int32_t walWriteWithSyncInfo(SWal *pWal, int64_t index, tmsg_t msgType, SWalSync
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pWal->pIdxFile == NULL || pWal->pIdxFile == NULL || pWal->writeCur < 0) {
|
||||
if (pWal->pIdxFile == NULL || pWal->pLogFile == NULL || pWal->writeCur < 0) {
|
||||
if (walInitWriteFile(pWal) < 0) {
|
||||
taosThreadMutexUnlock(&pWal->mutex);
|
||||
return -1;
|
||||
|
|
|
@ -21,11 +21,12 @@
|
|||
#include <io.h>
|
||||
#include <WinBase.h>
|
||||
#include <ktmw32.h>
|
||||
#include <windows.h>
|
||||
#define F_OK 0
|
||||
#define W_OK 2
|
||||
#define R_OK 4
|
||||
|
||||
#define _SEND_FILE_STEP_ 1000
|
||||
#define _SEND_FILE_STEP_ 1024
|
||||
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
|
@ -44,12 +45,22 @@
|
|||
|
||||
typedef int32_t FileFd;
|
||||
|
||||
#ifdef WINDOWS
|
||||
typedef struct TdFile {
|
||||
TdThreadRwlock rwlock;
|
||||
int refId;
|
||||
HANDLE hFile;
|
||||
FILE* fp;
|
||||
int32_t tdFileOptions;
|
||||
} TdFile;
|
||||
#else
|
||||
typedef struct TdFile {
|
||||
TdThreadRwlock rwlock;
|
||||
int refId;
|
||||
FileFd fd;
|
||||
FILE *fp;
|
||||
} TdFile;
|
||||
#endif // WINDOWS
|
||||
|
||||
#define FILE_WITH_LOCK 1
|
||||
|
||||
|
@ -240,15 +251,12 @@ int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime, int32_t *a
|
|||
return 0;
|
||||
}
|
||||
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
|
||||
if (pFile == NULL || pFile->fd < 0) {
|
||||
#ifdef WINDOWS
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION bhfi;
|
||||
HANDLE handle = (HANDLE)_get_osfhandle(pFile->fd);
|
||||
if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
|
||||
if (GetFileInformationByHandle(pFile->hFile, &bhfi) == FALSE) {
|
||||
printf("taosFStatFile get file info fail.");
|
||||
return -1;
|
||||
}
|
||||
|
@ -262,7 +270,9 @@ int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
|
|||
}
|
||||
|
||||
#else
|
||||
|
||||
if (pFile == NULL || pFile->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
struct stat fileStat;
|
||||
int32_t code = fstat(pFile->fd, &fileStat);
|
||||
if (code < 0) {
|
||||
|
@ -282,10 +292,7 @@ int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
|
||||
int fd = -1;
|
||||
FILE *fp = NULL;
|
||||
if (tdFileOptions & TD_FILE_STREAM) {
|
||||
FILE *taosOpenFileForStream(const char *path, int32_t tdFileOptions) {
|
||||
char *mode = NULL;
|
||||
if (tdFileOptions & TD_FILE_APPEND) {
|
||||
mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
|
||||
|
@ -300,11 +307,333 @@ TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
|
|||
if (tdFileOptions & TD_FILE_EXCL) {
|
||||
return NULL;
|
||||
}
|
||||
fp = fopen(path, mode);
|
||||
if (fp == NULL) {
|
||||
return NULL;
|
||||
return fopen(path, mode);
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
HANDLE taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
|
||||
DWORD openMode = 0;
|
||||
DWORD access = 0;
|
||||
DWORD fileFlag = FILE_ATTRIBUTE_NORMAL;
|
||||
DWORD shareMode = FILE_SHARE_READ;
|
||||
|
||||
openMode = OPEN_EXISTING;
|
||||
if (tdFileOptions & TD_FILE_CREATE) {
|
||||
openMode = OPEN_ALWAYS;
|
||||
} else if (tdFileOptions & TD_FILE_EXCL) {
|
||||
openMode = CREATE_NEW;
|
||||
} else if ((tdFileOptions & TD_FILE_TRUNC)) {
|
||||
openMode = TRUNCATE_EXISTING;
|
||||
access |= GENERIC_WRITE;
|
||||
}
|
||||
if (tdFileOptions & TD_FILE_APPEND) {
|
||||
access |= FILE_APPEND_DATA;
|
||||
}
|
||||
if (tdFileOptions & TD_FILE_WRITE) {
|
||||
access |= GENERIC_WRITE;
|
||||
}
|
||||
|
||||
shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
access |= GENERIC_READ;
|
||||
|
||||
if (tdFileOptions & TD_FILE_AUTO_DEL) {
|
||||
fileFlag |= FILE_ATTRIBUTE_TEMPORARY;
|
||||
}
|
||||
if (tdFileOptions & TD_FILE_WRITE_THROUGH) {
|
||||
fileFlag |= FILE_FLAG_WRITE_THROUGH;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFile(path, access, shareMode, NULL, openMode, fileFlag, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE && (tdFileOptions & TD_FILE_APPEND) && (tdFileOptions & TD_FILE_WRITE)) {
|
||||
SetFilePointer(h, 0, NULL, FILE_END);
|
||||
}
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD dwError = GetLastError();
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
|
||||
0,
|
||||
(LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
printf("CreateFile failed with error %d: %s", dwError, (char*)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockRdlock(&(pFile->rwlock));
|
||||
#endif
|
||||
if (pFile->hFile == NULL) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD bytesRead;
|
||||
if (!ReadFile(pFile->hFile, buf, count, &bytesRead, NULL)) {
|
||||
bytesRead = -1;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockWrlock(&(pFile->rwlock));
|
||||
#endif
|
||||
|
||||
DWORD bytesWritten;
|
||||
if (!WriteFile(pFile->hFile, buf, count, &bytesWritten, NULL)) {
|
||||
bytesWritten = -1;
|
||||
}
|
||||
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockWrlock(&(pFile->rwlock));
|
||||
#endif
|
||||
ASSERT(pFile->hFile != NULL); // Please check if you have closed the file.
|
||||
if (pFile->hFile == NULL) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD ret = 0;
|
||||
OVERLAPPED ol = {0};
|
||||
ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
|
||||
ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
|
||||
|
||||
SetLastError(0);
|
||||
BOOL result = WriteFile(pFile->hFile, buf, count, &ret, &ol);
|
||||
if (!result) {
|
||||
errno = GetLastError();
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockRdlock(&(pFile->rwlock));
|
||||
#endif
|
||||
|
||||
LARGE_INTEGER liOffset;
|
||||
liOffset.QuadPart = offset;
|
||||
if (!SetFilePointerEx(pFile->hFile, liOffset, NULL, whence)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
liOffset.QuadPart = 0;
|
||||
if (!SetFilePointerEx(pFile->hFile, liOffset, &liOffset, FILE_CURRENT)) {
|
||||
return -1;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return liOffset.QuadPart;
|
||||
}
|
||||
|
||||
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size != NULL) {
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(pFile->hFile, &fileSize)) {
|
||||
return -1; // Error getting file size
|
||||
}
|
||||
*size = fileSize.QuadPart;
|
||||
}
|
||||
|
||||
if (mtime != NULL) {
|
||||
FILETIME creationTime, lastAccessTime, lastWriteTime;
|
||||
if (!GetFileTime(pFile->hFile, &creationTime, &lastAccessTime, &lastWriteTime)) {
|
||||
return -1; // Error getting file time
|
||||
}
|
||||
// Convert the FILETIME structure to a time_t value
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = lastWriteTime.dwLowDateTime;
|
||||
ull.HighPart = lastWriteTime.dwHighDateTime;
|
||||
*mtime = (int32_t)((ull.QuadPart - 116444736000000000ULL) / 10000000ULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t taosLockFile(TdFilePtr pFile) {
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL fSuccess = FALSE;
|
||||
LARGE_INTEGER fileSize;
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
fSuccess = LockFileEx(pFile->hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
|
||||
0, // reserved
|
||||
~0, // number of bytes to lock low
|
||||
~0, // number of bytes to lock high
|
||||
&overlapped // overlapped structure
|
||||
);
|
||||
if (!fSuccess) {
|
||||
return GetLastError();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t taosUnLockFile(TdFilePtr pFile) {
|
||||
if (pFile == NULL || pFile->hFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BOOL fSuccess = FALSE;
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
fSuccess = UnlockFileEx(pFile->hFile, 0, ~0, ~0, &overlapped);
|
||||
if (!fSuccess) {
|
||||
return GetLastError();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (pFile->hFile == NULL) {
|
||||
printf("Ftruncate file error, hFile was null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LARGE_INTEGER li_0;
|
||||
li_0.QuadPart = (int64_t)0;
|
||||
BOOL cur = SetFilePointerEx(pFile->hFile, li_0, NULL, FILE_CURRENT);
|
||||
if (!cur) {
|
||||
printf("SetFilePointerEx Error getting current position in file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LARGE_INTEGER li_size;
|
||||
li_size.QuadPart = l_size;
|
||||
BOOL cur2 = SetFilePointerEx(pFile->hFile, li_size, NULL, FILE_BEGIN);
|
||||
if (cur2 == 0) {
|
||||
int error = GetLastError();
|
||||
printf("SetFilePointerEx GetLastError is: %d\n", error);
|
||||
switch (error) {
|
||||
case ERROR_INVALID_HANDLE:
|
||||
errno = EBADF;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SetEndOfFile(pFile->hFile)) {
|
||||
int error = GetLastError();
|
||||
printf("SetEndOfFile GetLastError is:%d", error);
|
||||
switch (error) {
|
||||
case ERROR_INVALID_HANDLE:
|
||||
errno = EBADF;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
|
||||
if (pFileOut == NULL || pFileIn == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (pFileIn->hFile == NULL || pFileOut->hFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileOffset;
|
||||
fileOffset.QuadPart = *offset;
|
||||
|
||||
if (!SetFilePointerEx(pFileIn->hFile, fileOffset, &fileOffset, FILE_BEGIN)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t writeLen = 0;
|
||||
uint8_t buffer[_SEND_FILE_STEP_] = {0};
|
||||
|
||||
DWORD bytesRead;
|
||||
DWORD bytesWritten;
|
||||
for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
|
||||
if (!ReadFile(pFileIn->hFile, buffer, _SEND_FILE_STEP_, &bytesRead, NULL)) {
|
||||
return writeLen;
|
||||
}
|
||||
|
||||
if (bytesRead <= 0) {
|
||||
return writeLen;
|
||||
} else if (bytesRead < _SEND_FILE_STEP_) {
|
||||
if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
|
||||
return -1;
|
||||
} else {
|
||||
return (int64_t)(writeLen + bytesRead);
|
||||
}
|
||||
} else {
|
||||
if (!WriteFile(pFileOut->hFile, buffer, _SEND_FILE_STEP_, &bytesWritten, NULL)) {
|
||||
return -1;
|
||||
} else {
|
||||
writeLen += _SEND_FILE_STEP_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t remain = size - writeLen;
|
||||
if (remain > 0) {
|
||||
DWORD bytesRead;
|
||||
if (!ReadFile(pFileIn->hFile, buffer, (DWORD)remain, &bytesRead, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytesRead <= 0) {
|
||||
return writeLen;
|
||||
} else {
|
||||
DWORD bytesWritten;
|
||||
if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
|
||||
return -1;
|
||||
} else {
|
||||
writeLen += bytesWritten;
|
||||
}
|
||||
}
|
||||
}
|
||||
return writeLen;
|
||||
}
|
||||
|
||||
#else
|
||||
int taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
|
||||
int access = O_BINARY;
|
||||
access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
|
||||
if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
|
||||
|
@ -318,80 +647,8 @@ TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
|
|||
access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
|
||||
access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
|
||||
access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
|
||||
#ifdef WINDOWS
|
||||
int32_t pmode = _S_IREAD | _S_IWRITE;
|
||||
if (tdFileOptions & TD_FILE_AUTO_DEL) {
|
||||
pmode |= _O_TEMPORARY;
|
||||
}
|
||||
fd = _open(path, access, pmode);
|
||||
#else
|
||||
fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
#endif
|
||||
if (fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
|
||||
if (pFile == NULL) {
|
||||
if (fd >= 0) close(fd);
|
||||
if (fp != NULL) fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockInit(&(pFile->rwlock), NULL);
|
||||
#endif
|
||||
pFile->fd = fd;
|
||||
pFile->fp = fp;
|
||||
pFile->refId = 0;
|
||||
|
||||
if (tdFileOptions & TD_FILE_AUTO_DEL) {
|
||||
#ifdef WINDOWS
|
||||
// do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
|
||||
// the file handle, as well as the space on disk.
|
||||
#else
|
||||
// Remove it instantly, so when the program exits normally/abnormally, the file
|
||||
// will be automatically remove by OS.
|
||||
unlink(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
int32_t taosCloseFile(TdFilePtr *ppFile) {
|
||||
int32_t code = 0;
|
||||
if (ppFile == NULL || *ppFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockWrlock(&((*ppFile)->rwlock));
|
||||
#endif
|
||||
if ((*ppFile)->fp != NULL) {
|
||||
fflush((*ppFile)->fp);
|
||||
fclose((*ppFile)->fp);
|
||||
(*ppFile)->fp = NULL;
|
||||
}
|
||||
if ((*ppFile)->fd >= 0) {
|
||||
#ifdef WINDOWS
|
||||
HANDLE h = (HANDLE)_get_osfhandle((*ppFile)->fd);
|
||||
!FlushFileBuffers(h);
|
||||
#else
|
||||
// warning: never fsync silently in base lib
|
||||
/*fsync((*ppFile)->fd);*/
|
||||
#endif
|
||||
code = close((*ppFile)->fd);
|
||||
(*ppFile)->fd = -1;
|
||||
}
|
||||
(*ppFile)->refId = 0;
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&((*ppFile)->rwlock));
|
||||
taosThreadRwlockDestroy(&((*ppFile)->rwlock));
|
||||
#endif
|
||||
taosMemoryFree(*ppFile);
|
||||
*ppFile = NULL;
|
||||
return code;
|
||||
int fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
|
||||
|
@ -441,42 +698,6 @@ int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
|
|||
return count;
|
||||
}
|
||||
|
||||
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockRdlock(&(pFile->rwlock));
|
||||
#endif
|
||||
ASSERT(pFile->fd >= 0); // Please check if you have closed the file.
|
||||
if (pFile->fd < 0) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
DWORD ret = 0;
|
||||
OVERLAPPED ol = {0};
|
||||
ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
|
||||
ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
|
||||
|
||||
HANDLE handle = (HANDLE)_get_osfhandle(pFile->fd);
|
||||
SetLastError(0);
|
||||
BOOL result = ReadFile(handle, buf, count, &ret, &ol);
|
||||
if (!result && GetLastError() != ERROR_HANDLE_EOF) {
|
||||
errno = GetLastError();
|
||||
ret = -1;
|
||||
}
|
||||
#else
|
||||
int64_t ret = pread(pFile->fd, buf, count, offset);
|
||||
#endif
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
|
@ -706,25 +927,6 @@ int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int32_t taosFsyncFile(TdFilePtr pFile) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this implementation is WRONG
|
||||
// fflush is not a replacement of fsync
|
||||
if (pFile->fp != NULL) return fflush(pFile->fp);
|
||||
if (pFile->fd >= 0) {
|
||||
#ifdef WINDOWS
|
||||
HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
|
||||
return !FlushFileBuffers(h);
|
||||
#else
|
||||
return fsync(pFile->fd);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
|
||||
if (pFileOut == NULL || pFileIn == NULL) {
|
||||
return 0;
|
||||
|
@ -824,6 +1026,167 @@ int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, in
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif // WINDOWS
|
||||
|
||||
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
|
||||
FILE *fp = NULL;
|
||||
#ifdef WINDOWS
|
||||
HANDLE hFile = NULL;
|
||||
#else
|
||||
int fd = -1;
|
||||
#endif
|
||||
if (tdFileOptions & TD_FILE_STREAM) {
|
||||
fp = taosOpenFileForStream(path, tdFileOptions);
|
||||
if (fp == NULL) return NULL;
|
||||
} else {
|
||||
#ifdef WINDOWS
|
||||
hFile = taosOpenFileNotStream(path, tdFileOptions);
|
||||
if (hFile == INVALID_HANDLE_VALUE) return NULL;
|
||||
#else
|
||||
fd = taosOpenFileNotStream(path, tdFileOptions);
|
||||
if (fd == -1) return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
|
||||
if (pFile == NULL) {
|
||||
#ifdef WINDOWS
|
||||
if (hFile != NULL) CloseHandle(hFile);
|
||||
#else
|
||||
if (fd >= 0) close(fd);
|
||||
#endif
|
||||
if (fp != NULL) fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockInit(&(pFile->rwlock), NULL);
|
||||
#endif
|
||||
pFile->fp = fp;
|
||||
pFile->refId = 0;
|
||||
|
||||
#ifdef WINDOWS
|
||||
pFile->hFile = hFile;
|
||||
pFile->tdFileOptions = tdFileOptions;
|
||||
// do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
|
||||
// the file handle, as well as the space on disk.
|
||||
#else
|
||||
pFile->fd = fd;
|
||||
// Remove it instantly, so when the program exits normally/abnormally, the file
|
||||
// will be automatically remove by OS.
|
||||
if (tdFileOptions & TD_FILE_AUTO_DEL) {
|
||||
unlink(path);
|
||||
}
|
||||
#endif
|
||||
return pFile;
|
||||
}
|
||||
|
||||
int32_t taosCloseFile(TdFilePtr *ppFile) {
|
||||
int32_t code = 0;
|
||||
if (ppFile == NULL || *ppFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockWrlock(&((*ppFile)->rwlock));
|
||||
#endif
|
||||
if ((*ppFile)->fp != NULL) {
|
||||
fflush((*ppFile)->fp);
|
||||
fclose((*ppFile)->fp);
|
||||
(*ppFile)->fp = NULL;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
if ((*ppFile)->hFile != NULL) {
|
||||
// FlushFileBuffers((*ppFile)->hFile);
|
||||
if (!CloseHandle((*ppFile)->hFile)) {
|
||||
code = -1;
|
||||
}
|
||||
(*ppFile)->hFile = NULL;
|
||||
#else
|
||||
if ((*ppFile)->fd >= 0) {
|
||||
// warning: never fsync silently in base lib
|
||||
/*fsync((*ppFile)->fd);*/
|
||||
code = close((*ppFile)->fd);
|
||||
(*ppFile)->fd = -1;
|
||||
#endif
|
||||
}
|
||||
(*ppFile)->refId = 0;
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&((*ppFile)->rwlock));
|
||||
taosThreadRwlockDestroy(&((*ppFile)->rwlock));
|
||||
#endif
|
||||
taosMemoryFree(*ppFile);
|
||||
*ppFile = NULL;
|
||||
return code;
|
||||
}
|
||||
|
||||
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockRdlock(&(pFile->rwlock));
|
||||
#endif
|
||||
ASSERT(pFile->hFile != NULL); // Please check if you have closed the file.
|
||||
if (pFile->hFile == NULL) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
DWORD ret = 0;
|
||||
OVERLAPPED ol = {0};
|
||||
ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
|
||||
ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
|
||||
|
||||
SetLastError(0);
|
||||
BOOL result = ReadFile(pFile->hFile, buf, count, &ret, &ol);
|
||||
if (!result && GetLastError() != ERROR_HANDLE_EOF) {
|
||||
errno = GetLastError();
|
||||
ret = -1;
|
||||
}
|
||||
#else
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockRdlock(&(pFile->rwlock));
|
||||
#endif
|
||||
ASSERT(pFile->fd >= 0); // Please check if you have closed the file.
|
||||
if (pFile->fd < 0) {
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
int64_t ret = pread(pFile->fd, buf, count, offset);
|
||||
#endif
|
||||
#if FILE_WITH_LOCK
|
||||
taosThreadRwlockUnlock(&(pFile->rwlock));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t taosFsyncFile(TdFilePtr pFile) {
|
||||
if (pFile == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this implementation is WRONG
|
||||
// fflush is not a replacement of fsync
|
||||
if (pFile->fp != NULL) return fflush(pFile->fp);
|
||||
#ifdef WINDOWS
|
||||
if (pFile->hFile != NULL) {
|
||||
if (pFile->tdFileOptions & TD_FILE_WRITE_THROUGH) {
|
||||
return 0;
|
||||
}
|
||||
return !FlushFileBuffers(pFile->hFile);
|
||||
#else
|
||||
if (pFile->fd >= 0) {
|
||||
return fsync(pFile->fd);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
|
||||
if (pFile == NULL || pFile->fp == NULL) {
|
||||
return;
|
||||
|
@ -834,7 +1197,13 @@ void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
bool taosValidFile(TdFilePtr pFile) { return pFile != NULL && pFile->fd > 0; }
|
||||
bool taosValidFile(TdFilePtr pFile) {
|
||||
#ifdef WINDOWS
|
||||
return pFile != NULL && pFile->hFile != NULL;
|
||||
#else
|
||||
return pFile != NULL && pFile->fd > 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t taosUmaskFile(int32_t maskVal) {
|
||||
#ifdef WINDOWS
|
||||
|
@ -960,14 +1329,20 @@ int32_t taosCompressFile(char *srcFileName, char *destFileName) {
|
|||
goto cmp_end;
|
||||
}
|
||||
|
||||
pFile = taosOpenFile(destFileName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||
if (pFile == NULL) {
|
||||
int access = O_BINARY | O_WRONLY | O_TRUNC | O_CREAT;
|
||||
#ifdef WINDOWS
|
||||
int32_t pmode = _S_IREAD | _S_IWRITE;
|
||||
#else
|
||||
int32_t pmode = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
#endif
|
||||
int fd = open(destFileName, access, pmode);
|
||||
if (fd < 0) {
|
||||
ret = -2;
|
||||
goto cmp_end;
|
||||
}
|
||||
|
||||
// Both gzclose() and fclose() will close the associated fd, so they need to have different fds.
|
||||
FileFd gzFd = dup(pFile->fd);
|
||||
FileFd gzFd = dup(fd);
|
||||
if (gzFd < 0) {
|
||||
ret = -4;
|
||||
goto cmp_end;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <inttypes.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
|
@ -29,6 +30,10 @@
|
|||
#include "os.h"
|
||||
#include "tlog.h"
|
||||
|
||||
#ifdef WINDOWS
|
||||
#include <windows.h>
|
||||
#endif // WINDOWS
|
||||
|
||||
TEST(osTest, osSystem) {
|
||||
const char *flags = "UTL FATAL ";
|
||||
ELogLevel level = DEBUG_FATAL;
|
||||
|
@ -68,7 +73,8 @@ void fileOperateOnBusy(void *param) {
|
|||
char * fname = (char *)param;
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE);
|
||||
printf("On busy thread open file\n");
|
||||
ASSERT_NE(pFile, nullptr);
|
||||
if (pFile == NULL) return;
|
||||
// ASSERT_NE(pFile, nullptr);
|
||||
|
||||
int ret = taosLockFile(pFile);
|
||||
printf("On busy thread lock file ret:%d\n", ret);
|
||||
|
@ -97,6 +103,7 @@ TEST(osTest, osFile) {
|
|||
TdFilePtr pOutFD = taosCreateFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
|
||||
ASSERT_NE(pOutFD, nullptr);
|
||||
printf("create file success\n");
|
||||
taosCloseFile(&pOutFD);
|
||||
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE);
|
||||
printf("open file\n");
|
||||
|
@ -135,4 +142,178 @@ TEST(osTest, osFile) {
|
|||
//printf("remove file success");
|
||||
}
|
||||
|
||||
#ifndef OSFILE_PERFORMANCE_TEST
|
||||
|
||||
#define MAX_WORDS 100
|
||||
#define MAX_WORD_LENGTH 20
|
||||
#define MAX_TEST_FILE_SIZE 100000
|
||||
#define TESTTIMES 1000
|
||||
|
||||
char *getRandomWord() {
|
||||
static char words[][MAX_WORD_LENGTH] = {
|
||||
"Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
|
||||
"sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna",
|
||||
"aliqua", "Ut", "enim", "ad", "minim", "veniam", "quis", "nostrud", "exercitation", "ullamco",
|
||||
"Why", "do", "programmers", "prefer", "using", "dark", "mode?", "Because", "light", "attracts",
|
||||
"bugs", "and", "they", "want", "to", "code", "in", "peace,", "like", "a", "ninja", "in", "the", "shadows."
|
||||
"aliqua", "Ut", "enim", "ad", "minim", "veniam", "quis", "nostrud", "exercitation", "ullamco",
|
||||
"laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo", "consequat", "Duis", "aute", "irure",
|
||||
"dolor", "in", "reprehenderit", "in", "voluptate", "velit", "esse", "cillum", "dolore", "eu",
|
||||
"fugiat", "nulla", "pariatur", "Excepteur", "sint", "occaecat", "cupidatat", "non", "proident",
|
||||
"sunt", "in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum"
|
||||
};
|
||||
|
||||
return words[taosRand() % MAX_WORDS];
|
||||
}
|
||||
|
||||
int64_t fillBufferWithRandomWords(char *buffer, int64_t maxBufferSize) {
|
||||
int64_t len = 0;
|
||||
while (len < maxBufferSize) {
|
||||
char * word = getRandomWord();
|
||||
size_t wordLen = strlen(word);
|
||||
|
||||
if (len + wordLen + 1 < maxBufferSize) {
|
||||
strcat(buffer, word);
|
||||
strcat(buffer, " ");
|
||||
len += wordLen + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int64_t calculateAverage(int64_t arr[], int size) {
|
||||
int64_t sum = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
sum += arr[i];
|
||||
}
|
||||
return sum / size;
|
||||
}
|
||||
|
||||
int64_t calculateMax(int64_t arr[], int size) {
|
||||
int64_t max = arr[0];
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (arr[i] > max) {
|
||||
max = arr[i];
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
int64_t calculateMin(int64_t arr[], int size) {
|
||||
int64_t min = arr[0];
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (arr[i] < min) {
|
||||
min = arr[i];
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
TEST(osTest, osFilePerformance) {
|
||||
printf("os file performance testting...\n");
|
||||
int64_t WriteFileCost;
|
||||
int64_t ReadFileCost;
|
||||
int64_t OpenForWriteCloseFileCost;
|
||||
int64_t OpenForReadCloseFileCost;
|
||||
|
||||
char * buffer;
|
||||
char * writeBuffer = (char *)taosMemoryCalloc(1, MAX_TEST_FILE_SIZE);
|
||||
char * readBuffer = (char *)taosMemoryCalloc(1, MAX_TEST_FILE_SIZE);
|
||||
int64_t size = fillBufferWithRandomWords(writeBuffer, MAX_TEST_FILE_SIZE);
|
||||
char * fname = "./osFilePerformanceTest.txt";
|
||||
|
||||
TdFilePtr pOutFD = taosCreateFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
|
||||
ASSERT_NE(pOutFD, nullptr);
|
||||
taosCloseFile(&pOutFD);
|
||||
|
||||
printf("os file performance start write...\n");
|
||||
int64_t t1 = taosGetTimestampUs();
|
||||
for (int i = 0; i < TESTTIMES; ++i) {
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_WRITE_THROUGH);
|
||||
ASSERT_NE(pFile, nullptr);
|
||||
taosWriteFile(pFile, writeBuffer, size);
|
||||
taosFsyncFile(pFile);
|
||||
taosCloseFile(&pFile);
|
||||
}
|
||||
|
||||
int64_t t2 = taosGetTimestampUs();
|
||||
WriteFileCost = t2 - t1;
|
||||
|
||||
printf("os file performance start read...\n");
|
||||
for (int i = 0; i < TESTTIMES; ++i) {
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_READ);
|
||||
ASSERT_NE(pFile, nullptr);
|
||||
taosReadFile(pFile, readBuffer, size);
|
||||
taosCloseFile(&pFile);
|
||||
int readLine = strlen(readBuffer);
|
||||
ASSERT_EQ(size, readLine);
|
||||
}
|
||||
int64_t t3 = taosGetTimestampUs();
|
||||
ReadFileCost = t3 - t2;
|
||||
|
||||
printf("os file performance start open1...\n");
|
||||
for (int i = 0; i < TESTTIMES; ++i) {
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE);
|
||||
ASSERT_NE(pFile, nullptr);
|
||||
taosCloseFile(&pFile);
|
||||
}
|
||||
int64_t t4 = taosGetTimestampUs();
|
||||
OpenForWriteCloseFileCost = t4 - t3;
|
||||
|
||||
printf("os file performance start open2...\n");
|
||||
for (int i = 0; i < TESTTIMES; ++i) {
|
||||
TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_READ);
|
||||
ASSERT_NE(pFile, nullptr);
|
||||
taosCloseFile(&pFile);
|
||||
}
|
||||
int64_t t5 = taosGetTimestampUs();
|
||||
OpenForReadCloseFileCost = t5 - t4;
|
||||
|
||||
#ifdef WINDOWS
|
||||
printf("os file performance start window native...\n");
|
||||
for (int i = 0; i < TESTTIMES; ++i) {
|
||||
HANDLE hFile = CreateFile(fname, // 文件名
|
||||
GENERIC_WRITE, // 写权限
|
||||
FILE_SHARE_READ, // 不共享
|
||||
NULL, // 默认安全描述符
|
||||
OPEN_ALWAYS, // 打开已存在的文件
|
||||
FILE_FLAG_WRITE_THROUGH, // 文件标志,可以根据实际需求调整
|
||||
NULL // 模板文件句柄,对于创建新文件不需要
|
||||
);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
printf("Error opening file\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// 写入数据
|
||||
DWORD bytesWritten;
|
||||
if (!WriteFile(hFile, writeBuffer, size, &bytesWritten, NULL)) {
|
||||
// 处理错误
|
||||
printf("Error writing to file\n");
|
||||
CloseHandle(hFile);
|
||||
break;
|
||||
}
|
||||
// 关闭文件
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
int64_t t6 = taosGetTimestampUs();
|
||||
int64_t nativeWritCost = t6 - t5;
|
||||
|
||||
printf("Test Write file using native API %d times, cost: %" PRId64 "us\n", TESTTIMES, nativeWritCost);
|
||||
#endif // WINDOWS
|
||||
|
||||
taosMemoryFree(writeBuffer);
|
||||
taosMemoryFree(readBuffer);
|
||||
|
||||
printf("Test Write file %d times, cost: %" PRId64 "us\n", TESTTIMES, WriteFileCost);
|
||||
printf("Test Read file %d times, cost: %" PRId64 "us\n", TESTTIMES, ReadFileCost);
|
||||
printf("Test OpenForWrite & Close file %d times, cost: %" PRId64 "us\n", TESTTIMES, OpenForWriteCloseFileCost);
|
||||
printf("Test OpenForRead & Close file %d times, cost: %" PRId64 "us\n", TESTTIMES, OpenForReadCloseFileCost);
|
||||
}
|
||||
|
||||
#endif OSFILE_PERFORMANCE_TEST
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
|
@ -280,8 +280,7 @@ int32_t tsDecompressINTImp(const char *const input, const int32_t nelements, cha
|
|||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------Bool Compression
|
||||
* ---------------------------------------------- */
|
||||
/* ----------------------------------------------Bool Compression ---------------------------------------------- */
|
||||
// TODO: You can also implement it using RLE method.
|
||||
int32_t tsCompressBoolImp(const char *const input, const int32_t nelements, char *const output) {
|
||||
int32_t pos = -1;
|
||||
|
@ -387,8 +386,7 @@ int32_t tsDecompressBoolRLEImp(const char *const input, const int32_t nelements,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------String Compression
|
||||
* ---------------------------------------------- */
|
||||
/* ----------------------------------------------String Compression ---------------------------------------------- */
|
||||
// Note: the size of the output must be larger than input_size + 1 and
|
||||
// LZ4_compressBound(size) + 1;
|
||||
// >= max(input_size, LZ4_compressBound(input_size)) + 1;
|
||||
|
@ -430,8 +428,7 @@ int32_t tsDecompressStringImp(const char *const input, int32_t compressedSize, c
|
|||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------Timestamp Compression
|
||||
* ---------------------------------------------- */
|
||||
/* --------------------------------------------Timestamp Compression ---------------------------------------------- */
|
||||
// TODO: Take care here, we assumes little endian encoding.
|
||||
int32_t tsCompressTimestampImp(const char *const input, const int32_t nelements, char *const output) {
|
||||
int32_t _pos = 1;
|
||||
|
@ -751,8 +748,7 @@ int32_t tsDecompressDoubleImp(const char *const input, const int32_t nelements,
|
|||
return nelements * DOUBLE_BYTES;
|
||||
}
|
||||
|
||||
/* --------------------------------------------Float Compression
|
||||
* ---------------------------------------------- */
|
||||
/* --------------------------------------------Float Compression ---------------------------------------------- */
|
||||
void encodeFloatValue(uint32_t diff, uint8_t flag, char *const output, int32_t *const pos) {
|
||||
uint8_t nbytes = (flag & INT8MASK(3)) + 1;
|
||||
int32_t nshift = (FLOAT_BYTES * BITS_PER_BYTE - nbytes * BITS_PER_BYTE) * (flag >> 3);
|
||||
|
|
|
@ -50,7 +50,7 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
const char *ip = input + 1;
|
||||
int32_t count = 0;
|
||||
int32_t _pos = 0;
|
||||
int64_t prev_value = 0;
|
||||
int64_t prevValue = 0;
|
||||
|
||||
#if __AVX2__
|
||||
while (1) {
|
||||
|
@ -80,13 +80,13 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
if (selector == 0 || selector == 1) {
|
||||
if (tsSIMDEnable && tsAVX2Enable) {
|
||||
for (int32_t i = 0; i < batch; ++i) {
|
||||
__m256i prev = _mm256_set1_epi64x(prev_value);
|
||||
__m256i prev = _mm256_set1_epi64x(prevValue);
|
||||
_mm256_storeu_si256((__m256i *)&p[_pos], prev);
|
||||
_pos += 4;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < remain; ++i) {
|
||||
p[_pos++] = prev_value;
|
||||
p[_pos++] = prevValue;
|
||||
}
|
||||
} else if (tsSIMDEnable && tsAVX512Enable) {
|
||||
#if __AVX512F__
|
||||
|
@ -94,7 +94,7 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
#endif
|
||||
} else { // alternative implementation without SIMD instructions.
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
p[_pos++] = prev_value;
|
||||
p[_pos++] = prevValue;
|
||||
v += bit;
|
||||
}
|
||||
}
|
||||
|
@ -118,16 +118,16 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
__m256i delta = _mm256_xor_si256(_mm256_srli_epi64(zigzagVal, 1), signmask);
|
||||
|
||||
// calculate the cumulative sum (prefix sum) for each number
|
||||
// decode[0] = prev_value + final[0]
|
||||
// decode[1] = decode[0] + final[1] -----> prev_value + final[0] + final[1]
|
||||
// decode[2] = decode[1] + final[2] -----> prev_value + final[0] + final[1] + final[2]
|
||||
// decode[3] = decode[2] + final[3] -----> prev_value + final[0] + final[1] + final[2] + final[3]
|
||||
// decode[0] = prevValue + final[0]
|
||||
// decode[1] = decode[0] + final[1] -----> prevValue + final[0] + final[1]
|
||||
// decode[2] = decode[1] + final[2] -----> prevValue + final[0] + final[1] + final[2]
|
||||
// decode[3] = decode[2] + final[3] -----> prevValue + final[0] + final[1] + final[2] + final[3]
|
||||
|
||||
// 1, 2, 3, 4
|
||||
//+ 0, 1, 0, 3
|
||||
// 1, 3, 3, 7
|
||||
// shift and add for the first round
|
||||
__m128i prev = _mm_set1_epi64x(prev_value);
|
||||
__m128i prev = _mm_set1_epi64x(prevValue);
|
||||
__m256i x = _mm256_slli_si256(delta, 8);
|
||||
|
||||
delta = _mm256_add_epi64(delta, x);
|
||||
|
@ -148,16 +148,16 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
_mm_storeu_si128((__m128i *)&p[_pos + 2], secPart);
|
||||
|
||||
shiftBits = _mm256_add_epi64(shiftBits, inc);
|
||||
prev_value = p[_pos + 3];
|
||||
prevValue = p[_pos + 3];
|
||||
_pos += 4;
|
||||
}
|
||||
|
||||
// handle the remain value
|
||||
for (int32_t i = 0; i < remain; i++) {
|
||||
zigzag_value = ((w >> (v + (batch * bit * 4))) & mask);
|
||||
prev_value += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
prevValue += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
|
||||
p[_pos++] = prev_value;
|
||||
p[_pos++] = prevValue;
|
||||
v += bit;
|
||||
}
|
||||
} else if (tsSIMDEnable && tsAVX512Enable) {
|
||||
|
@ -167,9 +167,9 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
} else { // alternative implementation without SIMD instructions.
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
zigzag_value = ((w >> v) & mask);
|
||||
prev_value += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
prevValue += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
|
||||
p[_pos++] = prev_value;
|
||||
p[_pos++] = prevValue;
|
||||
v += bit;
|
||||
}
|
||||
}
|
||||
|
@ -180,14 +180,14 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
|
||||
if (selector == 0 || selector == 1) {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
p[_pos++] = (int32_t)prev_value;
|
||||
p[_pos++] = (int32_t)prevValue;
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
zigzag_value = ((w >> v) & mask);
|
||||
prev_value += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
prevValue += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
|
||||
p[_pos++] = (int32_t)prev_value;
|
||||
p[_pos++] = (int32_t)prevValue;
|
||||
v += bit;
|
||||
}
|
||||
}
|
||||
|
@ -197,14 +197,14 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
|
||||
if (selector == 0 || selector == 1) {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
p[_pos++] = (int16_t)prev_value;
|
||||
p[_pos++] = (int16_t)prevValue;
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
zigzag_value = ((w >> v) & mask);
|
||||
prev_value += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
prevValue += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
|
||||
p[_pos++] = (int16_t)prev_value;
|
||||
p[_pos++] = (int16_t)prevValue;
|
||||
v += bit;
|
||||
}
|
||||
}
|
||||
|
@ -215,14 +215,14 @@ int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements,
|
|||
|
||||
if (selector == 0 || selector == 1) {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
p[_pos++] = (int8_t)prev_value;
|
||||
p[_pos++] = (int8_t)prevValue;
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 0; i < elems && count < nelements; i++, count++) {
|
||||
zigzag_value = ((w >> v) & mask);
|
||||
prev_value += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
prevValue += ZIGZAG_DECODE(int64_t, zigzag_value);
|
||||
|
||||
p[_pos++] = (int8_t)prev_value;
|
||||
p[_pos++] = (int8_t)prevValue;
|
||||
v += bit;
|
||||
}
|
||||
}
|
||||
|
@ -249,3 +249,74 @@ int32_t tsDecompressFloatImplAvx2(const char *const input, const int32_t nelemen
|
|||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsDecompressTimestampAvx2(const char* const input, const int32_t nelements, char *const output, bool bigEndian) {
|
||||
int64_t *ostream = (int64_t *)output;
|
||||
int32_t ipos = 1, opos = 0;
|
||||
int8_t nbytes = 0;
|
||||
|
||||
int64_t prevValue = 0;
|
||||
int64_t prevDelta = 0;
|
||||
|
||||
int64_t deltaOfDelta = 0;
|
||||
int32_t longBytes = LONG_BYTES;
|
||||
|
||||
#if __AVX2__
|
||||
|
||||
int32_t batch = nelements >> 2;
|
||||
int32_t remainder = nelements & 0x1;
|
||||
|
||||
while (1) {
|
||||
uint8_t flags = input[ipos++];
|
||||
|
||||
// Decode dd1
|
||||
uint64_t dd1 = 0;
|
||||
nbytes = flags & INT8MASK(4);
|
||||
|
||||
if (nbytes == 0) {
|
||||
deltaOfDelta = 0;
|
||||
} else {
|
||||
if (bigEndian) {
|
||||
memcpy(((char *)(&dd1)) + longBytes - nbytes, input + ipos, nbytes);
|
||||
} else {
|
||||
memcpy(&dd1, input + ipos, nbytes);
|
||||
}
|
||||
deltaOfDelta = ZIGZAG_DECODE(int64_t, dd1);
|
||||
}
|
||||
|
||||
ipos += nbytes;
|
||||
prevDelta += deltaOfDelta;
|
||||
prevValue += prevDelta;
|
||||
ostream[opos++] = prevValue;
|
||||
|
||||
if (opos == nelements) {
|
||||
return nelements * longBytes;
|
||||
}
|
||||
|
||||
// Decode dd2
|
||||
uint64_t dd2 = 0;
|
||||
nbytes = (flags >> 4) & INT8MASK(4);
|
||||
if (nbytes == 0) {
|
||||
deltaOfDelta = 0;
|
||||
} else {
|
||||
if (bigEndian) {
|
||||
memcpy(((char *)(&dd2)) + longBytes - nbytes, input + ipos, nbytes);
|
||||
} else {
|
||||
memcpy(&dd2, input + ipos, nbytes);
|
||||
}
|
||||
// zigzag_decoding
|
||||
deltaOfDelta = ZIGZAG_DECODE(int64_t, dd2);
|
||||
}
|
||||
|
||||
ipos += nbytes;
|
||||
prevDelta += deltaOfDelta;
|
||||
prevValue += prevDelta;
|
||||
ostream[opos++] = prevValue;
|
||||
|
||||
if (opos == nelements) {
|
||||
return nelements * longBytes;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -444,6 +444,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_PAR_DEC_IVLD_KLEN, "Invalid klen to decod
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_GEN_IVLD_KEY, "Invalid key to gen active code")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_GEN_APP_LIMIT, "Limited app num to gen active code")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_GEN_ENC_IVLD_KLEN, "Invalid klen to encode active code")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_PAR_IVLD_DIST, "Invalid dist to parse active code")
|
||||
|
||||
// sync
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_TIMEOUT, "Sync timeout")
|
||||
|
|
|
@ -110,6 +110,7 @@ int32_t metaDebugFlag = 131;
|
|||
int32_t udfDebugFlag = 131;
|
||||
int32_t smaDebugFlag = 131;
|
||||
int32_t idxDebugFlag = 131;
|
||||
int32_t sndDebugFlag = 131;
|
||||
|
||||
int64_t dbgEmptyW = 0;
|
||||
int64_t dbgWN = 0;
|
||||
|
@ -153,7 +154,12 @@ int32_t taosInitSlowLog() {
|
|||
#endif
|
||||
|
||||
if (strlen(tsLogDir) != 0) {
|
||||
char lastC = tsLogDir[strlen(tsLogDir) - 1];
|
||||
if (lastC == '\\' || lastC == '/') {
|
||||
snprintf(fullName, PATH_MAX, "%s" "%s", tsLogDir, logFileName);
|
||||
} else {
|
||||
snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logFileName);
|
||||
}
|
||||
} else {
|
||||
snprintf(fullName, PATH_MAX, "%s", logFileName);
|
||||
}
|
||||
|
@ -177,7 +183,12 @@ int32_t taosInitLog(const char *logName, int32_t maxFiles) {
|
|||
|
||||
char fullName[PATH_MAX] = {0};
|
||||
if (strlen(tsLogDir) != 0) {
|
||||
char lastC = tsLogDir[strlen(tsLogDir) - 1];
|
||||
if (lastC == '\\' || lastC == '/') {
|
||||
snprintf(fullName, PATH_MAX, "%s" "%s", tsLogDir, logName);
|
||||
} else {
|
||||
snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logName);
|
||||
}
|
||||
} else {
|
||||
snprintf(fullName, PATH_MAX, "%s", logName);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
,,y,system-test,./pytest.sh python3 ./test.py -f 8-stream/window_close_session_ext.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 8-stream/partition_interval.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 8-stream/pause_resume_test.py
|
||||
#,,n,system-test,python3 ./test.py -f 8-stream/vnode_restart.py -N 4
|
||||
#,,n,system-test,python3 ./test.py -f 8-stream/snode_restart.py -N 4
|
||||
,,n,system-test,python3 ./test.py -f 8-stream/snode_restart_with_checkpoint.py -N 4
|
||||
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbname_vgroup.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stbJoin.py
|
||||
|
|
|
@ -247,7 +247,10 @@ class TDTestCase:
|
|||
tdSql.error('alter all dnodes "activeCode" "' + self.str510 + '"')
|
||||
tdSql.query(f'select * from information_schema.ins_dnodes')
|
||||
tdSql.checkEqual(tdSql.queryResult[0][8],"")
|
||||
tdSql.execute('alter dnode 1 "activeCode" ""')
|
||||
tdSql.error('alter dnode 1 "activeCode" ""')
|
||||
tdSql.error('alter dnode 1 "activeCode"')
|
||||
tdSql.execute('alter all dnodes "activeCode" ""')
|
||||
tdSql.execute('alter all dnodes "activeCode"')
|
||||
tdSql.query(f'select active_code,c_active_code from information_schema.ins_dnodes')
|
||||
tdSql.checkEqual(tdSql.queryResult[0][0],"")
|
||||
tdSql.checkEqual(tdSql.queryResult[0][1],'')
|
||||
|
@ -259,6 +262,10 @@ class TDTestCase:
|
|||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str257 + '"')
|
||||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str254 + '"')
|
||||
tdSql.error('alter dnode 1 "cActiveCode" "' + self.str510 + '"')
|
||||
tdSql.error('alter dnode 1 "cActiveCode" ""')
|
||||
tdSql.error('alter dnode 1 "cActiveCode"')
|
||||
tdSql.execute('alter all dnodes "cActiveCode" ""')
|
||||
tdSql.execute('alter all dnodes "cActiveCode"')
|
||||
tdSql.query(f'select active_code,c_active_code from information_schema.ins_dnodes')
|
||||
tdSql.checkEqual(tdSql.queryResult[0][0],"")
|
||||
tdSql.checkEqual(tdSql.queryResult[0][1],"")
|
||||
|
|
|
@ -162,7 +162,7 @@ class TDTestCase:
|
|||
assert('TIMESTAMP' in data_type_list and 'INT' in data_type_list and 'INT UNSIGNED' in data_type_list and 'BIGINT' in data_type_list and 'BIGINT UNSIGNED' in data_type_list and 'FLOAT' in data_type_list and 'DOUBLE' in data_type_list and 'VARCHAR' in data_type_list and 'SMALLINT' in data_type_list and 'SMALLINT UNSIGNED' in data_type_list and 'TINYINT' in data_type_list and 'TINYINT UNSIGNED' in data_type_list and 'BOOL' in data_type_list and 'VARCHAR' in data_type_list and 'NCHAR' in data_type_list and 'GEOMETRY' in data_type_list and 'VARBINARY' in data_type_list)
|
||||
tdSql.execute("create view v2 as select * from tb where c1 >5 and c7 like '%ab%';")
|
||||
self.check_view_num(2)
|
||||
tdSql.error("create view v3 as select * from tb where c1 like '%ab%';", expectErrInfo='Invalid value type')
|
||||
tdSql.error("create view v3 as select * from tb where c1 like '%ab%';", expectErrInfo='Invalid operation')
|
||||
tdSql.execute("create view v3 as select first(ts), sum(c1) from tb group by c2 having avg(c4) > 0;")
|
||||
tdSql.execute("create view v4 as select _wstart,sum(c6) from tb interval(10s);")
|
||||
tdSql.execute("create view v5 as select * from tb join v2 on tb.ts = v2.ts;")
|
||||
|
|
|
@ -55,7 +55,7 @@ class TDTestCase:
|
|||
tdSql.checkData(0, 2, 0)
|
||||
|
||||
tdSql.query("show dnode 1 variables like '%debugFlag'")
|
||||
tdSql.checkRows(22)
|
||||
tdSql.checkRows(23)
|
||||
|
||||
tdSql.query("show dnode 1 variables like '____debugFlag'")
|
||||
tdSql.checkRows(2)
|
||||
|
|
|
@ -105,7 +105,6 @@ class TDTestCase:
|
|||
|
||||
topicNameList = ['topic1']
|
||||
# expectRowsList = []
|
||||
tmqCom.initConsumerTable("cdb", self.replicaVar)
|
||||
|
||||
tdLog.info("create topics from stb with filter")
|
||||
queryString = "select * from %s.%s"%(paraDict['dbName'], paraDict['stbName'])
|
||||
|
@ -133,14 +132,15 @@ class TDTestCase:
|
|||
tmqCom.getStartConsumeNotifyFromTmqsim()
|
||||
tmqCom.getStartCommitNotifyFromTmqsim()
|
||||
|
||||
tdSql.query("select * from information_schema.ins_vnodes")
|
||||
# tdLog.debug(tdSql.queryResult)
|
||||
tdDnodes = cluster.dnodes
|
||||
for result in tdSql.queryResult:
|
||||
if result[2] == 'dbt' and result[3] == 'leader':
|
||||
tdLog.debug("leader is %d"%(result[0] - 1))
|
||||
tdDnodes[result[0] - 1].stoptaosd()
|
||||
break
|
||||
tdSql.query("balance vgroup leader")
|
||||
# tdSql.query("select * from information_schema.ins_vnodes")
|
||||
# # tdLog.debug(tdSql.queryResult)
|
||||
# tdDnodes = cluster.dnodes
|
||||
# for result in tdSql.queryResult:
|
||||
# if result[2] == 'dbt' and result[3] == 'leader':
|
||||
# tdLog.debug("leader is %d"%(result[0] - 1))
|
||||
# tdDnodes[result[0] - 1].stoptaosd()
|
||||
# break
|
||||
|
||||
pInsertThread.join()
|
||||
expectRows = 1
|
||||
|
@ -159,7 +159,6 @@ class TDTestCase:
|
|||
tdLog.printNoPrefix("======== test case 1 end ...... ")
|
||||
|
||||
def run(self):
|
||||
tdSql.prepare()
|
||||
self.prepareTestEnv()
|
||||
self.tmqCase1()
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
|
||||
import taos
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import os
|
||||
import threading
|
||||
import math
|
||||
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
from util.dnodes import *
|
||||
from util.common import *
|
||||
from util.cluster import *
|
||||
|
||||
class TDTestCase:
|
||||
updatecfgDict = {'checkpointInterval': 1100}
|
||||
print("===================: ", updatecfgDict)
|
||||
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), False)
|
||||
|
||||
|
||||
def case1(self):
|
||||
tdLog.debug("========case1 start========")
|
||||
|
||||
os.system("nohup taosBenchmark -y -B 1 -t 4 -S 1000 -n 1000 -i 1000 -v 2 > /dev/null 2>&1 &")
|
||||
time.sleep(4)
|
||||
tdSql.query("use test")
|
||||
tdSql.query("create snode on dnode 4")
|
||||
tdSql.query("create stream if not exists s1 trigger at_once ignore expired 0 ignore update 0 fill_history 1 into st1 as select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s)")
|
||||
tdLog.debug("========create stream useing snode and insert data ok========")
|
||||
time.sleep(4)
|
||||
|
||||
tdDnodes = cluster.dnodes
|
||||
tdDnodes[3].stoptaosd()
|
||||
time.sleep(2)
|
||||
tdDnodes[3].starttaosd()
|
||||
tdLog.debug("========snode restart ok========")
|
||||
|
||||
time.sleep(30)
|
||||
os.system("kill -9 `pgrep taosBenchmark`")
|
||||
tdLog.debug("========stop insert ok========")
|
||||
time.sleep(2)
|
||||
|
||||
tdSql.query("select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s) order by groupid,_wstart")
|
||||
rowCnt = tdSql.getRows()
|
||||
results = []
|
||||
for i in range(rowCnt):
|
||||
results.append(tdSql.getData(i,1))
|
||||
|
||||
tdSql.query("select * from st1 order by groupid,_wstart")
|
||||
tdSql.checkRows(rowCnt)
|
||||
for i in range(rowCnt):
|
||||
data1 = tdSql.getData(i,1)
|
||||
data2 = results[i]
|
||||
if data1 != data2:
|
||||
tdLog.info("num: %d, act data: %d, expect data: %d"%(i, data1, data2))
|
||||
tdLog.exit("check data error!")
|
||||
|
||||
# tdLog.debug("========sleep 500s========")
|
||||
# time.sleep(500)
|
||||
|
||||
tdLog.debug("case1 end")
|
||||
|
||||
def run(self):
|
||||
self.case1()
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
event = threading.Event()
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -0,0 +1,78 @@
|
|||
|
||||
import taos
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import os
|
||||
import threading
|
||||
import math
|
||||
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
from util.dnodes import *
|
||||
from util.common import *
|
||||
from util.cluster import *
|
||||
|
||||
class TDTestCase:
|
||||
# updatecfgDict = {'checkpointInterval': 5}
|
||||
# print("===================: ", updatecfgDict)
|
||||
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), False)
|
||||
|
||||
|
||||
def case1(self):
|
||||
tdLog.debug("========case1 start========")
|
||||
|
||||
os.system("nohup taosBenchmark -y -B 1 -t 4 -S 1000 -n 1000 -i 1000 -v 2 > /dev/null 2>&1 &")
|
||||
time.sleep(4)
|
||||
tdSql.query("use test")
|
||||
tdSql.query("create snode on dnode 4")
|
||||
tdSql.query("create stream if not exists s1 trigger at_once ignore expired 0 ignore update 0 fill_history 1 into st1 as select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s)")
|
||||
tdLog.debug("========create stream useing snode and insert data ok========")
|
||||
time.sleep(60)
|
||||
|
||||
tdDnodes = cluster.dnodes
|
||||
tdDnodes[3].stoptaosd()
|
||||
time.sleep(2)
|
||||
tdDnodes[3].starttaosd()
|
||||
tdLog.debug("========snode restart ok========")
|
||||
|
||||
time.sleep(30)
|
||||
os.system("kill -9 `pgrep taosBenchmark`")
|
||||
tdLog.debug("========stop insert ok========")
|
||||
time.sleep(2)
|
||||
|
||||
tdSql.query("select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s) order by groupid,_wstart")
|
||||
rowCnt = tdSql.getRows()
|
||||
results = []
|
||||
for i in range(rowCnt):
|
||||
results.append(tdSql.getData(i,1))
|
||||
|
||||
tdSql.query("select * from st1 order by groupid,_wstart")
|
||||
tdSql.checkRows(rowCnt)
|
||||
for i in range(rowCnt):
|
||||
data1 = tdSql.getData(i,1)
|
||||
data2 = results[i]
|
||||
if data1 != data2:
|
||||
tdLog.info("num: %d, act data: %d, expect data: %d"%(i, data1, data2))
|
||||
tdLog.exit("check data error!")
|
||||
|
||||
# tdLog.debug("========sleep 500s========")
|
||||
# time.sleep(500)
|
||||
|
||||
tdLog.debug("case1 end")
|
||||
|
||||
def run(self):
|
||||
self.case1()
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
event = threading.Event()
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
import taos
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import os
|
||||
import threading
|
||||
import math
|
||||
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
from util.dnodes import *
|
||||
from util.common import *
|
||||
from util.cluster import *
|
||||
|
||||
class TDTestCase:
|
||||
updatecfgDict = {'checkpointInterval': 1100}
|
||||
print("===================: ", updatecfgDict)
|
||||
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), False)
|
||||
|
||||
|
||||
def case1(self):
|
||||
tdLog.debug("========case1 start========")
|
||||
|
||||
os.system("nohup taosBenchmark -y -B 1 -t 4 -S 1000 -n 1000 -i 1000 -v 2 > /dev/null 2>&1 &")
|
||||
time.sleep(4)
|
||||
tdSql.query("use test")
|
||||
tdSql.query("create stream if not exists s1 trigger at_once ignore expired 0 ignore update 0 fill_history 1 into st1 as select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s)")
|
||||
tdLog.debug("========create stream useing snode and insert data ok========")
|
||||
time.sleep(4)
|
||||
|
||||
tdDnodes = cluster.dnodes
|
||||
tdDnodes[2].stoptaosd()
|
||||
time.sleep(2)
|
||||
tdDnodes[2].starttaosd()
|
||||
tdLog.debug("========vnode restart ok========")
|
||||
|
||||
time.sleep(30)
|
||||
os.system("kill -9 `pgrep taosBenchmark`")
|
||||
tdLog.debug("========stop insert ok========")
|
||||
time.sleep(2)
|
||||
|
||||
tdSql.query("select _wstart,sum(voltage),groupid from meters partition by groupid interval(2s) order by groupid,_wstart")
|
||||
rowCnt = tdSql.getRows()
|
||||
results = []
|
||||
for i in range(rowCnt):
|
||||
results.append(tdSql.getData(i,1))
|
||||
|
||||
tdSql.query("select * from st1 order by groupid,_wstart")
|
||||
tdSql.checkRows(rowCnt)
|
||||
for i in range(rowCnt):
|
||||
data1 = tdSql.getData(i,1)
|
||||
data2 = results[i]
|
||||
if data1 != data2:
|
||||
tdLog.info("num: %d, act data: %d, expect data: %d"%(i, data1, data2))
|
||||
tdLog.exit("check data error!")
|
||||
|
||||
# tdLog.debug("========sleep 500s========")
|
||||
# time.sleep(500)
|
||||
|
||||
tdLog.debug("case1 end")
|
||||
|
||||
def run(self):
|
||||
self.case1()
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
event = threading.Event()
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -582,7 +582,7 @@ if __name__ == "__main__":
|
|||
tdDnodes.setAsan(asan)
|
||||
tdDnodes.stopAll()
|
||||
for dnode in tdDnodes.dnodes:
|
||||
tdDnodes.deploy(dnode.index,{})
|
||||
tdDnodes.deploy(dnode.index,updateCfgDict)
|
||||
for dnode in tdDnodes.dnodes:
|
||||
tdDnodes.starttaosd(dnode.index)
|
||||
tdCases.logSql(logSql)
|
||||
|
|
|
@ -30,7 +30,7 @@ typedef struct {
|
|||
int meta;
|
||||
int srcVgroups;
|
||||
int dstVgroups;
|
||||
char dir[64];
|
||||
char dir[256];
|
||||
} Config;
|
||||
|
||||
Config g_conf = {0};
|
||||
|
@ -409,6 +409,30 @@ int buildStable(TAOS* pConn, TAOS_RES* pRes) {
|
|||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
#ifdef WINDOWS
|
||||
pRes = taos_query(pConn,
|
||||
"CREATE STABLE `meters_summary` (`_wstart` TIMESTAMP, `current` FLOAT, `groupid` INT, `location` VARCHAR(16)) TAGS (`group_id` BIGINT UNSIGNED)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table meters_summary, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn,
|
||||
" CREATE TABLE `t_d2a450ee819dcf7576f0282d9ac22dbc` USING `meters_summary` (`group_id`) TAGS (13135550082773579308)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table meters_summary, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into t_d2a450ee819dcf7576f0282d9ac22dbc values (now, 120, 1, 'San Francisco')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into table d0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
#else
|
||||
pRes = taos_query(pConn,
|
||||
"create stream meters_summary_s trigger at_once IGNORE EXPIRED 0 into meters_summary as select _wstart, max(current) as current, "
|
||||
"groupid, location from meters partition by groupid, location interval(10m)");
|
||||
|
@ -417,6 +441,7 @@ int buildStable(TAOS* pConn, TAOS_RES* pRes) {
|
|||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
#endif
|
||||
|
||||
pRes = taos_query(pConn, "insert into d0 (ts, current) values (now, 120)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
|
@ -598,8 +623,8 @@ void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) {
|
|||
}
|
||||
|
||||
void initLogFile() {
|
||||
char f1[256] = {0};
|
||||
char f2[256] = {0};
|
||||
char f1[1024] = {0};
|
||||
char f2[1024] = {0};
|
||||
|
||||
if (g_conf.snapShot) {
|
||||
sprintf(f1, "%s/../log/tmq_taosx_tmp_snapshot.source", g_conf.dir);
|
||||
|
|
Loading…
Reference in New Issue